├── assets ├── 2^n.gif ├── arrays.gif ├── bfs.gif ├── bst.gif ├── bucket-sort.gif ├── constant.gif ├── dfs.gif ├── dijkstra.gif ├── graphs.gif ├── hashmap.gif ├── heaps.gif ├── insertion-sort.gif ├── linear.gif ├── linked-list.gif ├── logn.gif ├── merge-sort.gif ├── n squared.gif ├── n!.gif ├── nlogn.gif ├── onm.gif ├── queues.gif ├── quick-sort.gif ├── sqrt(n).gif ├── topological.gif ├── trie.gif └── union-find.gif ├── bigO.md ├── dataStructures.md ├── designPatterns.md ├── dsaGlossary.md ├── graphAlgorithms.md ├── grpc-demo ├── .gitignore ├── grpc-server.js ├── package-lock.json ├── package.json ├── protos │ └── helloworld.proto ├── rest-server.js └── test.js ├── howToUseNeetcode.md ├── mongodb.md ├── python.md ├── sortingAlgorithms.md └── youtubeDesignDoc.md /assets/2^n.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/2^n.gif -------------------------------------------------------------------------------- /assets/arrays.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/arrays.gif -------------------------------------------------------------------------------- /assets/bfs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/bfs.gif -------------------------------------------------------------------------------- /assets/bst.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/bst.gif -------------------------------------------------------------------------------- /assets/bucket-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/bucket-sort.gif -------------------------------------------------------------------------------- /assets/constant.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/constant.gif -------------------------------------------------------------------------------- /assets/dfs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/dfs.gif -------------------------------------------------------------------------------- /assets/dijkstra.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/dijkstra.gif -------------------------------------------------------------------------------- /assets/graphs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/graphs.gif -------------------------------------------------------------------------------- /assets/hashmap.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/hashmap.gif -------------------------------------------------------------------------------- /assets/heaps.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/heaps.gif -------------------------------------------------------------------------------- /assets/insertion-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/insertion-sort.gif -------------------------------------------------------------------------------- /assets/linear.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/linear.gif -------------------------------------------------------------------------------- /assets/linked-list.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/linked-list.gif -------------------------------------------------------------------------------- /assets/logn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/logn.gif -------------------------------------------------------------------------------- /assets/merge-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/merge-sort.gif -------------------------------------------------------------------------------- /assets/n squared.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/n squared.gif -------------------------------------------------------------------------------- /assets/n!.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/n!.gif -------------------------------------------------------------------------------- /assets/nlogn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/nlogn.gif -------------------------------------------------------------------------------- /assets/onm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/onm.gif -------------------------------------------------------------------------------- /assets/queues.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/queues.gif -------------------------------------------------------------------------------- /assets/quick-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/quick-sort.gif -------------------------------------------------------------------------------- /assets/sqrt(n).gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/sqrt(n).gif -------------------------------------------------------------------------------- /assets/topological.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/topological.gif -------------------------------------------------------------------------------- /assets/trie.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/trie.gif -------------------------------------------------------------------------------- /assets/union-find.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neetcode-gh/lesson-data/d3be926c949867f5c94acb9fc0fe2ab2f8b207d0/assets/union-find.gif -------------------------------------------------------------------------------- /bigO.md: -------------------------------------------------------------------------------- 1 | # Big O Notation Cheat Sheet 2 | 3 | > Updated: Jan 23, 2025 4 | > Author: Navdeep Singh 5 | 6 | Big O notation is a way to describe the time complexity of an algorithm. It is a measure of how the runtime of an algorithm grows as the input size grows. To learn more about Big O notation, check out the [Data Structures and Algorithms for Beginners](https://neetcode.io/courses/dsa-for-beginners/0) course. 7 | 8 | It is important to note that Big O notation is a worst-case scenario. It is the maximum amount of time an algorithm will take to complete. 9 | 10 | ## O( 1 ) 11 | 12 | Constant time complexity. The runtime of the algorithm is constant and does not depend on the input size. For example, accessing an element in an array by its index is O(1) because it takes the same amount of time no matter how large the array is. 13 | 14 | ![](https://nc-gifs.pages.dev/constant.gif) 15 | 16 | ```python 17 | # Array 18 | nums = [1, 2, 3] 19 | nums.append(4) # push to end 20 | nums.pop() # pop from end 21 | nums[0] # lookup 22 | nums[1] 23 | nums[2] 24 | 25 | 26 | # HashMap / Set 27 | hashMap = {} 28 | hashMap["key"] = 10 # insert 29 | print("key" in hashMap) # lookup 30 | print(hashMap["key"]) # lookup 31 | hashMap.pop("key") # remove 32 | ``` 33 | 34 | ## O( n ) 35 | 36 | Linear time complexity. The runtime of the algorithm grows linearly with the input size. For example, iterating through an array of size n is O(n) because the time it takes to iterate through the array is proportional to the size of the array. 37 | 38 | ![](https://nc-gifs.pages.dev/linear.gif) 39 | 40 | ```python 41 | nums = [1, 2, 3] 42 | sum(nums) # sum of array 43 | for n in nums: # looping 44 | print(n) 45 | 46 | nums.insert(1, 100) # insert middle 47 | nums.remove(100) # remove middle 48 | print(100 in nums) # search 49 | 50 | import heapq 51 | heapq.heapify(nums) # build heap 52 | 53 | # sometimes even nested loops can be O(n) 54 | # (e.g. monotonic stack or sliding window) 55 | ``` 56 | 57 | ## O( n^2 ) 58 | 59 | Quadratic time complexity. The runtime of the algorithm grows quadratically with the input size. For example, iterating through an array of size n and then iterating through an array of size n again is O(n^2) because it takes n * n operations to complete. 60 | 61 | Even if the inner loop does not run for the entire length of the outer loop, the time complexity is still O(n^2) because the outer loop runs n times and the inner loop runs proportionally to the length of the input array. 62 | 63 | ![](https://nc-gifs.pages.dev/n%20squared.gif) 64 | 65 | ```python 66 | # Traverse a square grid 67 | nums = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 68 | for i in range(len(nums)): 69 | for j in range(len(nums[i])): 70 | print(nums[i][j]) 71 | 72 | 73 | # Get every pair of elements in array 74 | nums = [1, 2, 3] 75 | for i in range(len(nums)): 76 | for j in range(i + 1, len(nums)): 77 | print(nums[i], nums[j]) 78 | 79 | # Insertion sort (insert in middle n times -> n^2) 80 | ``` 81 | 82 | ## O( n * m ) 83 | 84 | This is the time complexity of a nested loop where the inner loop runs m times for each iteration of the outer loop. For example, iterating through an array of size n and then iterating through an array of size m is O(n * m) because it takes n * m operations to complete. 85 | 86 | ![](https://nc-gifs.pages.dev/onm.gif) 87 | 88 | ```python 89 | # Get every pair of elements from two arrays 90 | nums1, nums2 = [1, 2, 3], [4, 5] 91 | for i in range(len(nums1)): 92 | for j in range(len(nums2)): 93 | print(nums1[i], nums2[j]) 94 | 95 | # Traverse rectangle grid 96 | nums = [[1, 2, 3], [4, 5, 6]] 97 | for i in range(len(nums)): 98 | for j in range(len(nums[i])): 99 | print(nums[i][j]) 100 | ``` 101 | 102 | ## O( n^3 ) 103 | 104 | Cubic time complexity. The runtime of the algorithm grows cubically with the input size. For example, iterating through an array of size n and then iterating through an array of size n again and then iterating through an array of size n again is O(n^3) because it takes n * n * n operations to complete. 105 | 106 | ```python 107 | # Get every triplet of elements in array 108 | nums = [1, 2, 3] 109 | for i in range(len(nums)): 110 | for j in range(i + 1, len(nums)): 111 | for k in range(j + 1, len(nums)): 112 | print(nums[i], nums[j], nums[k]) 113 | ``` 114 | 115 | 116 | ## O( logn ) 117 | 118 | Logarithmic time complexity. The runtime of the algorithm grows logarithmically with the input size. For example, searching for an element in a sorted array is O(logn). 119 | 120 | If you are not familiar with log math, this just means that the number of times you can divide a number, n, by 2 until you get to 1 is logn. 121 | 122 | This is why binary search is O(logn) because you can eliminate half of the elements in the array each time you make a comparison. 123 | 124 | ![](https://nc-gifs.pages.dev/logn.gif) 125 | 126 | ```python 127 | # Binary search 128 | nums = [1, 2, 3, 4, 5] 129 | target = 6 130 | l, r = 0, len(nums) - 1 131 | while l <= r: 132 | m = (l + r) // 2 133 | if target < nums[m]: 134 | r = m - 1 135 | elif target > nums[m]: 136 | l = m + 1 137 | else: 138 | print(m) 139 | break 140 | 141 | # Binary Search on BST 142 | def search(root, target): 143 | if not root: 144 | return False 145 | if target < root.val: 146 | return search(root.left, target) 147 | elif target > root.val: 148 | return search(root.right, target) 149 | else: 150 | return True 151 | 152 | # Heap Push and Pop 153 | import heapq 154 | minHeap = [] 155 | heapq.heappush(minHeap, 5) 156 | heapq.heappop(minHeap) 157 | ``` 158 | 159 | 160 | ## O( nlogn ) 161 | 162 | The runtime of the algorithm grows linearly with the input size and the logarithm of the input size. For example, sorting an array is O(nlogn) because it takes n operations to sort the array and logn operations to sort each element. 163 | 164 | ![](https://nc-gifs.pages.dev/nlogn.gif) 165 | 166 | ```python 167 | # HeapSort 168 | import heapq 169 | nums = [1, 2, 3, 4, 5] 170 | heapq.heapify(nums) # O(n) 171 | while nums: 172 | heapq.heappop(nums) # O(logn) 173 | 174 | # MergeSort (and most built-in sorting functions) 175 | ``` 176 | 177 | ## O( 2^n ) 178 | 179 | Exponential time complexity. The runtime of the algorithm grows exponentially with the input size. For example, generating all permutations of an array is O(2^n) because there are 2^n possible permutations. 180 | 181 | ![](https://nc-gifs.pages.dev/2%5En.gif) 182 | 183 | ```python 184 | # Recursion, tree height n, two branches 185 | def recursion(i, nums): 186 | if i == len(nums): 187 | return 0 188 | branch1 = recursion(i + 1, nums) 189 | branch2 = recursion(i + 2, nums) 190 | ``` 191 | 192 | ## O( c^n ) 193 | 194 | Exponential time complexity. The runtime of the algorithm grows exponentially with the input size. For example, generating all permutations of an array is O(2^n) because there are 2^n possible permutations. 195 | 196 | ```python 197 | # c branches, where c is sometimes n. 198 | def recursion(i, nums, c): 199 | if i == len(nums): 200 | return 0 201 | 202 | for j in range(i, i + c): 203 | branch = recursion(j + 1, nums) 204 | ``` 205 | 206 | ## O( n! ) 207 | 208 | Factorial time complexity. The runtime of the algorithm grows factorially with the input size. For example, generating all permutations of an array is O(n!) because there are n! possible permutations. 209 | 210 | ![](https://nc-gifs.pages.dev/n!.gif) 211 | 212 | ```python 213 | # Permutations 214 | def permute(nums): 215 | def backtrack(path, nums): 216 | if not nums: 217 | res.append(path) 218 | return 219 | for i in range(len(nums)): 220 | backtrack(path + [nums[i]], nums[:i] + nums[i + 1:]) 221 | res = [] 222 | backtrack([], nums) 223 | return res 224 | ``` 225 | 226 | ## O( sqrt(n) ) 227 | 228 | Square root time complexity. The runtime of the algorithm grows as the square root of the input size. For example, finding all factors of a number is O(sqrt(n)) because there are sqrt(n) possible factors. 229 | 230 | ![](https://nc-gifs.pages.dev/sqrt(n).gif) 231 | 232 | ```python 233 | # Get all factors of n 234 | import math 235 | n = 12 236 | factors = set() 237 | for i in range(1, int(math.sqrt(n)) + 1): 238 | if n % i == 0: 239 | factors.add(i) 240 | factors.add(n // i) 241 | ``` 242 | -------------------------------------------------------------------------------- /dataStructures.md: -------------------------------------------------------------------------------- 1 | # Top 8 Data Structures for Coding Interviews 2 | 3 | > Updated: Jan 22, 2025 4 | > Author: Navdeep Singh 5 | 6 | ## 1. Arrays 7 | 8 | The most fundamental data structure. Arrays are stored contiguously in memory. 9 | 10 | ![](https://nc-gifs.pages.dev/arrays.gif) 11 | 12 | [Learn more about Arrays](https://neetcode.io/courses/dsa-for-beginners/2) 13 | 14 | ## 2. Linked Lists 15 | 16 | These also store an ordered list of elements, but the values are not contiguous in RAM. Linked list nodes have pointers connecting them. 17 | 18 | ![](https://nc-gifs.pages.dev/linked-list.gif) 19 | 20 | [Learn more about Linked Lists](https://neetcode.io/courses/dsa-for-beginners/5) 21 | 22 | ## 3. HashMaps 23 | 24 | Probably the most useful data structure as well. They use a hash function to map keys to indexes within an array. This allows us to have an amortized time of O(1) for most operations. 25 | 26 | ![](https://nc-gifs.pages.dev/hashmap.gif) 27 | 28 | [Learn more about HashMaps](https://neetcode.io/courses/dsa-for-beginners/23) 29 | 30 | ## 4. Queues 31 | 32 | Typically used to process elements in the same order as they are added. These follow a FIFO (first-in first-out approach). Queues can be double-ended, which allow you to add and remove elements from both the front and the back. 33 | 34 | ![](https://nc-gifs.pages.dev/queues.gif) 35 | 36 | [Learn more about Queues](https://neetcode.io/courses/dsa-for-beginners/7) 37 | 38 | ## 5. Trees 39 | 40 | A Binary Tree is an ordered tree data structure where each node is connected to at most two more nodes (called the left and the right child). Being ordered means we can perform DFS and BFS in O(log n) time. 41 | 42 | ![](https://nc-gifs.pages.dev/bst.gif) 43 | 44 | [Learn more about Trees](https://neetcode.io/courses/dsa-for-beginners/16) 45 | 46 | ## 6. Prefix Trees (Tries) 47 | 48 | Here, each node represents a character in the alphabet and can have at most 26 children. This allows us to save space when inserting words. Tries are useful for auto-complete features and allow us to search for words using their prefix. 49 | 50 | ![](https://nc-gifs.pages.dev/trie.gif) 51 | 52 | [Learn more about Tries](https://neetcode.io/courses/advanced-algorithms/6) 53 | 54 | ## 7. Heaps 55 | 56 | Heaps are a nearly complete binary tree, with potentially the last level being not full. They are implemented with arrays under the hood. Heaps serve as priority queues, and always have the smallest (min-heap) or the largest (max-heap) item stored at the root node. 57 | 58 | ![](https://nc-gifs.pages.dev/heaps.gif) 59 | 60 | [Learn more about Heaps](https://neetcode.io/courses/dsa-for-beginners/23) 61 | 62 | ## 8. Graphs 63 | 64 | A graph is a bunch of nodes (vertices) connected by edges. Linked Lists and Trees are also special type of graphs, but a more general graph can have an arbitrary number of vertices connected to it. A good way to represent graphs in interviews is through an adjacency list. 65 | 66 | ![](https://nc-gifs.pages.dev/graphs.gif) 67 | 68 | [Learn more about Graphs](https://neetcode.io/courses/dsa-for-beginners/28) 69 | -------------------------------------------------------------------------------- /designPatterns.md: -------------------------------------------------------------------------------- 1 | # 8 Design Patterns Every Programmer Should Know 2 | 3 | ## Creational Patterns 4 | 5 | ### Factory 6 | 7 | ```python 8 | class Burger: 9 | def __init__(self, ingredients): 10 | self.ingredients = ingredients 11 | 12 | def print(self): 13 | print(self.ingredients) 14 | 15 | class BurgerFactory: 16 | 17 | def createCheeseBurger(self): 18 | ingredients = ["bun", "cheese", "beef-patty"] 19 | return Burger(ingredients) 20 | 21 | def createDeluxeCheeseBurger(self): 22 | ingredients = ["bun", "tomatoe", "lettuce", "cheese", "beef-patty"] 23 | return Burger(ingredients) 24 | 25 | def createVeganBurger(self): 26 | ingredients = ["bun", "special-sauce", "veggie-patty"] 27 | return Burger(ingredients) 28 | 29 | burgerFactory = BurgerFactory() 30 | burgerFactory.createCheeseBurger().print() 31 | burgerFactory.createDeluxeCheeseBurger().print() 32 | burgerFactory.createVeganBurger().print() 33 | ``` 34 | Output 35 | > `['bun', 'cheese', 'beef-patty']` 36 | > 37 | > `['bun', 'tomatoe', 'lettuce', 'cheese', 'beef-patty']` 38 | > 39 | > `['bun', 'special-sauce', 'veggie-patty']` 40 | 41 | ### Builder 42 | 43 | ```python 44 | class Burger: 45 | def __init__(self): 46 | self.buns = None 47 | self.patty = None 48 | self.cheese = None 49 | 50 | def setBuns(self, bunStyle): 51 | self.buns = bunStyle 52 | 53 | def setPatty(self, pattyStyle): 54 | self.patty = pattyStyle 55 | 56 | def setCheese(self, cheeseStyle): 57 | self.cheese = cheeseStyle 58 | 59 | class BurgerBuilder: 60 | def __init__(self): 61 | self.burger = Burger() 62 | 63 | def addBuns(self, bunStyle): 64 | self.burger.setBuns(bunStyle) 65 | return self 66 | 67 | def addPatty(self, pattyStyle): 68 | self.burger.setPatty(pattyStyle) 69 | return self 70 | 71 | def addCheese(self, cheeseStyle): 72 | self.burger.setCheese(cheeseStyle) 73 | return self 74 | 75 | def build(self): 76 | return self.burger 77 | 78 | burger = BurgerBuilder() \ 79 | .addBuns("sesame") \ 80 | .addPatty("fish-patty") \ 81 | .addCheese("swiss cheese") \ 82 | .build() 83 | ``` 84 | 85 | ### Singleton 86 | 87 | ```python 88 | class ApplicationState: 89 | instance = None 90 | 91 | def __init__(self): 92 | self.isLoggedIn = False 93 | 94 | @staticmethod 95 | def getAppState(): 96 | if not ApplicationState.instance: 97 | ApplicationState.instance = ApplicationState() 98 | return ApplicationState.instance 99 | 100 | appState1 = ApplicationState.getAppState() 101 | print(appState1.isLoggedIn) 102 | 103 | appState2 = ApplicationState.getAppState() 104 | appState1.isLoggedIn = True 105 | 106 | print(appState1.isLoggedIn) 107 | print(appState2.isLoggedIn) 108 | ``` 109 | Output 110 | > `False` 111 | > 112 | > `True` 113 | > 114 | > `True` 115 | 116 | ## Behavioural Patterns 117 | 118 | ### Observer / PubSub 119 | 120 | It's common for different components of an app to respond to events or state changes, but how can we communicate these events? 121 | The Observer pattern is a popular solution. We have a Subject (aka Publisher) which will be the source of events. And we could have multiple Observers (aka Subscribers) which will recieve events from the Subject in realtime. 122 | 123 | ```python 124 | class YoutubeChannel: 125 | def __init__(self, name): 126 | self.name = name 127 | self.subscribers = [] 128 | 129 | def subscribe(self, sub): 130 | self.subscribers.append(sub) 131 | 132 | def notify(self, event): 133 | for sub in self.subscribers: 134 | sub.sendNotification(self.name, event) 135 | 136 | from abc import ABC, abstractmethod 137 | 138 | class YoutubeSubscriber(ABC): 139 | @abstractmethod 140 | def sendNotification(self, event): 141 | pass 142 | 143 | class YoutubeUser(YoutubeSubscriber): 144 | def __init__(self, name): 145 | self.name = name 146 | 147 | def sendNotification(self, channel, event): 148 | print(f"User {self.name} received notification from {channel}: {event}") 149 | 150 | channel = YoutubeChannel("neetcode") 151 | 152 | channel.subscribe(YoutubeUser("sub1")) 153 | channel.subscribe(YoutubeUser("sub2")) 154 | channel.subscribe(YoutubeUser("sub3")) 155 | 156 | channel.notify("A new video released") 157 | ``` 158 | In this case we have multiple Subscribers listening to a single published. But users could also be subscribed to multiple channels. 159 | Since the Publishers & Subscribers don't have to worry about each others' implementations, they are loosely coupled. 160 | 161 | > `User sub1 received notification from neetcode: A new video released` 162 | > 163 | > `User sub2 received notification from neetcode: A new video released` 164 | > 165 | > `User sub3 received notification from neetcode: A new video released` 166 | 167 | ### Iterator 168 | 169 | Many objects in python have built-in iterators. That's why we can conveniently iterate through an array using the key word `in`. 170 | ```python 171 | myList = [1, 2, 3] 172 | for n in myList: 173 | print(n) 174 | ``` 175 | 176 | Output 177 | > `1` 178 | > 179 | > `2` 180 | > 181 | > `3` 182 | 183 | For more complex objects, like Linked Lists or Binary Search Trees, we can define our own iterators. 184 | 185 | ```python 186 | class ListNode: 187 | def __init__(self, val): 188 | self.val = val 189 | self.next = None 190 | 191 | class LinkedList: 192 | def __init__(self, head): 193 | self.head = head 194 | self.cur = None 195 | 196 | # Define Iterator 197 | def __iter__(self): 198 | self.cur = self.head 199 | return self 200 | 201 | # Iterate 202 | def __next__(self): 203 | if self.cur: 204 | val = self.cur.val 205 | self.cur = self.cur.next 206 | return val 207 | else: 208 | raise StopIteration 209 | 210 | # Initialize LinkedList 211 | head = ListNode(1) 212 | head.next = ListNode(2) 213 | head.next.next = ListNode(3) 214 | myList = LinkedList(head) 215 | 216 | # Iterate through LinkedList 217 | for n in myList: 218 | print(n) 219 | ``` 220 | 221 | Output 222 | > `1` 223 | > 224 | > `2` 225 | > 226 | > `3` 227 | 228 | ### Strategy 229 | 230 | A Class may have different behaviour, or invoke a different method based on something we define (i.e. a Strategy). For example, we can filter an array by removing positive values; or we could filter it by removing all odd values. These are two filtering strategies we could implement, but we could add many more. 231 | 232 | ```python 233 | from abc import ABC, abstractmethod 234 | 235 | class FilterStrategy(ABC): 236 | 237 | @abstractmethod 238 | def removeValue(self, val): 239 | pass 240 | 241 | class RemoveNegativeStrategy(FilterStrategy): 242 | 243 | def removeValue(self, val): 244 | return val < 0 245 | 246 | class RemoveOddStrategy(FilterStrategy): 247 | 248 | def removeValue(self, val): 249 | return abs(val) % 2 250 | 251 | 252 | class Values: 253 | def __init__(self, vals): 254 | self.vals = vals 255 | 256 | def filter(self, strategy): 257 | res = [] 258 | for n in self.vals: 259 | if not strategy.removeValue(n): 260 | res.append(n) 261 | return res 262 | 263 | values = Values([-7, -4, -1, 0, 2, 6, 9]) 264 | 265 | print(values.filter(RemoveNegativeStrategy())) 266 | print(values.filter(RemoveOddStrategy())) 267 | 268 | ``` 269 | Output 270 | > `[0, 2, 6, 9]` 271 | > 272 | > `[-4, 0, 2, 6]` 273 | 274 | A common alternative to this pattern is to simply pass in an inline / lambda function, which allows us to extend the behaviour of a method or class. 275 | 276 | 277 | ## Structural Patterns 278 | 279 | ### Facade 280 | 281 | According to Oxford Languages, a Facade is 282 | > an outward appearance that is maintained to conceal a less pleasant or creditable reality. 283 | 284 | In the programming world, the "outward appearance" is the class or interface we interact with as programmers. And the "less pleasant reality" is the complexity that is hidden from us. 285 | So a Facade, is simply a wrapper class that can be used to abstract lower-level details that we don't want to worry about. 286 | 287 | ```python 288 | # Python arrays are dynamic by default, but this is an example of resizing. 289 | class Array: 290 | def __init__(self): 291 | self.capacity = 2 292 | self.length = 0 293 | self.arr = [0] * 2 # Array of capacity = 2 294 | 295 | # Insert n in the last position of the array 296 | def pushback(self, n): 297 | if self.length == self.capacity: 298 | self.resize() 299 | 300 | # insert at next empty position 301 | self.arr[self.length] = n 302 | self.length += 1 303 | 304 | def resize(self): 305 | # Create new array of double capacity 306 | self.capacity = 2 * self.capacity 307 | newArr = [0] * self.capacity 308 | 309 | # Copy elements to newArr 310 | for i in range(self.length): 311 | newArr[i] = self.arr[i] 312 | self.arr = newArr 313 | 314 | # Remove the last element in the array 315 | def popback(self): 316 | if self.length > 0: 317 | self.length -= 1 318 | ``` 319 | 320 | ### Adapter 321 | 322 | Adapters allow incompatible objects to be used together. Following the Open-Closed principle, we can extend class behaviour without modifying the class itself. 323 | If a `MicroUsbCable` class is initially incompatible with `UsbPort`, we can create a wrapper class (i.e. an Adapter), which makes them compatible. In this case, a `MicroToUsbAdapter` makes them compatible, similar to how we use adapters in the real-world. 324 | 325 | ```python 326 | class UsbCable: 327 | def __init__(self): 328 | self.isPlugged = False 329 | 330 | def plugUsb(self): 331 | self.isPlugged = True 332 | 333 | class UsbPort: 334 | def __init__(self): 335 | self.portAvailable = True 336 | 337 | def plug(self, usb): 338 | if self.portAvailable: 339 | usb.plugUsb() 340 | self.portAvailable = False 341 | 342 | # UsbCables can plug directly into Usb ports 343 | usbCable = UsbCable() 344 | usbPort1 = UsbPort() 345 | usbPort1.plug(usbCable) 346 | 347 | class MicroUsbCable: 348 | def __init__(self): 349 | self.isPlugged = False 350 | 351 | def plugMicroUsb(self): 352 | self.isPlugged = True 353 | 354 | class MicroToUsbAdapter(UsbCable): 355 | def __init__(self, microUsbCable): 356 | self.microUsbCable = microUsbCable 357 | self.microUsbCable.plugMicroUsb() 358 | 359 | # can override UsbCable.plugUsb() if needed 360 | 361 | # MicroUsbCables can plug into Usb ports via an adapter 362 | microToUsbAdapter = MicroToUsbAdapter(MicroUsbCable()) 363 | usbPort2 = UsbPort() 364 | usbPort2.plug(microToUsbAdapter) 365 | ``` 366 | -------------------------------------------------------------------------------- /dsaGlossary.md: -------------------------------------------------------------------------------- 1 | # Data Structures and Algorithms Glossary (for Coding Interviews) 2 | 3 | 4 | This article includes the most common terms you will encounter in DSA interviews. 5 | 6 | Knowing and understanding these beforehand can save you a significant amount of time when solving problems in live interviews. 7 | 8 | 9 | ## Arrays & Strings 10 | 11 | | Term | Definition | 12 | |------|------------| 13 | | Subarray | A contiguous portion of an array | 14 | | Subsequence | A sequence derived by deleting elements without changing their order | 15 | | Monotonic | Elements are entirely non-decreasing or non-increasing | 16 | | Circular Array | Array where the end connects to the beginning | 17 | | Partition | Dividing array into parts based on specific criteria | 18 | | Kadane's Algorithm | Technique to find maximum sum subarray | 19 | | Two Pointers | Using two index pointers to solve array problems | 20 | | Sliding Window | Technique of maintaining a window that slides through an array | 21 | | Prefix Sum | Array where each element is sum of all previous elements | 22 | | Suffix Sum | Array where each element is sum of all elements after it | 23 | | Rotation | Shifting array elements by a certain offset | 24 | | In-place | Algorithm that transforms input without creating another data structure | 25 | | Anagram | A string formed by rearranging the characters from another | 26 | | Lexicographic Order | Dictionary ordering of strings | 27 | 28 | ## Trees 29 | 30 | | Term | Definition | 31 | |------|------------| 32 | | Binary Tree | Tree where each node has at most two children | 33 | | BST (Binary Search Tree) | Binary tree where left child < parent < right child | 34 | | Complete Binary Tree | Every level filled except possibly last, which is filled left to right | 35 | | Perfect Binary Tree | All internal nodes have exactly two children and all leaf nodes are at same level | 36 | | Balanced Tree | Height difference between left and right subtrees is limited (often ≤1) | 37 | | Self-Balancing Tree | Automatically maintains balance after insertions/deletions (e.g., AVL, Red-Black) | 38 | | Traversal | Methods to visit all nodes (preorder, inorder, postorder, level-order) | 39 | | Lowest Common Ancestor (LCA) | Deepest node that is an ancestor of two given nodes | 40 | | Serialization/ Deserialization | Converting a tree to/from a string representation | 41 | | Diameter | Longest path between any two nodes in a tree | 42 | | Level Order | Processing tree nodes level by level | 43 | | Segment Tree | Data structure for range queries | 44 | | BFS | Traversing the tree level by level | 45 | | DFS | Traversing the tree in a depth-first manner | 46 | 47 | ## Graphs 48 | 49 | | Term | Definition | 50 | |------|------------| 51 | | Directed / Undirected | Edges with/without direction | 52 | | Weighted / Unweighted | Edges with/without values - known as weights | 53 | | Connected Component | Subset of vertices where any two vertices are connected by a path | 54 | | Strongly Connected Component (SCC) | In a directed graph, subset where every vertex is reachable from every other | 55 | | Bipartite Graph | Can be divided into two sets with no edges within each set | 56 | | DAG (Directed Acyclic Graph) | Directed graph with no cycles | 57 | | Topological Sort | Linear ordering of vertices where for every edge (u,v), u comes before v. Works with DAGs | 58 | | Adjacency List | Graph representation derived from an array of edges | 59 | | BFS/DFS | Breadth-First Search and Depth-First Search traversal strategies | 60 | | MST (Minimum Spanning Tree) | Tree connecting all vertices with minimum total edge weight | 61 | | Bellman-Ford/Dijkstra /Floyd-Warshall | Shortest path algorithms | 62 | | Union-Find | Data structure for disjoint sets operations | 63 | | Cycle Detection | Algorithms to find cycles in graphs | 64 | | A* Algorithm | Best-first search algorithm for path finding | 65 | 66 | ## Dynamic Programming 67 | 68 | | Term | Definition | 69 | |------|------------| 70 | | Memoization | Cache technique to avoid redundant calculations | 71 | | Tabulation | Bottom-up approach using arrays to store subproblem results | 72 | | State | Snapshot of progress you've made in solving the larger problem | 73 | | Overlapping Subproblems | When the same subproblems are solved multiple times | 74 | | 1-Dimensional | The result for the current state only depends on one previous state or a linear history, e.g. Fib | 75 | | 2-Dimensional | The problem depends on two varying factors, often two strings, two sequences, or two indices | 76 | | Top Down | Start from the final problem and recursively break it into smaller subproblems | 77 | | Bottom Up | Build the solution from the base case all the way up to the final solution | 78 | | Longest Common Subsequence (LCS) | Finding the longest subsequence common to two sequences | 79 | | Longest Increasing Subsequence (LIS) | Finding the longest subsequence where elements are in ascending order | 80 | | 0 / 1 Knapsack | Each item can be picked at most once | 81 | | Unbounded Knapsack | Each item can be picked unlimited times | 82 | 83 | ## Heap & Priority Queue 84 | 85 | | Term | Definition | 86 | |------|------------| 87 | | Min Heap / Max Heap | Tree-based data structure where parent is smaller/larger than children | 88 | | Heap Sort | Sorting algorithm using a heap | 89 | | Priority Queue | Abstract data type providing efficient access to the minimum/maximum element | 90 | | Heapify | Process of creating a heap from an array | 91 | | K-Way Merge | Merging k sorted arrays/lists (often using heaps) | 92 | | Build Heap | The process of running heapify() on the entire heap to create a valid heap | 93 | | Two Heaps | A technique used to find the median of a data stream using a max and a min heap | 94 | 95 | ## Backtracking 96 | 97 | | Term | Definition | 98 | |------|------------| 99 | | Subsets | Set A is a subset to Set B if all of its elements are found in Set B | 100 | | Combinations | Number of ways of selection and arrangement of items where order does not matter | 101 | | Permutations | Number of ways of selection and arrangement of items where order matters | 102 | | Pruning | Used to eliminate branches early on that can never lead to valid solutions | 103 | | Constraint | A condition that must be satisfied to reach a valid solution | 104 | | Base Case | Determines when a valid solution has been found | 105 | | Candidate Solution | Start from the final problem and recursively break it into smaller subproblems | 106 | | Unique Combination | Two combinations are unique if the frequency of chosen numbers is not the same | 107 | 108 | ## Miscellaneous 109 | 110 | | Term | Definition | 111 | |------|------------| 112 | | Amortized Analysis | Analyzing average performance over a sequence of operations | 113 | | Randomized Algorithm | Algorithm that uses random numbers to decide next step | 114 | | Skip List | Probabilistic data structure for efficient search | 115 | | Execution Time | The raw time taken in seconds to execute an algorithm | 116 | | Stable Sorting Algorithm | A sorting algorithm that maintains the relative order of elements after sorting | 117 | | Unstable Sorting Algorithm | A sorting algorithm that does not maintain the relative order of elements after sorting | 118 | -------------------------------------------------------------------------------- /graphAlgorithms.md: -------------------------------------------------------------------------------- 1 | # 5 Most Important Graph Algorithms 2 | 3 | > Updated: Jan 22, 2025 4 | > Author: Navdeep Singh 5 | 6 | Graphs are an extremely common question type in coding interviews, mainly because a graph is an abstract concept, rather than a data structure stored in memory. From highway networks to LinkedIn connections, and even file directories, can be represented as graphs. 7 | I've combined a list of 5 common graph algorithms that will be helpful to you in coding interviews. 8 | 9 | ## 1. Depth First Search (DFS) 10 | 11 | Prioritizes depth first. This search will go as deep as possible exploring each node before hitting the base case, after which it explores other nodes. A hash set is used to keep track of visited nodes. 12 | 13 | ![](https://nc-gifs.pages.dev/dfs.gif) 14 | 15 | [Learn more about DFS](https://neetcode.io/courses/dsa-for-beginners/29) 16 | 17 | ## 2. Breadth First Search (BFS) 18 | 19 | Prioritizes breadth first. It explores all possible neighbors of a vertex before moving on to the next level of neighbors, sometimes also called layers. This uses a queue and a hash set, and can be used to find the length of the shortest path from one vertex to the other. 20 | 21 | ![](https://nc-gifs.pages.dev/bfs.gif) 22 | 23 | [Learn more about BFS](https://neetcode.io/courses/dsa-for-beginners/30) 24 | 25 | ## 3. Union-Find 26 | 27 | Used to combine disjoint sets. It's useful for when we want to know the number of connected components in a graph. It's also used in Kruskal's algorithm for detecting cycles. 28 | 29 | ![](https://nc-gifs.pages.dev/union-find.gif) 30 | 31 | [Learn more about Union-Find](https://neetcode.io/courses/advanced-algorithms/7) 32 | 33 | ## 4. Topological Sort 34 | 35 | Implemented on a directed acyclic graph, it's used to order vertices such that for every directed edge u -> v, vertex u appears before vertex v. This is useful if an interview problem talks about pre-requisites where one condition must be fulfilled before moving on to the next. 36 | 37 | ![](https://nc-gifs.pages.dev/topological.gif) 38 | 39 | [Learn more about Topological Sort](https://neetcode.io/courses/advanced-algorithms/17) 40 | 41 | ## 5. Dijkstra's Algorithm 42 | 43 | A greedy algorithm that operates on weighted graphs, used to find the shortest path from one source to all other vertices in the graph. It uses a min heap to pick the shortest path at each step and a hash set to avoid cycles. 44 | 45 | ![](https://nc-gifs.pages.dev/dijkstra.gif) 46 | 47 | [Learn more about Dijkstra's Algorithm](https://neetcode.io/courses/advanced-algorithms/14) 48 | -------------------------------------------------------------------------------- /grpc-demo/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/* -------------------------------------------------------------------------------- /grpc-demo/grpc-server.js: -------------------------------------------------------------------------------- 1 | const grpc = require('@grpc/grpc-js'); 2 | const protoLoader = require('@grpc/proto-loader'); 3 | const packageDefinition = protoLoader.loadSync('./protos/helloworld.proto', {}); 4 | 5 | const server = new grpc.Server(); 6 | const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld; 7 | 8 | // Define and register helloworld RPC handler 9 | function sayHello(call, callback) { 10 | callback(null, {message: 'Hello ' + call.request.name}); 11 | } 12 | 13 | server.addService(hello_proto.HelloWorld.service, { 14 | SayHello: sayHello 15 | }); 16 | 17 | // Create a gRPC server and listen on port 50051 18 | server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => { 19 | server.start(); 20 | console.log('Server running on port 50051'); 21 | }); 22 | -------------------------------------------------------------------------------- /grpc-demo/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grpc", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "grpc", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@grpc/grpc-js": "^1.8.16", 13 | "@grpc/proto-loader": "^0.7.7", 14 | "express": "^4.18.2", 15 | "node-fetch": "^2.6.11", 16 | "node-fetch2": "^1.6.3" 17 | }, 18 | "devDependencies": { 19 | "grpc_tools_node_protoc_ts": "^5.3.3", 20 | "grpc-tools": "^1.12.4" 21 | } 22 | }, 23 | "node_modules/@grpc/grpc-js": { 24 | "version": "1.8.16", 25 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.16.tgz", 26 | "integrity": "sha512-Nvlq4V7XQmdRVDGgecR8ZPPCeY+uH1LhzbC+QxklwAahpQlq8YLsiOQgfkub9FiakRiohaDy361xqlTLkq9EHw==", 27 | "dependencies": { 28 | "@grpc/proto-loader": "^0.7.0", 29 | "@types/node": ">=12.12.47" 30 | }, 31 | "engines": { 32 | "node": "^8.13.0 || >=10.10.0" 33 | } 34 | }, 35 | "node_modules/@grpc/proto-loader": { 36 | "version": "0.7.7", 37 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.7.tgz", 38 | "integrity": "sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==", 39 | "dependencies": { 40 | "@types/long": "^4.0.1", 41 | "lodash.camelcase": "^4.3.0", 42 | "long": "^4.0.0", 43 | "protobufjs": "^7.0.0", 44 | "yargs": "^17.7.2" 45 | }, 46 | "bin": { 47 | "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" 48 | }, 49 | "engines": { 50 | "node": ">=6" 51 | } 52 | }, 53 | "node_modules/@mapbox/node-pre-gyp": { 54 | "version": "1.0.10", 55 | "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", 56 | "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", 57 | "dev": true, 58 | "dependencies": { 59 | "detect-libc": "^2.0.0", 60 | "https-proxy-agent": "^5.0.0", 61 | "make-dir": "^3.1.0", 62 | "node-fetch": "^2.6.7", 63 | "nopt": "^5.0.0", 64 | "npmlog": "^5.0.1", 65 | "rimraf": "^3.0.2", 66 | "semver": "^7.3.5", 67 | "tar": "^6.1.11" 68 | }, 69 | "bin": { 70 | "node-pre-gyp": "bin/node-pre-gyp" 71 | } 72 | }, 73 | "node_modules/@protobufjs/aspromise": { 74 | "version": "1.1.2", 75 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 76 | "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" 77 | }, 78 | "node_modules/@protobufjs/base64": { 79 | "version": "1.1.2", 80 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 81 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 82 | }, 83 | "node_modules/@protobufjs/codegen": { 84 | "version": "2.0.4", 85 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 86 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 87 | }, 88 | "node_modules/@protobufjs/eventemitter": { 89 | "version": "1.1.0", 90 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 91 | "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" 92 | }, 93 | "node_modules/@protobufjs/fetch": { 94 | "version": "1.1.0", 95 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 96 | "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", 97 | "dependencies": { 98 | "@protobufjs/aspromise": "^1.1.1", 99 | "@protobufjs/inquire": "^1.1.0" 100 | } 101 | }, 102 | "node_modules/@protobufjs/float": { 103 | "version": "1.0.2", 104 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 105 | "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" 106 | }, 107 | "node_modules/@protobufjs/inquire": { 108 | "version": "1.1.0", 109 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 110 | "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" 111 | }, 112 | "node_modules/@protobufjs/path": { 113 | "version": "1.1.2", 114 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 115 | "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" 116 | }, 117 | "node_modules/@protobufjs/pool": { 118 | "version": "1.1.0", 119 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 120 | "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" 121 | }, 122 | "node_modules/@protobufjs/utf8": { 123 | "version": "1.1.0", 124 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 125 | "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" 126 | }, 127 | "node_modules/@types/long": { 128 | "version": "4.0.2", 129 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", 130 | "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" 131 | }, 132 | "node_modules/@types/node": { 133 | "version": "20.3.1", 134 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", 135 | "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" 136 | }, 137 | "node_modules/abbrev": { 138 | "version": "1.1.1", 139 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 140 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 141 | "dev": true 142 | }, 143 | "node_modules/accepts": { 144 | "version": "1.3.8", 145 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 146 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 147 | "dependencies": { 148 | "mime-types": "~2.1.34", 149 | "negotiator": "0.6.3" 150 | }, 151 | "engines": { 152 | "node": ">= 0.6" 153 | } 154 | }, 155 | "node_modules/agent-base": { 156 | "version": "6.0.2", 157 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 158 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 159 | "dev": true, 160 | "dependencies": { 161 | "debug": "4" 162 | }, 163 | "engines": { 164 | "node": ">= 6.0.0" 165 | } 166 | }, 167 | "node_modules/ansi-regex": { 168 | "version": "5.0.1", 169 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 170 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 171 | "engines": { 172 | "node": ">=8" 173 | } 174 | }, 175 | "node_modules/ansi-styles": { 176 | "version": "4.3.0", 177 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 178 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 179 | "dependencies": { 180 | "color-convert": "^2.0.1" 181 | }, 182 | "engines": { 183 | "node": ">=8" 184 | }, 185 | "funding": { 186 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 187 | } 188 | }, 189 | "node_modules/aproba": { 190 | "version": "2.0.0", 191 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", 192 | "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", 193 | "dev": true 194 | }, 195 | "node_modules/are-we-there-yet": { 196 | "version": "2.0.0", 197 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", 198 | "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", 199 | "dev": true, 200 | "dependencies": { 201 | "delegates": "^1.0.0", 202 | "readable-stream": "^3.6.0" 203 | }, 204 | "engines": { 205 | "node": ">=10" 206 | } 207 | }, 208 | "node_modules/array-flatten": { 209 | "version": "1.1.1", 210 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 211 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 212 | }, 213 | "node_modules/babel-runtime": { 214 | "version": "6.26.0", 215 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 216 | "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", 217 | "dependencies": { 218 | "core-js": "^2.4.0", 219 | "regenerator-runtime": "^0.11.0" 220 | } 221 | }, 222 | "node_modules/balanced-match": { 223 | "version": "1.0.2", 224 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 225 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 226 | "dev": true 227 | }, 228 | "node_modules/body-parser": { 229 | "version": "1.20.1", 230 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 231 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 232 | "dependencies": { 233 | "bytes": "3.1.2", 234 | "content-type": "~1.0.4", 235 | "debug": "2.6.9", 236 | "depd": "2.0.0", 237 | "destroy": "1.2.0", 238 | "http-errors": "2.0.0", 239 | "iconv-lite": "0.4.24", 240 | "on-finished": "2.4.1", 241 | "qs": "6.11.0", 242 | "raw-body": "2.5.1", 243 | "type-is": "~1.6.18", 244 | "unpipe": "1.0.0" 245 | }, 246 | "engines": { 247 | "node": ">= 0.8", 248 | "npm": "1.2.8000 || >= 1.4.16" 249 | } 250 | }, 251 | "node_modules/body-parser/node_modules/debug": { 252 | "version": "2.6.9", 253 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 254 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 255 | "dependencies": { 256 | "ms": "2.0.0" 257 | } 258 | }, 259 | "node_modules/body-parser/node_modules/ms": { 260 | "version": "2.0.0", 261 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 262 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 263 | }, 264 | "node_modules/brace-expansion": { 265 | "version": "1.1.11", 266 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 267 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 268 | "dev": true, 269 | "dependencies": { 270 | "balanced-match": "^1.0.0", 271 | "concat-map": "0.0.1" 272 | } 273 | }, 274 | "node_modules/buffer-to-arraybuffer": { 275 | "version": "0.0.4", 276 | "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.4.tgz", 277 | "integrity": "sha512-/ON9xjCtPIO0uycXhHXHZ0CIu7hHA1UJUVro/nXYDfYHb+5vuMq4jOkvZ4QIeB6TClTxPVt9VayplwMyW1BZag==" 278 | }, 279 | "node_modules/bytes": { 280 | "version": "3.1.2", 281 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 282 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 283 | "engines": { 284 | "node": ">= 0.8" 285 | } 286 | }, 287 | "node_modules/call-bind": { 288 | "version": "1.0.2", 289 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 290 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 291 | "dependencies": { 292 | "function-bind": "^1.1.1", 293 | "get-intrinsic": "^1.0.2" 294 | }, 295 | "funding": { 296 | "url": "https://github.com/sponsors/ljharb" 297 | } 298 | }, 299 | "node_modules/chownr": { 300 | "version": "2.0.0", 301 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", 302 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", 303 | "dev": true, 304 | "engines": { 305 | "node": ">=10" 306 | } 307 | }, 308 | "node_modules/cliui": { 309 | "version": "8.0.1", 310 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 311 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 312 | "dependencies": { 313 | "string-width": "^4.2.0", 314 | "strip-ansi": "^6.0.1", 315 | "wrap-ansi": "^7.0.0" 316 | }, 317 | "engines": { 318 | "node": ">=12" 319 | } 320 | }, 321 | "node_modules/color-convert": { 322 | "version": "2.0.1", 323 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 324 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 325 | "dependencies": { 326 | "color-name": "~1.1.4" 327 | }, 328 | "engines": { 329 | "node": ">=7.0.0" 330 | } 331 | }, 332 | "node_modules/color-name": { 333 | "version": "1.1.4", 334 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 335 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 336 | }, 337 | "node_modules/color-support": { 338 | "version": "1.1.3", 339 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", 340 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", 341 | "dev": true, 342 | "bin": { 343 | "color-support": "bin.js" 344 | } 345 | }, 346 | "node_modules/concat-map": { 347 | "version": "0.0.1", 348 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 349 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 350 | "dev": true 351 | }, 352 | "node_modules/console-control-strings": { 353 | "version": "1.1.0", 354 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 355 | "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", 356 | "dev": true 357 | }, 358 | "node_modules/content-disposition": { 359 | "version": "0.5.4", 360 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 361 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 362 | "dependencies": { 363 | "safe-buffer": "5.2.1" 364 | }, 365 | "engines": { 366 | "node": ">= 0.6" 367 | } 368 | }, 369 | "node_modules/content-type": { 370 | "version": "1.0.5", 371 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 372 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 373 | "engines": { 374 | "node": ">= 0.6" 375 | } 376 | }, 377 | "node_modules/cookie": { 378 | "version": "0.5.0", 379 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 380 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 381 | "engines": { 382 | "node": ">= 0.6" 383 | } 384 | }, 385 | "node_modules/cookie-signature": { 386 | "version": "1.0.6", 387 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 388 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 389 | }, 390 | "node_modules/core-js": { 391 | "version": "2.6.12", 392 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", 393 | "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", 394 | "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", 395 | "hasInstallScript": true 396 | }, 397 | "node_modules/debug": { 398 | "version": "4.3.4", 399 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 400 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 401 | "dev": true, 402 | "dependencies": { 403 | "ms": "2.1.2" 404 | }, 405 | "engines": { 406 | "node": ">=6.0" 407 | }, 408 | "peerDependenciesMeta": { 409 | "supports-color": { 410 | "optional": true 411 | } 412 | } 413 | }, 414 | "node_modules/delegates": { 415 | "version": "1.0.0", 416 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 417 | "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", 418 | "dev": true 419 | }, 420 | "node_modules/depd": { 421 | "version": "2.0.0", 422 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 423 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 424 | "engines": { 425 | "node": ">= 0.8" 426 | } 427 | }, 428 | "node_modules/destroy": { 429 | "version": "1.2.0", 430 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 431 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 432 | "engines": { 433 | "node": ">= 0.8", 434 | "npm": "1.2.8000 || >= 1.4.16" 435 | } 436 | }, 437 | "node_modules/detect-libc": { 438 | "version": "2.0.1", 439 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", 440 | "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", 441 | "dev": true, 442 | "engines": { 443 | "node": ">=8" 444 | } 445 | }, 446 | "node_modules/ee-first": { 447 | "version": "1.1.1", 448 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 449 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 450 | }, 451 | "node_modules/emoji-regex": { 452 | "version": "8.0.0", 453 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 454 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 455 | }, 456 | "node_modules/encodeurl": { 457 | "version": "1.0.2", 458 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 459 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 460 | "engines": { 461 | "node": ">= 0.8" 462 | } 463 | }, 464 | "node_modules/encoding": { 465 | "version": "0.1.13", 466 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", 467 | "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", 468 | "dependencies": { 469 | "iconv-lite": "^0.6.2" 470 | } 471 | }, 472 | "node_modules/encoding/node_modules/iconv-lite": { 473 | "version": "0.6.3", 474 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 475 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 476 | "dependencies": { 477 | "safer-buffer": ">= 2.1.2 < 3.0.0" 478 | }, 479 | "engines": { 480 | "node": ">=0.10.0" 481 | } 482 | }, 483 | "node_modules/escalade": { 484 | "version": "3.1.1", 485 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 486 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 487 | "engines": { 488 | "node": ">=6" 489 | } 490 | }, 491 | "node_modules/escape-html": { 492 | "version": "1.0.3", 493 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 494 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 495 | }, 496 | "node_modules/etag": { 497 | "version": "1.8.1", 498 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 499 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 500 | "engines": { 501 | "node": ">= 0.6" 502 | } 503 | }, 504 | "node_modules/express": { 505 | "version": "4.18.2", 506 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 507 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 508 | "dependencies": { 509 | "accepts": "~1.3.8", 510 | "array-flatten": "1.1.1", 511 | "body-parser": "1.20.1", 512 | "content-disposition": "0.5.4", 513 | "content-type": "~1.0.4", 514 | "cookie": "0.5.0", 515 | "cookie-signature": "1.0.6", 516 | "debug": "2.6.9", 517 | "depd": "2.0.0", 518 | "encodeurl": "~1.0.2", 519 | "escape-html": "~1.0.3", 520 | "etag": "~1.8.1", 521 | "finalhandler": "1.2.0", 522 | "fresh": "0.5.2", 523 | "http-errors": "2.0.0", 524 | "merge-descriptors": "1.0.1", 525 | "methods": "~1.1.2", 526 | "on-finished": "2.4.1", 527 | "parseurl": "~1.3.3", 528 | "path-to-regexp": "0.1.7", 529 | "proxy-addr": "~2.0.7", 530 | "qs": "6.11.0", 531 | "range-parser": "~1.2.1", 532 | "safe-buffer": "5.2.1", 533 | "send": "0.18.0", 534 | "serve-static": "1.15.0", 535 | "setprototypeof": "1.2.0", 536 | "statuses": "2.0.1", 537 | "type-is": "~1.6.18", 538 | "utils-merge": "1.0.1", 539 | "vary": "~1.1.2" 540 | }, 541 | "engines": { 542 | "node": ">= 0.10.0" 543 | } 544 | }, 545 | "node_modules/express/node_modules/debug": { 546 | "version": "2.6.9", 547 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 548 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 549 | "dependencies": { 550 | "ms": "2.0.0" 551 | } 552 | }, 553 | "node_modules/express/node_modules/ms": { 554 | "version": "2.0.0", 555 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 556 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 557 | }, 558 | "node_modules/finalhandler": { 559 | "version": "1.2.0", 560 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 561 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 562 | "dependencies": { 563 | "debug": "2.6.9", 564 | "encodeurl": "~1.0.2", 565 | "escape-html": "~1.0.3", 566 | "on-finished": "2.4.1", 567 | "parseurl": "~1.3.3", 568 | "statuses": "2.0.1", 569 | "unpipe": "~1.0.0" 570 | }, 571 | "engines": { 572 | "node": ">= 0.8" 573 | } 574 | }, 575 | "node_modules/finalhandler/node_modules/debug": { 576 | "version": "2.6.9", 577 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 578 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 579 | "dependencies": { 580 | "ms": "2.0.0" 581 | } 582 | }, 583 | "node_modules/finalhandler/node_modules/ms": { 584 | "version": "2.0.0", 585 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 586 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 587 | }, 588 | "node_modules/forwarded": { 589 | "version": "0.2.0", 590 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 591 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 592 | "engines": { 593 | "node": ">= 0.6" 594 | } 595 | }, 596 | "node_modules/fresh": { 597 | "version": "0.5.2", 598 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 599 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 600 | "engines": { 601 | "node": ">= 0.6" 602 | } 603 | }, 604 | "node_modules/fs-minipass": { 605 | "version": "2.1.0", 606 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", 607 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", 608 | "dev": true, 609 | "dependencies": { 610 | "minipass": "^3.0.0" 611 | }, 612 | "engines": { 613 | "node": ">= 8" 614 | } 615 | }, 616 | "node_modules/fs-minipass/node_modules/minipass": { 617 | "version": "3.3.6", 618 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 619 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 620 | "dev": true, 621 | "dependencies": { 622 | "yallist": "^4.0.0" 623 | }, 624 | "engines": { 625 | "node": ">=8" 626 | } 627 | }, 628 | "node_modules/fs.realpath": { 629 | "version": "1.0.0", 630 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 631 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 632 | "dev": true 633 | }, 634 | "node_modules/function-bind": { 635 | "version": "1.1.1", 636 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 637 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 638 | }, 639 | "node_modules/gauge": { 640 | "version": "3.0.2", 641 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", 642 | "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", 643 | "dev": true, 644 | "dependencies": { 645 | "aproba": "^1.0.3 || ^2.0.0", 646 | "color-support": "^1.1.2", 647 | "console-control-strings": "^1.0.0", 648 | "has-unicode": "^2.0.1", 649 | "object-assign": "^4.1.1", 650 | "signal-exit": "^3.0.0", 651 | "string-width": "^4.2.3", 652 | "strip-ansi": "^6.0.1", 653 | "wide-align": "^1.1.2" 654 | }, 655 | "engines": { 656 | "node": ">=10" 657 | } 658 | }, 659 | "node_modules/get-caller-file": { 660 | "version": "2.0.5", 661 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 662 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 663 | "engines": { 664 | "node": "6.* || 8.* || >= 10.*" 665 | } 666 | }, 667 | "node_modules/get-intrinsic": { 668 | "version": "1.2.1", 669 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", 670 | "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", 671 | "dependencies": { 672 | "function-bind": "^1.1.1", 673 | "has": "^1.0.3", 674 | "has-proto": "^1.0.1", 675 | "has-symbols": "^1.0.3" 676 | }, 677 | "funding": { 678 | "url": "https://github.com/sponsors/ljharb" 679 | } 680 | }, 681 | "node_modules/glob": { 682 | "version": "7.2.3", 683 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 684 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 685 | "dev": true, 686 | "dependencies": { 687 | "fs.realpath": "^1.0.0", 688 | "inflight": "^1.0.4", 689 | "inherits": "2", 690 | "minimatch": "^3.1.1", 691 | "once": "^1.3.0", 692 | "path-is-absolute": "^1.0.0" 693 | }, 694 | "engines": { 695 | "node": "*" 696 | }, 697 | "funding": { 698 | "url": "https://github.com/sponsors/isaacs" 699 | } 700 | }, 701 | "node_modules/google-protobuf": { 702 | "version": "3.15.8", 703 | "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.15.8.tgz", 704 | "integrity": "sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==", 705 | "dev": true 706 | }, 707 | "node_modules/grpc_tools_node_protoc_ts": { 708 | "version": "5.3.3", 709 | "resolved": "https://registry.npmjs.org/grpc_tools_node_protoc_ts/-/grpc_tools_node_protoc_ts-5.3.3.tgz", 710 | "integrity": "sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==", 711 | "dev": true, 712 | "dependencies": { 713 | "google-protobuf": "3.15.8", 714 | "handlebars": "4.7.7" 715 | }, 716 | "bin": { 717 | "protoc-gen-ts": "bin/protoc-gen-ts" 718 | } 719 | }, 720 | "node_modules/grpc-tools": { 721 | "version": "1.12.4", 722 | "resolved": "https://registry.npmjs.org/grpc-tools/-/grpc-tools-1.12.4.tgz", 723 | "integrity": "sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==", 724 | "dev": true, 725 | "hasInstallScript": true, 726 | "dependencies": { 727 | "@mapbox/node-pre-gyp": "^1.0.5" 728 | }, 729 | "bin": { 730 | "grpc_tools_node_protoc": "bin/protoc.js", 731 | "grpc_tools_node_protoc_plugin": "bin/protoc_plugin.js" 732 | } 733 | }, 734 | "node_modules/handlebars": { 735 | "version": "4.7.7", 736 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", 737 | "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", 738 | "dev": true, 739 | "dependencies": { 740 | "minimist": "^1.2.5", 741 | "neo-async": "^2.6.0", 742 | "source-map": "^0.6.1", 743 | "wordwrap": "^1.0.0" 744 | }, 745 | "bin": { 746 | "handlebars": "bin/handlebars" 747 | }, 748 | "engines": { 749 | "node": ">=0.4.7" 750 | }, 751 | "optionalDependencies": { 752 | "uglify-js": "^3.1.4" 753 | } 754 | }, 755 | "node_modules/has": { 756 | "version": "1.0.3", 757 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 758 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 759 | "dependencies": { 760 | "function-bind": "^1.1.1" 761 | }, 762 | "engines": { 763 | "node": ">= 0.4.0" 764 | } 765 | }, 766 | "node_modules/has-proto": { 767 | "version": "1.0.1", 768 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 769 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 770 | "engines": { 771 | "node": ">= 0.4" 772 | }, 773 | "funding": { 774 | "url": "https://github.com/sponsors/ljharb" 775 | } 776 | }, 777 | "node_modules/has-symbols": { 778 | "version": "1.0.3", 779 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 780 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 781 | "engines": { 782 | "node": ">= 0.4" 783 | }, 784 | "funding": { 785 | "url": "https://github.com/sponsors/ljharb" 786 | } 787 | }, 788 | "node_modules/has-unicode": { 789 | "version": "2.0.1", 790 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 791 | "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", 792 | "dev": true 793 | }, 794 | "node_modules/http-errors": { 795 | "version": "2.0.0", 796 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 797 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 798 | "dependencies": { 799 | "depd": "2.0.0", 800 | "inherits": "2.0.4", 801 | "setprototypeof": "1.2.0", 802 | "statuses": "2.0.1", 803 | "toidentifier": "1.0.1" 804 | }, 805 | "engines": { 806 | "node": ">= 0.8" 807 | } 808 | }, 809 | "node_modules/https-proxy-agent": { 810 | "version": "5.0.1", 811 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 812 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 813 | "dev": true, 814 | "dependencies": { 815 | "agent-base": "6", 816 | "debug": "4" 817 | }, 818 | "engines": { 819 | "node": ">= 6" 820 | } 821 | }, 822 | "node_modules/iconv-lite": { 823 | "version": "0.4.24", 824 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 825 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 826 | "dependencies": { 827 | "safer-buffer": ">= 2.1.2 < 3" 828 | }, 829 | "engines": { 830 | "node": ">=0.10.0" 831 | } 832 | }, 833 | "node_modules/inflight": { 834 | "version": "1.0.6", 835 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 836 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 837 | "dev": true, 838 | "dependencies": { 839 | "once": "^1.3.0", 840 | "wrappy": "1" 841 | } 842 | }, 843 | "node_modules/inherits": { 844 | "version": "2.0.4", 845 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 846 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 847 | }, 848 | "node_modules/ipaddr.js": { 849 | "version": "1.9.1", 850 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 851 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 852 | "engines": { 853 | "node": ">= 0.10" 854 | } 855 | }, 856 | "node_modules/is-fullwidth-code-point": { 857 | "version": "3.0.0", 858 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 859 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 860 | "engines": { 861 | "node": ">=8" 862 | } 863 | }, 864 | "node_modules/is-stream": { 865 | "version": "1.1.0", 866 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 867 | "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", 868 | "engines": { 869 | "node": ">=0.10.0" 870 | } 871 | }, 872 | "node_modules/lodash.camelcase": { 873 | "version": "4.3.0", 874 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 875 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" 876 | }, 877 | "node_modules/long": { 878 | "version": "4.0.0", 879 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 880 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 881 | }, 882 | "node_modules/lru-cache": { 883 | "version": "6.0.0", 884 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 885 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 886 | "dev": true, 887 | "dependencies": { 888 | "yallist": "^4.0.0" 889 | }, 890 | "engines": { 891 | "node": ">=10" 892 | } 893 | }, 894 | "node_modules/make-dir": { 895 | "version": "3.1.0", 896 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 897 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 898 | "dev": true, 899 | "dependencies": { 900 | "semver": "^6.0.0" 901 | }, 902 | "engines": { 903 | "node": ">=8" 904 | }, 905 | "funding": { 906 | "url": "https://github.com/sponsors/sindresorhus" 907 | } 908 | }, 909 | "node_modules/make-dir/node_modules/semver": { 910 | "version": "6.3.0", 911 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 912 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 913 | "dev": true, 914 | "bin": { 915 | "semver": "bin/semver.js" 916 | } 917 | }, 918 | "node_modules/media-typer": { 919 | "version": "0.3.0", 920 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 921 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 922 | "engines": { 923 | "node": ">= 0.6" 924 | } 925 | }, 926 | "node_modules/merge-descriptors": { 927 | "version": "1.0.1", 928 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 929 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 930 | }, 931 | "node_modules/methods": { 932 | "version": "1.1.2", 933 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 934 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 935 | "engines": { 936 | "node": ">= 0.6" 937 | } 938 | }, 939 | "node_modules/mime": { 940 | "version": "1.6.0", 941 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 942 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 943 | "bin": { 944 | "mime": "cli.js" 945 | }, 946 | "engines": { 947 | "node": ">=4" 948 | } 949 | }, 950 | "node_modules/mime-db": { 951 | "version": "1.52.0", 952 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 953 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 954 | "engines": { 955 | "node": ">= 0.6" 956 | } 957 | }, 958 | "node_modules/mime-types": { 959 | "version": "2.1.35", 960 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 961 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 962 | "dependencies": { 963 | "mime-db": "1.52.0" 964 | }, 965 | "engines": { 966 | "node": ">= 0.6" 967 | } 968 | }, 969 | "node_modules/minimatch": { 970 | "version": "3.1.2", 971 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 972 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 973 | "dev": true, 974 | "dependencies": { 975 | "brace-expansion": "^1.1.7" 976 | }, 977 | "engines": { 978 | "node": "*" 979 | } 980 | }, 981 | "node_modules/minimist": { 982 | "version": "1.2.8", 983 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 984 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 985 | "dev": true, 986 | "funding": { 987 | "url": "https://github.com/sponsors/ljharb" 988 | } 989 | }, 990 | "node_modules/minipass": { 991 | "version": "5.0.0", 992 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 993 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 994 | "dev": true, 995 | "engines": { 996 | "node": ">=8" 997 | } 998 | }, 999 | "node_modules/minizlib": { 1000 | "version": "2.1.2", 1001 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", 1002 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", 1003 | "dev": true, 1004 | "dependencies": { 1005 | "minipass": "^3.0.0", 1006 | "yallist": "^4.0.0" 1007 | }, 1008 | "engines": { 1009 | "node": ">= 8" 1010 | } 1011 | }, 1012 | "node_modules/minizlib/node_modules/minipass": { 1013 | "version": "3.3.6", 1014 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 1015 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 1016 | "dev": true, 1017 | "dependencies": { 1018 | "yallist": "^4.0.0" 1019 | }, 1020 | "engines": { 1021 | "node": ">=8" 1022 | } 1023 | }, 1024 | "node_modules/mkdirp": { 1025 | "version": "1.0.4", 1026 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 1027 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 1028 | "dev": true, 1029 | "bin": { 1030 | "mkdirp": "bin/cmd.js" 1031 | }, 1032 | "engines": { 1033 | "node": ">=10" 1034 | } 1035 | }, 1036 | "node_modules/ms": { 1037 | "version": "2.1.2", 1038 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1039 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1040 | "dev": true 1041 | }, 1042 | "node_modules/negotiator": { 1043 | "version": "0.6.3", 1044 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1045 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 1046 | "engines": { 1047 | "node": ">= 0.6" 1048 | } 1049 | }, 1050 | "node_modules/neo-async": { 1051 | "version": "2.6.2", 1052 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 1053 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 1054 | "dev": true 1055 | }, 1056 | "node_modules/node-fetch": { 1057 | "version": "2.6.11", 1058 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", 1059 | "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", 1060 | "dependencies": { 1061 | "whatwg-url": "^5.0.0" 1062 | }, 1063 | "engines": { 1064 | "node": "4.x || >=6.0.0" 1065 | }, 1066 | "peerDependencies": { 1067 | "encoding": "^0.1.0" 1068 | }, 1069 | "peerDependenciesMeta": { 1070 | "encoding": { 1071 | "optional": true 1072 | } 1073 | } 1074 | }, 1075 | "node_modules/node-fetch2": { 1076 | "version": "1.6.3", 1077 | "resolved": "https://registry.npmjs.org/node-fetch2/-/node-fetch2-1.6.3.tgz", 1078 | "integrity": "sha512-90wPxY5+/CodbDXy0lfy3hC3xHcqbxEq3ufVKtrPx42Hkm/NbruE/DFOrjiVjn05I2AARFYGuGe1AU6RcPIfpQ==", 1079 | "dependencies": { 1080 | "babel-runtime": "^6.11.6", 1081 | "buffer-to-arraybuffer": "0.0.4", 1082 | "encoding": "^0.1.11", 1083 | "is-stream": "^1.0.1" 1084 | } 1085 | }, 1086 | "node_modules/nopt": { 1087 | "version": "5.0.0", 1088 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", 1089 | "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", 1090 | "dev": true, 1091 | "dependencies": { 1092 | "abbrev": "1" 1093 | }, 1094 | "bin": { 1095 | "nopt": "bin/nopt.js" 1096 | }, 1097 | "engines": { 1098 | "node": ">=6" 1099 | } 1100 | }, 1101 | "node_modules/npmlog": { 1102 | "version": "5.0.1", 1103 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", 1104 | "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", 1105 | "dev": true, 1106 | "dependencies": { 1107 | "are-we-there-yet": "^2.0.0", 1108 | "console-control-strings": "^1.1.0", 1109 | "gauge": "^3.0.0", 1110 | "set-blocking": "^2.0.0" 1111 | } 1112 | }, 1113 | "node_modules/object-assign": { 1114 | "version": "4.1.1", 1115 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1116 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1117 | "dev": true, 1118 | "engines": { 1119 | "node": ">=0.10.0" 1120 | } 1121 | }, 1122 | "node_modules/object-inspect": { 1123 | "version": "1.12.3", 1124 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 1125 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 1126 | "funding": { 1127 | "url": "https://github.com/sponsors/ljharb" 1128 | } 1129 | }, 1130 | "node_modules/on-finished": { 1131 | "version": "2.4.1", 1132 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1133 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1134 | "dependencies": { 1135 | "ee-first": "1.1.1" 1136 | }, 1137 | "engines": { 1138 | "node": ">= 0.8" 1139 | } 1140 | }, 1141 | "node_modules/once": { 1142 | "version": "1.4.0", 1143 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1144 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1145 | "dev": true, 1146 | "dependencies": { 1147 | "wrappy": "1" 1148 | } 1149 | }, 1150 | "node_modules/parseurl": { 1151 | "version": "1.3.3", 1152 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1153 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1154 | "engines": { 1155 | "node": ">= 0.8" 1156 | } 1157 | }, 1158 | "node_modules/path-is-absolute": { 1159 | "version": "1.0.1", 1160 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1161 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1162 | "dev": true, 1163 | "engines": { 1164 | "node": ">=0.10.0" 1165 | } 1166 | }, 1167 | "node_modules/path-to-regexp": { 1168 | "version": "0.1.7", 1169 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1170 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1171 | }, 1172 | "node_modules/protobufjs": { 1173 | "version": "7.2.3", 1174 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", 1175 | "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", 1176 | "hasInstallScript": true, 1177 | "dependencies": { 1178 | "@protobufjs/aspromise": "^1.1.2", 1179 | "@protobufjs/base64": "^1.1.2", 1180 | "@protobufjs/codegen": "^2.0.4", 1181 | "@protobufjs/eventemitter": "^1.1.0", 1182 | "@protobufjs/fetch": "^1.1.0", 1183 | "@protobufjs/float": "^1.0.2", 1184 | "@protobufjs/inquire": "^1.1.0", 1185 | "@protobufjs/path": "^1.1.2", 1186 | "@protobufjs/pool": "^1.1.0", 1187 | "@protobufjs/utf8": "^1.1.0", 1188 | "@types/node": ">=13.7.0", 1189 | "long": "^5.0.0" 1190 | }, 1191 | "engines": { 1192 | "node": ">=12.0.0" 1193 | } 1194 | }, 1195 | "node_modules/protobufjs/node_modules/long": { 1196 | "version": "5.2.3", 1197 | "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", 1198 | "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" 1199 | }, 1200 | "node_modules/proxy-addr": { 1201 | "version": "2.0.7", 1202 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1203 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1204 | "dependencies": { 1205 | "forwarded": "0.2.0", 1206 | "ipaddr.js": "1.9.1" 1207 | }, 1208 | "engines": { 1209 | "node": ">= 0.10" 1210 | } 1211 | }, 1212 | "node_modules/qs": { 1213 | "version": "6.11.0", 1214 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1215 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1216 | "dependencies": { 1217 | "side-channel": "^1.0.4" 1218 | }, 1219 | "engines": { 1220 | "node": ">=0.6" 1221 | }, 1222 | "funding": { 1223 | "url": "https://github.com/sponsors/ljharb" 1224 | } 1225 | }, 1226 | "node_modules/range-parser": { 1227 | "version": "1.2.1", 1228 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1229 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1230 | "engines": { 1231 | "node": ">= 0.6" 1232 | } 1233 | }, 1234 | "node_modules/raw-body": { 1235 | "version": "2.5.1", 1236 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1237 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1238 | "dependencies": { 1239 | "bytes": "3.1.2", 1240 | "http-errors": "2.0.0", 1241 | "iconv-lite": "0.4.24", 1242 | "unpipe": "1.0.0" 1243 | }, 1244 | "engines": { 1245 | "node": ">= 0.8" 1246 | } 1247 | }, 1248 | "node_modules/readable-stream": { 1249 | "version": "3.6.2", 1250 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 1251 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 1252 | "dev": true, 1253 | "dependencies": { 1254 | "inherits": "^2.0.3", 1255 | "string_decoder": "^1.1.1", 1256 | "util-deprecate": "^1.0.1" 1257 | }, 1258 | "engines": { 1259 | "node": ">= 6" 1260 | } 1261 | }, 1262 | "node_modules/regenerator-runtime": { 1263 | "version": "0.11.1", 1264 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 1265 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" 1266 | }, 1267 | "node_modules/require-directory": { 1268 | "version": "2.1.1", 1269 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1270 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 1271 | "engines": { 1272 | "node": ">=0.10.0" 1273 | } 1274 | }, 1275 | "node_modules/rimraf": { 1276 | "version": "3.0.2", 1277 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1278 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1279 | "dev": true, 1280 | "dependencies": { 1281 | "glob": "^7.1.3" 1282 | }, 1283 | "bin": { 1284 | "rimraf": "bin.js" 1285 | }, 1286 | "funding": { 1287 | "url": "https://github.com/sponsors/isaacs" 1288 | } 1289 | }, 1290 | "node_modules/safe-buffer": { 1291 | "version": "5.2.1", 1292 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1293 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1294 | "funding": [ 1295 | { 1296 | "type": "github", 1297 | "url": "https://github.com/sponsors/feross" 1298 | }, 1299 | { 1300 | "type": "patreon", 1301 | "url": "https://www.patreon.com/feross" 1302 | }, 1303 | { 1304 | "type": "consulting", 1305 | "url": "https://feross.org/support" 1306 | } 1307 | ] 1308 | }, 1309 | "node_modules/safer-buffer": { 1310 | "version": "2.1.2", 1311 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1312 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1313 | }, 1314 | "node_modules/semver": { 1315 | "version": "7.5.3", 1316 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", 1317 | "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", 1318 | "dev": true, 1319 | "dependencies": { 1320 | "lru-cache": "^6.0.0" 1321 | }, 1322 | "bin": { 1323 | "semver": "bin/semver.js" 1324 | }, 1325 | "engines": { 1326 | "node": ">=10" 1327 | } 1328 | }, 1329 | "node_modules/send": { 1330 | "version": "0.18.0", 1331 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1332 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1333 | "dependencies": { 1334 | "debug": "2.6.9", 1335 | "depd": "2.0.0", 1336 | "destroy": "1.2.0", 1337 | "encodeurl": "~1.0.2", 1338 | "escape-html": "~1.0.3", 1339 | "etag": "~1.8.1", 1340 | "fresh": "0.5.2", 1341 | "http-errors": "2.0.0", 1342 | "mime": "1.6.0", 1343 | "ms": "2.1.3", 1344 | "on-finished": "2.4.1", 1345 | "range-parser": "~1.2.1", 1346 | "statuses": "2.0.1" 1347 | }, 1348 | "engines": { 1349 | "node": ">= 0.8.0" 1350 | } 1351 | }, 1352 | "node_modules/send/node_modules/debug": { 1353 | "version": "2.6.9", 1354 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1355 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1356 | "dependencies": { 1357 | "ms": "2.0.0" 1358 | } 1359 | }, 1360 | "node_modules/send/node_modules/debug/node_modules/ms": { 1361 | "version": "2.0.0", 1362 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1363 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1364 | }, 1365 | "node_modules/send/node_modules/ms": { 1366 | "version": "2.1.3", 1367 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1368 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1369 | }, 1370 | "node_modules/serve-static": { 1371 | "version": "1.15.0", 1372 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1373 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1374 | "dependencies": { 1375 | "encodeurl": "~1.0.2", 1376 | "escape-html": "~1.0.3", 1377 | "parseurl": "~1.3.3", 1378 | "send": "0.18.0" 1379 | }, 1380 | "engines": { 1381 | "node": ">= 0.8.0" 1382 | } 1383 | }, 1384 | "node_modules/set-blocking": { 1385 | "version": "2.0.0", 1386 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1387 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", 1388 | "dev": true 1389 | }, 1390 | "node_modules/setprototypeof": { 1391 | "version": "1.2.0", 1392 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1393 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1394 | }, 1395 | "node_modules/side-channel": { 1396 | "version": "1.0.4", 1397 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1398 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1399 | "dependencies": { 1400 | "call-bind": "^1.0.0", 1401 | "get-intrinsic": "^1.0.2", 1402 | "object-inspect": "^1.9.0" 1403 | }, 1404 | "funding": { 1405 | "url": "https://github.com/sponsors/ljharb" 1406 | } 1407 | }, 1408 | "node_modules/signal-exit": { 1409 | "version": "3.0.7", 1410 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 1411 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", 1412 | "dev": true 1413 | }, 1414 | "node_modules/source-map": { 1415 | "version": "0.6.1", 1416 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1417 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1418 | "dev": true, 1419 | "engines": { 1420 | "node": ">=0.10.0" 1421 | } 1422 | }, 1423 | "node_modules/statuses": { 1424 | "version": "2.0.1", 1425 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1426 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1427 | "engines": { 1428 | "node": ">= 0.8" 1429 | } 1430 | }, 1431 | "node_modules/string_decoder": { 1432 | "version": "1.3.0", 1433 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1434 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1435 | "dev": true, 1436 | "dependencies": { 1437 | "safe-buffer": "~5.2.0" 1438 | } 1439 | }, 1440 | "node_modules/string-width": { 1441 | "version": "4.2.3", 1442 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1443 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1444 | "dependencies": { 1445 | "emoji-regex": "^8.0.0", 1446 | "is-fullwidth-code-point": "^3.0.0", 1447 | "strip-ansi": "^6.0.1" 1448 | }, 1449 | "engines": { 1450 | "node": ">=8" 1451 | } 1452 | }, 1453 | "node_modules/strip-ansi": { 1454 | "version": "6.0.1", 1455 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1456 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1457 | "dependencies": { 1458 | "ansi-regex": "^5.0.1" 1459 | }, 1460 | "engines": { 1461 | "node": ">=8" 1462 | } 1463 | }, 1464 | "node_modules/tar": { 1465 | "version": "6.1.15", 1466 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", 1467 | "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", 1468 | "dev": true, 1469 | "dependencies": { 1470 | "chownr": "^2.0.0", 1471 | "fs-minipass": "^2.0.0", 1472 | "minipass": "^5.0.0", 1473 | "minizlib": "^2.1.1", 1474 | "mkdirp": "^1.0.3", 1475 | "yallist": "^4.0.0" 1476 | }, 1477 | "engines": { 1478 | "node": ">=10" 1479 | } 1480 | }, 1481 | "node_modules/toidentifier": { 1482 | "version": "1.0.1", 1483 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1484 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1485 | "engines": { 1486 | "node": ">=0.6" 1487 | } 1488 | }, 1489 | "node_modules/tr46": { 1490 | "version": "0.0.3", 1491 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1492 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 1493 | }, 1494 | "node_modules/type-is": { 1495 | "version": "1.6.18", 1496 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1497 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1498 | "dependencies": { 1499 | "media-typer": "0.3.0", 1500 | "mime-types": "~2.1.24" 1501 | }, 1502 | "engines": { 1503 | "node": ">= 0.6" 1504 | } 1505 | }, 1506 | "node_modules/uglify-js": { 1507 | "version": "3.17.4", 1508 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", 1509 | "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", 1510 | "dev": true, 1511 | "optional": true, 1512 | "bin": { 1513 | "uglifyjs": "bin/uglifyjs" 1514 | }, 1515 | "engines": { 1516 | "node": ">=0.8.0" 1517 | } 1518 | }, 1519 | "node_modules/unpipe": { 1520 | "version": "1.0.0", 1521 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1522 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1523 | "engines": { 1524 | "node": ">= 0.8" 1525 | } 1526 | }, 1527 | "node_modules/util-deprecate": { 1528 | "version": "1.0.2", 1529 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1530 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 1531 | "dev": true 1532 | }, 1533 | "node_modules/utils-merge": { 1534 | "version": "1.0.1", 1535 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1536 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1537 | "engines": { 1538 | "node": ">= 0.4.0" 1539 | } 1540 | }, 1541 | "node_modules/vary": { 1542 | "version": "1.1.2", 1543 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1544 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1545 | "engines": { 1546 | "node": ">= 0.8" 1547 | } 1548 | }, 1549 | "node_modules/webidl-conversions": { 1550 | "version": "3.0.1", 1551 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1552 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 1553 | }, 1554 | "node_modules/whatwg-url": { 1555 | "version": "5.0.0", 1556 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1557 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 1558 | "dependencies": { 1559 | "tr46": "~0.0.3", 1560 | "webidl-conversions": "^3.0.0" 1561 | } 1562 | }, 1563 | "node_modules/wide-align": { 1564 | "version": "1.1.5", 1565 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", 1566 | "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", 1567 | "dev": true, 1568 | "dependencies": { 1569 | "string-width": "^1.0.2 || 2 || 3 || 4" 1570 | } 1571 | }, 1572 | "node_modules/wordwrap": { 1573 | "version": "1.0.0", 1574 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1575 | "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", 1576 | "dev": true 1577 | }, 1578 | "node_modules/wrap-ansi": { 1579 | "version": "7.0.0", 1580 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1581 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1582 | "dependencies": { 1583 | "ansi-styles": "^4.0.0", 1584 | "string-width": "^4.1.0", 1585 | "strip-ansi": "^6.0.0" 1586 | }, 1587 | "engines": { 1588 | "node": ">=10" 1589 | }, 1590 | "funding": { 1591 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1592 | } 1593 | }, 1594 | "node_modules/wrappy": { 1595 | "version": "1.0.2", 1596 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1597 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1598 | "dev": true 1599 | }, 1600 | "node_modules/y18n": { 1601 | "version": "5.0.8", 1602 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1603 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1604 | "engines": { 1605 | "node": ">=10" 1606 | } 1607 | }, 1608 | "node_modules/yallist": { 1609 | "version": "4.0.0", 1610 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1611 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1612 | "dev": true 1613 | }, 1614 | "node_modules/yargs": { 1615 | "version": "17.7.2", 1616 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 1617 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 1618 | "dependencies": { 1619 | "cliui": "^8.0.1", 1620 | "escalade": "^3.1.1", 1621 | "get-caller-file": "^2.0.5", 1622 | "require-directory": "^2.1.1", 1623 | "string-width": "^4.2.3", 1624 | "y18n": "^5.0.5", 1625 | "yargs-parser": "^21.1.1" 1626 | }, 1627 | "engines": { 1628 | "node": ">=12" 1629 | } 1630 | }, 1631 | "node_modules/yargs-parser": { 1632 | "version": "21.1.1", 1633 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 1634 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 1635 | "engines": { 1636 | "node": ">=12" 1637 | } 1638 | } 1639 | }, 1640 | "dependencies": { 1641 | "@grpc/grpc-js": { 1642 | "version": "1.8.16", 1643 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.16.tgz", 1644 | "integrity": "sha512-Nvlq4V7XQmdRVDGgecR8ZPPCeY+uH1LhzbC+QxklwAahpQlq8YLsiOQgfkub9FiakRiohaDy361xqlTLkq9EHw==", 1645 | "requires": { 1646 | "@grpc/proto-loader": "^0.7.0", 1647 | "@types/node": ">=12.12.47" 1648 | } 1649 | }, 1650 | "@grpc/proto-loader": { 1651 | "version": "0.7.7", 1652 | "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.7.tgz", 1653 | "integrity": "sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==", 1654 | "requires": { 1655 | "@types/long": "^4.0.1", 1656 | "lodash.camelcase": "^4.3.0", 1657 | "long": "^4.0.0", 1658 | "protobufjs": "^7.0.0", 1659 | "yargs": "^17.7.2" 1660 | } 1661 | }, 1662 | "@mapbox/node-pre-gyp": { 1663 | "version": "1.0.10", 1664 | "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", 1665 | "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", 1666 | "dev": true, 1667 | "requires": { 1668 | "detect-libc": "^2.0.0", 1669 | "https-proxy-agent": "^5.0.0", 1670 | "make-dir": "^3.1.0", 1671 | "node-fetch": "^2.6.7", 1672 | "nopt": "^5.0.0", 1673 | "npmlog": "^5.0.1", 1674 | "rimraf": "^3.0.2", 1675 | "semver": "^7.3.5", 1676 | "tar": "^6.1.11" 1677 | } 1678 | }, 1679 | "@protobufjs/aspromise": { 1680 | "version": "1.1.2", 1681 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 1682 | "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" 1683 | }, 1684 | "@protobufjs/base64": { 1685 | "version": "1.1.2", 1686 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 1687 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 1688 | }, 1689 | "@protobufjs/codegen": { 1690 | "version": "2.0.4", 1691 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 1692 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 1693 | }, 1694 | "@protobufjs/eventemitter": { 1695 | "version": "1.1.0", 1696 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 1697 | "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" 1698 | }, 1699 | "@protobufjs/fetch": { 1700 | "version": "1.1.0", 1701 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 1702 | "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", 1703 | "requires": { 1704 | "@protobufjs/aspromise": "^1.1.1", 1705 | "@protobufjs/inquire": "^1.1.0" 1706 | } 1707 | }, 1708 | "@protobufjs/float": { 1709 | "version": "1.0.2", 1710 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 1711 | "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" 1712 | }, 1713 | "@protobufjs/inquire": { 1714 | "version": "1.1.0", 1715 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 1716 | "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" 1717 | }, 1718 | "@protobufjs/path": { 1719 | "version": "1.1.2", 1720 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 1721 | "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" 1722 | }, 1723 | "@protobufjs/pool": { 1724 | "version": "1.1.0", 1725 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 1726 | "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" 1727 | }, 1728 | "@protobufjs/utf8": { 1729 | "version": "1.1.0", 1730 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 1731 | "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" 1732 | }, 1733 | "@types/long": { 1734 | "version": "4.0.2", 1735 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", 1736 | "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" 1737 | }, 1738 | "@types/node": { 1739 | "version": "20.3.1", 1740 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", 1741 | "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" 1742 | }, 1743 | "abbrev": { 1744 | "version": "1.1.1", 1745 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 1746 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", 1747 | "dev": true 1748 | }, 1749 | "accepts": { 1750 | "version": "1.3.8", 1751 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 1752 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 1753 | "requires": { 1754 | "mime-types": "~2.1.34", 1755 | "negotiator": "0.6.3" 1756 | } 1757 | }, 1758 | "agent-base": { 1759 | "version": "6.0.2", 1760 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 1761 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 1762 | "dev": true, 1763 | "requires": { 1764 | "debug": "4" 1765 | } 1766 | }, 1767 | "ansi-regex": { 1768 | "version": "5.0.1", 1769 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1770 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 1771 | }, 1772 | "ansi-styles": { 1773 | "version": "4.3.0", 1774 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1775 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1776 | "requires": { 1777 | "color-convert": "^2.0.1" 1778 | } 1779 | }, 1780 | "aproba": { 1781 | "version": "2.0.0", 1782 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", 1783 | "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", 1784 | "dev": true 1785 | }, 1786 | "are-we-there-yet": { 1787 | "version": "2.0.0", 1788 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", 1789 | "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", 1790 | "dev": true, 1791 | "requires": { 1792 | "delegates": "^1.0.0", 1793 | "readable-stream": "^3.6.0" 1794 | } 1795 | }, 1796 | "array-flatten": { 1797 | "version": "1.1.1", 1798 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1799 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 1800 | }, 1801 | "babel-runtime": { 1802 | "version": "6.26.0", 1803 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 1804 | "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", 1805 | "requires": { 1806 | "core-js": "^2.4.0", 1807 | "regenerator-runtime": "^0.11.0" 1808 | } 1809 | }, 1810 | "balanced-match": { 1811 | "version": "1.0.2", 1812 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1813 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1814 | "dev": true 1815 | }, 1816 | "body-parser": { 1817 | "version": "1.20.1", 1818 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 1819 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 1820 | "requires": { 1821 | "bytes": "3.1.2", 1822 | "content-type": "~1.0.4", 1823 | "debug": "2.6.9", 1824 | "depd": "2.0.0", 1825 | "destroy": "1.2.0", 1826 | "http-errors": "2.0.0", 1827 | "iconv-lite": "0.4.24", 1828 | "on-finished": "2.4.1", 1829 | "qs": "6.11.0", 1830 | "raw-body": "2.5.1", 1831 | "type-is": "~1.6.18", 1832 | "unpipe": "1.0.0" 1833 | }, 1834 | "dependencies": { 1835 | "debug": { 1836 | "version": "2.6.9", 1837 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1838 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1839 | "requires": { 1840 | "ms": "2.0.0" 1841 | } 1842 | }, 1843 | "ms": { 1844 | "version": "2.0.0", 1845 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1846 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1847 | } 1848 | } 1849 | }, 1850 | "brace-expansion": { 1851 | "version": "1.1.11", 1852 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1853 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1854 | "dev": true, 1855 | "requires": { 1856 | "balanced-match": "^1.0.0", 1857 | "concat-map": "0.0.1" 1858 | } 1859 | }, 1860 | "buffer-to-arraybuffer": { 1861 | "version": "0.0.4", 1862 | "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.4.tgz", 1863 | "integrity": "sha512-/ON9xjCtPIO0uycXhHXHZ0CIu7hHA1UJUVro/nXYDfYHb+5vuMq4jOkvZ4QIeB6TClTxPVt9VayplwMyW1BZag==" 1864 | }, 1865 | "bytes": { 1866 | "version": "3.1.2", 1867 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1868 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 1869 | }, 1870 | "call-bind": { 1871 | "version": "1.0.2", 1872 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 1873 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 1874 | "requires": { 1875 | "function-bind": "^1.1.1", 1876 | "get-intrinsic": "^1.0.2" 1877 | } 1878 | }, 1879 | "chownr": { 1880 | "version": "2.0.0", 1881 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", 1882 | "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", 1883 | "dev": true 1884 | }, 1885 | "cliui": { 1886 | "version": "8.0.1", 1887 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 1888 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 1889 | "requires": { 1890 | "string-width": "^4.2.0", 1891 | "strip-ansi": "^6.0.1", 1892 | "wrap-ansi": "^7.0.0" 1893 | } 1894 | }, 1895 | "color-convert": { 1896 | "version": "2.0.1", 1897 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1898 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1899 | "requires": { 1900 | "color-name": "~1.1.4" 1901 | } 1902 | }, 1903 | "color-name": { 1904 | "version": "1.1.4", 1905 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1906 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 1907 | }, 1908 | "color-support": { 1909 | "version": "1.1.3", 1910 | "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", 1911 | "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", 1912 | "dev": true 1913 | }, 1914 | "concat-map": { 1915 | "version": "0.0.1", 1916 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1917 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 1918 | "dev": true 1919 | }, 1920 | "console-control-strings": { 1921 | "version": "1.1.0", 1922 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 1923 | "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", 1924 | "dev": true 1925 | }, 1926 | "content-disposition": { 1927 | "version": "0.5.4", 1928 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 1929 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 1930 | "requires": { 1931 | "safe-buffer": "5.2.1" 1932 | } 1933 | }, 1934 | "content-type": { 1935 | "version": "1.0.5", 1936 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 1937 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 1938 | }, 1939 | "cookie": { 1940 | "version": "0.5.0", 1941 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 1942 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 1943 | }, 1944 | "cookie-signature": { 1945 | "version": "1.0.6", 1946 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1947 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 1948 | }, 1949 | "core-js": { 1950 | "version": "2.6.12", 1951 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", 1952 | "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" 1953 | }, 1954 | "debug": { 1955 | "version": "4.3.4", 1956 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1957 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1958 | "dev": true, 1959 | "requires": { 1960 | "ms": "2.1.2" 1961 | } 1962 | }, 1963 | "delegates": { 1964 | "version": "1.0.0", 1965 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 1966 | "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", 1967 | "dev": true 1968 | }, 1969 | "depd": { 1970 | "version": "2.0.0", 1971 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1972 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 1973 | }, 1974 | "destroy": { 1975 | "version": "1.2.0", 1976 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 1977 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 1978 | }, 1979 | "detect-libc": { 1980 | "version": "2.0.1", 1981 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", 1982 | "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", 1983 | "dev": true 1984 | }, 1985 | "ee-first": { 1986 | "version": "1.1.1", 1987 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1988 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 1989 | }, 1990 | "emoji-regex": { 1991 | "version": "8.0.0", 1992 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1993 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 1994 | }, 1995 | "encodeurl": { 1996 | "version": "1.0.2", 1997 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1998 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 1999 | }, 2000 | "encoding": { 2001 | "version": "0.1.13", 2002 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", 2003 | "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", 2004 | "requires": { 2005 | "iconv-lite": "^0.6.2" 2006 | }, 2007 | "dependencies": { 2008 | "iconv-lite": { 2009 | "version": "0.6.3", 2010 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 2011 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 2012 | "requires": { 2013 | "safer-buffer": ">= 2.1.2 < 3.0.0" 2014 | } 2015 | } 2016 | } 2017 | }, 2018 | "escalade": { 2019 | "version": "3.1.1", 2020 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 2021 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" 2022 | }, 2023 | "escape-html": { 2024 | "version": "1.0.3", 2025 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 2026 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 2027 | }, 2028 | "etag": { 2029 | "version": "1.8.1", 2030 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 2031 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 2032 | }, 2033 | "express": { 2034 | "version": "4.18.2", 2035 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 2036 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 2037 | "requires": { 2038 | "accepts": "~1.3.8", 2039 | "array-flatten": "1.1.1", 2040 | "body-parser": "1.20.1", 2041 | "content-disposition": "0.5.4", 2042 | "content-type": "~1.0.4", 2043 | "cookie": "0.5.0", 2044 | "cookie-signature": "1.0.6", 2045 | "debug": "2.6.9", 2046 | "depd": "2.0.0", 2047 | "encodeurl": "~1.0.2", 2048 | "escape-html": "~1.0.3", 2049 | "etag": "~1.8.1", 2050 | "finalhandler": "1.2.0", 2051 | "fresh": "0.5.2", 2052 | "http-errors": "2.0.0", 2053 | "merge-descriptors": "1.0.1", 2054 | "methods": "~1.1.2", 2055 | "on-finished": "2.4.1", 2056 | "parseurl": "~1.3.3", 2057 | "path-to-regexp": "0.1.7", 2058 | "proxy-addr": "~2.0.7", 2059 | "qs": "6.11.0", 2060 | "range-parser": "~1.2.1", 2061 | "safe-buffer": "5.2.1", 2062 | "send": "0.18.0", 2063 | "serve-static": "1.15.0", 2064 | "setprototypeof": "1.2.0", 2065 | "statuses": "2.0.1", 2066 | "type-is": "~1.6.18", 2067 | "utils-merge": "1.0.1", 2068 | "vary": "~1.1.2" 2069 | }, 2070 | "dependencies": { 2071 | "debug": { 2072 | "version": "2.6.9", 2073 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2074 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2075 | "requires": { 2076 | "ms": "2.0.0" 2077 | } 2078 | }, 2079 | "ms": { 2080 | "version": "2.0.0", 2081 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2082 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 2083 | } 2084 | } 2085 | }, 2086 | "finalhandler": { 2087 | "version": "1.2.0", 2088 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 2089 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 2090 | "requires": { 2091 | "debug": "2.6.9", 2092 | "encodeurl": "~1.0.2", 2093 | "escape-html": "~1.0.3", 2094 | "on-finished": "2.4.1", 2095 | "parseurl": "~1.3.3", 2096 | "statuses": "2.0.1", 2097 | "unpipe": "~1.0.0" 2098 | }, 2099 | "dependencies": { 2100 | "debug": { 2101 | "version": "2.6.9", 2102 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2103 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2104 | "requires": { 2105 | "ms": "2.0.0" 2106 | } 2107 | }, 2108 | "ms": { 2109 | "version": "2.0.0", 2110 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2111 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 2112 | } 2113 | } 2114 | }, 2115 | "forwarded": { 2116 | "version": "0.2.0", 2117 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 2118 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 2119 | }, 2120 | "fresh": { 2121 | "version": "0.5.2", 2122 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 2123 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 2124 | }, 2125 | "fs-minipass": { 2126 | "version": "2.1.0", 2127 | "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", 2128 | "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", 2129 | "dev": true, 2130 | "requires": { 2131 | "minipass": "^3.0.0" 2132 | }, 2133 | "dependencies": { 2134 | "minipass": { 2135 | "version": "3.3.6", 2136 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 2137 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 2138 | "dev": true, 2139 | "requires": { 2140 | "yallist": "^4.0.0" 2141 | } 2142 | } 2143 | } 2144 | }, 2145 | "fs.realpath": { 2146 | "version": "1.0.0", 2147 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 2148 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 2149 | "dev": true 2150 | }, 2151 | "function-bind": { 2152 | "version": "1.1.1", 2153 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 2154 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 2155 | }, 2156 | "gauge": { 2157 | "version": "3.0.2", 2158 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", 2159 | "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", 2160 | "dev": true, 2161 | "requires": { 2162 | "aproba": "^1.0.3 || ^2.0.0", 2163 | "color-support": "^1.1.2", 2164 | "console-control-strings": "^1.0.0", 2165 | "has-unicode": "^2.0.1", 2166 | "object-assign": "^4.1.1", 2167 | "signal-exit": "^3.0.0", 2168 | "string-width": "^4.2.3", 2169 | "strip-ansi": "^6.0.1", 2170 | "wide-align": "^1.1.2" 2171 | } 2172 | }, 2173 | "get-caller-file": { 2174 | "version": "2.0.5", 2175 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 2176 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 2177 | }, 2178 | "get-intrinsic": { 2179 | "version": "1.2.1", 2180 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", 2181 | "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", 2182 | "requires": { 2183 | "function-bind": "^1.1.1", 2184 | "has": "^1.0.3", 2185 | "has-proto": "^1.0.1", 2186 | "has-symbols": "^1.0.3" 2187 | } 2188 | }, 2189 | "glob": { 2190 | "version": "7.2.3", 2191 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 2192 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 2193 | "dev": true, 2194 | "requires": { 2195 | "fs.realpath": "^1.0.0", 2196 | "inflight": "^1.0.4", 2197 | "inherits": "2", 2198 | "minimatch": "^3.1.1", 2199 | "once": "^1.3.0", 2200 | "path-is-absolute": "^1.0.0" 2201 | } 2202 | }, 2203 | "google-protobuf": { 2204 | "version": "3.15.8", 2205 | "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.15.8.tgz", 2206 | "integrity": "sha512-2jtfdqTaSxk0cuBJBtTTWsot4WtR9RVr2rXg7x7OoqiuOKopPrwXpM1G4dXIkLcUNRh3RKzz76C8IOkksZSeOw==", 2207 | "dev": true 2208 | }, 2209 | "grpc_tools_node_protoc_ts": { 2210 | "version": "5.3.3", 2211 | "resolved": "https://registry.npmjs.org/grpc_tools_node_protoc_ts/-/grpc_tools_node_protoc_ts-5.3.3.tgz", 2212 | "integrity": "sha512-M/YrklvVXMtuuj9kb42PxeouZhs7Ul+R4e/31XwrankUcKL8cQQP50Q9q+KEHGyHQaPt6VtKKsxMgLaKbCxeww==", 2213 | "dev": true, 2214 | "requires": { 2215 | "google-protobuf": "3.15.8", 2216 | "handlebars": "4.7.7" 2217 | } 2218 | }, 2219 | "grpc-tools": { 2220 | "version": "1.12.4", 2221 | "resolved": "https://registry.npmjs.org/grpc-tools/-/grpc-tools-1.12.4.tgz", 2222 | "integrity": "sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==", 2223 | "dev": true, 2224 | "requires": { 2225 | "@mapbox/node-pre-gyp": "^1.0.5" 2226 | } 2227 | }, 2228 | "handlebars": { 2229 | "version": "4.7.7", 2230 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", 2231 | "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", 2232 | "dev": true, 2233 | "requires": { 2234 | "minimist": "^1.2.5", 2235 | "neo-async": "^2.6.0", 2236 | "source-map": "^0.6.1", 2237 | "uglify-js": "^3.1.4", 2238 | "wordwrap": "^1.0.0" 2239 | } 2240 | }, 2241 | "has": { 2242 | "version": "1.0.3", 2243 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 2244 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 2245 | "requires": { 2246 | "function-bind": "^1.1.1" 2247 | } 2248 | }, 2249 | "has-proto": { 2250 | "version": "1.0.1", 2251 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 2252 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" 2253 | }, 2254 | "has-symbols": { 2255 | "version": "1.0.3", 2256 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 2257 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 2258 | }, 2259 | "has-unicode": { 2260 | "version": "2.0.1", 2261 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 2262 | "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", 2263 | "dev": true 2264 | }, 2265 | "http-errors": { 2266 | "version": "2.0.0", 2267 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 2268 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 2269 | "requires": { 2270 | "depd": "2.0.0", 2271 | "inherits": "2.0.4", 2272 | "setprototypeof": "1.2.0", 2273 | "statuses": "2.0.1", 2274 | "toidentifier": "1.0.1" 2275 | } 2276 | }, 2277 | "https-proxy-agent": { 2278 | "version": "5.0.1", 2279 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", 2280 | "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", 2281 | "dev": true, 2282 | "requires": { 2283 | "agent-base": "6", 2284 | "debug": "4" 2285 | } 2286 | }, 2287 | "iconv-lite": { 2288 | "version": "0.4.24", 2289 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 2290 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 2291 | "requires": { 2292 | "safer-buffer": ">= 2.1.2 < 3" 2293 | } 2294 | }, 2295 | "inflight": { 2296 | "version": "1.0.6", 2297 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 2298 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 2299 | "dev": true, 2300 | "requires": { 2301 | "once": "^1.3.0", 2302 | "wrappy": "1" 2303 | } 2304 | }, 2305 | "inherits": { 2306 | "version": "2.0.4", 2307 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 2308 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 2309 | }, 2310 | "ipaddr.js": { 2311 | "version": "1.9.1", 2312 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 2313 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 2314 | }, 2315 | "is-fullwidth-code-point": { 2316 | "version": "3.0.0", 2317 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2318 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 2319 | }, 2320 | "is-stream": { 2321 | "version": "1.1.0", 2322 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 2323 | "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" 2324 | }, 2325 | "lodash.camelcase": { 2326 | "version": "4.3.0", 2327 | "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 2328 | "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" 2329 | }, 2330 | "long": { 2331 | "version": "4.0.0", 2332 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 2333 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 2334 | }, 2335 | "lru-cache": { 2336 | "version": "6.0.0", 2337 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 2338 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 2339 | "dev": true, 2340 | "requires": { 2341 | "yallist": "^4.0.0" 2342 | } 2343 | }, 2344 | "make-dir": { 2345 | "version": "3.1.0", 2346 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 2347 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 2348 | "dev": true, 2349 | "requires": { 2350 | "semver": "^6.0.0" 2351 | }, 2352 | "dependencies": { 2353 | "semver": { 2354 | "version": "6.3.0", 2355 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 2356 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 2357 | "dev": true 2358 | } 2359 | } 2360 | }, 2361 | "media-typer": { 2362 | "version": "0.3.0", 2363 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 2364 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 2365 | }, 2366 | "merge-descriptors": { 2367 | "version": "1.0.1", 2368 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 2369 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 2370 | }, 2371 | "methods": { 2372 | "version": "1.1.2", 2373 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2374 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 2375 | }, 2376 | "mime": { 2377 | "version": "1.6.0", 2378 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 2379 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 2380 | }, 2381 | "mime-db": { 2382 | "version": "1.52.0", 2383 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 2384 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 2385 | }, 2386 | "mime-types": { 2387 | "version": "2.1.35", 2388 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2389 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 2390 | "requires": { 2391 | "mime-db": "1.52.0" 2392 | } 2393 | }, 2394 | "minimatch": { 2395 | "version": "3.1.2", 2396 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2397 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2398 | "dev": true, 2399 | "requires": { 2400 | "brace-expansion": "^1.1.7" 2401 | } 2402 | }, 2403 | "minimist": { 2404 | "version": "1.2.8", 2405 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 2406 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 2407 | "dev": true 2408 | }, 2409 | "minipass": { 2410 | "version": "5.0.0", 2411 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 2412 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 2413 | "dev": true 2414 | }, 2415 | "minizlib": { 2416 | "version": "2.1.2", 2417 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", 2418 | "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", 2419 | "dev": true, 2420 | "requires": { 2421 | "minipass": "^3.0.0", 2422 | "yallist": "^4.0.0" 2423 | }, 2424 | "dependencies": { 2425 | "minipass": { 2426 | "version": "3.3.6", 2427 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", 2428 | "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", 2429 | "dev": true, 2430 | "requires": { 2431 | "yallist": "^4.0.0" 2432 | } 2433 | } 2434 | } 2435 | }, 2436 | "mkdirp": { 2437 | "version": "1.0.4", 2438 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 2439 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 2440 | "dev": true 2441 | }, 2442 | "ms": { 2443 | "version": "2.1.2", 2444 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2445 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2446 | "dev": true 2447 | }, 2448 | "negotiator": { 2449 | "version": "0.6.3", 2450 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 2451 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 2452 | }, 2453 | "neo-async": { 2454 | "version": "2.6.2", 2455 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 2456 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 2457 | "dev": true 2458 | }, 2459 | "node-fetch": { 2460 | "version": "2.6.11", 2461 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", 2462 | "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", 2463 | "requires": { 2464 | "whatwg-url": "^5.0.0" 2465 | } 2466 | }, 2467 | "node-fetch2": { 2468 | "version": "1.6.3", 2469 | "resolved": "https://registry.npmjs.org/node-fetch2/-/node-fetch2-1.6.3.tgz", 2470 | "integrity": "sha512-90wPxY5+/CodbDXy0lfy3hC3xHcqbxEq3ufVKtrPx42Hkm/NbruE/DFOrjiVjn05I2AARFYGuGe1AU6RcPIfpQ==", 2471 | "requires": { 2472 | "babel-runtime": "^6.11.6", 2473 | "buffer-to-arraybuffer": "0.0.4", 2474 | "encoding": "^0.1.11", 2475 | "is-stream": "^1.0.1" 2476 | } 2477 | }, 2478 | "nopt": { 2479 | "version": "5.0.0", 2480 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", 2481 | "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", 2482 | "dev": true, 2483 | "requires": { 2484 | "abbrev": "1" 2485 | } 2486 | }, 2487 | "npmlog": { 2488 | "version": "5.0.1", 2489 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", 2490 | "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", 2491 | "dev": true, 2492 | "requires": { 2493 | "are-we-there-yet": "^2.0.0", 2494 | "console-control-strings": "^1.1.0", 2495 | "gauge": "^3.0.0", 2496 | "set-blocking": "^2.0.0" 2497 | } 2498 | }, 2499 | "object-assign": { 2500 | "version": "4.1.1", 2501 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2502 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 2503 | "dev": true 2504 | }, 2505 | "object-inspect": { 2506 | "version": "1.12.3", 2507 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 2508 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" 2509 | }, 2510 | "on-finished": { 2511 | "version": "2.4.1", 2512 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 2513 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 2514 | "requires": { 2515 | "ee-first": "1.1.1" 2516 | } 2517 | }, 2518 | "once": { 2519 | "version": "1.4.0", 2520 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2521 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 2522 | "dev": true, 2523 | "requires": { 2524 | "wrappy": "1" 2525 | } 2526 | }, 2527 | "parseurl": { 2528 | "version": "1.3.3", 2529 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2530 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 2531 | }, 2532 | "path-is-absolute": { 2533 | "version": "1.0.1", 2534 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2535 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 2536 | "dev": true 2537 | }, 2538 | "path-to-regexp": { 2539 | "version": "0.1.7", 2540 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 2541 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 2542 | }, 2543 | "protobufjs": { 2544 | "version": "7.2.3", 2545 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", 2546 | "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", 2547 | "requires": { 2548 | "@protobufjs/aspromise": "^1.1.2", 2549 | "@protobufjs/base64": "^1.1.2", 2550 | "@protobufjs/codegen": "^2.0.4", 2551 | "@protobufjs/eventemitter": "^1.1.0", 2552 | "@protobufjs/fetch": "^1.1.0", 2553 | "@protobufjs/float": "^1.0.2", 2554 | "@protobufjs/inquire": "^1.1.0", 2555 | "@protobufjs/path": "^1.1.2", 2556 | "@protobufjs/pool": "^1.1.0", 2557 | "@protobufjs/utf8": "^1.1.0", 2558 | "@types/node": ">=13.7.0", 2559 | "long": "^5.0.0" 2560 | }, 2561 | "dependencies": { 2562 | "long": { 2563 | "version": "5.2.3", 2564 | "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", 2565 | "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" 2566 | } 2567 | } 2568 | }, 2569 | "proxy-addr": { 2570 | "version": "2.0.7", 2571 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 2572 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 2573 | "requires": { 2574 | "forwarded": "0.2.0", 2575 | "ipaddr.js": "1.9.1" 2576 | } 2577 | }, 2578 | "qs": { 2579 | "version": "6.11.0", 2580 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 2581 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 2582 | "requires": { 2583 | "side-channel": "^1.0.4" 2584 | } 2585 | }, 2586 | "range-parser": { 2587 | "version": "1.2.1", 2588 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 2589 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 2590 | }, 2591 | "raw-body": { 2592 | "version": "2.5.1", 2593 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 2594 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 2595 | "requires": { 2596 | "bytes": "3.1.2", 2597 | "http-errors": "2.0.0", 2598 | "iconv-lite": "0.4.24", 2599 | "unpipe": "1.0.0" 2600 | } 2601 | }, 2602 | "readable-stream": { 2603 | "version": "3.6.2", 2604 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", 2605 | "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", 2606 | "dev": true, 2607 | "requires": { 2608 | "inherits": "^2.0.3", 2609 | "string_decoder": "^1.1.1", 2610 | "util-deprecate": "^1.0.1" 2611 | } 2612 | }, 2613 | "regenerator-runtime": { 2614 | "version": "0.11.1", 2615 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 2616 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" 2617 | }, 2618 | "require-directory": { 2619 | "version": "2.1.1", 2620 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2621 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" 2622 | }, 2623 | "rimraf": { 2624 | "version": "3.0.2", 2625 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2626 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2627 | "dev": true, 2628 | "requires": { 2629 | "glob": "^7.1.3" 2630 | } 2631 | }, 2632 | "safe-buffer": { 2633 | "version": "5.2.1", 2634 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2635 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 2636 | }, 2637 | "safer-buffer": { 2638 | "version": "2.1.2", 2639 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2640 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2641 | }, 2642 | "semver": { 2643 | "version": "7.5.3", 2644 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", 2645 | "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", 2646 | "dev": true, 2647 | "requires": { 2648 | "lru-cache": "^6.0.0" 2649 | } 2650 | }, 2651 | "send": { 2652 | "version": "0.18.0", 2653 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 2654 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 2655 | "requires": { 2656 | "debug": "2.6.9", 2657 | "depd": "2.0.0", 2658 | "destroy": "1.2.0", 2659 | "encodeurl": "~1.0.2", 2660 | "escape-html": "~1.0.3", 2661 | "etag": "~1.8.1", 2662 | "fresh": "0.5.2", 2663 | "http-errors": "2.0.0", 2664 | "mime": "1.6.0", 2665 | "ms": "2.1.3", 2666 | "on-finished": "2.4.1", 2667 | "range-parser": "~1.2.1", 2668 | "statuses": "2.0.1" 2669 | }, 2670 | "dependencies": { 2671 | "debug": { 2672 | "version": "2.6.9", 2673 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2674 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2675 | "requires": { 2676 | "ms": "2.0.0" 2677 | }, 2678 | "dependencies": { 2679 | "ms": { 2680 | "version": "2.0.0", 2681 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2682 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 2683 | } 2684 | } 2685 | }, 2686 | "ms": { 2687 | "version": "2.1.3", 2688 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2689 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 2690 | } 2691 | } 2692 | }, 2693 | "serve-static": { 2694 | "version": "1.15.0", 2695 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 2696 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 2697 | "requires": { 2698 | "encodeurl": "~1.0.2", 2699 | "escape-html": "~1.0.3", 2700 | "parseurl": "~1.3.3", 2701 | "send": "0.18.0" 2702 | } 2703 | }, 2704 | "set-blocking": { 2705 | "version": "2.0.0", 2706 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 2707 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", 2708 | "dev": true 2709 | }, 2710 | "setprototypeof": { 2711 | "version": "1.2.0", 2712 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 2713 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 2714 | }, 2715 | "side-channel": { 2716 | "version": "1.0.4", 2717 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 2718 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 2719 | "requires": { 2720 | "call-bind": "^1.0.0", 2721 | "get-intrinsic": "^1.0.2", 2722 | "object-inspect": "^1.9.0" 2723 | } 2724 | }, 2725 | "signal-exit": { 2726 | "version": "3.0.7", 2727 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", 2728 | "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", 2729 | "dev": true 2730 | }, 2731 | "source-map": { 2732 | "version": "0.6.1", 2733 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2734 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2735 | "dev": true 2736 | }, 2737 | "statuses": { 2738 | "version": "2.0.1", 2739 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 2740 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 2741 | }, 2742 | "string_decoder": { 2743 | "version": "1.3.0", 2744 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 2745 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 2746 | "dev": true, 2747 | "requires": { 2748 | "safe-buffer": "~5.2.0" 2749 | } 2750 | }, 2751 | "string-width": { 2752 | "version": "4.2.3", 2753 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2754 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2755 | "requires": { 2756 | "emoji-regex": "^8.0.0", 2757 | "is-fullwidth-code-point": "^3.0.0", 2758 | "strip-ansi": "^6.0.1" 2759 | } 2760 | }, 2761 | "strip-ansi": { 2762 | "version": "6.0.1", 2763 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2764 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2765 | "requires": { 2766 | "ansi-regex": "^5.0.1" 2767 | } 2768 | }, 2769 | "tar": { 2770 | "version": "6.1.15", 2771 | "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", 2772 | "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", 2773 | "dev": true, 2774 | "requires": { 2775 | "chownr": "^2.0.0", 2776 | "fs-minipass": "^2.0.0", 2777 | "minipass": "^5.0.0", 2778 | "minizlib": "^2.1.1", 2779 | "mkdirp": "^1.0.3", 2780 | "yallist": "^4.0.0" 2781 | } 2782 | }, 2783 | "toidentifier": { 2784 | "version": "1.0.1", 2785 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 2786 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 2787 | }, 2788 | "tr46": { 2789 | "version": "0.0.3", 2790 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 2791 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 2792 | }, 2793 | "type-is": { 2794 | "version": "1.6.18", 2795 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 2796 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 2797 | "requires": { 2798 | "media-typer": "0.3.0", 2799 | "mime-types": "~2.1.24" 2800 | } 2801 | }, 2802 | "uglify-js": { 2803 | "version": "3.17.4", 2804 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", 2805 | "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", 2806 | "dev": true, 2807 | "optional": true 2808 | }, 2809 | "unpipe": { 2810 | "version": "1.0.0", 2811 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2812 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 2813 | }, 2814 | "util-deprecate": { 2815 | "version": "1.0.2", 2816 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2817 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", 2818 | "dev": true 2819 | }, 2820 | "utils-merge": { 2821 | "version": "1.0.1", 2822 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2823 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 2824 | }, 2825 | "vary": { 2826 | "version": "1.1.2", 2827 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2828 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 2829 | }, 2830 | "webidl-conversions": { 2831 | "version": "3.0.1", 2832 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2833 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 2834 | }, 2835 | "whatwg-url": { 2836 | "version": "5.0.0", 2837 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2838 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2839 | "requires": { 2840 | "tr46": "~0.0.3", 2841 | "webidl-conversions": "^3.0.0" 2842 | } 2843 | }, 2844 | "wide-align": { 2845 | "version": "1.1.5", 2846 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", 2847 | "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", 2848 | "dev": true, 2849 | "requires": { 2850 | "string-width": "^1.0.2 || 2 || 3 || 4" 2851 | } 2852 | }, 2853 | "wordwrap": { 2854 | "version": "1.0.0", 2855 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 2856 | "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", 2857 | "dev": true 2858 | }, 2859 | "wrap-ansi": { 2860 | "version": "7.0.0", 2861 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2862 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2863 | "requires": { 2864 | "ansi-styles": "^4.0.0", 2865 | "string-width": "^4.1.0", 2866 | "strip-ansi": "^6.0.0" 2867 | } 2868 | }, 2869 | "wrappy": { 2870 | "version": "1.0.2", 2871 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2872 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2873 | "dev": true 2874 | }, 2875 | "y18n": { 2876 | "version": "5.0.8", 2877 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2878 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" 2879 | }, 2880 | "yallist": { 2881 | "version": "4.0.0", 2882 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2883 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2884 | "dev": true 2885 | }, 2886 | "yargs": { 2887 | "version": "17.7.2", 2888 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 2889 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 2890 | "requires": { 2891 | "cliui": "^8.0.1", 2892 | "escalade": "^3.1.1", 2893 | "get-caller-file": "^2.0.5", 2894 | "require-directory": "^2.1.1", 2895 | "string-width": "^4.2.3", 2896 | "y18n": "^5.0.5", 2897 | "yargs-parser": "^21.1.1" 2898 | } 2899 | }, 2900 | "yargs-parser": { 2901 | "version": "21.1.1", 2902 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 2903 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" 2904 | } 2905 | } 2906 | } 2907 | -------------------------------------------------------------------------------- /grpc-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "grpc", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@grpc/grpc-js": "^1.8.16", 14 | "@grpc/proto-loader": "^0.7.7", 15 | "express": "^4.18.2", 16 | "node-fetch": "^2.6.11", 17 | "node-fetch2": "^1.6.3" 18 | }, 19 | "devDependencies": { 20 | "grpc_tools_node_protoc_ts": "^5.3.3", 21 | "grpc-tools": "^1.12.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /grpc-demo/protos/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package helloworld; 4 | 5 | service HelloWorld { 6 | rpc SayHello (HelloRequest) returns (HelloResponse); 7 | } 8 | 9 | message HelloRequest { 10 | string name = 1; 11 | } 12 | 13 | message HelloResponse { 14 | string message = 1; 15 | } 16 | -------------------------------------------------------------------------------- /grpc-demo/rest-server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | app.use(express.json()); 4 | 5 | // Define and register /sayHello REST endpoint 6 | app.post('/sayHello', (req, res) => { 7 | const name = req.body.name; 8 | res.json({ message: 'Hello ' + name }); 9 | }); 10 | 11 | 12 | // Create an HTTP server and listen on port 3000 13 | app.listen(3000, () => { 14 | console.log('Server running on http://localhost:3000'); 15 | }); 16 | -------------------------------------------------------------------------------- /grpc-demo/test.js: -------------------------------------------------------------------------------- 1 | /** Test gRPC server */ 2 | const grpc = require('@grpc/grpc-js'); 3 | const protoLoader = require('@grpc/proto-loader'); 4 | 5 | // Load the protobuf files 6 | const packageDefinition = protoLoader.loadSync('protos/helloworld.proto', {}); 7 | const helloProto = grpc.loadPackageDefinition(packageDefinition).helloworld; 8 | 9 | // Create a new client instance 10 | const client = new helloProto.HelloWorld('localhost:50051', grpc.credentials.createInsecure()); 11 | 12 | // Define your request 13 | const request = {name: 'World'}; 14 | 15 | // Make a call to the 'SayHello' method 16 | client.sayHello(request, (err, response) => { 17 | if (err) { 18 | console.error('Error:', err); 19 | } else { 20 | // Print the response 21 | console.log('Response:', response); 22 | 23 | // Calculate the size of the response 24 | const responseSize = Buffer.byteLength(JSON.stringify(response), 'utf8'); 25 | console.log('Response size:', responseSize); 26 | } 27 | }); 28 | 29 | 30 | /** Test express server */ 31 | const fetch = require('node-fetch'); 32 | 33 | // Define your request 34 | const expressRequest = { 35 | method: 'POST', 36 | body: JSON.stringify({name: 'World'}), 37 | headers: { 'Content-Type': 'application/json' }, 38 | }; 39 | 40 | // Make a call to the '/sayHello' endpoint 41 | fetch('http://localhost:3000/sayHello', expressRequest) 42 | .then(res => res.json()) 43 | .then(response => { 44 | // Print the response 45 | console.log('Response:', response); 46 | 47 | // Calculate the size of the response 48 | const responseSize = Buffer.byteLength(JSON.stringify(response), 'utf8'); 49 | console.log('Response size:', responseSize); 50 | }) 51 | .catch(err => { 52 | console.error('Error:', err); 53 | }); 54 | 55 | -------------------------------------------------------------------------------- /howToUseNeetcode.md: -------------------------------------------------------------------------------- 1 | # How to use NeetCode Effectively (How to prepare for coding interviews) 2 | 3 | > Updated: Feb 2, 2025 4 | > Author: Navdeep Singh 5 | 6 | ## Prerequisites 7 | 8 | ### 1. Programming Language 9 | 10 | ![programming language](https://imagedelivery.net/CLfkmk9Wzy8_9HRyug4EVA/a6fa7949-1a3e-488c-0897-961f2619df00/public) 11 | 12 | You should be comfortable programming in at least one common language. This means you know the basic syntax, like loops, conditionals and functions. 13 | 14 | I recommend using the Python language for coding interviews. It's readable, has good error messages and is easy to learn. I personally learned Python only for coding interviews and it only took a few hours to learn the basics. 15 | 16 | Java and C++ are also good choices. Other common languages like JavaScript and Golang are also fine, but they have less built-in libraries and data structures. 17 | 18 | > In a real interview, if your programming language does not have a built-in data structure that you need, your interviewer will let you define your own interface / API for it. You probably won't have to actually implement it from scratch, unless that's part of the problem. 19 | 20 | If you're interested in learning Python, you may find these courses on NeetCode helpful: 21 | 22 | 23 | - [Python for Beginners](https://neetcode.io/problems/python-hello-world) - Learn the basics of Python with 80 interactive coding challenges. 24 | - [Python for Coding Interviews](https://neetcode.io/problems/python-sort-custom) - Learn how to use all of the built-in data structures and algorithms in Python. 25 | - [Python for Object-Oriented Programming](https://neetcode.io/problems/python-intro-to-classes) - Learn how to write object-oriented code in Python. 26 | 27 | ### 2. Data Structures and Algorithms 28 | 29 | ![data structures and algorithms](https://imagedelivery.net/CLfkmk9Wzy8_9HRyug4EVA/52463902-1eef-4184-bd57-75cfa1899200/public) 30 | 31 | You should be familiar with the most common data structures and algorithms. This includes: 32 | 33 | 1. Knowing the time and space complexity of each. 34 | 2. Knowing how to implement them. 35 | 3. *Most importantly*, knowing how to use them in your programming language of choice. 36 | 37 | Here are the **most common data structures** in no particular order: 38 | 39 | 1. Dynamic Arrays 40 | 2. Linked Lists 41 | 3. Stacks (Usually implemented with a dynamic array) 42 | 4. Queues 43 | 5. Binary Trees 44 | 6. Hash Maps / Sets 45 | 7. Heaps 46 | 8. Graphs 47 | 48 | Here are the **most common algorithms** in no particular order: 49 | 50 | 1. Binary Search 51 | 2. Binary Tree Traversals 52 | 3. Sorting (Merge Sort or Quick Sort) 53 | 4. Breadth-First Search (BFS) 54 | 5. Depth-First Search (DFS) 55 | 56 | You don't need to be familiar with *all* of these topics, but these are almost guaranteed to come up in coding interviews. Many colleges will touch on these topics, but coding interviews will require you to be intimately familiar with them. 57 | 58 | You may find these resources on NeetCode helpful for learning these topics: 59 | 60 | - [Data Structures and Algorithms for Beginners](https://neetcode.io/courses/dsa-for-beginners/0) course on NeetCode 61 | - [Practice Problems](https://neetcode.io/practice?tab=coreSkills) to implement common data structures and algorithms from scratch. 62 | 63 | ### 3. (Optional) Advanced Algorithms and Math 64 | 65 | There are many more advanced concepts and math topics that can come up in more difficult coding interviews. These include: 66 | 67 | 1. Dynamic Programming 68 | 2. Complex Graph Algorithms 69 | 3. Segment Trees 70 | 71 | Many hard problems will require you to know one or more of these concepts. Without them, you will have little chance of solving these problems on your own. 72 | 73 | These concepts take time and practice to learn. I recommend learning these concepts as you go. Learn them when you actually encounter them in practice problems, otherwise you will probably forget them anyway. 74 | 75 | Unless you're a competitive programmer willing to dedicate thousands of hours to practicing, it's impossible to know every advanced topic in-depth. Try to prioritize the more common & easier topics before moving to the more difficult ones. 76 | 77 | You may find these resources on NeetCode helpful for learning advanced topics: 78 | 79 | - [Advanced Algorithms](https://neetcode.io/courses/advanced-algorithms/0) course on NeetCode 80 | - [Practice Problems](https://neetcode.io/practice?tab=advanced) to implement common advanced algorithms from scratch. 81 | 82 | ## How to Practice 83 | 84 | ### 1. Just Start 85 | 86 | Just get started and don't overthink it. Find a reasonable list of problems and start solving them. 87 | 88 | Solve the first problem in the [NeetCode 150](https://neetcode.io/practice?tab=problems) or [NeetCode 250](https://neetcode.io/practice?tab=problems) list. And then keep going and never look back. 89 | 90 | Both of these lists are comprehensive and provide a good mix of easy and hard problems. 91 | 92 | You probably want to plan out the *best* way to study. That's reasonable. But don't overthink it. So many **people spend more time thinking about the best way to study than actually studying**. 93 | 94 | Just get started. What's the worst that can happen? Maybe you attempt a problem that's too difficult. That's fine. You can always come back to it later. 95 | 96 | ### 2. What if I can't solve a Problem? 97 | 98 | ![Stop Sign](https://imagedelivery.net/CLfkmk9Wzy8_9HRyug4EVA/1ac671c1-fe17-4041-b737-f68c38a9d500/public) 99 | 100 | Many people are discouraged when they can't solve a problem. 101 | 102 | But consider this: Many of these problems were first solved by professional mathematicians in the past. You're **not** expected to easily figure these out on your own. 103 | 104 | Each problem on NeetCode has a video solution and code solutions in several languages. Take advantage of them. It's not "cheating" to look at the solution. As long as you can understand the solution, you're doing great. 105 | 106 | **Do not**: 107 | 108 | * Copy and paste the solution. 109 | * Spend several hours trying to solve a problem you're stuck on. 110 | * Blindly memorize algorithms without understanding *why* they work. 111 | 112 | **Do**: 113 | 114 | * Attempt the problem on your own. 115 | * Try drawing out the problem on paper. 116 | * Look at the solution if you're not making progress after 15 - 20 minutes. 117 | * If you can't understand the solution within 45 - 60 minutes, try an easier problem. 118 | * Revisit problems that were challenging for you, resolve them from scratch. 119 | 120 | > Tip: The difficulty of some problems is not accurate. Often, there are "medium" problems that are actually more difficult than "hard" problems. Don't focus too much on the difficulty rating, just try to learn the algorithms. 121 | 122 | ### 3. How do I know I'm ready for FAANG+ interviews? 123 | 124 | ![Distribution](https://imagedelivery.net/CLfkmk9Wzy8_9HRyug4EVA/6f1878b9-f0f3-4082-7de6-c4d1c4969e00/public) 125 | 126 | You probably want to maximize your chances of passing the interview, right? So how do you decide when you are *done preparing and ready for the interview?* 127 | 128 | That's the thing. Technically you're never *done* preparing. You will never have a 100% chance of passing any given interview. Think of it more as a game of probability or a distribution. 129 | 130 | You might prepare enough that you can pass 50% of interviews, or 90% of interviews, but never 100%. 131 | 132 | A **good rule of thumb** is if you can solve most medium problems that you haven't seen before, within 20 to 25 minutes, you can probably pass most interviews. 133 | 134 | ### 4. Which topics are most important? 135 | 136 | If you have limited time, here are the most important topics to focus on: 137 | 138 | 1. Arrays 139 | 2. Hash Maps 140 | 3. Trees 141 | 4. Graphs 142 | 143 | 144 | The hard thing about these topics is that they are very open-ended. For example, arrays are simple, yet there are hundreds of algorithms that can be performed on them, like binary search or sliding window. 145 | 146 | Graphs are even more complex. Some problems may require a simple DFS, but others may require a complex algorithm like Dijkstra's or a topological sort. 147 | 148 | To solve this problem, I created the [NeetCode 150](https://neetcode.io/practice?tab=problems) and [NeetCode 250](https://neetcode.io/practice?tab=problems) lists. These lists touch upon the vast majority of the topics you will see in coding interviews. They are ordered in a way that each problem builds on the previous ones. 149 | 150 | You don't need to solve *every* problem in them, but the more you practice the higher your chances. If you're in a rush, you should prioritize the easy and medium problems in these lists. 151 | 152 | ### 5. Other Resources 153 | 154 | #### How I would learn DSA If I Could Start Over 155 | 156 |
160 | 169 |
170 | 171 | 172 | #### Mock Coding Interview with Meta Intern 173 | 174 |
178 | 187 |
188 | 189 | #### How I Failed the Google Coding Interview (And Lessons I Learned) 190 | 191 |
195 | 204 |
205 | -------------------------------------------------------------------------------- /mongodb.md: -------------------------------------------------------------------------------- 1 | # MongoDB Cheatsheet (Crashcourse) 2 | 3 | ## Setup 4 | 5 | ### Install MongoDB Community Edition 6 | https://www.mongodb.com/docs/manual/installation/ 7 | 8 | ### Register for MongoDB Atlas 9 | https://www.mongodb.com/cloud/atlas/register 10 | 11 | ## MongoDB Shell 12 | 13 | ### Connect to MongoDB Shell 14 | ```javascript 15 | mongosh // connects to mongodb://127.0.0.1:27017 by default 16 | mongo "mongodb+srv://cluster-name.abcde.mongodb.net/" --username // MongoDB Atlas 17 | ``` 18 | 19 | ### Basic Commands 20 | ```javascript 21 | show dbs // show databases 22 | use // use or create database 23 | show collections // show collections 24 | ``` 25 | 26 | ### Collections 27 | 28 | ```javascript 29 | db.createCollection("coll") // creates the collection `coll` 30 | db.coll.drop() // removes the collection `coll` 31 | ``` 32 | 33 | Create a collection with a `$jsonschema` validator 34 | ```javascript 35 | // Create collection with a $jsonschema 36 | db.createCollection("hosts", { 37 | validator: {$jsonSchema: { 38 | bsonType: "object", 39 | required: ["email"], // required fields 40 | properties: { 41 | // All possible fields 42 | phone: { 43 | bsonType: "string", 44 | description: "must be a string and is required" 45 | }, 46 | email: { 47 | bsonType: "string", 48 | pattern: "@mongodb\.com$", 49 | description: "must be a string and match the regular expression pattern" 50 | }, 51 | } 52 | }} 53 | }) 54 | ``` 55 | 56 | ### CRUD 57 | 58 | #### Create 59 | ```javascript 60 | db.coll.insertOne({name: "Navi", age: 25}) // insert one document 61 | db.coll.insertMany([{name: "Navi", age: 25}, {name: "Alice", age: 30}]) // insert many documents 62 | ``` 63 | 64 | #### Read 65 | ```javascript 66 | db.coll.count() // count all documents in 'coll' collection 67 | db.coll.count({name: "Navi"}) // count all documents with name "Navi" 68 | 69 | db.coll.find() // list all documents 70 | db.coll.find({name: "Navi"}) // list all documents with name "Navi" 71 | db.coll.find({name: "Navi", age: 25}).limit(1) // list all documents with name "Navi" and age 25, and return only one document. 72 | 73 | db.coll.find({name: "Navi"}).explain("executionStats") // find document and show execution stats 74 | ``` 75 | 76 | #### Update 77 | ```javascript 78 | db.coll.update({name: "Navi"}, {$set: {age: 26}}) // update all documents with name "Navi" and set age to 26 79 | db.coll.update({name: "Navi"}, {$inc: {age: 1}}) // update all documents with name "Navi" and increment age by 1 80 | 81 | db.coll.update({name: "Navi"}, {$unset: {age: 1}}) // update all documents with name "Navi" and set age to null 82 | db.coll.updateMany({age: {$exists: true}}, {$unset: {age: ""}}) // remove age field from all documents with age field 83 | 84 | ``` 85 | 86 | #### Delete 87 | ```javascript 88 | db.coll.deleteMany({name: "Navi"}) // remove all documents with name "Navi" 89 | db.coll.deleteOne({name: "Navi"}) // remove one document with name "Navi" 90 | ``` 91 | 92 | ### Aggregation 93 | 94 | #### Aggregation Pipeline 95 | 96 | ```javascript 97 | db.listingsAndReviews.aggregate([ 98 | { 99 | $match: { 100 | number_of_reviews: { $gte: 100 } // Listings with more than 100 reviews 101 | } 102 | }, 103 | { 104 | $group : { 105 | _id : "$property_type", // Group by property type 106 | count: { $sum : 1 }, // Total listings 107 | reviewCount: { $sum : "$number_of_reviews" }, // Total reviews 108 | avgPrice: { $avg : "$price" }, // Average price 109 | }, 110 | }, 111 | { 112 | $project: { 113 | _id: 1, 114 | count: 1, 115 | reviewCount: 1, 116 | avgPrice: { $ceil : "$avgPrice" } // Round up avgPrice 117 | } 118 | }, 119 | { 120 | $match: { 121 | reviewCount: { $gte: 10000 } // Listings by property with more than 10000 total reviews 122 | } 123 | }, 124 | { 125 | $sort : { 126 | count : -1, // Sort by count descending 127 | avgPrice: 1 // Sort by avgPrice ascending 128 | } 129 | } 130 | ]) 131 | ``` 132 | 133 | #### $lookup (Join) 134 | 135 | ```javascript 136 | db.accounts.aggregate([ 137 | { 138 | $lookup: 139 | { 140 | from: "transactions", // join with 'transactions' collection 141 | localField: "account_id", // field from the 'accounts' collection 142 | foreignField: "account_id", // field from the 'transactions' collection 143 | as: "customer_orders" // output array field 144 | } 145 | }, 146 | { 147 | $match: { $expr: { $lt: [ {$size: "$customer_orders"}, 5 ] } } // filter for documents where 'customer_orders' is < 5 148 | }, 149 | ]) 150 | ``` 151 | 152 | ### Indexes 153 | 154 | ```javascript 155 | db.coll.getIndexes() // list indexes 156 | db.coll.getIndexKeys() // list index keys 157 | 158 | db.coll.createIndex({"name": 1}) // create index 159 | db.coll.createIndex({"name": 1, "date": 1}) // create a compound index 160 | 161 | db.coll.dropIndex("name_1") // drop index 162 | ``` 163 | 164 | ### Complex Operators 165 | 166 | #### **Query and Projection Operators** 167 | 168 | - **`$eq`**: Matches values that are equal to a specified value. 169 | - **`$gt`**: Matches values that are greater than a specified value. 170 | - **`$gte`**: Matches values that are greater than or equal to a specified value. 171 | - **`$lt`**: Matches values that are less than a specified value. 172 | - **`$lte`**: Matches values that are less than or equal to a specified value. 173 | - **`$ne`**: Matches all values that are not equal to a specified value. 174 | - **`$in`**: Matches any value in the specified array. 175 | - **`$nin`**: Matches none of the values specified in an array. 176 | 177 | #### **Logical Operators** 178 | 179 | - **`$or`**: Joins query clauses with a logical OR, returns all documents that match the conditions of either clause. 180 | - **`$and`**: Joins query clauses with a logical AND, returns all documents that match the conditions of both clauses. 181 | - **`$not`**: Inverts the effect of a query expression and returns documents that do not match the query expression. 182 | - **`$nor`**: Joins query clauses with a logical NOR, returns all documents that fail to match both clauses. 183 | 184 | #### **Array Operators** 185 | 186 | - **`$all`**: Matches arrays that contain all elements specified in the query. 187 | - **`$elemMatch`**: Selects documents if element in the array field matches all the specified $elemMatch conditions. 188 | - **`$size`**: Selects documents if the array field is a specified size. 189 | 190 | #### **Update Operators** 191 | 192 | - **`$set`**: Sets the value of a field in a document. 193 | - **`$unset`**: Removes the specified field from a document. 194 | - **`$inc`**: Increments the value of the field by the specified amount. 195 | - **`$mul`**: Multiplies the value of the field by the specified amount. 196 | - **`$push`**: Appends a specified value to an array. 197 | - **`$pop`**: Removes the first or last element of an array. 198 | - **`$pull`**: Removes all array elements that match a specified query. 199 | 200 | #### **Aggregation Operators** 201 | 202 | - **`$match`**: Filters the documents to pass only documents that match the specified condition(s) to the next pipeline stage. 203 | - **`$group`**: Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. 204 | - **`$project`**: Passes along the documents with only the specified fields to the next stage in the pipeline. 205 | - **`$sort`**: Sorts all input documents and outputs them to the next stage in the specified sort order. 206 | - **`$limit`**: Passes the first n documents unmodified to the pipeline where n is the specified limit. 207 | 208 | ### ACID Compliance 209 | 210 | | ACID Property | MongoDB Implementation | 211 | | --- | --- | 212 | | Atomicity | MongoDB ensures atomicity at the single-document level, meaning changes to a single document are always atomic. Starting with version 4.0, MongoDB provides multi-document transactions and guarantees the atomicity of the transactions. | 213 | | Consistency | MongoDB uses schema validation, a feature that allows you to define the specific structure of documents in each MongoDB collection. If the document structure deviates from the defined schema, MongoDB will return an error. This is how MongoDB enforces its version of consistency, however, it's optional and less rigid than in traditional SQL databases. | 214 | | Isolation | MongoDB isolates write operations on a per-document level. By default, clients do not wait for acknowledgement of write operations. However, users can configure write concern to guarantee a desired level of isolation. Multi-document transactions in MongoDB are isolated across participating nodes for the duration of each transaction. | 215 | | Durability | MongoDB allows you to specify the level of durability when writing documents. You can choose to wait until the data is written to a certain number of servers, or even to the disk. This is configurable by setting the write concern when writing data. | 216 | 217 | ## References 218 | - https://www.mongodb.com/developer/products/mongodb/cheat-sheet/ 219 | -------------------------------------------------------------------------------- /python.md: -------------------------------------------------------------------------------- 1 | # Python Cheat Sheet 2 | 3 | 4 | > Updated: Jan 22, 2025 5 | > Author: Navdeep Singh 6 | 7 | This guide is a collection of Python code snippets that cover the basics of the language. It is intended to be a quick reference for anyone who is new to Python or needs a refresher. 8 | 9 | You may also find the following courses helpful: 10 | 11 | - [Python for Beginners](https://neetcode.io/problems/python-hello-world) - Learn the basics of Python with 80 interactive coding challenges. 12 | - [Python for Coding Interviews](https://neetcode.io/problems/python-sort-custom) - Learn how to use all of the built-in data structures and algorithms in Python. 13 | - [Python for Object-Oriented Programming](https://neetcode.io/problems/python-intro-to-classes) - Learn how to write object-oriented code in Python. 14 | 15 | ## Variables 16 | ```python 17 | # Variables are dynamicly typed 18 | n = 0 19 | print('n =', n) 20 | >>> n = 0 21 | 22 | n = "abc" 23 | print('n =', n) 24 | >>> n = abc 25 | 26 | # Multiple assignments 27 | n, m = 0, "abc" 28 | n, m, z = 0.125, "abc", False 29 | 30 | # Increment 31 | n = n + 1 # good 32 | n += 1 # good 33 | n++ # bad 34 | 35 | # None is null (absence of value) 36 | n = 4 37 | n = None 38 | print("n =", n) 39 | >>> n = None 40 | ``` 41 | 42 | ## If-statements 43 | ```python 44 | # If statements don't need parentheses 45 | # or curly braces. 46 | n = 1 47 | if n > 2: 48 | n -= 1 49 | elif n == 2: 50 | n *= 2 51 | else: 52 | n += 2 53 | 54 | # Parentheses needed for multi-line conditions. 55 | # and = && 56 | # or = || 57 | n, m = 1, 2 58 | if ((n > 2 and 59 | n != m) or n == m): 60 | n += 1 61 | ``` 62 | 63 | ## Loops 64 | ```python 65 | n = 5 66 | while n < 5: 67 | print(n) 68 | n += 1 69 | 70 | # Looping from i = 0 to i = 4 71 | for i in range(5): 72 | print(i) 73 | 74 | # Looping from i = 2 to i = 5 75 | for i in range(2, 6): 76 | print(i) 77 | 78 | # Looping from i = 5 to i = 2 79 | for i in range(5, 1, -1): 80 | print(i) 81 | ``` 82 | 83 | ## Math 84 | ```python 85 | # Division is decimal by default 86 | print(5 / 2) 87 | 88 | # Double slash rounds down 89 | print(5 // 2) 90 | 91 | # CAREFUL: most languages round towards 0 by default 92 | # So negative numbers will round down 93 | print(-3 // 2) 94 | 95 | # A workaround for rounding towards zero 96 | # is to use decimal division and then convert to int. 97 | print(int(-3 / 2)) 98 | 99 | 100 | # Modding is similar to most languages 101 | print(10 % 3) 102 | 103 | # Except for negative values 104 | print(-10 % 3) 105 | 106 | # To be consistent with other languages modulo 107 | import math 108 | from multiprocessing import heap 109 | print(math.fmod(-10, 3)) 110 | 111 | # More math helpers 112 | print(math.floor(3 / 2)) 113 | print(math.ceil(3 / 2)) 114 | print(math.sqrt(2)) 115 | print(math.pow(2, 3)) 116 | 117 | # Max / Min Int 118 | float("inf") 119 | float("-inf") 120 | 121 | # Python numbers are infinite so they never overflow 122 | print(math.pow(2, 200)) 123 | 124 | # But still less than infinity 125 | print(math.pow(2, 200) < float("inf")) 126 | ``` 127 | 128 | ## Arrays 129 | ```python 130 | # Arrays (called lists in python) 131 | arr = [1, 2, 3] 132 | print(arr) 133 | 134 | # Can be used as a stack 135 | arr.append(4) 136 | arr.append(5) 137 | print(arr) 138 | 139 | arr.pop() 140 | print(arr) 141 | 142 | arr.insert(1, 7) 143 | print(arr) 144 | 145 | arr[0] = 0 146 | arr[3] = 0 147 | print(arr) 148 | 149 | # Initialize arr of size n with default value of 1 150 | n = 5 151 | arr = [1] * n 152 | print(arr) 153 | print(len(arr)) 154 | 155 | # Careful: -1 is not out of bounds, it's the last value 156 | arr = [1, 2, 3] 157 | print(arr[-1]) 158 | 159 | # Indexing -2 is the second to last value, etc. 160 | print(arr[-2]) 161 | 162 | # Sublists (aka slicing) 163 | arr = [1, 2, 3, 4] 164 | print(arr[1:3]) 165 | 166 | # Similar to for-loop ranges, last index is non-inclusive 167 | print(arr[0:4]) 168 | 169 | # But no out of bounds error 170 | print(arr[0:10]) 171 | 172 | # Unpacking 173 | a, b, c = [1, 2, 3] 174 | print(a, b, c) 175 | 176 | # Be careful though 177 | # a, b = [1, 2, 3] 178 | 179 | # Loop through arrays 180 | nums = [1, 2, 3] 181 | 182 | # Using index 183 | for i in range(len(nums)): 184 | print(nums[i]) 185 | 186 | # Without index 187 | for n in nums: 188 | print(n) 189 | 190 | # With index and value 191 | for i, n in enumerate(nums): 192 | print(i, n) 193 | 194 | # Loop through multiple arrays simultaneously with unpacking 195 | nums1 = [1, 3, 5] 196 | nums2 = [2, 4, 6] 197 | for n1, n2 in zip(nums1, nums2): 198 | print(n1, n2) 199 | 200 | # Reverse 201 | nums = [1, 2, 3] 202 | nums.reverse() 203 | print(nums) 204 | 205 | # Sorting 206 | arr = [5, 4, 7, 3, 8] 207 | arr.sort() 208 | print(arr) 209 | 210 | arr.sort(reverse=True) 211 | print(arr) 212 | 213 | arr = ["bob", "alice", "jane", "doe"] 214 | arr.sort() 215 | print(arr) 216 | 217 | # Custom sort (by length of string) 218 | arr.sort(key=lambda x: len(x)) 219 | print(arr) 220 | 221 | 222 | # List comprehension 223 | arr = [i for i in range(5)] 224 | print(arr) 225 | 226 | # 2-D lists 227 | arr = [[0] * 4 for i in range(4)] 228 | print(arr) 229 | print(arr[0][0], arr[3][3]) 230 | 231 | # This won't work 232 | # arr = [[0] * 4] * 4 233 | ``` 234 | 235 | ## Strings 236 | ```python 237 | # Strings are similar to arrays 238 | s = "abc" 239 | print(s[0:2]) 240 | 241 | # But they are immutable 242 | # s[0] = "A" 243 | 244 | # So this creates a new string 245 | s += "def" 246 | print(s) 247 | 248 | # Valid numeric strings can be converted 249 | print(int("123") + int("123")) 250 | 251 | # And numbers can be converted to strings 252 | print(str(123) + str(123)) 253 | 254 | # In rare cases you may need the ASCII value of a char 255 | print(ord("a")) 256 | print(ord("b")) 257 | 258 | # Combine a list of strings (with an empty string delimitor) 259 | strings = ["ab", "cd", "ef"] 260 | print("".join(strings)) 261 | ``` 262 | 263 | ## Queues 264 | ```python 265 | # Queues (double ended queue) 266 | from collections import deque 267 | 268 | queue = deque() 269 | queue.append(1) 270 | queue.append(2) 271 | print(queue) 272 | 273 | queue.popleft() 274 | print(queue) 275 | 276 | queue.appendleft(1) 277 | print(queue) 278 | 279 | queue.pop() 280 | print(queue) 281 | ``` 282 | 283 | ## HashSets 284 | ```python 285 | # HashSet 286 | mySet = set() 287 | 288 | mySet.add(1) 289 | mySet.add(2) 290 | print(mySet) 291 | print(len(mySet)) 292 | 293 | print(1 in mySet) 294 | print(2 in mySet) 295 | print(3 in mySet) 296 | 297 | mySet.remove(2) 298 | print(2 in mySet) 299 | 300 | # list to set 301 | print(set([1, 2, 3])) 302 | 303 | # Set comprehension 304 | mySet = { i for i in range(5) } 305 | print(mySet) 306 | ``` 307 | 308 | # HashMaps 309 | ```python 310 | # HashMap (aka dict) 311 | myMap = {} 312 | myMap["alice"] = 88 313 | myMap["bob"] = 77 314 | print(myMap) 315 | print(len(myMap)) 316 | 317 | myMap["alice"] = 80 318 | print(myMap["alice"]) 319 | 320 | print("alice" in myMap) 321 | myMap.pop("alice") 322 | print("alice" in myMap) 323 | 324 | myMap = { "alice": 90, "bob": 70 } 325 | print(myMap) 326 | 327 | # Dict comprehension 328 | myMap = { i: 2*i for i in range(3) } 329 | print(myMap) 330 | 331 | # Looping through maps 332 | myMap = { "alice": 90, "bob": 70 } 333 | for key in myMap: 334 | print(key, myMap[key]) 335 | 336 | for val in myMap.values(): 337 | print(val) 338 | 339 | for key, val in myMap.items(): 340 | print(key, val) 341 | ``` 342 | 343 | ## Tuples 344 | ```python 345 | # Tuples are like arrays but immutable 346 | tup = (1, 2, 3) 347 | print(tup) 348 | print(tup[0]) 349 | print(tup[-1]) 350 | 351 | # Can't modify 352 | # tup[0] = 0 353 | 354 | # Can be used as key for hash map/set 355 | myMap = { (1,2): 3 } 356 | print(myMap[(1,2)]) 357 | 358 | mySet = set() 359 | mySet.add((1, 2)) 360 | print((1, 2) in mySet) 361 | 362 | # Lists can't be keys 363 | # myMap[[3, 4]] = 5 364 | ``` 365 | 366 | ## Heaps 367 | ```python 368 | import heapq 369 | 370 | # under the hood are arrays 371 | minHeap = [] 372 | heapq.heappush(minHeap, 3) 373 | heapq.heappush(minHeap, 2) 374 | heapq.heappush(minHeap, 4) 375 | 376 | # Min is always at index 0 377 | print(minHeap[0]) 378 | 379 | while len(minHeap): 380 | print(heapq.heappop(minHeap)) 381 | 382 | # No max heaps by default, work around is 383 | # to use min heap and multiply by -1 when push & pop. 384 | maxHeap = [] 385 | heapq.heappush(maxHeap, -3) 386 | heapq.heappush(maxHeap, -2) 387 | heapq.heappush(maxHeap, -4) 388 | 389 | # Max is always at index 0 390 | print(-1 * maxHeap[0]) 391 | 392 | while len(maxHeap): 393 | print(-1 * heapq.heappop(maxHeap)) 394 | 395 | # Build heap from initial values 396 | arr = [2, 1, 8, 4, 5] 397 | heapq.heapify(arr) 398 | while arr: 399 | print(heapq.heappop(arr)) 400 | ``` 401 | 402 | ## Functions 403 | ```python 404 | def myFunc(n, m): 405 | return n * m 406 | 407 | print(myFunc(3, 4)) 408 | 409 | # Nested functions have access to outer variables 410 | def outer(a, b): 411 | c = "c" 412 | 413 | def inner(): 414 | return a + b + c 415 | return inner() 416 | 417 | print(outer("a", "b")) 418 | 419 | # Can modify objects but not reassign 420 | # unless using nonlocal keyword 421 | def double(arr, val): 422 | def helper(): 423 | # Modifying array works 424 | for i, n in enumerate(arr): 425 | arr[i] *= 2 426 | 427 | # will only modify val in the helper scope 428 | # val *= 2 429 | 430 | # this will modify val outside helper scope 431 | nonlocal val 432 | val *= 2 433 | helper() 434 | print(arr, val) 435 | 436 | nums = [1, 2] 437 | val = 3 438 | double(nums, val) 439 | ``` 440 | ## Classes 441 | ```python 442 | class MyClass: 443 | # Constructor 444 | def __init__(self, nums): 445 | # Create member variables 446 | self.nums = nums 447 | self.size = len(nums) 448 | 449 | # self key word required as param 450 | def getLength(self): 451 | return self.size 452 | 453 | def getDoubleLength(self): 454 | return 2 * self.getLength() 455 | 456 | myObj = MyClass([1, 2, 3]) 457 | print(myObj.getLength()) 458 | print(myObj.getDoubleLength()) 459 | ``` 460 | -------------------------------------------------------------------------------- /sortingAlgorithms.md: -------------------------------------------------------------------------------- 1 | # Sorting Algorithm Cheat Sheet 2 | 3 | > Updated: Jan 22, 2025 4 | > Author: Navdeep Singh 5 | 6 | ## 1. Insertion Sort 7 | 8 | Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. 9 | 10 | It sorts the array by inserting each element into its correct position. At any point, the left side of the array is sorted while the right side is unsorted. We choose the first element in the unsorted array and insert it into the sorted array in the correct position. We then repeat this process for the next element in the unsorted array. 11 | 12 | It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. 13 | 14 | ![](https://nc-gifs.pages.dev/insertion-sort.gif) 15 | 16 | ::tabs-start 17 | 18 | ```python 19 | def insertion_sort(arr): 20 | for i in range(1, len(arr)): 21 | key = arr[i] 22 | j = i - 1 23 | while j >= 0 and arr[j] > key: 24 | arr[j + 1] = arr[j] 25 | j -= 1 26 | arr[j + 1] = key 27 | return arr 28 | ``` 29 | 30 | 31 | ```java 32 | public class InsertionSort { 33 | public static void insertionSort(int[] arr) { 34 | for (int i = 1; i < arr.length; i++) { 35 | int key = arr[i]; 36 | int j = i - 1; 37 | while (j >= 0 && arr[j] > key) { 38 | arr[j + 1] = arr[j]; 39 | j--; 40 | } 41 | arr[j + 1] = key; 42 | } 43 | } 44 | } 45 | ``` 46 | 47 | 48 | ```cpp 49 | void insertionSort(int arr[], int n) { 50 | for (int i = 1; i < n; i++) { 51 | int key = arr[i]; 52 | int j = i - 1; 53 | while (j >= 0 && arr[j] > key) { 54 | arr[j + 1] = arr[j]; 55 | j--; 56 | } 57 | arr[j + 1] = key; 58 | } 59 | } 60 | ``` 61 | 62 | 63 | ```javascript 64 | function insertionSort(arr) { 65 | for (let i = 1; i < arr.length; i++) { 66 | let key = arr[i]; 67 | let j = i - 1; 68 | while (j >= 0 && arr[j] > key) { 69 | arr[j + 1] = arr[j]; 70 | j--; 71 | } 72 | arr[j + 1] = key; 73 | } 74 | return arr; 75 | } 76 | ``` 77 | 78 | ::tabs-end 79 | 80 | Time Complexity: $O(n^2)$ 81 | Space Complexity: $O(1)$ 82 | 83 | ## 2. Merge Sort 84 | 85 | Merge sort is a divide and conquer algorithm that divides the input array into two halves, calls itself for the two halves, and then merges the two sorted halves. 86 | 87 | ![](https://nc-gifs.pages.dev/merge-sort.gif) 88 | 89 | ::tabs-start 90 | 91 | ```python 92 | def merge_sort(arr): 93 | if len(arr) <= 1: 94 | return arr 95 | 96 | mid = len(arr) // 2 97 | left = merge_sort(arr[:mid]) 98 | right = merge_sort(arr[mid:]) 99 | 100 | return merge(left, right) 101 | 102 | def merge(left, right): 103 | result = [] 104 | i = j = 0 105 | 106 | while i < len(left) and j < len(right): 107 | if left[i] <= right[j]: 108 | result.append(left[i]) 109 | i += 1 110 | else: 111 | result.append(right[j]) 112 | j += 1 113 | 114 | result.extend(left[i:]) 115 | result.extend(right[j:]) 116 | return result 117 | ``` 118 | 119 | 120 | ```java 121 | public class MergeSort { 122 | public static void mergeSort(int[] arr, int left, int right) { 123 | if (left < right) { 124 | int mid = (left + right) / 2; 125 | mergeSort(arr, left, mid); 126 | mergeSort(arr, mid + 1, right); 127 | merge(arr, left, mid, right); 128 | } 129 | } 130 | 131 | private static void merge(int[] arr, int left, int mid, int right) { 132 | int n1 = mid - left + 1; 133 | int n2 = right - mid; 134 | 135 | int[] L = new int[n1]; 136 | int[] R = new int[n2]; 137 | 138 | for (int i = 0; i < n1; i++) 139 | L[i] = arr[left + i]; 140 | for (int j = 0; j < n2; j++) 141 | R[j] = arr[mid + 1 + j]; 142 | 143 | int i = 0, j = 0, k = left; 144 | 145 | while (i < n1 && j < n2) { 146 | if (L[i] <= R[j]) { 147 | arr[k] = L[i]; 148 | i++; 149 | } else { 150 | arr[k] = R[j]; 151 | j++; 152 | } 153 | k++; 154 | } 155 | 156 | while (i < n1) { 157 | arr[k] = L[i]; 158 | i++; 159 | k++; 160 | } 161 | 162 | while (j < n2) { 163 | arr[k] = R[j]; 164 | j++; 165 | k++; 166 | } 167 | } 168 | } 169 | ``` 170 | 171 | 172 | ```cpp 173 | void merge(int arr[], int left, int mid, int right) { 174 | int n1 = mid - left + 1; 175 | int n2 = right - mid; 176 | 177 | int* L = new int[n1]; 178 | int* R = new int[n2]; 179 | 180 | for (int i = 0; i < n1; i++) 181 | L[i] = arr[left + i]; 182 | for (int j = 0; j < n2; j++) 183 | R[j] = arr[mid + 1 + j]; 184 | 185 | int i = 0, j = 0, k = left; 186 | 187 | while (i < n1 && j < n2) { 188 | if (L[i] <= R[j]) { 189 | arr[k] = L[i]; 190 | i++; 191 | } else { 192 | arr[k] = R[j]; 193 | j++; 194 | } 195 | k++; 196 | } 197 | 198 | while (i < n1) { 199 | arr[k] = L[i]; 200 | i++; 201 | k++; 202 | } 203 | 204 | while (j < n2) { 205 | arr[k] = R[j]; 206 | j++; 207 | k++; 208 | } 209 | 210 | delete[] L; 211 | delete[] R; 212 | } 213 | 214 | void mergeSort(int arr[], int left, int right) { 215 | if (left < right) { 216 | int mid = (left + right) / 2; 217 | mergeSort(arr, left, mid); 218 | mergeSort(arr, mid + 1, right); 219 | merge(arr, left, mid, right); 220 | } 221 | } 222 | ``` 223 | 224 | 225 | ```javascript 226 | function mergeSort(arr) { 227 | if (arr.length <= 1) return arr; 228 | 229 | const mid = Math.floor(arr.length / 2); 230 | const left = mergeSort(arr.slice(0, mid)); 231 | const right = mergeSort(arr.slice(mid)); 232 | 233 | return merge(left, right); 234 | } 235 | 236 | function merge(left, right) { 237 | const result = []; 238 | let i = 0, j = 0; 239 | 240 | while (i < left.length && j < right.length) { 241 | if (left[i] <= right[j]) { 242 | result.push(left[i]); 243 | i++; 244 | } else { 245 | result.push(right[j]); 246 | j++; 247 | } 248 | } 249 | 250 | return result.concat(left.slice(i)).concat(right.slice(j)); 251 | } 252 | ``` 253 | 254 | ::tabs-end 255 | 256 | Time Complexity: $O(n log n)$ 257 | Space Complexity: $O(n)$ 258 | 259 | 260 | ## 3. Quick Sort 261 | 262 | Quick sort is a divide and conquer algorithm that picks an element as pivot and partitions the given array around the picked pivot. 263 | 264 | Unlike merge sort, quick sort is not a stable sort. This means that the input order of equal elements in the sorted output may not be preserved. 265 | 266 | ![](https://nc-gifs.pages.dev/quick-sort.gif) 267 | 268 | 269 | ::tabs-start 270 | 271 | ```python 272 | def quick_sort(arr): 273 | if len(arr) <= 1: 274 | return arr 275 | 276 | pivot = arr[len(arr) // 2] 277 | left = [x for x in arr if x < pivot] 278 | middle = [x for x in arr if x == pivot] 279 | right = [x for x in arr if x > pivot] 280 | 281 | return quick_sort(left) + middle + quick_sort(right) 282 | ``` 283 | 284 | 285 | ```java 286 | public class QuickSort { 287 | public static void quickSort(int[] arr, int low, int high) { 288 | if (low < high) { 289 | int pi = partition(arr, low, high); 290 | quickSort(arr, low, pi - 1); 291 | quickSort(arr, pi + 1, high); 292 | } 293 | } 294 | 295 | private static int partition(int[] arr, int low, int high) { 296 | int pivot = arr[high]; 297 | int i = low - 1; 298 | 299 | for (int j = low; j < high; j++) { 300 | if (arr[j] < pivot) { 301 | i++; 302 | int temp = arr[i]; 303 | arr[i] = arr[j]; 304 | arr[j] = temp; 305 | } 306 | } 307 | 308 | int temp = arr[i + 1]; 309 | arr[i + 1] = arr[high]; 310 | arr[high] = temp; 311 | 312 | return i + 1; 313 | } 314 | } 315 | ``` 316 | 317 | 318 | ```cpp 319 | int partition(int arr[], int low, int high) { 320 | int pivot = arr[high]; 321 | int i = low - 1; 322 | 323 | for (int j = low; j < high; j++) { 324 | if (arr[j] < pivot) { 325 | i++; 326 | std::swap(arr[i], arr[j]); 327 | } 328 | } 329 | 330 | std::swap(arr[i + 1], arr[high]); 331 | return i + 1; 332 | } 333 | 334 | void quickSort(int arr[], int low, int high) { 335 | if (low < high) { 336 | int pi = partition(arr, low, high); 337 | quickSort(arr, low, pi - 1); 338 | quickSort(arr, pi + 1, high); 339 | } 340 | } 341 | ``` 342 | 343 | 344 | ```javascript 345 | function quickSort(arr) { 346 | if (arr.length <= 1) return arr; 347 | 348 | const pivot = arr[Math.floor(arr.length / 2)]; 349 | const left = arr.filter(x => x < pivot); 350 | const middle = arr.filter(x => x === pivot); 351 | const right = arr.filter(x => x > pivot); 352 | 353 | return [...quickSort(left), ...middle, ...quickSort(right)]; 354 | } 355 | ``` 356 | 357 | ::tabs-end 358 | 359 | Time Complexity: $O(n log n)$ 360 | Space Complexity: $O(log n)$ 361 | 362 | ## 4. Bucket Sort 363 | 364 | Bucket sort is a sorting algorithm that distributes the elements of an array into several groups, called buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. 365 | 366 | ![](https://nc-gifs.pages.dev/bucket-sort.gif) 367 | 368 | ::tabs-start 369 | 370 | ```python 371 | def bucket_sort(arr): 372 | if not arr: 373 | return arr 374 | 375 | # Find range of values 376 | max_val, min_val = max(arr), min(arr) 377 | 378 | # Create buckets 379 | bucket_range = (max_val - min_val) / len(arr) 380 | buckets = [[] for _ in range(len(arr) + 1)] 381 | 382 | # Distribute input array values into buckets 383 | for i in arr: 384 | if i == max_val: 385 | bucket_idx = len(arr) - 1 386 | else: 387 | bucket_idx = int((i - min_val) / bucket_range) 388 | buckets[bucket_idx].append(i) 389 | 390 | # Sort individual buckets 391 | for bucket in buckets: 392 | bucket.sort() 393 | 394 | # Concatenate all buckets into final array 395 | result = [] 396 | for bucket in buckets: 397 | result.extend(bucket) 398 | 399 | return result 400 | ``` 401 | 402 | 403 | ```java 404 | public class BucketSort { 405 | public static void bucketSort(float[] arr) { 406 | if (arr == null || arr.length <= 0) 407 | return; 408 | 409 | // Create buckets 410 | @SuppressWarnings("unchecked") 411 | ArrayList[] buckets = new ArrayList[arr.length]; 412 | 413 | for (int i = 0; i < arr.length; i++) 414 | buckets[i] = new ArrayList(); 415 | 416 | // Distribute input array values into buckets 417 | for (float item : arr) { 418 | int bucketIndex = (int) (item * arr.length); 419 | buckets[bucketIndex].add(item); 420 | } 421 | 422 | // Sort individual buckets 423 | for (ArrayList bucket : buckets) { 424 | Collections.sort(bucket); 425 | } 426 | 427 | // Concatenate all buckets into final array 428 | int index = 0; 429 | for (ArrayList bucket : buckets) { 430 | for (float item : bucket) { 431 | arr[index++] = item; 432 | } 433 | } 434 | } 435 | } 436 | ``` 437 | 438 | 439 | ```cpp 440 | void bucketSort(float arr[], int n) { 441 | if (n <= 0) return; 442 | 443 | // Create buckets 444 | vector> buckets(n); 445 | 446 | // Distribute input array values into buckets 447 | for (int i = 0; i < n; i++) { 448 | int bucketIndex = n * arr[i]; 449 | buckets[bucketIndex].push_back(arr[i]); 450 | } 451 | 452 | // Sort individual buckets 453 | for (int i = 0; i < n; i++) { 454 | sort(buckets[i].begin(), buckets[i].end()); 455 | } 456 | 457 | // Concatenate all buckets into final array 458 | int index = 0; 459 | for (int i = 0; i < n; i++) { 460 | for (int j = 0; j < buckets[i].size(); j++) { 461 | arr[index++] = buckets[i][j]; 462 | } 463 | } 464 | } 465 | ``` 466 | 467 | 468 | ```javascript 469 | function bucketSort(arr) { 470 | if (arr.length === 0) return arr; 471 | 472 | // Find range of values 473 | let max = Math.max(...arr); 474 | let min = Math.min(...arr); 475 | 476 | // Create buckets 477 | let bucketCount = arr.length; 478 | let buckets = new Array(bucketCount).fill().map(() => []); 479 | let bucketRange = (max - min) / (bucketCount - 1); 480 | 481 | // Distribute input array values into buckets 482 | for (let num of arr) { 483 | if (num === max) { 484 | buckets[bucketCount - 1].push(num); 485 | } else { 486 | let bucketIndex = Math.floor((num - min) / bucketRange); 487 | buckets[bucketIndex].push(num); 488 | } 489 | } 490 | 491 | // Sort individual buckets 492 | buckets = buckets.map(bucket => bucket.sort((a, b) => a - b)); 493 | 494 | // Concatenate all buckets into final array 495 | return [].concat(...buckets); 496 | } 497 | ``` 498 | 499 | ::tabs-end 500 | 501 | Time Complexity: $O(n)$ 502 | Space Complexity: $O(n + k)$, where $k$ is the number of buckets 503 | -------------------------------------------------------------------------------- /youtubeDesignDoc.md: -------------------------------------------------------------------------------- 1 | # YouTube Skeleton Clone Design 2 | 3 | ## Introduction 4 | 5 | This document designs a simplified YouTube clone, which I implemented within my [Full Stack Development course](https://neetcode.io/courses/full-stack-dev/0). 6 | 7 | The goal of this project is *not* to build a 1 to 1 clone of YouTube, but rather to build a rough skeleton where the core functionality of YouTube is implemented. 8 | 9 | We are focused on keeping the design as simple as possible, while still addressing some scalability tradeoffs. We are focused on learning, not building a production ready system. 10 | 11 | ## Background 12 | 13 | YouTube is a video sharing platform that allows users to upload, view, rate, share, and comment on videos. 14 | 15 | The scope of YouTube is very large, such that even "trivial" features like rating and commenting on videos are actually quite complex at this scale (1B+ daily active users). For this reason, we will be focusing mostly on uploading videos, and a bit on viewing videos. 16 | 17 | ## Requirements 18 | 19 | * Users can sign in/out using their Google account 20 | * Users can upload videos while signed in 21 | * Videos should be transcoded to multiple formats (e.g. 360p, 720p) 22 | * Users can view a list of uploaded videos (signed in or not) 23 | * Users can view individual videos (signed in or not) 24 | 25 | ## High Level Design 26 | 27 | ![diagram](https://imagedelivery.net/CLfkmk9Wzy8_9HRyug4EVA/2d33be5f-6a51-4475-6975-7350d9d3d700/public) 28 | > The high level architecture of the app, specifically the cloud services we will use. 29 | 30 | ### **Video Storage (Cloud Storage)** 31 | 32 | Google Cloud Storage will be used to host the raw and processed videos. This is a simple, scalable, and cost effective solution for storing and serving large files. 33 | 34 | ### **Video Upload Events (Cloud Pub/Sub)** 35 | 36 | When a video is uploaded, we will publish a message to a Cloud Pub/Sub topic. This will allow us to add a durability layer for video upload events and process videos asynchronously. 37 | 38 | ### **Video Processing Workers (Cloud Run)** 39 | 40 | When a video upload event is published, a video processing worker will receive a message from Pub/Sub and transcode the video. For transcoding the video we will use [ffmpeg](https://ffmpeg.org/), which is a popular open source tool for video processing and it's widely used in industry (including at YouTube). 41 | 42 | The nature of video processing can lead to inconsistent workloads, so we will use Cloud Run to scale up and down as needed. Processed videos will be uploaded back to Cloud Storage. 43 | 44 | ### **Video Metadata (Firestore)** 45 | 46 | After a video is processed, we will store the metadata in Firestore. This will allow us to display processed videos in the web client along with other relevant info (e.g. title, description, etc). 47 | 48 | ### **Video API (Firebase Functions)** 49 | 50 | We will use Firebase Functions to build a simple API that will allow users to upload videos and retrieve video metadata. This can easily be extended to support additional Create, Read, Update, Delete (CRUD) operations. 51 | 52 | 53 | ### **Web Client (Next.js / Cloud Run)** 54 | 55 | We will use Next.js to build a simple web client that will allow users to sign in and upload videos. The web client will be hosted on Cloud Run. 56 | 57 | ### **Authentication (Firebase Auth)** 58 | 59 | We will use Firebase Auth to handle user authentication. This will allow us to easily integrate with Google Sign In. 60 | 61 | ## Detailed Design 62 | 63 | ### **1. User Sign Up** 64 | 65 | Users can sign up using their Google account and this easily handled by Firebase Auth. A user record will be created including a unique auto-generated ID for the user, as well as the user's email address. 66 | 67 | For us to include additional info about the user we will create a Firestore document for each user, which will be apart of the `users` collection. This will allow us to store additional info about the user (e.g. name, profile picture, etc). 68 | 69 | Firebase Auth is mainly integrated into client code, which in our case will be within our Next.js app. While it's possible to trigger a user document creation directly from the client (after a new user signs up), this approach has some error prone edge cases. 70 | 71 | What if there is an network issue or the user's browser crashes right after the user signs up but *before* the user document is created? 72 | 73 | Fortunately, Firebase Auth provides [triggers](https://firebase.google.com/docs/functions/auth-events) so that we don't have to rely on the client for this operation. We can just trigger a Firebase Function (i.e. a server-side endpoint) to create the user document whenever a new user is created. 74 | 75 | ### **2. Video Upload** 76 | 77 | Ideally, we should only allow authenticated users to upload videos. This will allow us to associate the uploaded video with the user who uploaded it. In the future this could also allow us to enforce quotas on video uploads (e.g. 10 videos per day). 78 | 79 | While we could allow users to upload videos directly to a server we manage ourselves, it's more simple to use a service like Google Cloud Storage, which is specifically designed for arbitrarily large files like videos. 80 | 81 | But to prevent unauthorized users from uploading videos, we will generate a [signed URL](https://cloud.google.com/storage/docs/access-control/signed-urls) that will allow the user to upload a video directly to Cloud Storage. We will implement this in a public Firebase Function, but this way we can easily ensure the user is authenticated before generating the URL. 82 | 83 | > Note: We will invoke this function only *after* the user has specificed which video they want to upload. This is because we need to know the extension of the video file before we can generate the signed URL. 84 | 85 | The signed URL can be used directly from the client to upload a video to our private Cloud Storage bucket for raw videos. 86 | 87 | ### **3. Video Processing** 88 | 89 | We'd like to process videos as soon as they come in, but it's possible that we could receive a large number of uploads at once which we can't immediately process. To solve this problem we will introduce a message queue to our system - Cloud Pub/Sub. 90 | 91 | This provides many benefits: 92 | 93 | 1. When a video is uploaded to Cloud Storage, we can publish a message to a Pub/Sub topic. This will allow us to decouple the video upload from the video processing. 94 | 2. We will use a Pub/Sub subscriptions to *[push](https://cloud.google.com/pubsub/docs/push)* messages to our video processing workers. In the future we can add additional subscriptions to fan-out these messages, e.g. for analytics. 95 | 3. If the workers don't have enough capacity to process all the messages, Pub/Sub will automatically buffer the messages for us. This will allow us to scale our workers up and down as needed. 96 | 97 | 98 | After a video is processed, we will upload it to a public Cloud Storage bucket. We will also store the video metadata in Firestore, including the video's processing status. This will allow us to display the processed videos in the web client. 99 | 100 | There are some noteworthy limitations with this approach, such as: 101 | 102 | * A Cloud Run request has a max timeout of 3600 seconds 103 | * Pub/Sub will redeliver a message after at most 600 seconds, closing the previous HTTP connection 104 | * We don't check for illegal content within videos 105 | 106 | I won't discuss these in-depth here, but see the next section for more details. 107 | 108 | ## Limitations & Future Work 109 | 110 | Please see the [limitations](http://neetcode.io/courses/full-stack-dev/21) section for a detailed list of limitations and potential future tasks. 111 | 112 | ## References 113 | 114 | * Firebase Auth: https://firebase.google.com/docs/auth 115 | * Cloud Storage Signed URLs: https://cloud.google.com/storage/docs/access-control/signed-urls 116 | * Pub/Sub Push subscriptions: https://cloud.google.com/pubsub/docs/push 117 | * Using Pub/Sub with Cloud Storage: https://cloud.google.com/storage/docs/pubsub-notifications 118 | * Using Pub/Sub with Cloud Run: https://cloud.google.com/run/docs/tutorials/pubsub 119 | --------------------------------------------------------------------------------