├── README.md ├── examples └── wallet-watcher │ ├── favicon.png │ ├── index.html │ ├── main.js │ └── mwck ├── package-lock.json ├── package.json ├── src ├── address.ts ├── api.ts ├── index.ts ├── interfaces.ts ├── wallet.ts └── websocket.ts ├── tsconfig.json └── webpack.config.js /README.md: -------------------------------------------------------------------------------- 1 | # Mempool Wallet Connector Kit 2 | 3 | *(**work in progress** - relies on the multi-address tracking feature from https://github.com/mempool/mempool/pull/4137)* 4 | 5 | A lightweight utility library for efficiently syncing Bitcoin wallet history from an instance of The Mempool Open Source Project® backend. 6 | 7 | Mwck uses websocket push notifications to discover new address transaction events, eliminating the need to constantly poll the REST API. 8 | 9 | ## Quick start 10 | 11 | ```typescript 12 | const mwck = require('mwck'); 13 | const wallet = new mwck.MempoolWallet({ 14 | hostname: 'mempool.space' 15 | }); 16 | wallet.connect(); 17 | 18 | wallet.subscribe('addressReady', ({ address, state }) => { 19 | // finished loading address transactions 20 | }); 21 | 22 | wallet.subscribe('txEvent', ({event, address, tx}) => { 23 | switch (event) { 24 | 'added': { 25 | // discovered a new transaction related to this address 26 | } break; 27 | 28 | 'confirmed': { 29 | // a transaction related to this address was included in a block 30 | } break; 31 | 32 | 'removed': { 33 | // a transaction related to this address was dropped from the mempool 34 | } break; 35 | } 36 | }); 37 | 38 | wallet.trackAddresses([ 39 | 'bc1p...xyz', 40 | '3AB...123' 41 | ]); 42 | ``` 43 | 44 | ## API 45 | 46 | ### `MempoolWallet.connect()` (async) 47 | 48 | Starts the websocket connection to the configured Mempool server. 49 | 50 | Regular ping/pong messages are sent to maintain the connection, and the websocket will attempt to automatically recover from interruptions. 51 | 52 | ### `MempoolWallet.disconnect()` 53 | 54 | Disconnect the websocket until `connect()` is called again 55 | 56 | ### `MempoolWallet.subscribe(event: WalletEvent, callback)` 57 | 58 | Subscribe to event notifications. 59 | 60 | When an event of the requested type occurs, the provided callback is invoked. 61 | 62 | See [Events](#Events) for a list of valid event topics and callback signatures. 63 | 64 | ### `MempoolWallet.getAddressState(address: string)` 65 | 66 | Returns an `AddressState` object representing the current state of an address. 67 | 68 | If the address is invalid or not being tracked, returns null. 69 | 70 | ### `MempoolWallet.getWalletState(): WalletState` 71 | 72 | Returns a `WalletState` object representing the state of all currently tracked addresses and combined balances for the whole wallet. 73 | 74 | ### `MempoolWallet.restore(state: WalletState)` (async) 75 | 76 | Restores the state of a wallet from a snapshot previously obtained from `getWalletState()`. 77 | 78 | Useful for persisting a session across restarts/refreshes, or switching between different wallets. 79 | 80 | ### `MempoolWallet.async trackAddresses(addresses: string[])` (async) 81 | 82 | Adds the list of addresses to the wallet, and attempts to sync their transaction history. 83 | 84 | Returns once all new addresses are in sync, or immediately if the websocket is offline. 85 | 86 | ### `MempoolWallet.untrackAddresses(addresses: string[])` 87 | 88 | Removes the addresses from the wallet, unloads related state, and stops watching for new transaction activity involving these addresses. 89 | 90 | ### `MempoolWallet.destroy()` 91 | 92 | Call before discarding the `MempoolWallet` object to disconnect the websocket and clean up event handlers etc. 93 | 94 | ## Events 95 | 96 | The `MempoolWallet` class can either be used synchronously by fetching snapshots of address or wallet state, or via an observer-style subscription model. 97 | 98 | Subscriptions are supported for the following event types: 99 | 100 | ### `wsConnected` 101 | Emitted when the websocket succeeds in connecting (or reconnecting) to the configured Mempool server. 102 | 103 | Callback takes no arguments 104 | 105 | ### `wsDisconnected` 106 | Emitted when the websocket loses connection 107 | 108 | Callback takes no arguments 109 | 110 | ### `addressReady` 111 | Emitted after the wallet finishes loading transaction history, and a tracked address is now in sync with the server. 112 | 113 | Callback invoked with an argument of the form 114 | ```typescript 115 | { 116 | address: string, 117 | state: AddressState, 118 | } 119 | ``` 120 | 121 | ### `txAdded` 122 | Emitted every time a new transaction related to a tracked address is received. 123 | 124 | Callback invoked with an argument of the form 125 | ```typescript 126 | { 127 | address: string, 128 | tx: Transaction, 129 | } 130 | ``` 131 | 132 | ### `txConfirmed` 133 | Emitted every time a transaction related to a tracked address is found to be confirmed in a mined block. 134 | 135 | Callback invoked with an argument of the form 136 | ```typescript 137 | { 138 | address: string, 139 | tx: Transaction, 140 | } 141 | ``` 142 | 143 | ### `txRemoved` 144 | Emitted every time a transaction related to a tracked address is dropped from the mempool. 145 | 146 | Callback invoked with an argument of the form 147 | ```typescript 148 | { 149 | address: string, 150 | tx: Transaction, 151 | } 152 | ``` 153 | 154 | ### `txEvent` 155 | Emitted for all of the above `tx...` events. 156 | 157 | Callback invoked with an argument of the form 158 | ```typescript 159 | { 160 | event: 'added' | 'confirmed' | 'removed', 161 | address: string, 162 | tx: Transaction, 163 | } 164 | ``` 165 | 166 | ## Types/Interfaces 167 | 168 | Check `src/interfaces.ts` for the structure of return types and arguments. -------------------------------------------------------------------------------- /examples/wallet-watcher/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mempool/mwck-js/82cef6097c4c4761430e67cf2977aabfbf84f2b7/examples/wallet-watcher/favicon.png -------------------------------------------------------------------------------- /examples/wallet-watcher/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mempool Wallet Watcher 6 | 7 | 8 | 9 | 70 | 71 | 72 |

👀 Mempool Wallet Watcher 👀

73 | 74 | 78 | 79 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /examples/wallet-watcher/main.js: -------------------------------------------------------------------------------- 1 | const { MempoolWallet } = Mwck; 2 | 3 | const wallet = new MempoolWallet({ 4 | hostname: 'localhost:4200', 5 | secure: false, 6 | }); 7 | window.wallet = wallet; 8 | 9 | const addressMap = {}; 10 | const addressList = []; 11 | const regexAddress = /^([a-km-zA-HJ-NP-Z1-9]{26,35}|[a-km-zA-HJ-NP-Z1-9]{80}|[A-z]{2,5}1[a-zA-HJ-NP-Z0-9]{39,59}|04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64})$/; 12 | const addressInput = document.getElementById('addressInput'); 13 | 14 | wallet.subscribe('addressReady', ({ address, state }) => { 15 | updateTableRow(address); 16 | }); 17 | 18 | wallet.subscribe('txEvent', ({event, address, tx}) => { 19 | updateTableRow(address); 20 | }); 21 | 22 | wallet.connect(); 23 | 24 | function trackAddress(address) { 25 | if (regexAddress.test(address)) { 26 | if (!addressMap[address]) { 27 | addressMap[address] = true; 28 | addTableRow(address); 29 | addressList.push(address); 30 | wallet.trackAddresses([address]); 31 | } 32 | return true; 33 | } else { 34 | alert(`${address} is not a valid bitcoin address!`); 35 | return false; 36 | } 37 | } 38 | 39 | function onTrackAddress(event) { 40 | const address = addressInput.value 41 | if (trackAddress(address)) { 42 | addressInput.value = ''; 43 | } 44 | } 45 | 46 | function addTableRow(address) { 47 | const table = document.getElementById('addressTable'); 48 | if (addressList.length === 0) { 49 | table.classList.remove('hidden'); 50 | } 51 | const newRow = document.createElement('tr'); 52 | const newCell = document.createElement('td'); 53 | newCell.textContent = address; 54 | newRow.appendChild(newCell); 55 | for (let i = 0; i < 3; i++) { 56 | newRow.appendChild(document.createElement('td')); 57 | } 58 | table.querySelector('tbody').appendChild(newRow); 59 | } 60 | 61 | function updateTableRow(address) { 62 | const table = document.getElementById('addressTable'); 63 | const i = addressList.indexOf(address); 64 | const addressData = wallet.getAddressState(address); 65 | const rows = table.querySelector('tbody').getElementsByTagName('tr'); 66 | const row = rows[i]; 67 | const cells = row.getElementsByTagName('td'); 68 | if (addressData && addressData.ready) { 69 | const prevBalance = Number(cells[1].textContent.slice(0, -4)) * 100_000_000; 70 | cells[1].textContent = `${(addressData.balance.total / 100_000_000).toFixed(8)} BTC`; 71 | cells[2].textContent = `${addressData.transactions.length}`; 72 | cells[3].textContent = `${addressData.utxos.length}`; 73 | if (prevBalance != null && !isNaN(prevBalance) && addressData.balance.total && !row.className) { 74 | if (prevBalance < addressData.balance.total) { 75 | row.classList.add("credit"); 76 | row.classList.add("flash-once"); 77 | } else if (prevBalance > addressData.balance.total) { 78 | row.classList.add("debit"); 79 | row.classList.add("flash-once"); 80 | } else { 81 | row.classList.add("conf"); 82 | row.classList.add("flash-once"); 83 | } 84 | let onAnimationEnd = () => { 85 | row.className = ""; 86 | row.removeEventListener("animationend", onAnimationEnd); 87 | } 88 | row.addEventListener("animationend", onAnimationEnd); 89 | } 90 | } 91 | } 92 | 93 | function saveState() { 94 | const state = wallet.getWalletState(); 95 | 96 | const openRequest = indexedDB.open('walletWatcher', 1); 97 | openRequest.onupgradeneeded = function(event) { 98 | const db = event.target.result; 99 | db.createObjectStore('objects'); 100 | }; 101 | 102 | document.getElementById('saveButton').textContent = '...'; 103 | 104 | openRequest.onsuccess = function(event) { 105 | const db = event.target.result; 106 | 107 | const transaction = db.transaction(['objects'], 'readwrite'); 108 | const objectStore = transaction.objectStore('objects'); 109 | objectStore.put(JSON.stringify(state), 'addressState'); 110 | 111 | document.getElementById('saveButton').textContent = 'Save'; 112 | }; 113 | } 114 | 115 | function restoreState() { 116 | const openRequest = indexedDB.open('walletWatcher', 1); 117 | openRequest.onupgradeneeded = function(event) { 118 | const db = event.target.result; 119 | db.createObjectStore('objects'); 120 | }; 121 | 122 | openRequest.onsuccess = function(event) { 123 | const db = event.target.result; 124 | 125 | const transaction = db.transaction(['objects'], 'readonly'); 126 | const objectStore = transaction.objectStore('objects'); 127 | const request = objectStore.get('addressState'); 128 | 129 | request.onsuccess = function(event) { 130 | const state = JSON.parse(event.target.result); 131 | if (state && state.addresses) { 132 | for (const address of Object.keys(state.addresses)) { 133 | if (regexAddress.test(address) && !addressMap[address]) { 134 | addressMap[address] = true; 135 | addTableRow(address); 136 | addressList.push(address); 137 | } 138 | } 139 | wallet.restore(state); 140 | } 141 | }; 142 | }; 143 | } 144 | 145 | document.getElementById('watchButton').addEventListener('click', onTrackAddress); 146 | document.getElementById('saveButton').addEventListener('click', saveState); 147 | document.getElementById('restoreButton').addEventListener('click', restoreState); -------------------------------------------------------------------------------- /examples/wallet-watcher/mwck: -------------------------------------------------------------------------------- 1 | ../../dist -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mwck", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "mwck", 9 | "version": "0.0.1", 10 | "license": "GNU Affero General Public License v3.0", 11 | "dependencies": { 12 | "cross-fetch": "^4.0.0", 13 | "isomorphic-ws": "^5.0.0", 14 | "ws": "^8.14.1" 15 | }, 16 | "devDependencies": { 17 | "@types/ws": "^8.5.5", 18 | "@typescript-eslint/eslint-plugin": "^6.7.0", 19 | "@typescript-eslint/parser": "^6.7.0", 20 | "eslint": "^8.49.0", 21 | "eslint-config-prettier": "^9.0.0", 22 | "ts-loader": "^9.4.4", 23 | "typescript": "^5.2.2", 24 | "webpack": "^5.88.2", 25 | "webpack-cli": "^5.1.4" 26 | } 27 | }, 28 | "node_modules/@aashutoshrathi/word-wrap": { 29 | "version": "1.2.6", 30 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", 31 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", 32 | "dev": true, 33 | "engines": { 34 | "node": ">=0.10.0" 35 | } 36 | }, 37 | "node_modules/@discoveryjs/json-ext": { 38 | "version": "0.5.7", 39 | "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", 40 | "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", 41 | "dev": true, 42 | "engines": { 43 | "node": ">=10.0.0" 44 | } 45 | }, 46 | "node_modules/@eslint-community/eslint-utils": { 47 | "version": "4.4.0", 48 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", 49 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", 50 | "dev": true, 51 | "dependencies": { 52 | "eslint-visitor-keys": "^3.3.0" 53 | }, 54 | "engines": { 55 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 56 | }, 57 | "peerDependencies": { 58 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 59 | } 60 | }, 61 | "node_modules/@eslint-community/regexpp": { 62 | "version": "4.8.0", 63 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", 64 | "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", 65 | "dev": true, 66 | "engines": { 67 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 68 | } 69 | }, 70 | "node_modules/@eslint/eslintrc": { 71 | "version": "2.1.2", 72 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", 73 | "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", 74 | "dev": true, 75 | "dependencies": { 76 | "ajv": "^6.12.4", 77 | "debug": "^4.3.2", 78 | "espree": "^9.6.0", 79 | "globals": "^13.19.0", 80 | "ignore": "^5.2.0", 81 | "import-fresh": "^3.2.1", 82 | "js-yaml": "^4.1.0", 83 | "minimatch": "^3.1.2", 84 | "strip-json-comments": "^3.1.1" 85 | }, 86 | "engines": { 87 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 88 | }, 89 | "funding": { 90 | "url": "https://opencollective.com/eslint" 91 | } 92 | }, 93 | "node_modules/@eslint/js": { 94 | "version": "8.49.0", 95 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", 96 | "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", 97 | "dev": true, 98 | "engines": { 99 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 100 | } 101 | }, 102 | "node_modules/@humanwhocodes/config-array": { 103 | "version": "0.11.11", 104 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", 105 | "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", 106 | "dev": true, 107 | "dependencies": { 108 | "@humanwhocodes/object-schema": "^1.2.1", 109 | "debug": "^4.1.1", 110 | "minimatch": "^3.0.5" 111 | }, 112 | "engines": { 113 | "node": ">=10.10.0" 114 | } 115 | }, 116 | "node_modules/@humanwhocodes/module-importer": { 117 | "version": "1.0.1", 118 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 119 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 120 | "dev": true, 121 | "engines": { 122 | "node": ">=12.22" 123 | }, 124 | "funding": { 125 | "type": "github", 126 | "url": "https://github.com/sponsors/nzakas" 127 | } 128 | }, 129 | "node_modules/@humanwhocodes/object-schema": { 130 | "version": "1.2.1", 131 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 132 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 133 | "dev": true 134 | }, 135 | "node_modules/@jridgewell/gen-mapping": { 136 | "version": "0.3.3", 137 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", 138 | "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", 139 | "dev": true, 140 | "dependencies": { 141 | "@jridgewell/set-array": "^1.0.1", 142 | "@jridgewell/sourcemap-codec": "^1.4.10", 143 | "@jridgewell/trace-mapping": "^0.3.9" 144 | }, 145 | "engines": { 146 | "node": ">=6.0.0" 147 | } 148 | }, 149 | "node_modules/@jridgewell/resolve-uri": { 150 | "version": "3.1.1", 151 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", 152 | "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", 153 | "dev": true, 154 | "engines": { 155 | "node": ">=6.0.0" 156 | } 157 | }, 158 | "node_modules/@jridgewell/set-array": { 159 | "version": "1.1.2", 160 | "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", 161 | "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", 162 | "dev": true, 163 | "engines": { 164 | "node": ">=6.0.0" 165 | } 166 | }, 167 | "node_modules/@jridgewell/source-map": { 168 | "version": "0.3.5", 169 | "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", 170 | "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", 171 | "dev": true, 172 | "dependencies": { 173 | "@jridgewell/gen-mapping": "^0.3.0", 174 | "@jridgewell/trace-mapping": "^0.3.9" 175 | } 176 | }, 177 | "node_modules/@jridgewell/sourcemap-codec": { 178 | "version": "1.4.15", 179 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", 180 | "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", 181 | "dev": true 182 | }, 183 | "node_modules/@jridgewell/trace-mapping": { 184 | "version": "0.3.19", 185 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", 186 | "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", 187 | "dev": true, 188 | "dependencies": { 189 | "@jridgewell/resolve-uri": "^3.1.0", 190 | "@jridgewell/sourcemap-codec": "^1.4.14" 191 | } 192 | }, 193 | "node_modules/@nodelib/fs.scandir": { 194 | "version": "2.1.5", 195 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 196 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 197 | "dev": true, 198 | "dependencies": { 199 | "@nodelib/fs.stat": "2.0.5", 200 | "run-parallel": "^1.1.9" 201 | }, 202 | "engines": { 203 | "node": ">= 8" 204 | } 205 | }, 206 | "node_modules/@nodelib/fs.stat": { 207 | "version": "2.0.5", 208 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 209 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 210 | "dev": true, 211 | "engines": { 212 | "node": ">= 8" 213 | } 214 | }, 215 | "node_modules/@nodelib/fs.walk": { 216 | "version": "1.2.8", 217 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 218 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 219 | "dev": true, 220 | "dependencies": { 221 | "@nodelib/fs.scandir": "2.1.5", 222 | "fastq": "^1.6.0" 223 | }, 224 | "engines": { 225 | "node": ">= 8" 226 | } 227 | }, 228 | "node_modules/@types/eslint": { 229 | "version": "8.44.2", 230 | "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", 231 | "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", 232 | "dev": true, 233 | "dependencies": { 234 | "@types/estree": "*", 235 | "@types/json-schema": "*" 236 | } 237 | }, 238 | "node_modules/@types/eslint-scope": { 239 | "version": "3.7.4", 240 | "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", 241 | "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", 242 | "dev": true, 243 | "dependencies": { 244 | "@types/eslint": "*", 245 | "@types/estree": "*" 246 | } 247 | }, 248 | "node_modules/@types/estree": { 249 | "version": "1.0.1", 250 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", 251 | "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", 252 | "dev": true 253 | }, 254 | "node_modules/@types/json-schema": { 255 | "version": "7.0.12", 256 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", 257 | "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", 258 | "dev": true 259 | }, 260 | "node_modules/@types/node": { 261 | "version": "20.6.0", 262 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", 263 | "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==", 264 | "dev": true 265 | }, 266 | "node_modules/@types/semver": { 267 | "version": "7.5.1", 268 | "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", 269 | "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", 270 | "dev": true 271 | }, 272 | "node_modules/@types/ws": { 273 | "version": "8.5.5", 274 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", 275 | "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", 276 | "dev": true, 277 | "dependencies": { 278 | "@types/node": "*" 279 | } 280 | }, 281 | "node_modules/@typescript-eslint/eslint-plugin": { 282 | "version": "6.7.0", 283 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz", 284 | "integrity": "sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag==", 285 | "dev": true, 286 | "dependencies": { 287 | "@eslint-community/regexpp": "^4.5.1", 288 | "@typescript-eslint/scope-manager": "6.7.0", 289 | "@typescript-eslint/type-utils": "6.7.0", 290 | "@typescript-eslint/utils": "6.7.0", 291 | "@typescript-eslint/visitor-keys": "6.7.0", 292 | "debug": "^4.3.4", 293 | "graphemer": "^1.4.0", 294 | "ignore": "^5.2.4", 295 | "natural-compare": "^1.4.0", 296 | "semver": "^7.5.4", 297 | "ts-api-utils": "^1.0.1" 298 | }, 299 | "engines": { 300 | "node": "^16.0.0 || >=18.0.0" 301 | }, 302 | "funding": { 303 | "type": "opencollective", 304 | "url": "https://opencollective.com/typescript-eslint" 305 | }, 306 | "peerDependencies": { 307 | "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", 308 | "eslint": "^7.0.0 || ^8.0.0" 309 | }, 310 | "peerDependenciesMeta": { 311 | "typescript": { 312 | "optional": true 313 | } 314 | } 315 | }, 316 | "node_modules/@typescript-eslint/parser": { 317 | "version": "6.7.0", 318 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.0.tgz", 319 | "integrity": "sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng==", 320 | "dev": true, 321 | "dependencies": { 322 | "@typescript-eslint/scope-manager": "6.7.0", 323 | "@typescript-eslint/types": "6.7.0", 324 | "@typescript-eslint/typescript-estree": "6.7.0", 325 | "@typescript-eslint/visitor-keys": "6.7.0", 326 | "debug": "^4.3.4" 327 | }, 328 | "engines": { 329 | "node": "^16.0.0 || >=18.0.0" 330 | }, 331 | "funding": { 332 | "type": "opencollective", 333 | "url": "https://opencollective.com/typescript-eslint" 334 | }, 335 | "peerDependencies": { 336 | "eslint": "^7.0.0 || ^8.0.0" 337 | }, 338 | "peerDependenciesMeta": { 339 | "typescript": { 340 | "optional": true 341 | } 342 | } 343 | }, 344 | "node_modules/@typescript-eslint/scope-manager": { 345 | "version": "6.7.0", 346 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz", 347 | "integrity": "sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==", 348 | "dev": true, 349 | "dependencies": { 350 | "@typescript-eslint/types": "6.7.0", 351 | "@typescript-eslint/visitor-keys": "6.7.0" 352 | }, 353 | "engines": { 354 | "node": "^16.0.0 || >=18.0.0" 355 | }, 356 | "funding": { 357 | "type": "opencollective", 358 | "url": "https://opencollective.com/typescript-eslint" 359 | } 360 | }, 361 | "node_modules/@typescript-eslint/type-utils": { 362 | "version": "6.7.0", 363 | "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz", 364 | "integrity": "sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg==", 365 | "dev": true, 366 | "dependencies": { 367 | "@typescript-eslint/typescript-estree": "6.7.0", 368 | "@typescript-eslint/utils": "6.7.0", 369 | "debug": "^4.3.4", 370 | "ts-api-utils": "^1.0.1" 371 | }, 372 | "engines": { 373 | "node": "^16.0.0 || >=18.0.0" 374 | }, 375 | "funding": { 376 | "type": "opencollective", 377 | "url": "https://opencollective.com/typescript-eslint" 378 | }, 379 | "peerDependencies": { 380 | "eslint": "^7.0.0 || ^8.0.0" 381 | }, 382 | "peerDependenciesMeta": { 383 | "typescript": { 384 | "optional": true 385 | } 386 | } 387 | }, 388 | "node_modules/@typescript-eslint/types": { 389 | "version": "6.7.0", 390 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.0.tgz", 391 | "integrity": "sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==", 392 | "dev": true, 393 | "engines": { 394 | "node": "^16.0.0 || >=18.0.0" 395 | }, 396 | "funding": { 397 | "type": "opencollective", 398 | "url": "https://opencollective.com/typescript-eslint" 399 | } 400 | }, 401 | "node_modules/@typescript-eslint/typescript-estree": { 402 | "version": "6.7.0", 403 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz", 404 | "integrity": "sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==", 405 | "dev": true, 406 | "dependencies": { 407 | "@typescript-eslint/types": "6.7.0", 408 | "@typescript-eslint/visitor-keys": "6.7.0", 409 | "debug": "^4.3.4", 410 | "globby": "^11.1.0", 411 | "is-glob": "^4.0.3", 412 | "semver": "^7.5.4", 413 | "ts-api-utils": "^1.0.1" 414 | }, 415 | "engines": { 416 | "node": "^16.0.0 || >=18.0.0" 417 | }, 418 | "funding": { 419 | "type": "opencollective", 420 | "url": "https://opencollective.com/typescript-eslint" 421 | }, 422 | "peerDependenciesMeta": { 423 | "typescript": { 424 | "optional": true 425 | } 426 | } 427 | }, 428 | "node_modules/@typescript-eslint/utils": { 429 | "version": "6.7.0", 430 | "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.0.tgz", 431 | "integrity": "sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==", 432 | "dev": true, 433 | "dependencies": { 434 | "@eslint-community/eslint-utils": "^4.4.0", 435 | "@types/json-schema": "^7.0.12", 436 | "@types/semver": "^7.5.0", 437 | "@typescript-eslint/scope-manager": "6.7.0", 438 | "@typescript-eslint/types": "6.7.0", 439 | "@typescript-eslint/typescript-estree": "6.7.0", 440 | "semver": "^7.5.4" 441 | }, 442 | "engines": { 443 | "node": "^16.0.0 || >=18.0.0" 444 | }, 445 | "funding": { 446 | "type": "opencollective", 447 | "url": "https://opencollective.com/typescript-eslint" 448 | }, 449 | "peerDependencies": { 450 | "eslint": "^7.0.0 || ^8.0.0" 451 | } 452 | }, 453 | "node_modules/@typescript-eslint/visitor-keys": { 454 | "version": "6.7.0", 455 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz", 456 | "integrity": "sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==", 457 | "dev": true, 458 | "dependencies": { 459 | "@typescript-eslint/types": "6.7.0", 460 | "eslint-visitor-keys": "^3.4.1" 461 | }, 462 | "engines": { 463 | "node": "^16.0.0 || >=18.0.0" 464 | }, 465 | "funding": { 466 | "type": "opencollective", 467 | "url": "https://opencollective.com/typescript-eslint" 468 | } 469 | }, 470 | "node_modules/@webassemblyjs/ast": { 471 | "version": "1.11.6", 472 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", 473 | "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", 474 | "dev": true, 475 | "dependencies": { 476 | "@webassemblyjs/helper-numbers": "1.11.6", 477 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6" 478 | } 479 | }, 480 | "node_modules/@webassemblyjs/floating-point-hex-parser": { 481 | "version": "1.11.6", 482 | "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", 483 | "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", 484 | "dev": true 485 | }, 486 | "node_modules/@webassemblyjs/helper-api-error": { 487 | "version": "1.11.6", 488 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", 489 | "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", 490 | "dev": true 491 | }, 492 | "node_modules/@webassemblyjs/helper-buffer": { 493 | "version": "1.11.6", 494 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", 495 | "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", 496 | "dev": true 497 | }, 498 | "node_modules/@webassemblyjs/helper-numbers": { 499 | "version": "1.11.6", 500 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", 501 | "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", 502 | "dev": true, 503 | "dependencies": { 504 | "@webassemblyjs/floating-point-hex-parser": "1.11.6", 505 | "@webassemblyjs/helper-api-error": "1.11.6", 506 | "@xtuc/long": "4.2.2" 507 | } 508 | }, 509 | "node_modules/@webassemblyjs/helper-wasm-bytecode": { 510 | "version": "1.11.6", 511 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", 512 | "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", 513 | "dev": true 514 | }, 515 | "node_modules/@webassemblyjs/helper-wasm-section": { 516 | "version": "1.11.6", 517 | "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", 518 | "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", 519 | "dev": true, 520 | "dependencies": { 521 | "@webassemblyjs/ast": "1.11.6", 522 | "@webassemblyjs/helper-buffer": "1.11.6", 523 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 524 | "@webassemblyjs/wasm-gen": "1.11.6" 525 | } 526 | }, 527 | "node_modules/@webassemblyjs/ieee754": { 528 | "version": "1.11.6", 529 | "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", 530 | "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", 531 | "dev": true, 532 | "dependencies": { 533 | "@xtuc/ieee754": "^1.2.0" 534 | } 535 | }, 536 | "node_modules/@webassemblyjs/leb128": { 537 | "version": "1.11.6", 538 | "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", 539 | "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", 540 | "dev": true, 541 | "dependencies": { 542 | "@xtuc/long": "4.2.2" 543 | } 544 | }, 545 | "node_modules/@webassemblyjs/utf8": { 546 | "version": "1.11.6", 547 | "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", 548 | "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", 549 | "dev": true 550 | }, 551 | "node_modules/@webassemblyjs/wasm-edit": { 552 | "version": "1.11.6", 553 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", 554 | "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", 555 | "dev": true, 556 | "dependencies": { 557 | "@webassemblyjs/ast": "1.11.6", 558 | "@webassemblyjs/helper-buffer": "1.11.6", 559 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 560 | "@webassemblyjs/helper-wasm-section": "1.11.6", 561 | "@webassemblyjs/wasm-gen": "1.11.6", 562 | "@webassemblyjs/wasm-opt": "1.11.6", 563 | "@webassemblyjs/wasm-parser": "1.11.6", 564 | "@webassemblyjs/wast-printer": "1.11.6" 565 | } 566 | }, 567 | "node_modules/@webassemblyjs/wasm-gen": { 568 | "version": "1.11.6", 569 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", 570 | "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", 571 | "dev": true, 572 | "dependencies": { 573 | "@webassemblyjs/ast": "1.11.6", 574 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 575 | "@webassemblyjs/ieee754": "1.11.6", 576 | "@webassemblyjs/leb128": "1.11.6", 577 | "@webassemblyjs/utf8": "1.11.6" 578 | } 579 | }, 580 | "node_modules/@webassemblyjs/wasm-opt": { 581 | "version": "1.11.6", 582 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", 583 | "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", 584 | "dev": true, 585 | "dependencies": { 586 | "@webassemblyjs/ast": "1.11.6", 587 | "@webassemblyjs/helper-buffer": "1.11.6", 588 | "@webassemblyjs/wasm-gen": "1.11.6", 589 | "@webassemblyjs/wasm-parser": "1.11.6" 590 | } 591 | }, 592 | "node_modules/@webassemblyjs/wasm-parser": { 593 | "version": "1.11.6", 594 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", 595 | "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", 596 | "dev": true, 597 | "dependencies": { 598 | "@webassemblyjs/ast": "1.11.6", 599 | "@webassemblyjs/helper-api-error": "1.11.6", 600 | "@webassemblyjs/helper-wasm-bytecode": "1.11.6", 601 | "@webassemblyjs/ieee754": "1.11.6", 602 | "@webassemblyjs/leb128": "1.11.6", 603 | "@webassemblyjs/utf8": "1.11.6" 604 | } 605 | }, 606 | "node_modules/@webassemblyjs/wast-printer": { 607 | "version": "1.11.6", 608 | "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", 609 | "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", 610 | "dev": true, 611 | "dependencies": { 612 | "@webassemblyjs/ast": "1.11.6", 613 | "@xtuc/long": "4.2.2" 614 | } 615 | }, 616 | "node_modules/@webpack-cli/configtest": { 617 | "version": "2.1.1", 618 | "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", 619 | "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", 620 | "dev": true, 621 | "engines": { 622 | "node": ">=14.15.0" 623 | }, 624 | "peerDependencies": { 625 | "webpack": "5.x.x", 626 | "webpack-cli": "5.x.x" 627 | } 628 | }, 629 | "node_modules/@webpack-cli/info": { 630 | "version": "2.0.2", 631 | "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", 632 | "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", 633 | "dev": true, 634 | "engines": { 635 | "node": ">=14.15.0" 636 | }, 637 | "peerDependencies": { 638 | "webpack": "5.x.x", 639 | "webpack-cli": "5.x.x" 640 | } 641 | }, 642 | "node_modules/@webpack-cli/serve": { 643 | "version": "2.0.5", 644 | "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", 645 | "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", 646 | "dev": true, 647 | "engines": { 648 | "node": ">=14.15.0" 649 | }, 650 | "peerDependencies": { 651 | "webpack": "5.x.x", 652 | "webpack-cli": "5.x.x" 653 | }, 654 | "peerDependenciesMeta": { 655 | "webpack-dev-server": { 656 | "optional": true 657 | } 658 | } 659 | }, 660 | "node_modules/@xtuc/ieee754": { 661 | "version": "1.2.0", 662 | "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", 663 | "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", 664 | "dev": true 665 | }, 666 | "node_modules/@xtuc/long": { 667 | "version": "4.2.2", 668 | "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", 669 | "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", 670 | "dev": true 671 | }, 672 | "node_modules/acorn": { 673 | "version": "8.10.0", 674 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", 675 | "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", 676 | "dev": true, 677 | "bin": { 678 | "acorn": "bin/acorn" 679 | }, 680 | "engines": { 681 | "node": ">=0.4.0" 682 | } 683 | }, 684 | "node_modules/acorn-import-assertions": { 685 | "version": "1.9.0", 686 | "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", 687 | "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", 688 | "dev": true, 689 | "peerDependencies": { 690 | "acorn": "^8" 691 | } 692 | }, 693 | "node_modules/acorn-jsx": { 694 | "version": "5.3.2", 695 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 696 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 697 | "dev": true, 698 | "peerDependencies": { 699 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 700 | } 701 | }, 702 | "node_modules/ajv": { 703 | "version": "6.12.6", 704 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 705 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 706 | "dev": true, 707 | "dependencies": { 708 | "fast-deep-equal": "^3.1.1", 709 | "fast-json-stable-stringify": "^2.0.0", 710 | "json-schema-traverse": "^0.4.1", 711 | "uri-js": "^4.2.2" 712 | }, 713 | "funding": { 714 | "type": "github", 715 | "url": "https://github.com/sponsors/epoberezkin" 716 | } 717 | }, 718 | "node_modules/ajv-keywords": { 719 | "version": "3.5.2", 720 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", 721 | "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", 722 | "dev": true, 723 | "peerDependencies": { 724 | "ajv": "^6.9.1" 725 | } 726 | }, 727 | "node_modules/ansi-regex": { 728 | "version": "5.0.1", 729 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 730 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 731 | "dev": true, 732 | "engines": { 733 | "node": ">=8" 734 | } 735 | }, 736 | "node_modules/ansi-styles": { 737 | "version": "4.3.0", 738 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 739 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 740 | "dev": true, 741 | "dependencies": { 742 | "color-convert": "^2.0.1" 743 | }, 744 | "engines": { 745 | "node": ">=8" 746 | }, 747 | "funding": { 748 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 749 | } 750 | }, 751 | "node_modules/argparse": { 752 | "version": "2.0.1", 753 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 754 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 755 | "dev": true 756 | }, 757 | "node_modules/array-union": { 758 | "version": "2.1.0", 759 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 760 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 761 | "dev": true, 762 | "engines": { 763 | "node": ">=8" 764 | } 765 | }, 766 | "node_modules/balanced-match": { 767 | "version": "1.0.2", 768 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 769 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 770 | "dev": true 771 | }, 772 | "node_modules/brace-expansion": { 773 | "version": "1.1.11", 774 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 775 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 776 | "dev": true, 777 | "dependencies": { 778 | "balanced-match": "^1.0.0", 779 | "concat-map": "0.0.1" 780 | } 781 | }, 782 | "node_modules/braces": { 783 | "version": "3.0.2", 784 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 785 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 786 | "dev": true, 787 | "dependencies": { 788 | "fill-range": "^7.0.1" 789 | }, 790 | "engines": { 791 | "node": ">=8" 792 | } 793 | }, 794 | "node_modules/browserslist": { 795 | "version": "4.21.10", 796 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", 797 | "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", 798 | "dev": true, 799 | "funding": [ 800 | { 801 | "type": "opencollective", 802 | "url": "https://opencollective.com/browserslist" 803 | }, 804 | { 805 | "type": "tidelift", 806 | "url": "https://tidelift.com/funding/github/npm/browserslist" 807 | }, 808 | { 809 | "type": "github", 810 | "url": "https://github.com/sponsors/ai" 811 | } 812 | ], 813 | "dependencies": { 814 | "caniuse-lite": "^1.0.30001517", 815 | "electron-to-chromium": "^1.4.477", 816 | "node-releases": "^2.0.13", 817 | "update-browserslist-db": "^1.0.11" 818 | }, 819 | "bin": { 820 | "browserslist": "cli.js" 821 | }, 822 | "engines": { 823 | "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" 824 | } 825 | }, 826 | "node_modules/buffer-from": { 827 | "version": "1.1.2", 828 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 829 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 830 | "dev": true 831 | }, 832 | "node_modules/callsites": { 833 | "version": "3.1.0", 834 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 835 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 836 | "dev": true, 837 | "engines": { 838 | "node": ">=6" 839 | } 840 | }, 841 | "node_modules/caniuse-lite": { 842 | "version": "1.0.30001533", 843 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001533.tgz", 844 | "integrity": "sha512-9aY/b05NKU4Yl2sbcJhn4A7MsGwR1EPfW/nrqsnqVA0Oq50wpmPaGI+R1Z0UKlUl96oxUkGEOILWtOHck0eCWw==", 845 | "dev": true, 846 | "funding": [ 847 | { 848 | "type": "opencollective", 849 | "url": "https://opencollective.com/browserslist" 850 | }, 851 | { 852 | "type": "tidelift", 853 | "url": "https://tidelift.com/funding/github/npm/caniuse-lite" 854 | }, 855 | { 856 | "type": "github", 857 | "url": "https://github.com/sponsors/ai" 858 | } 859 | ] 860 | }, 861 | "node_modules/chalk": { 862 | "version": "4.1.2", 863 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 864 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 865 | "dev": true, 866 | "dependencies": { 867 | "ansi-styles": "^4.1.0", 868 | "supports-color": "^7.1.0" 869 | }, 870 | "engines": { 871 | "node": ">=10" 872 | }, 873 | "funding": { 874 | "url": "https://github.com/chalk/chalk?sponsor=1" 875 | } 876 | }, 877 | "node_modules/chrome-trace-event": { 878 | "version": "1.0.3", 879 | "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", 880 | "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", 881 | "dev": true, 882 | "engines": { 883 | "node": ">=6.0" 884 | } 885 | }, 886 | "node_modules/clone-deep": { 887 | "version": "4.0.1", 888 | "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", 889 | "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", 890 | "dev": true, 891 | "dependencies": { 892 | "is-plain-object": "^2.0.4", 893 | "kind-of": "^6.0.2", 894 | "shallow-clone": "^3.0.0" 895 | }, 896 | "engines": { 897 | "node": ">=6" 898 | } 899 | }, 900 | "node_modules/color-convert": { 901 | "version": "2.0.1", 902 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 903 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 904 | "dev": true, 905 | "dependencies": { 906 | "color-name": "~1.1.4" 907 | }, 908 | "engines": { 909 | "node": ">=7.0.0" 910 | } 911 | }, 912 | "node_modules/color-name": { 913 | "version": "1.1.4", 914 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 915 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 916 | "dev": true 917 | }, 918 | "node_modules/colorette": { 919 | "version": "2.0.20", 920 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", 921 | "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", 922 | "dev": true 923 | }, 924 | "node_modules/commander": { 925 | "version": "2.20.3", 926 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", 927 | "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", 928 | "dev": true 929 | }, 930 | "node_modules/concat-map": { 931 | "version": "0.0.1", 932 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 933 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 934 | "dev": true 935 | }, 936 | "node_modules/cross-fetch": { 937 | "version": "4.0.0", 938 | "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", 939 | "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", 940 | "dependencies": { 941 | "node-fetch": "^2.6.12" 942 | } 943 | }, 944 | "node_modules/cross-spawn": { 945 | "version": "7.0.3", 946 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 947 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 948 | "dev": true, 949 | "dependencies": { 950 | "path-key": "^3.1.0", 951 | "shebang-command": "^2.0.0", 952 | "which": "^2.0.1" 953 | }, 954 | "engines": { 955 | "node": ">= 8" 956 | } 957 | }, 958 | "node_modules/debug": { 959 | "version": "4.3.4", 960 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 961 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 962 | "dev": true, 963 | "dependencies": { 964 | "ms": "2.1.2" 965 | }, 966 | "engines": { 967 | "node": ">=6.0" 968 | }, 969 | "peerDependenciesMeta": { 970 | "supports-color": { 971 | "optional": true 972 | } 973 | } 974 | }, 975 | "node_modules/deep-is": { 976 | "version": "0.1.4", 977 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 978 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 979 | "dev": true 980 | }, 981 | "node_modules/dir-glob": { 982 | "version": "3.0.1", 983 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 984 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 985 | "dev": true, 986 | "dependencies": { 987 | "path-type": "^4.0.0" 988 | }, 989 | "engines": { 990 | "node": ">=8" 991 | } 992 | }, 993 | "node_modules/doctrine": { 994 | "version": "3.0.0", 995 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 996 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 997 | "dev": true, 998 | "dependencies": { 999 | "esutils": "^2.0.2" 1000 | }, 1001 | "engines": { 1002 | "node": ">=6.0.0" 1003 | } 1004 | }, 1005 | "node_modules/electron-to-chromium": { 1006 | "version": "1.4.517", 1007 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.517.tgz", 1008 | "integrity": "sha512-Int8C3a83q7OYvVZYktVnezC7u8NvLsBDDKJmyJBeKD8N9VrEGqKh3JOCSQz6Os77KgHVbUpCi4TMYtkZvvtuQ==", 1009 | "dev": true 1010 | }, 1011 | "node_modules/enhanced-resolve": { 1012 | "version": "5.15.0", 1013 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", 1014 | "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", 1015 | "dev": true, 1016 | "dependencies": { 1017 | "graceful-fs": "^4.2.4", 1018 | "tapable": "^2.2.0" 1019 | }, 1020 | "engines": { 1021 | "node": ">=10.13.0" 1022 | } 1023 | }, 1024 | "node_modules/envinfo": { 1025 | "version": "7.10.0", 1026 | "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", 1027 | "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", 1028 | "dev": true, 1029 | "bin": { 1030 | "envinfo": "dist/cli.js" 1031 | }, 1032 | "engines": { 1033 | "node": ">=4" 1034 | } 1035 | }, 1036 | "node_modules/es-module-lexer": { 1037 | "version": "1.3.1", 1038 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", 1039 | "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", 1040 | "dev": true 1041 | }, 1042 | "node_modules/escalade": { 1043 | "version": "3.1.1", 1044 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 1045 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 1046 | "dev": true, 1047 | "engines": { 1048 | "node": ">=6" 1049 | } 1050 | }, 1051 | "node_modules/escape-string-regexp": { 1052 | "version": "4.0.0", 1053 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1054 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1055 | "dev": true, 1056 | "engines": { 1057 | "node": ">=10" 1058 | }, 1059 | "funding": { 1060 | "url": "https://github.com/sponsors/sindresorhus" 1061 | } 1062 | }, 1063 | "node_modules/eslint": { 1064 | "version": "8.49.0", 1065 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", 1066 | "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", 1067 | "dev": true, 1068 | "dependencies": { 1069 | "@eslint-community/eslint-utils": "^4.2.0", 1070 | "@eslint-community/regexpp": "^4.6.1", 1071 | "@eslint/eslintrc": "^2.1.2", 1072 | "@eslint/js": "8.49.0", 1073 | "@humanwhocodes/config-array": "^0.11.11", 1074 | "@humanwhocodes/module-importer": "^1.0.1", 1075 | "@nodelib/fs.walk": "^1.2.8", 1076 | "ajv": "^6.12.4", 1077 | "chalk": "^4.0.0", 1078 | "cross-spawn": "^7.0.2", 1079 | "debug": "^4.3.2", 1080 | "doctrine": "^3.0.0", 1081 | "escape-string-regexp": "^4.0.0", 1082 | "eslint-scope": "^7.2.2", 1083 | "eslint-visitor-keys": "^3.4.3", 1084 | "espree": "^9.6.1", 1085 | "esquery": "^1.4.2", 1086 | "esutils": "^2.0.2", 1087 | "fast-deep-equal": "^3.1.3", 1088 | "file-entry-cache": "^6.0.1", 1089 | "find-up": "^5.0.0", 1090 | "glob-parent": "^6.0.2", 1091 | "globals": "^13.19.0", 1092 | "graphemer": "^1.4.0", 1093 | "ignore": "^5.2.0", 1094 | "imurmurhash": "^0.1.4", 1095 | "is-glob": "^4.0.0", 1096 | "is-path-inside": "^3.0.3", 1097 | "js-yaml": "^4.1.0", 1098 | "json-stable-stringify-without-jsonify": "^1.0.1", 1099 | "levn": "^0.4.1", 1100 | "lodash.merge": "^4.6.2", 1101 | "minimatch": "^3.1.2", 1102 | "natural-compare": "^1.4.0", 1103 | "optionator": "^0.9.3", 1104 | "strip-ansi": "^6.0.1", 1105 | "text-table": "^0.2.0" 1106 | }, 1107 | "bin": { 1108 | "eslint": "bin/eslint.js" 1109 | }, 1110 | "engines": { 1111 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1112 | }, 1113 | "funding": { 1114 | "url": "https://opencollective.com/eslint" 1115 | } 1116 | }, 1117 | "node_modules/eslint-config-prettier": { 1118 | "version": "9.0.0", 1119 | "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", 1120 | "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", 1121 | "dev": true, 1122 | "bin": { 1123 | "eslint-config-prettier": "bin/cli.js" 1124 | }, 1125 | "peerDependencies": { 1126 | "eslint": ">=7.0.0" 1127 | } 1128 | }, 1129 | "node_modules/eslint-scope": { 1130 | "version": "7.2.2", 1131 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", 1132 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", 1133 | "dev": true, 1134 | "dependencies": { 1135 | "esrecurse": "^4.3.0", 1136 | "estraverse": "^5.2.0" 1137 | }, 1138 | "engines": { 1139 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1140 | }, 1141 | "funding": { 1142 | "url": "https://opencollective.com/eslint" 1143 | } 1144 | }, 1145 | "node_modules/eslint-visitor-keys": { 1146 | "version": "3.4.3", 1147 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 1148 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 1149 | "dev": true, 1150 | "engines": { 1151 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1152 | }, 1153 | "funding": { 1154 | "url": "https://opencollective.com/eslint" 1155 | } 1156 | }, 1157 | "node_modules/espree": { 1158 | "version": "9.6.1", 1159 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", 1160 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", 1161 | "dev": true, 1162 | "dependencies": { 1163 | "acorn": "^8.9.0", 1164 | "acorn-jsx": "^5.3.2", 1165 | "eslint-visitor-keys": "^3.4.1" 1166 | }, 1167 | "engines": { 1168 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1169 | }, 1170 | "funding": { 1171 | "url": "https://opencollective.com/eslint" 1172 | } 1173 | }, 1174 | "node_modules/esquery": { 1175 | "version": "1.5.0", 1176 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", 1177 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", 1178 | "dev": true, 1179 | "dependencies": { 1180 | "estraverse": "^5.1.0" 1181 | }, 1182 | "engines": { 1183 | "node": ">=0.10" 1184 | } 1185 | }, 1186 | "node_modules/esrecurse": { 1187 | "version": "4.3.0", 1188 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1189 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1190 | "dev": true, 1191 | "dependencies": { 1192 | "estraverse": "^5.2.0" 1193 | }, 1194 | "engines": { 1195 | "node": ">=4.0" 1196 | } 1197 | }, 1198 | "node_modules/estraverse": { 1199 | "version": "5.3.0", 1200 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1201 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1202 | "dev": true, 1203 | "engines": { 1204 | "node": ">=4.0" 1205 | } 1206 | }, 1207 | "node_modules/esutils": { 1208 | "version": "2.0.3", 1209 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1210 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1211 | "dev": true, 1212 | "engines": { 1213 | "node": ">=0.10.0" 1214 | } 1215 | }, 1216 | "node_modules/events": { 1217 | "version": "3.3.0", 1218 | "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", 1219 | "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", 1220 | "dev": true, 1221 | "engines": { 1222 | "node": ">=0.8.x" 1223 | } 1224 | }, 1225 | "node_modules/fast-deep-equal": { 1226 | "version": "3.1.3", 1227 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1228 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1229 | "dev": true 1230 | }, 1231 | "node_modules/fast-glob": { 1232 | "version": "3.3.1", 1233 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", 1234 | "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", 1235 | "dev": true, 1236 | "dependencies": { 1237 | "@nodelib/fs.stat": "^2.0.2", 1238 | "@nodelib/fs.walk": "^1.2.3", 1239 | "glob-parent": "^5.1.2", 1240 | "merge2": "^1.3.0", 1241 | "micromatch": "^4.0.4" 1242 | }, 1243 | "engines": { 1244 | "node": ">=8.6.0" 1245 | } 1246 | }, 1247 | "node_modules/fast-glob/node_modules/glob-parent": { 1248 | "version": "5.1.2", 1249 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1250 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1251 | "dev": true, 1252 | "dependencies": { 1253 | "is-glob": "^4.0.1" 1254 | }, 1255 | "engines": { 1256 | "node": ">= 6" 1257 | } 1258 | }, 1259 | "node_modules/fast-json-stable-stringify": { 1260 | "version": "2.1.0", 1261 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1262 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1263 | "dev": true 1264 | }, 1265 | "node_modules/fast-levenshtein": { 1266 | "version": "2.0.6", 1267 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1268 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 1269 | "dev": true 1270 | }, 1271 | "node_modules/fastest-levenshtein": { 1272 | "version": "1.0.16", 1273 | "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", 1274 | "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", 1275 | "dev": true, 1276 | "engines": { 1277 | "node": ">= 4.9.1" 1278 | } 1279 | }, 1280 | "node_modules/fastq": { 1281 | "version": "1.15.0", 1282 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", 1283 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", 1284 | "dev": true, 1285 | "dependencies": { 1286 | "reusify": "^1.0.4" 1287 | } 1288 | }, 1289 | "node_modules/file-entry-cache": { 1290 | "version": "6.0.1", 1291 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1292 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1293 | "dev": true, 1294 | "dependencies": { 1295 | "flat-cache": "^3.0.4" 1296 | }, 1297 | "engines": { 1298 | "node": "^10.12.0 || >=12.0.0" 1299 | } 1300 | }, 1301 | "node_modules/fill-range": { 1302 | "version": "7.0.1", 1303 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1304 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1305 | "dev": true, 1306 | "dependencies": { 1307 | "to-regex-range": "^5.0.1" 1308 | }, 1309 | "engines": { 1310 | "node": ">=8" 1311 | } 1312 | }, 1313 | "node_modules/find-up": { 1314 | "version": "5.0.0", 1315 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1316 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1317 | "dev": true, 1318 | "dependencies": { 1319 | "locate-path": "^6.0.0", 1320 | "path-exists": "^4.0.0" 1321 | }, 1322 | "engines": { 1323 | "node": ">=10" 1324 | }, 1325 | "funding": { 1326 | "url": "https://github.com/sponsors/sindresorhus" 1327 | } 1328 | }, 1329 | "node_modules/flat-cache": { 1330 | "version": "3.1.0", 1331 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", 1332 | "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", 1333 | "dev": true, 1334 | "dependencies": { 1335 | "flatted": "^3.2.7", 1336 | "keyv": "^4.5.3", 1337 | "rimraf": "^3.0.2" 1338 | }, 1339 | "engines": { 1340 | "node": ">=12.0.0" 1341 | } 1342 | }, 1343 | "node_modules/flatted": { 1344 | "version": "3.2.7", 1345 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", 1346 | "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", 1347 | "dev": true 1348 | }, 1349 | "node_modules/fs.realpath": { 1350 | "version": "1.0.0", 1351 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1352 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 1353 | "dev": true 1354 | }, 1355 | "node_modules/function-bind": { 1356 | "version": "1.1.1", 1357 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1358 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 1359 | "dev": true 1360 | }, 1361 | "node_modules/glob": { 1362 | "version": "7.2.3", 1363 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 1364 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 1365 | "dev": true, 1366 | "dependencies": { 1367 | "fs.realpath": "^1.0.0", 1368 | "inflight": "^1.0.4", 1369 | "inherits": "2", 1370 | "minimatch": "^3.1.1", 1371 | "once": "^1.3.0", 1372 | "path-is-absolute": "^1.0.0" 1373 | }, 1374 | "engines": { 1375 | "node": "*" 1376 | }, 1377 | "funding": { 1378 | "url": "https://github.com/sponsors/isaacs" 1379 | } 1380 | }, 1381 | "node_modules/glob-parent": { 1382 | "version": "6.0.2", 1383 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1384 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1385 | "dev": true, 1386 | "dependencies": { 1387 | "is-glob": "^4.0.3" 1388 | }, 1389 | "engines": { 1390 | "node": ">=10.13.0" 1391 | } 1392 | }, 1393 | "node_modules/glob-to-regexp": { 1394 | "version": "0.4.1", 1395 | "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", 1396 | "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", 1397 | "dev": true 1398 | }, 1399 | "node_modules/globals": { 1400 | "version": "13.21.0", 1401 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", 1402 | "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", 1403 | "dev": true, 1404 | "dependencies": { 1405 | "type-fest": "^0.20.2" 1406 | }, 1407 | "engines": { 1408 | "node": ">=8" 1409 | }, 1410 | "funding": { 1411 | "url": "https://github.com/sponsors/sindresorhus" 1412 | } 1413 | }, 1414 | "node_modules/globby": { 1415 | "version": "11.1.0", 1416 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", 1417 | "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", 1418 | "dev": true, 1419 | "dependencies": { 1420 | "array-union": "^2.1.0", 1421 | "dir-glob": "^3.0.1", 1422 | "fast-glob": "^3.2.9", 1423 | "ignore": "^5.2.0", 1424 | "merge2": "^1.4.1", 1425 | "slash": "^3.0.0" 1426 | }, 1427 | "engines": { 1428 | "node": ">=10" 1429 | }, 1430 | "funding": { 1431 | "url": "https://github.com/sponsors/sindresorhus" 1432 | } 1433 | }, 1434 | "node_modules/graceful-fs": { 1435 | "version": "4.2.11", 1436 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1437 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1438 | "dev": true 1439 | }, 1440 | "node_modules/graphemer": { 1441 | "version": "1.4.0", 1442 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", 1443 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", 1444 | "dev": true 1445 | }, 1446 | "node_modules/has": { 1447 | "version": "1.0.3", 1448 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1449 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1450 | "dev": true, 1451 | "dependencies": { 1452 | "function-bind": "^1.1.1" 1453 | }, 1454 | "engines": { 1455 | "node": ">= 0.4.0" 1456 | } 1457 | }, 1458 | "node_modules/has-flag": { 1459 | "version": "4.0.0", 1460 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1461 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1462 | "dev": true, 1463 | "engines": { 1464 | "node": ">=8" 1465 | } 1466 | }, 1467 | "node_modules/ignore": { 1468 | "version": "5.2.4", 1469 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", 1470 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", 1471 | "dev": true, 1472 | "engines": { 1473 | "node": ">= 4" 1474 | } 1475 | }, 1476 | "node_modules/import-fresh": { 1477 | "version": "3.3.0", 1478 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1479 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1480 | "dev": true, 1481 | "dependencies": { 1482 | "parent-module": "^1.0.0", 1483 | "resolve-from": "^4.0.0" 1484 | }, 1485 | "engines": { 1486 | "node": ">=6" 1487 | }, 1488 | "funding": { 1489 | "url": "https://github.com/sponsors/sindresorhus" 1490 | } 1491 | }, 1492 | "node_modules/import-local": { 1493 | "version": "3.1.0", 1494 | "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", 1495 | "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", 1496 | "dev": true, 1497 | "dependencies": { 1498 | "pkg-dir": "^4.2.0", 1499 | "resolve-cwd": "^3.0.0" 1500 | }, 1501 | "bin": { 1502 | "import-local-fixture": "fixtures/cli.js" 1503 | }, 1504 | "engines": { 1505 | "node": ">=8" 1506 | }, 1507 | "funding": { 1508 | "url": "https://github.com/sponsors/sindresorhus" 1509 | } 1510 | }, 1511 | "node_modules/imurmurhash": { 1512 | "version": "0.1.4", 1513 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1514 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 1515 | "dev": true, 1516 | "engines": { 1517 | "node": ">=0.8.19" 1518 | } 1519 | }, 1520 | "node_modules/inflight": { 1521 | "version": "1.0.6", 1522 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1523 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1524 | "dev": true, 1525 | "dependencies": { 1526 | "once": "^1.3.0", 1527 | "wrappy": "1" 1528 | } 1529 | }, 1530 | "node_modules/inherits": { 1531 | "version": "2.0.4", 1532 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1533 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1534 | "dev": true 1535 | }, 1536 | "node_modules/interpret": { 1537 | "version": "3.1.1", 1538 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", 1539 | "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", 1540 | "dev": true, 1541 | "engines": { 1542 | "node": ">=10.13.0" 1543 | } 1544 | }, 1545 | "node_modules/is-core-module": { 1546 | "version": "2.13.0", 1547 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", 1548 | "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", 1549 | "dev": true, 1550 | "dependencies": { 1551 | "has": "^1.0.3" 1552 | }, 1553 | "funding": { 1554 | "url": "https://github.com/sponsors/ljharb" 1555 | } 1556 | }, 1557 | "node_modules/is-extglob": { 1558 | "version": "2.1.1", 1559 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1560 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1561 | "dev": true, 1562 | "engines": { 1563 | "node": ">=0.10.0" 1564 | } 1565 | }, 1566 | "node_modules/is-glob": { 1567 | "version": "4.0.3", 1568 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1569 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1570 | "dev": true, 1571 | "dependencies": { 1572 | "is-extglob": "^2.1.1" 1573 | }, 1574 | "engines": { 1575 | "node": ">=0.10.0" 1576 | } 1577 | }, 1578 | "node_modules/is-number": { 1579 | "version": "7.0.0", 1580 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1581 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1582 | "dev": true, 1583 | "engines": { 1584 | "node": ">=0.12.0" 1585 | } 1586 | }, 1587 | "node_modules/is-path-inside": { 1588 | "version": "3.0.3", 1589 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 1590 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 1591 | "dev": true, 1592 | "engines": { 1593 | "node": ">=8" 1594 | } 1595 | }, 1596 | "node_modules/is-plain-object": { 1597 | "version": "2.0.4", 1598 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1599 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1600 | "dev": true, 1601 | "dependencies": { 1602 | "isobject": "^3.0.1" 1603 | }, 1604 | "engines": { 1605 | "node": ">=0.10.0" 1606 | } 1607 | }, 1608 | "node_modules/isexe": { 1609 | "version": "2.0.0", 1610 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1611 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1612 | "dev": true 1613 | }, 1614 | "node_modules/isobject": { 1615 | "version": "3.0.1", 1616 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1617 | "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", 1618 | "dev": true, 1619 | "engines": { 1620 | "node": ">=0.10.0" 1621 | } 1622 | }, 1623 | "node_modules/isomorphic-ws": { 1624 | "version": "5.0.0", 1625 | "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", 1626 | "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", 1627 | "peerDependencies": { 1628 | "ws": "*" 1629 | } 1630 | }, 1631 | "node_modules/jest-worker": { 1632 | "version": "27.5.1", 1633 | "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", 1634 | "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", 1635 | "dev": true, 1636 | "dependencies": { 1637 | "@types/node": "*", 1638 | "merge-stream": "^2.0.0", 1639 | "supports-color": "^8.0.0" 1640 | }, 1641 | "engines": { 1642 | "node": ">= 10.13.0" 1643 | } 1644 | }, 1645 | "node_modules/jest-worker/node_modules/supports-color": { 1646 | "version": "8.1.1", 1647 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1648 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1649 | "dev": true, 1650 | "dependencies": { 1651 | "has-flag": "^4.0.0" 1652 | }, 1653 | "engines": { 1654 | "node": ">=10" 1655 | }, 1656 | "funding": { 1657 | "url": "https://github.com/chalk/supports-color?sponsor=1" 1658 | } 1659 | }, 1660 | "node_modules/js-yaml": { 1661 | "version": "4.1.0", 1662 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1663 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1664 | "dev": true, 1665 | "dependencies": { 1666 | "argparse": "^2.0.1" 1667 | }, 1668 | "bin": { 1669 | "js-yaml": "bin/js-yaml.js" 1670 | } 1671 | }, 1672 | "node_modules/json-buffer": { 1673 | "version": "3.0.1", 1674 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 1675 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 1676 | "dev": true 1677 | }, 1678 | "node_modules/json-parse-even-better-errors": { 1679 | "version": "2.3.1", 1680 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 1681 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", 1682 | "dev": true 1683 | }, 1684 | "node_modules/json-schema-traverse": { 1685 | "version": "0.4.1", 1686 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1687 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1688 | "dev": true 1689 | }, 1690 | "node_modules/json-stable-stringify-without-jsonify": { 1691 | "version": "1.0.1", 1692 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1693 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 1694 | "dev": true 1695 | }, 1696 | "node_modules/keyv": { 1697 | "version": "4.5.3", 1698 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", 1699 | "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", 1700 | "dev": true, 1701 | "dependencies": { 1702 | "json-buffer": "3.0.1" 1703 | } 1704 | }, 1705 | "node_modules/kind-of": { 1706 | "version": "6.0.3", 1707 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", 1708 | "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", 1709 | "dev": true, 1710 | "engines": { 1711 | "node": ">=0.10.0" 1712 | } 1713 | }, 1714 | "node_modules/levn": { 1715 | "version": "0.4.1", 1716 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1717 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1718 | "dev": true, 1719 | "dependencies": { 1720 | "prelude-ls": "^1.2.1", 1721 | "type-check": "~0.4.0" 1722 | }, 1723 | "engines": { 1724 | "node": ">= 0.8.0" 1725 | } 1726 | }, 1727 | "node_modules/loader-runner": { 1728 | "version": "4.3.0", 1729 | "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", 1730 | "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", 1731 | "dev": true, 1732 | "engines": { 1733 | "node": ">=6.11.5" 1734 | } 1735 | }, 1736 | "node_modules/locate-path": { 1737 | "version": "6.0.0", 1738 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1739 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1740 | "dev": true, 1741 | "dependencies": { 1742 | "p-locate": "^5.0.0" 1743 | }, 1744 | "engines": { 1745 | "node": ">=10" 1746 | }, 1747 | "funding": { 1748 | "url": "https://github.com/sponsors/sindresorhus" 1749 | } 1750 | }, 1751 | "node_modules/lodash.merge": { 1752 | "version": "4.6.2", 1753 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1754 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1755 | "dev": true 1756 | }, 1757 | "node_modules/lru-cache": { 1758 | "version": "6.0.0", 1759 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1760 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1761 | "dev": true, 1762 | "dependencies": { 1763 | "yallist": "^4.0.0" 1764 | }, 1765 | "engines": { 1766 | "node": ">=10" 1767 | } 1768 | }, 1769 | "node_modules/merge-stream": { 1770 | "version": "2.0.0", 1771 | "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", 1772 | "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", 1773 | "dev": true 1774 | }, 1775 | "node_modules/merge2": { 1776 | "version": "1.4.1", 1777 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1778 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1779 | "dev": true, 1780 | "engines": { 1781 | "node": ">= 8" 1782 | } 1783 | }, 1784 | "node_modules/micromatch": { 1785 | "version": "4.0.5", 1786 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", 1787 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", 1788 | "dev": true, 1789 | "dependencies": { 1790 | "braces": "^3.0.2", 1791 | "picomatch": "^2.3.1" 1792 | }, 1793 | "engines": { 1794 | "node": ">=8.6" 1795 | } 1796 | }, 1797 | "node_modules/mime-db": { 1798 | "version": "1.52.0", 1799 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1800 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1801 | "dev": true, 1802 | "engines": { 1803 | "node": ">= 0.6" 1804 | } 1805 | }, 1806 | "node_modules/mime-types": { 1807 | "version": "2.1.35", 1808 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1809 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1810 | "dev": true, 1811 | "dependencies": { 1812 | "mime-db": "1.52.0" 1813 | }, 1814 | "engines": { 1815 | "node": ">= 0.6" 1816 | } 1817 | }, 1818 | "node_modules/minimatch": { 1819 | "version": "3.1.2", 1820 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1821 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1822 | "dev": true, 1823 | "dependencies": { 1824 | "brace-expansion": "^1.1.7" 1825 | }, 1826 | "engines": { 1827 | "node": "*" 1828 | } 1829 | }, 1830 | "node_modules/ms": { 1831 | "version": "2.1.2", 1832 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1833 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1834 | "dev": true 1835 | }, 1836 | "node_modules/natural-compare": { 1837 | "version": "1.4.0", 1838 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1839 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1840 | "dev": true 1841 | }, 1842 | "node_modules/neo-async": { 1843 | "version": "2.6.2", 1844 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", 1845 | "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 1846 | "dev": true 1847 | }, 1848 | "node_modules/node-fetch": { 1849 | "version": "2.7.0", 1850 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 1851 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 1852 | "dependencies": { 1853 | "whatwg-url": "^5.0.0" 1854 | }, 1855 | "engines": { 1856 | "node": "4.x || >=6.0.0" 1857 | }, 1858 | "peerDependencies": { 1859 | "encoding": "^0.1.0" 1860 | }, 1861 | "peerDependenciesMeta": { 1862 | "encoding": { 1863 | "optional": true 1864 | } 1865 | } 1866 | }, 1867 | "node_modules/node-releases": { 1868 | "version": "2.0.13", 1869 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", 1870 | "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", 1871 | "dev": true 1872 | }, 1873 | "node_modules/once": { 1874 | "version": "1.4.0", 1875 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1876 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1877 | "dev": true, 1878 | "dependencies": { 1879 | "wrappy": "1" 1880 | } 1881 | }, 1882 | "node_modules/optionator": { 1883 | "version": "0.9.3", 1884 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", 1885 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", 1886 | "dev": true, 1887 | "dependencies": { 1888 | "@aashutoshrathi/word-wrap": "^1.2.3", 1889 | "deep-is": "^0.1.3", 1890 | "fast-levenshtein": "^2.0.6", 1891 | "levn": "^0.4.1", 1892 | "prelude-ls": "^1.2.1", 1893 | "type-check": "^0.4.0" 1894 | }, 1895 | "engines": { 1896 | "node": ">= 0.8.0" 1897 | } 1898 | }, 1899 | "node_modules/p-limit": { 1900 | "version": "3.1.0", 1901 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1902 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1903 | "dev": true, 1904 | "dependencies": { 1905 | "yocto-queue": "^0.1.0" 1906 | }, 1907 | "engines": { 1908 | "node": ">=10" 1909 | }, 1910 | "funding": { 1911 | "url": "https://github.com/sponsors/sindresorhus" 1912 | } 1913 | }, 1914 | "node_modules/p-locate": { 1915 | "version": "5.0.0", 1916 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1917 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1918 | "dev": true, 1919 | "dependencies": { 1920 | "p-limit": "^3.0.2" 1921 | }, 1922 | "engines": { 1923 | "node": ">=10" 1924 | }, 1925 | "funding": { 1926 | "url": "https://github.com/sponsors/sindresorhus" 1927 | } 1928 | }, 1929 | "node_modules/p-try": { 1930 | "version": "2.2.0", 1931 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1932 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1933 | "dev": true, 1934 | "engines": { 1935 | "node": ">=6" 1936 | } 1937 | }, 1938 | "node_modules/parent-module": { 1939 | "version": "1.0.1", 1940 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1941 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1942 | "dev": true, 1943 | "dependencies": { 1944 | "callsites": "^3.0.0" 1945 | }, 1946 | "engines": { 1947 | "node": ">=6" 1948 | } 1949 | }, 1950 | "node_modules/path-exists": { 1951 | "version": "4.0.0", 1952 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1953 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1954 | "dev": true, 1955 | "engines": { 1956 | "node": ">=8" 1957 | } 1958 | }, 1959 | "node_modules/path-is-absolute": { 1960 | "version": "1.0.1", 1961 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1962 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1963 | "dev": true, 1964 | "engines": { 1965 | "node": ">=0.10.0" 1966 | } 1967 | }, 1968 | "node_modules/path-key": { 1969 | "version": "3.1.1", 1970 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1971 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1972 | "dev": true, 1973 | "engines": { 1974 | "node": ">=8" 1975 | } 1976 | }, 1977 | "node_modules/path-parse": { 1978 | "version": "1.0.7", 1979 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1980 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1981 | "dev": true 1982 | }, 1983 | "node_modules/path-type": { 1984 | "version": "4.0.0", 1985 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1986 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1987 | "dev": true, 1988 | "engines": { 1989 | "node": ">=8" 1990 | } 1991 | }, 1992 | "node_modules/picocolors": { 1993 | "version": "1.0.0", 1994 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1995 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", 1996 | "dev": true 1997 | }, 1998 | "node_modules/picomatch": { 1999 | "version": "2.3.1", 2000 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2001 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2002 | "dev": true, 2003 | "engines": { 2004 | "node": ">=8.6" 2005 | }, 2006 | "funding": { 2007 | "url": "https://github.com/sponsors/jonschlinkert" 2008 | } 2009 | }, 2010 | "node_modules/pkg-dir": { 2011 | "version": "4.2.0", 2012 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 2013 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 2014 | "dev": true, 2015 | "dependencies": { 2016 | "find-up": "^4.0.0" 2017 | }, 2018 | "engines": { 2019 | "node": ">=8" 2020 | } 2021 | }, 2022 | "node_modules/pkg-dir/node_modules/find-up": { 2023 | "version": "4.1.0", 2024 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 2025 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 2026 | "dev": true, 2027 | "dependencies": { 2028 | "locate-path": "^5.0.0", 2029 | "path-exists": "^4.0.0" 2030 | }, 2031 | "engines": { 2032 | "node": ">=8" 2033 | } 2034 | }, 2035 | "node_modules/pkg-dir/node_modules/locate-path": { 2036 | "version": "5.0.0", 2037 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 2038 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 2039 | "dev": true, 2040 | "dependencies": { 2041 | "p-locate": "^4.1.0" 2042 | }, 2043 | "engines": { 2044 | "node": ">=8" 2045 | } 2046 | }, 2047 | "node_modules/pkg-dir/node_modules/p-limit": { 2048 | "version": "2.3.0", 2049 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2050 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2051 | "dev": true, 2052 | "dependencies": { 2053 | "p-try": "^2.0.0" 2054 | }, 2055 | "engines": { 2056 | "node": ">=6" 2057 | }, 2058 | "funding": { 2059 | "url": "https://github.com/sponsors/sindresorhus" 2060 | } 2061 | }, 2062 | "node_modules/pkg-dir/node_modules/p-locate": { 2063 | "version": "4.1.0", 2064 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2065 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2066 | "dev": true, 2067 | "dependencies": { 2068 | "p-limit": "^2.2.0" 2069 | }, 2070 | "engines": { 2071 | "node": ">=8" 2072 | } 2073 | }, 2074 | "node_modules/prelude-ls": { 2075 | "version": "1.2.1", 2076 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2077 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2078 | "dev": true, 2079 | "engines": { 2080 | "node": ">= 0.8.0" 2081 | } 2082 | }, 2083 | "node_modules/punycode": { 2084 | "version": "2.3.0", 2085 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 2086 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 2087 | "dev": true, 2088 | "engines": { 2089 | "node": ">=6" 2090 | } 2091 | }, 2092 | "node_modules/queue-microtask": { 2093 | "version": "1.2.3", 2094 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2095 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2096 | "dev": true, 2097 | "funding": [ 2098 | { 2099 | "type": "github", 2100 | "url": "https://github.com/sponsors/feross" 2101 | }, 2102 | { 2103 | "type": "patreon", 2104 | "url": "https://www.patreon.com/feross" 2105 | }, 2106 | { 2107 | "type": "consulting", 2108 | "url": "https://feross.org/support" 2109 | } 2110 | ] 2111 | }, 2112 | "node_modules/randombytes": { 2113 | "version": "2.1.0", 2114 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 2115 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 2116 | "dev": true, 2117 | "dependencies": { 2118 | "safe-buffer": "^5.1.0" 2119 | } 2120 | }, 2121 | "node_modules/rechoir": { 2122 | "version": "0.8.0", 2123 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", 2124 | "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", 2125 | "dev": true, 2126 | "dependencies": { 2127 | "resolve": "^1.20.0" 2128 | }, 2129 | "engines": { 2130 | "node": ">= 10.13.0" 2131 | } 2132 | }, 2133 | "node_modules/resolve": { 2134 | "version": "1.22.4", 2135 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", 2136 | "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", 2137 | "dev": true, 2138 | "dependencies": { 2139 | "is-core-module": "^2.13.0", 2140 | "path-parse": "^1.0.7", 2141 | "supports-preserve-symlinks-flag": "^1.0.0" 2142 | }, 2143 | "bin": { 2144 | "resolve": "bin/resolve" 2145 | }, 2146 | "funding": { 2147 | "url": "https://github.com/sponsors/ljharb" 2148 | } 2149 | }, 2150 | "node_modules/resolve-cwd": { 2151 | "version": "3.0.0", 2152 | "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", 2153 | "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", 2154 | "dev": true, 2155 | "dependencies": { 2156 | "resolve-from": "^5.0.0" 2157 | }, 2158 | "engines": { 2159 | "node": ">=8" 2160 | } 2161 | }, 2162 | "node_modules/resolve-cwd/node_modules/resolve-from": { 2163 | "version": "5.0.0", 2164 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 2165 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 2166 | "dev": true, 2167 | "engines": { 2168 | "node": ">=8" 2169 | } 2170 | }, 2171 | "node_modules/resolve-from": { 2172 | "version": "4.0.0", 2173 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2174 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2175 | "dev": true, 2176 | "engines": { 2177 | "node": ">=4" 2178 | } 2179 | }, 2180 | "node_modules/reusify": { 2181 | "version": "1.0.4", 2182 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2183 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2184 | "dev": true, 2185 | "engines": { 2186 | "iojs": ">=1.0.0", 2187 | "node": ">=0.10.0" 2188 | } 2189 | }, 2190 | "node_modules/rimraf": { 2191 | "version": "3.0.2", 2192 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2193 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2194 | "dev": true, 2195 | "dependencies": { 2196 | "glob": "^7.1.3" 2197 | }, 2198 | "bin": { 2199 | "rimraf": "bin.js" 2200 | }, 2201 | "funding": { 2202 | "url": "https://github.com/sponsors/isaacs" 2203 | } 2204 | }, 2205 | "node_modules/run-parallel": { 2206 | "version": "1.2.0", 2207 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2208 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2209 | "dev": true, 2210 | "funding": [ 2211 | { 2212 | "type": "github", 2213 | "url": "https://github.com/sponsors/feross" 2214 | }, 2215 | { 2216 | "type": "patreon", 2217 | "url": "https://www.patreon.com/feross" 2218 | }, 2219 | { 2220 | "type": "consulting", 2221 | "url": "https://feross.org/support" 2222 | } 2223 | ], 2224 | "dependencies": { 2225 | "queue-microtask": "^1.2.2" 2226 | } 2227 | }, 2228 | "node_modules/safe-buffer": { 2229 | "version": "5.2.1", 2230 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2231 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2232 | "dev": true, 2233 | "funding": [ 2234 | { 2235 | "type": "github", 2236 | "url": "https://github.com/sponsors/feross" 2237 | }, 2238 | { 2239 | "type": "patreon", 2240 | "url": "https://www.patreon.com/feross" 2241 | }, 2242 | { 2243 | "type": "consulting", 2244 | "url": "https://feross.org/support" 2245 | } 2246 | ] 2247 | }, 2248 | "node_modules/schema-utils": { 2249 | "version": "3.3.0", 2250 | "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", 2251 | "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", 2252 | "dev": true, 2253 | "dependencies": { 2254 | "@types/json-schema": "^7.0.8", 2255 | "ajv": "^6.12.5", 2256 | "ajv-keywords": "^3.5.2" 2257 | }, 2258 | "engines": { 2259 | "node": ">= 10.13.0" 2260 | }, 2261 | "funding": { 2262 | "type": "opencollective", 2263 | "url": "https://opencollective.com/webpack" 2264 | } 2265 | }, 2266 | "node_modules/semver": { 2267 | "version": "7.5.4", 2268 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", 2269 | "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", 2270 | "dev": true, 2271 | "dependencies": { 2272 | "lru-cache": "^6.0.0" 2273 | }, 2274 | "bin": { 2275 | "semver": "bin/semver.js" 2276 | }, 2277 | "engines": { 2278 | "node": ">=10" 2279 | } 2280 | }, 2281 | "node_modules/serialize-javascript": { 2282 | "version": "6.0.1", 2283 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", 2284 | "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", 2285 | "dev": true, 2286 | "dependencies": { 2287 | "randombytes": "^2.1.0" 2288 | } 2289 | }, 2290 | "node_modules/shallow-clone": { 2291 | "version": "3.0.1", 2292 | "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", 2293 | "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", 2294 | "dev": true, 2295 | "dependencies": { 2296 | "kind-of": "^6.0.2" 2297 | }, 2298 | "engines": { 2299 | "node": ">=8" 2300 | } 2301 | }, 2302 | "node_modules/shebang-command": { 2303 | "version": "2.0.0", 2304 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2305 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2306 | "dev": true, 2307 | "dependencies": { 2308 | "shebang-regex": "^3.0.0" 2309 | }, 2310 | "engines": { 2311 | "node": ">=8" 2312 | } 2313 | }, 2314 | "node_modules/shebang-regex": { 2315 | "version": "3.0.0", 2316 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2317 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2318 | "dev": true, 2319 | "engines": { 2320 | "node": ">=8" 2321 | } 2322 | }, 2323 | "node_modules/slash": { 2324 | "version": "3.0.0", 2325 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2326 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2327 | "dev": true, 2328 | "engines": { 2329 | "node": ">=8" 2330 | } 2331 | }, 2332 | "node_modules/source-map": { 2333 | "version": "0.6.1", 2334 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2335 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2336 | "dev": true, 2337 | "engines": { 2338 | "node": ">=0.10.0" 2339 | } 2340 | }, 2341 | "node_modules/source-map-support": { 2342 | "version": "0.5.21", 2343 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 2344 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 2345 | "dev": true, 2346 | "dependencies": { 2347 | "buffer-from": "^1.0.0", 2348 | "source-map": "^0.6.0" 2349 | } 2350 | }, 2351 | "node_modules/strip-ansi": { 2352 | "version": "6.0.1", 2353 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2354 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2355 | "dev": true, 2356 | "dependencies": { 2357 | "ansi-regex": "^5.0.1" 2358 | }, 2359 | "engines": { 2360 | "node": ">=8" 2361 | } 2362 | }, 2363 | "node_modules/strip-json-comments": { 2364 | "version": "3.1.1", 2365 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2366 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2367 | "dev": true, 2368 | "engines": { 2369 | "node": ">=8" 2370 | }, 2371 | "funding": { 2372 | "url": "https://github.com/sponsors/sindresorhus" 2373 | } 2374 | }, 2375 | "node_modules/supports-color": { 2376 | "version": "7.2.0", 2377 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2378 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2379 | "dev": true, 2380 | "dependencies": { 2381 | "has-flag": "^4.0.0" 2382 | }, 2383 | "engines": { 2384 | "node": ">=8" 2385 | } 2386 | }, 2387 | "node_modules/supports-preserve-symlinks-flag": { 2388 | "version": "1.0.0", 2389 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 2390 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 2391 | "dev": true, 2392 | "engines": { 2393 | "node": ">= 0.4" 2394 | }, 2395 | "funding": { 2396 | "url": "https://github.com/sponsors/ljharb" 2397 | } 2398 | }, 2399 | "node_modules/tapable": { 2400 | "version": "2.2.1", 2401 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", 2402 | "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", 2403 | "dev": true, 2404 | "engines": { 2405 | "node": ">=6" 2406 | } 2407 | }, 2408 | "node_modules/terser": { 2409 | "version": "5.19.4", 2410 | "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.4.tgz", 2411 | "integrity": "sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==", 2412 | "dev": true, 2413 | "dependencies": { 2414 | "@jridgewell/source-map": "^0.3.3", 2415 | "acorn": "^8.8.2", 2416 | "commander": "^2.20.0", 2417 | "source-map-support": "~0.5.20" 2418 | }, 2419 | "bin": { 2420 | "terser": "bin/terser" 2421 | }, 2422 | "engines": { 2423 | "node": ">=10" 2424 | } 2425 | }, 2426 | "node_modules/terser-webpack-plugin": { 2427 | "version": "5.3.9", 2428 | "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", 2429 | "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", 2430 | "dev": true, 2431 | "dependencies": { 2432 | "@jridgewell/trace-mapping": "^0.3.17", 2433 | "jest-worker": "^27.4.5", 2434 | "schema-utils": "^3.1.1", 2435 | "serialize-javascript": "^6.0.1", 2436 | "terser": "^5.16.8" 2437 | }, 2438 | "engines": { 2439 | "node": ">= 10.13.0" 2440 | }, 2441 | "funding": { 2442 | "type": "opencollective", 2443 | "url": "https://opencollective.com/webpack" 2444 | }, 2445 | "peerDependencies": { 2446 | "webpack": "^5.1.0" 2447 | }, 2448 | "peerDependenciesMeta": { 2449 | "@swc/core": { 2450 | "optional": true 2451 | }, 2452 | "esbuild": { 2453 | "optional": true 2454 | }, 2455 | "uglify-js": { 2456 | "optional": true 2457 | } 2458 | } 2459 | }, 2460 | "node_modules/text-table": { 2461 | "version": "0.2.0", 2462 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2463 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 2464 | "dev": true 2465 | }, 2466 | "node_modules/to-regex-range": { 2467 | "version": "5.0.1", 2468 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2469 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2470 | "dev": true, 2471 | "dependencies": { 2472 | "is-number": "^7.0.0" 2473 | }, 2474 | "engines": { 2475 | "node": ">=8.0" 2476 | } 2477 | }, 2478 | "node_modules/tr46": { 2479 | "version": "0.0.3", 2480 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 2481 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" 2482 | }, 2483 | "node_modules/ts-api-utils": { 2484 | "version": "1.0.3", 2485 | "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", 2486 | "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", 2487 | "dev": true, 2488 | "engines": { 2489 | "node": ">=16.13.0" 2490 | }, 2491 | "peerDependencies": { 2492 | "typescript": ">=4.2.0" 2493 | } 2494 | }, 2495 | "node_modules/ts-loader": { 2496 | "version": "9.4.4", 2497 | "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz", 2498 | "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==", 2499 | "dev": true, 2500 | "dependencies": { 2501 | "chalk": "^4.1.0", 2502 | "enhanced-resolve": "^5.0.0", 2503 | "micromatch": "^4.0.0", 2504 | "semver": "^7.3.4" 2505 | }, 2506 | "engines": { 2507 | "node": ">=12.0.0" 2508 | }, 2509 | "peerDependencies": { 2510 | "typescript": "*", 2511 | "webpack": "^5.0.0" 2512 | } 2513 | }, 2514 | "node_modules/type-check": { 2515 | "version": "0.4.0", 2516 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2517 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2518 | "dev": true, 2519 | "dependencies": { 2520 | "prelude-ls": "^1.2.1" 2521 | }, 2522 | "engines": { 2523 | "node": ">= 0.8.0" 2524 | } 2525 | }, 2526 | "node_modules/type-fest": { 2527 | "version": "0.20.2", 2528 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2529 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2530 | "dev": true, 2531 | "engines": { 2532 | "node": ">=10" 2533 | }, 2534 | "funding": { 2535 | "url": "https://github.com/sponsors/sindresorhus" 2536 | } 2537 | }, 2538 | "node_modules/typescript": { 2539 | "version": "5.2.2", 2540 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 2541 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 2542 | "dev": true, 2543 | "bin": { 2544 | "tsc": "bin/tsc", 2545 | "tsserver": "bin/tsserver" 2546 | }, 2547 | "engines": { 2548 | "node": ">=14.17" 2549 | } 2550 | }, 2551 | "node_modules/update-browserslist-db": { 2552 | "version": "1.0.11", 2553 | "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", 2554 | "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", 2555 | "dev": true, 2556 | "funding": [ 2557 | { 2558 | "type": "opencollective", 2559 | "url": "https://opencollective.com/browserslist" 2560 | }, 2561 | { 2562 | "type": "tidelift", 2563 | "url": "https://tidelift.com/funding/github/npm/browserslist" 2564 | }, 2565 | { 2566 | "type": "github", 2567 | "url": "https://github.com/sponsors/ai" 2568 | } 2569 | ], 2570 | "dependencies": { 2571 | "escalade": "^3.1.1", 2572 | "picocolors": "^1.0.0" 2573 | }, 2574 | "bin": { 2575 | "update-browserslist-db": "cli.js" 2576 | }, 2577 | "peerDependencies": { 2578 | "browserslist": ">= 4.21.0" 2579 | } 2580 | }, 2581 | "node_modules/uri-js": { 2582 | "version": "4.4.1", 2583 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2584 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2585 | "dev": true, 2586 | "dependencies": { 2587 | "punycode": "^2.1.0" 2588 | } 2589 | }, 2590 | "node_modules/watchpack": { 2591 | "version": "2.4.0", 2592 | "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", 2593 | "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", 2594 | "dev": true, 2595 | "dependencies": { 2596 | "glob-to-regexp": "^0.4.1", 2597 | "graceful-fs": "^4.1.2" 2598 | }, 2599 | "engines": { 2600 | "node": ">=10.13.0" 2601 | } 2602 | }, 2603 | "node_modules/webidl-conversions": { 2604 | "version": "3.0.1", 2605 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2606 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" 2607 | }, 2608 | "node_modules/webpack": { 2609 | "version": "5.88.2", 2610 | "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", 2611 | "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", 2612 | "dev": true, 2613 | "dependencies": { 2614 | "@types/eslint-scope": "^3.7.3", 2615 | "@types/estree": "^1.0.0", 2616 | "@webassemblyjs/ast": "^1.11.5", 2617 | "@webassemblyjs/wasm-edit": "^1.11.5", 2618 | "@webassemblyjs/wasm-parser": "^1.11.5", 2619 | "acorn": "^8.7.1", 2620 | "acorn-import-assertions": "^1.9.0", 2621 | "browserslist": "^4.14.5", 2622 | "chrome-trace-event": "^1.0.2", 2623 | "enhanced-resolve": "^5.15.0", 2624 | "es-module-lexer": "^1.2.1", 2625 | "eslint-scope": "5.1.1", 2626 | "events": "^3.2.0", 2627 | "glob-to-regexp": "^0.4.1", 2628 | "graceful-fs": "^4.2.9", 2629 | "json-parse-even-better-errors": "^2.3.1", 2630 | "loader-runner": "^4.2.0", 2631 | "mime-types": "^2.1.27", 2632 | "neo-async": "^2.6.2", 2633 | "schema-utils": "^3.2.0", 2634 | "tapable": "^2.1.1", 2635 | "terser-webpack-plugin": "^5.3.7", 2636 | "watchpack": "^2.4.0", 2637 | "webpack-sources": "^3.2.3" 2638 | }, 2639 | "bin": { 2640 | "webpack": "bin/webpack.js" 2641 | }, 2642 | "engines": { 2643 | "node": ">=10.13.0" 2644 | }, 2645 | "funding": { 2646 | "type": "opencollective", 2647 | "url": "https://opencollective.com/webpack" 2648 | }, 2649 | "peerDependenciesMeta": { 2650 | "webpack-cli": { 2651 | "optional": true 2652 | } 2653 | } 2654 | }, 2655 | "node_modules/webpack-cli": { 2656 | "version": "5.1.4", 2657 | "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", 2658 | "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", 2659 | "dev": true, 2660 | "dependencies": { 2661 | "@discoveryjs/json-ext": "^0.5.0", 2662 | "@webpack-cli/configtest": "^2.1.1", 2663 | "@webpack-cli/info": "^2.0.2", 2664 | "@webpack-cli/serve": "^2.0.5", 2665 | "colorette": "^2.0.14", 2666 | "commander": "^10.0.1", 2667 | "cross-spawn": "^7.0.3", 2668 | "envinfo": "^7.7.3", 2669 | "fastest-levenshtein": "^1.0.12", 2670 | "import-local": "^3.0.2", 2671 | "interpret": "^3.1.1", 2672 | "rechoir": "^0.8.0", 2673 | "webpack-merge": "^5.7.3" 2674 | }, 2675 | "bin": { 2676 | "webpack-cli": "bin/cli.js" 2677 | }, 2678 | "engines": { 2679 | "node": ">=14.15.0" 2680 | }, 2681 | "funding": { 2682 | "type": "opencollective", 2683 | "url": "https://opencollective.com/webpack" 2684 | }, 2685 | "peerDependencies": { 2686 | "webpack": "5.x.x" 2687 | }, 2688 | "peerDependenciesMeta": { 2689 | "@webpack-cli/generators": { 2690 | "optional": true 2691 | }, 2692 | "webpack-bundle-analyzer": { 2693 | "optional": true 2694 | }, 2695 | "webpack-dev-server": { 2696 | "optional": true 2697 | } 2698 | } 2699 | }, 2700 | "node_modules/webpack-cli/node_modules/commander": { 2701 | "version": "10.0.1", 2702 | "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", 2703 | "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", 2704 | "dev": true, 2705 | "engines": { 2706 | "node": ">=14" 2707 | } 2708 | }, 2709 | "node_modules/webpack-merge": { 2710 | "version": "5.9.0", 2711 | "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", 2712 | "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", 2713 | "dev": true, 2714 | "dependencies": { 2715 | "clone-deep": "^4.0.1", 2716 | "wildcard": "^2.0.0" 2717 | }, 2718 | "engines": { 2719 | "node": ">=10.0.0" 2720 | } 2721 | }, 2722 | "node_modules/webpack-sources": { 2723 | "version": "3.2.3", 2724 | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", 2725 | "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", 2726 | "dev": true, 2727 | "engines": { 2728 | "node": ">=10.13.0" 2729 | } 2730 | }, 2731 | "node_modules/webpack/node_modules/eslint-scope": { 2732 | "version": "5.1.1", 2733 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 2734 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 2735 | "dev": true, 2736 | "dependencies": { 2737 | "esrecurse": "^4.3.0", 2738 | "estraverse": "^4.1.1" 2739 | }, 2740 | "engines": { 2741 | "node": ">=8.0.0" 2742 | } 2743 | }, 2744 | "node_modules/webpack/node_modules/estraverse": { 2745 | "version": "4.3.0", 2746 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 2747 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 2748 | "dev": true, 2749 | "engines": { 2750 | "node": ">=4.0" 2751 | } 2752 | }, 2753 | "node_modules/whatwg-url": { 2754 | "version": "5.0.0", 2755 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2756 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2757 | "dependencies": { 2758 | "tr46": "~0.0.3", 2759 | "webidl-conversions": "^3.0.0" 2760 | } 2761 | }, 2762 | "node_modules/which": { 2763 | "version": "2.0.2", 2764 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2765 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2766 | "dev": true, 2767 | "dependencies": { 2768 | "isexe": "^2.0.0" 2769 | }, 2770 | "bin": { 2771 | "node-which": "bin/node-which" 2772 | }, 2773 | "engines": { 2774 | "node": ">= 8" 2775 | } 2776 | }, 2777 | "node_modules/wildcard": { 2778 | "version": "2.0.1", 2779 | "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", 2780 | "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", 2781 | "dev": true 2782 | }, 2783 | "node_modules/wrappy": { 2784 | "version": "1.0.2", 2785 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2786 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2787 | "dev": true 2788 | }, 2789 | "node_modules/ws": { 2790 | "version": "8.14.1", 2791 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", 2792 | "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", 2793 | "engines": { 2794 | "node": ">=10.0.0" 2795 | }, 2796 | "peerDependencies": { 2797 | "bufferutil": "^4.0.1", 2798 | "utf-8-validate": ">=5.0.2" 2799 | }, 2800 | "peerDependenciesMeta": { 2801 | "bufferutil": { 2802 | "optional": true 2803 | }, 2804 | "utf-8-validate": { 2805 | "optional": true 2806 | } 2807 | } 2808 | }, 2809 | "node_modules/yallist": { 2810 | "version": "4.0.0", 2811 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2812 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2813 | "dev": true 2814 | }, 2815 | "node_modules/yocto-queue": { 2816 | "version": "0.1.0", 2817 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2818 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2819 | "dev": true, 2820 | "engines": { 2821 | "node": ">=10" 2822 | }, 2823 | "funding": { 2824 | "url": "https://github.com/sponsors/sindresorhus" 2825 | } 2826 | } 2827 | } 2828 | } 2829 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mwck", 3 | "version": "0.1.2-dev", 4 | "description": "mempool.space wallet connector kit", 5 | "main": "dist/index.js", 6 | "module": "dist/index.esm.js", 7 | "browser": "dist/index.umd.js", 8 | "types": "dist/types/index.d.ts", 9 | "scripts": { 10 | "tsc": "tsc", 11 | "build": "npm run tsc && webpack --mode production", 12 | "start": "node dist/index.js" 13 | }, 14 | "license": "GNU Affero General Public License v3.0", 15 | "devDependencies": { 16 | "@types/ws": "^8.5.5", 17 | "@typescript-eslint/eslint-plugin": "^6.7.0", 18 | "@typescript-eslint/parser": "^6.7.0", 19 | "eslint": "^8.49.0", 20 | "eslint-config-prettier": "^9.0.0", 21 | "ts-loader": "^9.4.4", 22 | "typescript": "^5.2.2", 23 | "webpack": "^5.88.2", 24 | "webpack-cli": "^5.1.4" 25 | }, 26 | "dependencies": { 27 | "cross-fetch": "^4.0.0", 28 | "isomorphic-ws": "^5.0.0", 29 | "ws": "^8.14.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/address.ts: -------------------------------------------------------------------------------- 1 | import { AddressState, Transaction, Utxo } from "./interfaces"; 2 | 3 | /** 4 | * Utility class for keeping track of address state 5 | * via idempotent "add" and "remove" transaction events 6 | */ 7 | export class AddressTracker { 8 | protected address: string; 9 | protected transactions: Map; 10 | protected balance: { 11 | total: number; 12 | confirmed: number; 13 | mempool: number; 14 | }; 15 | protected utxos: Map; 16 | 17 | // Map of spent inputs for which we haven't yet seen 18 | // the corresponding output. 19 | private spent: Set; 20 | 21 | // While loadingApi=true, websocket events are withheld in a pending queue 22 | private loadingApi = true; 23 | private pending: { event: 'add' | 'remove', tx?: Transaction, txid?: string }[] = []; 24 | 25 | constructor(address: string) { 26 | this.address = address; 27 | this.transactions = new Map(); 28 | this.balance = { 29 | total: 0, 30 | confirmed: 0, 31 | mempool: 0, 32 | }; 33 | this.utxos = new Map(); 34 | this.spent = new Set(); 35 | } 36 | 37 | public static from(state: AddressState): AddressTracker { 38 | const tracker = new AddressTracker(state.address); 39 | state.transactions.forEach(tx => tracker.transactions.set(tx.txid, tx)); 40 | state.utxos.forEach(utxo => tracker.utxos.set(`${utxo.txid}:${utxo.vout}`, utxo)); 41 | tracker.balance = state.balance; 42 | return tracker; 43 | } 44 | 45 | /** 46 | * Returns the current state of the address in a JSON-friendly format 47 | */ 48 | public getState(): AddressState { 49 | return { 50 | address: this.address, 51 | ready: !this.loadingApi, 52 | transactions: Array.from(this.transactions.values()), 53 | balance: { 54 | total: this.balance.total, 55 | mempool: this.balance.mempool, 56 | confirmed: this.balance.confirmed, 57 | }, 58 | utxos: Array.from(this.utxos.values()), 59 | }; 60 | } 61 | 62 | public hasTransaction(txid: string): boolean { 63 | return this.transactions.has(txid); 64 | } 65 | 66 | /** 67 | * Update the address state with the effect of a transaction 68 | * 69 | * Idempotent, but the most recent confirmation status applies, 70 | * so ordering matters 71 | */ 72 | public addTransaction(tx: Transaction, fromWs = false): void { 73 | // delay websocket events until we finished processing transactions from the REST API 74 | if (this.loadingApi && fromWs) { 75 | this.pending.push({ event: 'add', tx }); 76 | return; 77 | } 78 | 79 | // if we already have this transaction 80 | // undo the effects of that version before applying this one 81 | if (this.transactions.has(tx.txid)) { 82 | this.removeTransaction(tx.txid); 83 | } 84 | for (const vin of tx.vin) { 85 | if (vin?.prevout?.scriptpubkey_address === this.address) { 86 | const key = `${vin.txid}:${vin.vout}`; 87 | const utxo = this.utxos.get(key); 88 | if (utxo) { 89 | this.utxos.delete(key); 90 | this.balance[utxo.confirmed ? 'confirmed' : 'mempool'] -= utxo.value; 91 | this.balance.total -= utxo.value; 92 | } else { 93 | // we're missing the utxo for this input 94 | // record that so we don't double count it later 95 | this.spent.add(key); 96 | } 97 | } 98 | } 99 | for (const [index, vout] of tx.vout.entries()) { 100 | if (vout?.scriptpubkey_address === this.address) { 101 | const key = `${tx.txid}:${index}`; 102 | // skip outputs we've already seen spent 103 | if (!this.spent.delete(key)) { 104 | this.balance[tx.status.confirmed ? 'confirmed' : 'mempool'] += vout.value; 105 | this.balance.total += vout.value; 106 | this.utxos.set(key, { 107 | txid: tx.txid, 108 | vout: index, 109 | value: vout.value, 110 | confirmed: tx.status.confirmed, 111 | }) 112 | } 113 | } 114 | } 115 | this.transactions.set(tx.txid, tx); 116 | } 117 | 118 | /** 119 | * Undo the effect of a previously added transaction 120 | */ 121 | public removeTransaction(txid: string, fromWs = false): void { 122 | // delay processing websocket transactions until we finished loading from the REST API 123 | if (this.loadingApi && fromWs) { 124 | this.pending.push({ event: 'remove', txid }); 125 | return; 126 | } 127 | 128 | const tx = this.transactions.get(txid); 129 | if (!tx) { 130 | return; 131 | } 132 | this.transactions.delete(txid); 133 | for (const vin of tx.vin) { 134 | if (vin?.prevout?.scriptpubkey_address === this.address) { 135 | const key = `${vin.txid}:${vin.vout}`; 136 | const prevTx = this.transactions.get(vin.txid); 137 | if (prevTx) { 138 | this.balance[prevTx.status.confirmed ? 'confirmed' : 'mempool'] += vin.prevout.value; 139 | this.balance.total += vin.prevout.value; 140 | this.utxos.set(key, { 141 | txid: vin.txid, 142 | vout: vin.vout, 143 | value: vin.prevout.value, 144 | confirmed: prevTx.status.confirmed, 145 | }); 146 | } 147 | this.spent.delete(key); 148 | } 149 | } 150 | for (const [index, vout] of tx.vout.entries()) { 151 | if (vout?.scriptpubkey_address === this.address) { 152 | const key = `${tx.txid}:${index}`; 153 | if (this.utxos.delete(key)) { 154 | // this output was still unspent 155 | this.balance[tx.status.confirmed ? 'confirmed' : 'mempool'] -= vout.value; 156 | this.balance.total -= vout.value; 157 | } else { 158 | // record that the output is already spent 159 | this.spent.add(key); 160 | } 161 | } 162 | } 163 | } 164 | 165 | /** 166 | * Call after all API transactions have been processed 167 | * 168 | * Drains any pending websocket events 169 | */ 170 | public async onApiLoaded(): Promise { 171 | this.loadingApi = false; 172 | while (this.pending.length) { 173 | const event = this.pending.shift(); 174 | if (event?.event === 'add' && event.tx) { 175 | this.addTransaction(event.tx); 176 | } else if (event?.event === 'remove' && event.txid) { 177 | this.removeTransaction(event.txid); 178 | } 179 | } 180 | return this.getState(); 181 | } 182 | 183 | /** 184 | * Prepares for API transactions to be loaded 185 | */ 186 | public onApiLoading(): void { 187 | this.loadingApi = true; 188 | } 189 | } -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import fetch from 'cross-fetch'; 2 | import { MempoolOptions, Transaction, addDefaultOptions } from './interfaces'; 3 | 4 | export class MempoolApi { 5 | private options: MempoolOptions; 6 | private baseUrl: string; 7 | 8 | constructor(options: MempoolOptions) { 9 | this.options = addDefaultOptions(options); 10 | const networkPath = ['testnet', 'signet'].includes(this.options.network || '') ? ('/' + this.options.network) : ''; 11 | this.baseUrl = `${this.options.secure ? 'https' : 'http'}://${this.options.hostname}${networkPath}/api`; 12 | } 13 | 14 | /** 15 | * Fetch address transactions from the configured REST API 16 | * 17 | * `untilTxid` and `untilHeight` can be used to limit the number of API requests: 18 | * 19 | * If either is provided, the function will only fetch as much history as necessary to find 20 | * - a transaction with the given txid. 21 | * - a transaction confirmed at or below the given blockheight. 22 | * 23 | * If both are provided, history will be fetched until both conditions are met. 24 | */ 25 | public async getAddressTransactions(address: string, untilTxid?: string, untilHeight?: number): Promise { 26 | let allTxs: Transaction[] = []; 27 | let lastTxid: string | null = null; 28 | let done = false; 29 | const limitRequests = untilTxid || (untilHeight != null); 30 | let foundTxid = untilTxid == null; 31 | let foundHeight = untilHeight == null; 32 | while (!done && !(limitRequests && foundTxid && foundHeight)) { 33 | const result = await fetch(`${this.baseUrl}/address/${address}/txs${lastTxid ? '?after_txid=' + lastTxid : ''}`); 34 | const txs = await result.json() as Transaction[]; 35 | if (limitRequests) { 36 | if (!foundTxid && txs.findIndex(tx => tx.txid === untilTxid) >= 0) { 37 | foundTxid = true; 38 | } 39 | const lastTx = txs.slice(-1)[0]; 40 | const { confirmed, block_height } = lastTx?.status || {}; 41 | 42 | if (!foundHeight && txs.length && confirmed && block_height != null && block_height < untilHeight!) { 43 | foundHeight = true; 44 | } 45 | } 46 | if (txs.length === 50) { 47 | lastTxid = txs[txs.length - 1].txid; 48 | } else { 49 | done = true; 50 | } 51 | allTxs = allTxs.concat(txs); 52 | } 53 | return allTxs.reverse(); 54 | } 55 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./wallet"; -------------------------------------------------------------------------------- /src/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface MempoolOptions { 2 | hostname?: string; 3 | network?: 'mainnet' | 'testnet' | 'signet'; 4 | secure?: boolean; 5 | } 6 | 7 | export function addDefaultOptions(options: MempoolOptions): MempoolOptions { 8 | return { 9 | hostname: 'mempool.space', 10 | network: 'mainnet', 11 | secure: true, 12 | ...options 13 | }; 14 | } 15 | 16 | export interface Transaction { 17 | txid: string; 18 | version: number; 19 | locktime: number; 20 | size: number; 21 | weight: number; 22 | fee: number; 23 | vin: Vin[]; 24 | vout: Vout[]; 25 | status: Status; 26 | firstSeen?: number; 27 | feePerVsize?: number; 28 | effectiveFeePerVsize?: number; 29 | } 30 | 31 | export interface Vin { 32 | txid: string; 33 | vout: number; 34 | is_coinbase: boolean; 35 | scriptsig: string; 36 | scriptsig_asm: string; 37 | inner_redeemscript_asm?: string; 38 | inner_witnessscript_asm?: string; 39 | sequence: any; 40 | witness?: string[]; 41 | prevout: Vout; 42 | } 43 | 44 | export interface Vout { 45 | scriptpubkey: string; 46 | scriptpubkey_asm: string; 47 | scriptpubkey_type: string; 48 | scriptpubkey_address?: string; 49 | value: number; 50 | } 51 | 52 | export interface Status { 53 | confirmed: boolean; 54 | block_height?: number; 55 | block_hash?: string; 56 | block_time?: number; 57 | } 58 | 59 | export interface Utxo { 60 | txid: string, 61 | vout: number, 62 | value: number, 63 | confirmed: boolean, 64 | } 65 | 66 | export interface AddressState { 67 | address: string, 68 | ready: boolean, 69 | transactions: Transaction[]; 70 | balance: { 71 | total: number; 72 | confirmed: number; 73 | mempool: number; 74 | }; 75 | utxos: Utxo[]; 76 | } 77 | 78 | export interface WalletState extends AddressState { 79 | addresses: { [address: string]: AddressState }; 80 | } 81 | 82 | export interface AddressTransactionsResponse { 83 | [address: string]: { 84 | mempool: Transaction[]; 85 | confirmed: Transaction[]; 86 | removed: Transaction[]; 87 | } 88 | } -------------------------------------------------------------------------------- /src/wallet.ts: -------------------------------------------------------------------------------- 1 | import { MempoolApi } from './api'; 2 | import { AddressTxEvent, MempoolSocket } from './websocket'; 3 | import { MempoolOptions, Transaction, AddressState, Utxo, WalletState } from './interfaces'; 4 | import { AddressTracker } from './address'; 5 | 6 | const walletEventTypes = ['addressReady', 'txAdded', 'txConfirmed', 'txRemoved', 'txEvent', 'wsConnected', 'wsDisconnected', 'wsError'] as const; 7 | type WalletEvent = typeof walletEventTypes[number]; 8 | 9 | export interface SubscriptionEvent { 10 | event?: 'added' | 'confirmed' | 'removed'; 11 | address?: string; 12 | tx?: Transaction; 13 | state?: AddressState; 14 | err?: any; 15 | } 16 | 17 | type ObserverDict = { 18 | [event in WalletEvent]: { 19 | [oid: number]: (args: SubscriptionEvent) => void; 20 | }; 21 | }; 22 | 23 | export class MempoolWallet { 24 | private api: MempoolApi; 25 | private ws: MempoolSocket; 26 | private tracking: { [key: string]: AddressTracker } = {}; 27 | 28 | private observerId = 0; 29 | private observers: ObserverDict = Object.fromEntries(walletEventTypes.map(event => [event, {}])) as ObserverDict; 30 | 31 | 32 | constructor(options: MempoolOptions) { 33 | this.api = new MempoolApi(options); 34 | this.ws = new MempoolSocket(options); 35 | this.ws.on(AddressTxEvent.mempool, ({address, tx}) => { this.onTransactionUnconfirmed(address, tx, true); }); 36 | this.ws.on(AddressTxEvent.confirmed, ({address, tx}) => { this.onTransactionConfirmed(address, tx, true); }); 37 | this.ws.on(AddressTxEvent.removed, ({address, tx}) => { this.onTransactionRemoved(address, tx, true); }); 38 | this.ws.on('disconnected', () => { this.onWebsocketDisconnected() }); 39 | this.ws.on('connected', () => { this.onWebsocketConnected() }); 40 | this.ws.on('error', ({error}) => { this.onWebsocketError(error) }); 41 | } 42 | 43 | public destroy(): void { 44 | this.ws.disconnect(); 45 | this.ws.off(AddressTxEvent.mempool); 46 | this.ws.off(AddressTxEvent.confirmed); 47 | this.ws.off(AddressTxEvent.removed); 48 | this.ws.off('disconnected'); 49 | this.ws.off('connected'); 50 | this.ws.off('error'); 51 | } 52 | 53 | private notifyObservers(event: WalletEvent, args: SubscriptionEvent): void { 54 | Object.values(this.observers[event]).forEach(observer => observer(args)); 55 | } 56 | 57 | private onTransactionUnconfirmed(address?: string, tx?: Transaction, fromWs = false): void { 58 | if (tx && address && address in this.tracking) { 59 | this.tracking[address].addTransaction(tx, fromWs); 60 | this.notifyObservers('txAdded', {address, tx}); 61 | this.notifyObservers('txEvent', {event: 'added', address, tx}); 62 | } 63 | } 64 | 65 | private onTransactionConfirmed(address?: string, tx?: Transaction, fromWs = false): void { 66 | if (tx && address && address in this.tracking) { 67 | const isKnown = this.tracking[address].hasTransaction(tx.txid); 68 | this.tracking[address].addTransaction(tx, fromWs); 69 | if (!isKnown) { 70 | this.notifyObservers('txAdded', {address, tx}); 71 | this.notifyObservers('txEvent', {event: 'added', address, tx}); 72 | } 73 | this.notifyObservers('txConfirmed', {address, tx}); 74 | this.notifyObservers('txEvent', {event: 'confirmed', address, tx}); 75 | } 76 | } 77 | 78 | private onTransactionRemoved(address?: string, tx?: Transaction, fromWs = false): void { 79 | if (tx && address && address in this.tracking) { 80 | this.tracking[address].removeTransaction(tx.txid, fromWs); 81 | this.notifyObservers('txRemoved', {address, tx}); 82 | this.notifyObservers('txEvent', {event: 'removed', address, tx}); 83 | } 84 | } 85 | 86 | private async onWebsocketError(err: any): Promise { 87 | this.notifyObservers('wsError', { err }); 88 | await this.resync(); 89 | } 90 | 91 | private onWebsocketDisconnected(): void { 92 | this.notifyObservers('wsDisconnected', {}); 93 | } 94 | 95 | private async onWebsocketConnected(): Promise { 96 | this.notifyObservers('wsConnected', {}); 97 | await this.resync(); 98 | } 99 | 100 | private async fetchAddressBacklog(address: string, lookBack = 1) { 101 | const addressState = this.tracking[address]?.getState(); 102 | 103 | // fetch history back one block beyond the last known confirmed transaction 104 | const lastConfirmed = (addressState?.transactions.slice().reverse() || []).find(tx => tx.status?.confirmed); 105 | let lastTxid; 106 | let lastHeight; 107 | if (lastConfirmed) { 108 | lastTxid = lastConfirmed.txid; 109 | lastHeight = (lastConfirmed.status?.block_height || 1) - lookBack; 110 | } 111 | const fetchedTxids = new Set(); 112 | const initialTransactions = await this.api.getAddressTransactions(address, lastTxid, lastHeight); 113 | for (const tx of initialTransactions) { 114 | fetchedTxids.add(tx.txid); 115 | } 116 | 117 | // Clear transactions that were removed since our last good state 118 | for (const tx of addressState?.transactions.slice().reverse() || []) { 119 | // Only check as far back as our fresh data extends 120 | if (lastHeight && tx.status?.block_height && tx.status?.block_height < lastHeight) { 121 | break; 122 | } 123 | if (!fetchedTxids.has(tx.txid)) { 124 | this.onTransactionRemoved(address, tx); 125 | } 126 | } 127 | 128 | for (const tx of initialTransactions) { 129 | if (tx.status?.confirmed) { 130 | this.onTransactionConfirmed(address, tx); 131 | } else { 132 | this.onTransactionUnconfirmed(address, tx); 133 | } 134 | } 135 | const state = await this.tracking[address].onApiLoaded(); 136 | 137 | // notify observers that the address is synced and ready 138 | this.notifyObservers('addressReady', {address, state}); 139 | } 140 | 141 | public async connect(): Promise { 142 | await this.ws.connect(); 143 | } 144 | 145 | public disconnect(): void { 146 | this.ws.disconnect(); 147 | } 148 | 149 | public async resync(): Promise { 150 | for (const tracker of Object.values(this.tracking)) { 151 | tracker.onApiLoading(); 152 | } 153 | this.ws.trackAddresses(Object.keys(this.tracking)); 154 | for (const address of Object.keys(this.tracking)) { 155 | if (this.ws.isConnected()) { 156 | await this.fetchAddressBacklog(address); 157 | } else { 158 | // connection lost, we'll try again on reconnect 159 | return; 160 | } 161 | } 162 | } 163 | 164 | // register a handler for an event type 165 | // returns an unsubscribe function 166 | public subscribe(event: WalletEvent, fn: (args: SubscriptionEvent) => void): () => void { 167 | const oid = this.observerId++; 168 | this.observers[event][oid] = fn; 169 | return () => { delete this.observers[event][oid]; }; 170 | } 171 | 172 | public getAddressState(address: string): AddressState | null { 173 | if (this.tracking[address]) { 174 | return this.tracking[address].getState(); 175 | } else { 176 | return null; 177 | } 178 | } 179 | 180 | public getWalletState(): WalletState { 181 | const addresses: { [address: string]: AddressState } = {}; 182 | const transactions = new Map(); 183 | const balance = { 184 | total: 0, 185 | confirmed: 0, 186 | mempool: 0, 187 | }; 188 | let utxos: Utxo[] = []; 189 | Object.keys(this.tracking).forEach(address => { 190 | if (this.tracking[address]) { 191 | const addressState = this.tracking[address].getState(); 192 | addresses[address] = addressState; 193 | balance.total += addressState.balance.total; 194 | balance.confirmed += addressState.balance.confirmed; 195 | balance.mempool += addressState.balance.mempool; 196 | for (const tx of addressState.transactions) { 197 | transactions.set(tx.txid, tx); 198 | } 199 | utxos = utxos.concat(addressState.utxos); 200 | } 201 | }) 202 | return { 203 | address: 'wallet', 204 | ready: Object.values(addresses).reduce((ready, address) => ready && address.ready, true), 205 | addresses, 206 | balance, 207 | transactions: Array.from(transactions.values()), 208 | utxos, 209 | }; 210 | } 211 | 212 | public async restore(state: WalletState): Promise { 213 | this.tracking = {}; 214 | for (const address of Object.keys(state.addresses)) { 215 | const addressState = state.addresses[address]; 216 | this.tracking[address] = AddressTracker.from(addressState); 217 | } 218 | await this.resync(); 219 | } 220 | 221 | public async trackAddresses(addresses: string[]): Promise { 222 | addresses = addresses.filter(address => !(address in this.tracking)); 223 | if (!addresses.length) { 224 | return; 225 | } 226 | for (const address of addresses) { 227 | this.tracking[address] = new AddressTracker(address); 228 | } 229 | if (this.ws.isConnected()) { 230 | this.ws.trackAddresses(Object.keys(this.tracking)); 231 | for (const address of addresses) { 232 | await this.fetchAddressBacklog(address); 233 | } 234 | } 235 | } 236 | 237 | public untrackAddresses(addresses: string[]): void { 238 | let anyDeleted = false; 239 | for (const address of addresses) { 240 | if (address in this.tracking) { 241 | delete this.tracking[address]; 242 | anyDeleted = true; 243 | } 244 | } 245 | if (anyDeleted) { 246 | this.ws.trackAddresses(Object.keys(this.tracking)); 247 | } 248 | } 249 | } -------------------------------------------------------------------------------- /src/websocket.ts: -------------------------------------------------------------------------------- 1 | import WebSocket from 'isomorphic-ws'; 2 | import { MempoolOptions, addDefaultOptions, Transaction, AddressTransactionsResponse } from './interfaces'; 3 | 4 | export enum ConnectionState { 5 | connected, 6 | connecting, 7 | offline 8 | } 9 | 10 | export enum AddressTxEvent { 11 | removed = 'removed', 12 | mempool = 'mempool', 13 | confirmed = 'confirmed', 14 | } 15 | 16 | export type WebsocketEvent = AddressTxEvent | 'disconnected' | 'connected' | 'error'; 17 | 18 | export class MempoolSocket { 19 | private options: MempoolOptions; 20 | private wsUrl: string; 21 | 22 | private heartbeatTimer: ReturnType | null = null; 23 | private lastResponseTime = 0; 24 | private websocketState: ConnectionState = ConnectionState.offline; 25 | private ws: WebSocket | null = null; 26 | private eventCallbacks: { 27 | [event in WebsocketEvent]?: (args: { address?: string, tx?: Transaction, error?: any }) => void; 28 | } = {}; 29 | private outQueue: string[] = []; 30 | 31 | constructor(options: MempoolOptions = {}) { 32 | this.options = addDefaultOptions(options); 33 | const networkPath = ['testnet', 'signet'].includes(this.options.network || '') ? ('/' + this.options.network) : ''; 34 | this.wsUrl = `${this.options.secure ? 'wss' : 'ws'}://${this.options.hostname}${networkPath}/api/v1/ws`; 35 | } 36 | 37 | private async init(): Promise { 38 | while (!this.ws || this.websocketState !== ConnectionState.connected) { 39 | if (this.websocketState === ConnectionState.offline) { 40 | if (this.ws) { 41 | this.ws.close(); 42 | this.ws = null; 43 | } 44 | return new Promise((resolve, reject) => { 45 | this.websocketState = ConnectionState.connecting; 46 | const connectionTimeout = setTimeout(() => { reject('websocket connection timed out'); }, 5000); 47 | 48 | try { 49 | this.ws = new WebSocket(this.wsUrl); 50 | 51 | this.ws.onerror = (err) => { 52 | this.websocketState = ConnectionState.offline; 53 | if (this.eventCallbacks.error) { 54 | this.eventCallbacks['error']({ error: err }); 55 | } 56 | } 57 | 58 | this.ws.onclose = () => { 59 | this.handleClose(); 60 | }; 61 | 62 | this.ws.onmessage = (msg: any) => { 63 | this.handleResponse(msg); 64 | }; 65 | 66 | this.ws.onopen = () => { 67 | this.handleOpen(); 68 | clearTimeout(connectionTimeout); 69 | resolve(this.ws as WebSocket); 70 | }; 71 | } catch (e) { 72 | reject(e); 73 | } 74 | }); 75 | } else { 76 | // try again in 5 seconds 77 | await new Promise((resolve) => { 78 | setTimeout(resolve, 5000); 79 | }); 80 | } 81 | } 82 | return this.ws; 83 | } 84 | 85 | private reconnect(): void { 86 | if (this.ws) { 87 | this.ws.onclose = null; 88 | this.ws.close(); 89 | this.ws = null; 90 | } 91 | this.connect(); 92 | } 93 | 94 | private heartbeat(): void { 95 | if (this.websocketState === ConnectionState.offline || Date.now() - this.lastResponseTime > 180000) { 96 | this.websocketState = ConnectionState.offline; 97 | this.reconnect(); 98 | } else { 99 | this.send({ action: 'ping' }); 100 | } 101 | } 102 | 103 | private handleOpen(): void { 104 | this.websocketState = ConnectionState.connected; 105 | this.lastResponseTime = Date.now(); 106 | if (this.heartbeatTimer) { 107 | clearInterval(this.heartbeatTimer); 108 | } 109 | this.heartbeatTimer = setInterval(() => { this.heartbeat(); }, 15000); 110 | while (this.outQueue.length && this.ws) { 111 | this.ws.send(this.outQueue.shift() as string); 112 | } 113 | if (this.eventCallbacks.connected) { 114 | this.eventCallbacks.connected({}); 115 | } 116 | } 117 | 118 | private handleClose(): void { 119 | this.websocketState = ConnectionState.offline; 120 | if (this.eventCallbacks.disconnected) { 121 | this.eventCallbacks.disconnected({}); 122 | } 123 | } 124 | 125 | private handleResponse(msg: any): void { 126 | this.lastResponseTime = Date.now(); 127 | try { 128 | const result = JSON.parse(msg.data); 129 | if (result['multi-address-transactions']) { 130 | this.handleMultiAddressTransactions(result['multi-address-transactions']); 131 | } 132 | } catch (err) { 133 | if (this.eventCallbacks.error) { 134 | this.eventCallbacks['error']({ error: err }); 135 | } 136 | } 137 | } 138 | 139 | private handleMultiAddressTransactions(addressTransactions: AddressTransactionsResponse): void { 140 | for (const [address, events] of Object.entries(addressTransactions)) { 141 | for (const event in AddressTxEvent) { 142 | if (this.eventCallbacks[event as AddressTxEvent]) { 143 | for (const tx of events[event as AddressTxEvent] || []) { 144 | this.eventCallbacks[event as AddressTxEvent]?.({address, tx}); 145 | } 146 | } 147 | } 148 | } 149 | } 150 | 151 | private send(data: any): void { 152 | if (this.ws && this.websocketState === ConnectionState.connected) { 153 | this.ws.send(JSON.stringify(data)); 154 | } else { 155 | this.outQueue.push(JSON.stringify(data)); 156 | } 157 | } 158 | 159 | public isConnected(): boolean { 160 | return this.websocketState === ConnectionState.connected; 161 | } 162 | 163 | public async connect(): Promise { 164 | return this.init(); 165 | } 166 | 167 | public disconnect(): void { 168 | if (this.heartbeatTimer) { 169 | clearInterval(this.heartbeatTimer); 170 | } 171 | this.ws?.close(); 172 | } 173 | 174 | public on(event: WebsocketEvent, callback: (args: {address?: string, tx?: Transaction, error?: any}) => void): void { 175 | this.eventCallbacks[event] = callback; 176 | } 177 | 178 | public off(event: WebsocketEvent): void { 179 | delete this.eventCallbacks[event]; 180 | } 181 | 182 | public async trackAddresses(addresses: string[]): Promise { 183 | this.send({ 'track-addresses': addresses }); 184 | } 185 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2016", 4 | "module": "ESNext", 5 | "declaration": true, 6 | "outDir": "dist/types", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "moduleResolution": "node", 10 | "forceConsistentCasingInFileNames": true 11 | }, 12 | "include": [ 13 | "src/**/*.ts" 14 | ], 15 | "exclude": [ 16 | "node_modules" 17 | ] 18 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const common = { 4 | entry: './src/index.ts', 5 | module: { 6 | rules: [ 7 | { 8 | test: /\.tsx?$/, 9 | use: 'ts-loader', 10 | exclude: /node_modules/, 11 | }, 12 | ], 13 | }, 14 | resolve: { 15 | extensions: ['.tsx', '.ts', '.js'], 16 | }, 17 | }; 18 | 19 | const umdConfig = { 20 | ...common, 21 | output: { 22 | filename: 'index.umd.js', 23 | path: path.resolve(__dirname, 'dist'), 24 | libraryTarget: 'umd', 25 | library: 'Mwck', 26 | umdNamedDefine: true, 27 | globalObject: 'this', 28 | }, 29 | }; 30 | 31 | const commonJSConfig = { 32 | ...common, 33 | target: 'node', 34 | output: { 35 | filename: 'index.js', 36 | path: path.resolve(__dirname, 'dist'), 37 | libraryTarget: 'commonjs2', 38 | }, 39 | }; 40 | 41 | const esmConfig = { 42 | ...common, 43 | output: { 44 | filename: 'index.esm.js', 45 | path: path.resolve(__dirname, 'dist'), 46 | }, 47 | optimization: { 48 | runtimeChunk: false 49 | } 50 | }; 51 | 52 | module.exports = [umdConfig, commonJSConfig, esmConfig]; 53 | --------------------------------------------------------------------------------