diff --git a/.env b/.env index 1348d8552b..095a69072e 100644 --- a/.env +++ b/.env @@ -172,12 +172,15 @@ STACKS_NODE_TYPE=L1 # STACKS_ADDRESS_CACHE_SIZE=10000 # Specify a URL to redirect from /doc. If this URL is not provided, server renders local documentation -# of openapi.yaml for test / development NODE_ENV. +# of openapi.yaml for test / development NODE_ENV. # For production, /doc is not served if this env var is not provided. -# API_DOCS_URL="https://docs.hiro.so/api" +# API_DOCS_URL="https://docs.hiro.so/api" -# For use while syncing. Places the API into an "Initial Block Download(IBD)" mode, -# forcing it to stop any redundant processing until the node is fully synced up to its peers. -# Some examples of processing that are avoided are: +# For use while syncing. Places the API into an "Initial Block Download(IBD)" mode, +# forcing it to stop any redundant processing until the node is fully synced up to its peers. +# Some examples of processing that are avoided are: # REFRESH MATERIALIZED VIEW SQLs that are extremely CPU intensive on the PG instance, Mempool messages, etc., # IBD_MODE_UNTIL_BLOCK= + +# Folder with events to be imported by the event-replay. +STACKS_EVENTS_DIR=./eventssds diff --git a/Dockerfile b/Dockerfile index 6fbabe3c65..cc9a9afa19 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,18 @@ RUN echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env RUN npm config set unsafe-perm true && npm ci && npm run build && npm run build:docs && npm prune --production RUN apk del .build-deps +# As no pre-built binaries of duckdb can be found for Alpine (musl based), +# a rebuild of duckdb package is need. +# +# Library used by the event-replay based on parquet files. +ARG DUCKDB_VERSION=0.8.1 +WORKDIR /duckdb +RUN apk add --no-cache --virtual .duckdb-build-deps python3 git g++ make +RUN git clone https://github.com/duckdb/duckdb.git -b v${DUCKDB_VERSION} --depth 1 \ + && cd duckdb/tools/nodejs \ + && ./configure && make all +WORKDIR /app +RUN npm uninstall duckdb && npm install /duckdb/duckdb/tools/nodejs +RUN apk del .duckdb-build-deps + CMD ["node", "./lib/index.js"] diff --git a/README.md b/README.md index 767edec8e5..511d436f9d 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,23 @@ The feature can be used via program args. For example, if there are breaking cha SQL schema, like adding a new column that requires events to be re-played, the following steps could be run: -### Event Replay Instructions +### Event Replay V2 -#### V1 BNS Data +This version of the replay process relies on parquet files processing instead of TSV files. + +There are some improvements on the replay process and this version is is, around, 10x times faster than the previous (V1) one. + +__Note: the previous event-replay version is still available and can be used as well, for the same purpose.__ + +#### Instructions + +To run the new event-replay, please follow the instructions at [stacks-event-replay](https://github.com/hirosystems/stacks-event-replay#installation) repository. + +### Event Replay V1 + +#### Instructions + +##### V1 BNS Data **Optional but recommended** - If you want the V1 BNS data, there are going to be a few extra steps: @@ -139,7 +153,7 @@ could be run: ``` 1. Set the data's location as the value of `BNS_IMPORT_DIR` in your `.env` file. -#### Export and Import +##### Export and Import 1. Ensure the API process is not running. When stopping the API, let the process exit gracefully so that any in-progress SQL writes can finish. diff --git a/migrations/1620937804009_microblocks.js b/migrations/1620937804009_microblocks.js index a5731fb70d..46eae6314b 100644 --- a/migrations/1620937804009_microblocks.js +++ b/migrations/1620937804009_microblocks.js @@ -26,7 +26,7 @@ exports.up = pgm => { type: 'integer', notNull: true, }, - // For the first microblock (sequence number 0), this points to the parent/anchor block hash, + // For the first microblock (sequence number 0), this points to the parent/anchor block hash, // for subsequent microblocks it points to the previous microblock's hash. microblock_parent_hash: { type: 'bytea', diff --git a/migrations/1621511823381_nft_metadata.js b/migrations/1621511823381_nft_metadata.js index fe5981a200..c2906eb73c 100644 --- a/migrations/1621511823381_nft_metadata.js +++ b/migrations/1621511823381_nft_metadata.js @@ -20,14 +20,14 @@ exports.up = pgm => { image_uri: { type: 'string', notNull: true, - }, + }, image_canonical_uri: { - type: 'string', + type: 'string', notNull: true, - }, + }, contract_id: { - type: 'string', - notNull: true, + type: 'string', + notNull: true, unique: true, }, tx_id: { @@ -35,8 +35,8 @@ exports.up = pgm => { notNull: true, }, sender_address: { - type: 'string', - notNull: true, + type: 'string', + notNull: true, } }); diff --git a/migrations/1621511832113_ft_metadata.js b/migrations/1621511832113_ft_metadata.js index 4010df1b6b..7bd68731f9 100644 --- a/migrations/1621511832113_ft_metadata.js +++ b/migrations/1621511832113_ft_metadata.js @@ -20,31 +20,31 @@ exports.up = pgm => { image_uri: { type: 'string', notNull: true, - }, + }, image_canonical_uri: { - type: 'string', + type: 'string', notNull: true, - }, + }, contract_id: { - type: 'string', - notNull: true, + type: 'string', + notNull: true, unique: true, }, symbol: { - type: 'string', - notNull: true, + type: 'string', + notNull: true, }, decimals: { - type: 'integer', - notNull: true, + type: 'integer', + notNull: true, }, tx_id: { type: 'bytea', notNull: true, }, sender_address: { - type: 'string', - notNull: true, + type: 'string', + notNull: true, } }); diff --git a/migrations/1666703991492_pox_events.js b/migrations/1666703991492_pox_events.js index eeb44393ca..46240ebdee 100644 --- a/migrations/1666703991492_pox_events.js +++ b/migrations/1666703991492_pox_events.js @@ -132,46 +132,46 @@ exports.up = pgm => { }); pgm.addConstraint('pox2_events', 'valid_event_specific_columns', `CHECK ( - CASE name - WHEN 'handle-unlock' THEN - first_cycle_locked IS NOT NULL AND + CASE name + WHEN 'handle-unlock' THEN + first_cycle_locked IS NOT NULL AND first_unlocked_cycle IS NOT NULL WHEN 'stack-stx' THEN - lock_period IS NOT NULL AND - lock_amount IS NOT NULL AND - start_burn_height IS NOT NULL AND + lock_period IS NOT NULL AND + lock_amount IS NOT NULL AND + start_burn_height IS NOT NULL AND unlock_burn_height IS NOT NULL WHEN 'stack-increase' THEN - increase_by IS NOT NULL AND + increase_by IS NOT NULL AND total_locked IS NOT NULL WHEN 'stack-extend' THEN - extend_count IS NOT NULL AND + extend_count IS NOT NULL AND unlock_burn_height IS NOT NULL WHEN 'delegate-stx' THEN - amount_ustx IS NOT NULL AND + amount_ustx IS NOT NULL AND delegate_to IS NOT NULL WHEN 'delegate-stack-stx' THEN - lock_period IS NOT NULL AND - lock_amount IS NOT NULL AND - start_burn_height IS NOT NULL AND - unlock_burn_height IS NOT NULL AND + lock_period IS NOT NULL AND + lock_amount IS NOT NULL AND + start_burn_height IS NOT NULL AND + unlock_burn_height IS NOT NULL AND delegator IS NOT NULL WHEN 'delegate-stack-increase' THEN - increase_by IS NOT NULL AND + increase_by IS NOT NULL AND total_locked IS NOT NULL AND delegator IS NOT NULL WHEN 'delegate-stack-extend' THEN - extend_count IS NOT NULL AND - unlock_burn_height IS NOT NULL AND + extend_count IS NOT NULL AND + unlock_burn_height IS NOT NULL AND delegator IS NOT NULL WHEN 'stack-aggregation-commit' THEN - reward_cycle IS NOT NULL AND + reward_cycle IS NOT NULL AND amount_ustx IS NOT NULL WHEN 'stack-aggregation-commit-indexed' THEN - reward_cycle IS NOT NULL AND + reward_cycle IS NOT NULL AND amount_ustx IS NOT NULL WHEN 'stack-aggregation-increase' THEN - reward_cycle IS NOT NULL AND + reward_cycle IS NOT NULL AND amount_ustx IS NOT NULL ELSE false END diff --git a/package-lock.json b/package-lock.json index d085dd8f92..8acde7fd38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "cross-env": "7.0.3", "dotenv": "8.6.0", "dotenv-flow": "3.2.0", + "duckdb": "0.8.1", "ecpair": "2.1.0", "elliptic": "6.5.4", "escape-goat": "3.0.0", @@ -318,9 +319,9 @@ } }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -368,9 +369,9 @@ } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -1119,6 +1120,95 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1455,7 +1545,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", - "optional": true, "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -1471,20 +1560,10 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "optional": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "optional": true, "dependencies": { "glob": "^7.1.3" }, @@ -1496,18 +1575,17 @@ } }, "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "optional": true, + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/@microsoft/tsdoc": { @@ -1598,6 +1676,31 @@ "node": ">= 8" } }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@octokit/auth-token": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", @@ -1784,6 +1887,15 @@ "@octokit/openapi-types": "^11.2.0" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@promster/express": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@promster/express/-/express-6.0.0.tgz", @@ -2257,28 +2369,19 @@ "node": ">=10.13.0" } }, - "node_modules/@stacks/eslint-config/node_modules/lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@stacks/eslint-config/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/@stacks/network": { @@ -2912,28 +3015,19 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/@typescript-eslint/experimental-utils": { @@ -3034,28 +3128,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@typescript-eslint/experimental-utils/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/@typescript-eslint/parser": { @@ -3168,28 +3253,19 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/@typescript-eslint/utils": { @@ -3242,8 +3318,7 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "devOptional": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/abort-controller": { "version": "3.0.0", @@ -3324,7 +3399,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "devOptional": true, "dependencies": { "debug": "4" }, @@ -3332,6 +3406,39 @@ "node": ">= 6.0.0" } }, + "node_modules/agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "dependencies": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/agentkeepalive/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -3420,14 +3527,12 @@ "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -3806,7 +3911,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3978,6 +4082,98 @@ "node": ">=8" } }, + "node_modules/cacache": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.3.tgz", + "integrity": "sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/fs-minipass": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", + "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", + "dependencies": { + "minipass": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -4106,7 +4302,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true, "engines": { "node": ">=10" } @@ -4132,6 +4327,14 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -4198,7 +4401,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true, "bin": { "color-support": "bin.js" } @@ -4244,8 +4446,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "devOptional": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/concurrently": { "version": "7.3.0", @@ -4335,8 +4536,7 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "optional": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "node_modules/content-disposition": { "version": "0.5.4", @@ -4722,8 +4922,7 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "optional": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "node_modules/depd": { "version": "1.1.2", @@ -4867,6 +5066,22 @@ "node": ">= 8.0.0" } }, + "node_modules/duckdb": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/duckdb/-/duckdb-0.8.1.tgz", + "integrity": "sha512-a2SJDuvBVKy5muYFxXTANlqdNX1daF3NHzpqRdrk0Qx5n3Sh7BxL66O+WY9epaDFukiXEpz45sds5T1LaPaHog==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "*", + "node-gyp": "^9.3.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -4939,6 +5154,27 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -5041,6 +5277,19 @@ "node": ">=8.6" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -5760,6 +6009,11 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, "node_modules/express": { "version": "4.17.3", "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", @@ -6047,6 +6301,32 @@ } } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -6113,7 +6393,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "optional": true, "dependencies": { "minipass": "^3.0.0" }, @@ -6155,7 +6434,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -6284,7 +6562,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "devOptional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6361,8 +6638,7 @@ "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/har-schema": { "version": "2.0.0", @@ -6453,8 +6729,7 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "optional": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "node_modules/hash-base": { "version": "3.1.0", @@ -6564,6 +6839,11 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, "node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -6639,7 +6919,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "devOptional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -6657,6 +6936,14 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/husky": { "version": "4.3.8", "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", @@ -6814,7 +7101,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, "engines": { "node": ">=0.8.19" } @@ -6823,7 +7109,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "engines": { "node": ">=8" } @@ -6862,6 +7147,11 @@ "node": ">= 0.4" } }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -7002,7 +7292,12 @@ "node": ">=0.10.0" } }, - "node_modules/is-negative-zero": { + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, + "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", @@ -7222,9 +7517,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -7271,6 +7566,23 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -8242,7 +8554,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "devOptional": true, "dependencies": { "semver": "^6.0.0" }, @@ -8254,10 +8565,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "devOptional": true, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -8268,6 +8578,68 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -8475,7 +8847,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8515,7 +8886,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "optional": true, "dependencies": { "yallist": "^4.0.0" }, @@ -8523,11 +8893,78 @@ "node": ">=8" } }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", + "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", + "dependencies": { + "minipass": "^5.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "optional": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -8593,6 +9030,11 @@ "node": ">= 10.13" } }, + "node_modules/node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -8631,6 +9073,30 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/node-gyp": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", + "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, "node_modules/node-gyp-build": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", @@ -8642,6 +9108,92 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -8786,9 +9338,9 @@ } }, "node_modules/nodemon/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -8810,7 +9362,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, "dependencies": { "abbrev": "1" }, @@ -8836,28 +9387,19 @@ "node": ">=10" } }, - "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=10" } }, "node_modules/normalize-path": { @@ -8884,7 +9426,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -9096,6 +9637,20 @@ "node": ">=8" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-queue": { "version": "6.6.2", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", @@ -9193,7 +9748,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -9213,13 +9767,12 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.4.tgz", - "integrity": "sha512-Qp/9IHkdNiXJ3/Kon++At2nVpnhRiPq/aSvQN+H3U1WZbvNRK0RIQK/o4HMqPoXjpuGJUEWpHSs6Mnjxqh3TQg==", - "dev": true, + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dependencies": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -9229,10 +9782,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.0.1.tgz", - "integrity": "sha512-C8QsKIN1UIXeOs3iWmiZ1lQY+EnKDojWd37fXy1aSbJvH4iSma1uy2OWuoB3m4SYRli5+CUjDv3Dij5DVoetmg==", - "dev": true, + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", "engines": { "node": "14 || >=16.14" } @@ -9241,7 +9793,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -9765,6 +10316,18 @@ "node": ">=10" } }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -9987,9 +10550,9 @@ } }, "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -10261,6 +10824,14 @@ "node": ">=10" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10590,8 +11161,7 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "devOptional": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -10658,8 +11228,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-update-notifier": { "version": "1.0.7", @@ -10697,6 +11266,15 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/socket.io": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", @@ -10768,6 +11346,32 @@ "node": ">=10.0.0" } }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/sonic-boom": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", @@ -10869,6 +11473,25 @@ "node": ">=0.10.0" } }, + "node_modules/ssri": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", + "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", + "dependencies": { + "minipass": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -10965,6 +11588,20 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", @@ -11002,6 +11639,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -11186,7 +11835,6 @@ "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "optional": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -11705,6 +12353,28 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -11999,7 +12669,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -12104,9 +12773,9 @@ } }, "node_modules/windows-release/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -12170,6 +12839,23 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -12446,9 +13132,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -12485,9 +13171,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -13059,6 +13745,64 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -13332,7 +14076,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", - "optional": true, "requires": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -13345,28 +14088,20 @@ "tar": "^6.1.11" }, "dependencies": { - "lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "optional": true - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "optional": true, "requires": { "glob": "^7.1.3" } }, "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "optional": true, + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" } } } @@ -13437,6 +14172,24 @@ "fastq": "^1.6.0" } }, + "@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "requires": { + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "@octokit/auth-token": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", @@ -13627,6 +14380,12 @@ "@octokit/openapi-types": "^11.2.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, "@promster/express": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@promster/express/-/express-6.0.0.tgz", @@ -13969,19 +14728,13 @@ "is-glob": "^4.0.3" } }, - "lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true - }, "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" } } } @@ -14589,19 +15342,13 @@ "tsutils": "^3.21.0" }, "dependencies": { - "lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true - }, "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" } } } @@ -14661,19 +15408,13 @@ "eslint-visitor-keys": "^3.0.0" } }, - "lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true - }, "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" } } } @@ -14732,19 +15473,13 @@ "tsutils": "^3.21.0" }, "dependencies": { - "lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true - }, "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" } } } @@ -14782,8 +15517,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "devOptional": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "abort-controller": { "version": "3.0.0", @@ -14843,11 +15577,36 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "devOptional": true, "requires": { "debug": "4" } }, + "agentkeepalive": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "requires": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -14907,14 +15666,12 @@ "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "optional": true + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -15212,7 +15969,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -15335,6 +16091,73 @@ "cross-sha256": "^1.2.0" } }, + "cacache": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.3.tgz", + "integrity": "sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==", + "requires": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "fs-minipass": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", + "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", + "requires": { + "minipass": "^5.0.0" + } + }, + "glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + } + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -15417,8 +16240,7 @@ "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "ci-info": { "version": "3.3.0", @@ -15441,6 +16263,11 @@ "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", "dev": true }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -15498,8 +16325,7 @@ "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "colorette": { "version": "2.0.20", @@ -15539,8 +16365,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "devOptional": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concurrently": { "version": "7.3.0", @@ -15611,8 +16436,7 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "optional": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "content-disposition": { "version": "0.5.4", @@ -15912,8 +16736,7 @@ "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "optional": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "depd": { "version": "1.1.2", @@ -16020,6 +16843,21 @@ "dotenv": "^8.0.0" } }, + "duckdb": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/duckdb/-/duckdb-0.8.1.tgz", + "integrity": "sha512-a2SJDuvBVKy5muYFxXTANlqdNX1daF3NHzpqRdrk0Qx5n3Sh7BxL66O+WY9epaDFukiXEpz45sds5T1LaPaHog==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "*", + "node-gyp": "^9.3.0" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -16080,6 +16918,26 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -16149,6 +17007,16 @@ "ansi-colors": "^4.1.1" } }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -16694,6 +17562,11 @@ "jest-message-util": "^27.5.1" } }, + "exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" + }, "express": { "version": "4.17.3", "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", @@ -16931,6 +17804,22 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==" + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -16978,7 +17867,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "optional": true, "requires": { "minipass": "^3.0.0" } @@ -17010,7 +17898,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, "requires": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -17103,7 +17990,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "devOptional": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -17156,8 +18042,7 @@ "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "har-schema": { "version": "2.0.0", @@ -17217,8 +18102,7 @@ "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "optional": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "hash-base": { "version": "3.1.0", @@ -17312,6 +18196,11 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, "http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -17371,7 +18260,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "devOptional": true, "requires": { "agent-base": "6", "debug": "4" @@ -17383,6 +18271,14 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "requires": { + "ms": "^2.0.0" + } + }, "husky": { "version": "4.3.8", "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", @@ -17489,14 +18385,12 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, "inflight": { "version": "1.0.6", @@ -17529,6 +18423,11 @@ "side-channel": "^1.0.4" } }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -17624,6 +18523,11 @@ "is-extglob": "^2.1.1" } }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -17776,9 +18680,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -17815,6 +18719,15 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -18583,16 +19496,14 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "devOptional": true, "requires": { "semver": "^6.0.0" }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "devOptional": true + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -18602,6 +19513,55 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "dependencies": { + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + } + } + }, "makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -18759,7 +19719,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -18792,16 +19751,64 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "optional": true, "requires": { "yallist": "^4.0.0" } }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", + "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", + "requires": { + "encoding": "^0.1.13", + "minipass": "^5.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + } + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "requires": { + "minipass": "^3.0.0" + } + }, "minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "optional": true, "requires": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -18852,6 +19859,11 @@ "propagate": "^2.0.0" } }, + "node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -18881,6 +19893,85 @@ } } }, + "node-gyp": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", + "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "requires": { + "abbrev": "^1.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "node-gyp-build": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", @@ -18995,9 +20086,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "supports-color": { @@ -19015,7 +20106,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, "requires": { "abbrev": "1" } @@ -19032,19 +20122,13 @@ "validate-npm-package-license": "^3.0.1" }, "dependencies": { - "lru-cache": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", - "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", - "dev": true - }, "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { - "lru-cache": "^7.4.0" + "lru-cache": "^6.0.0" } } } @@ -19067,7 +20151,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, "requires": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -19225,6 +20308,14 @@ "p-limit": "^2.2.0" } }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-queue": { "version": "6.6.2", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", @@ -19294,8 +20385,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "devOptional": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", @@ -19309,26 +20399,23 @@ "dev": true }, "path-scurry": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.6.4.tgz", - "integrity": "sha512-Qp/9IHkdNiXJ3/Kon++At2nVpnhRiPq/aSvQN+H3U1WZbvNRK0RIQK/o4HMqPoXjpuGJUEWpHSs6Mnjxqh3TQg==", - "dev": true, + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "requires": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.0.1.tgz", - "integrity": "sha512-C8QsKIN1UIXeOs3iWmiZ1lQY+EnKDojWd37fXy1aSbJvH4iSma1uy2OWuoB3m4SYRli5+CUjDv3Dij5DVoetmg==", - "dev": true + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", + "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==" }, "minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" } } }, @@ -19709,6 +20796,15 @@ "tdigest": "^0.1.1" } }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -19853,9 +20949,9 @@ } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "type-fest": { @@ -20074,6 +21170,11 @@ "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", "dev": true }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -20307,8 +21408,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "devOptional": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setprototypeof": { "version": "1.2.0", @@ -20363,8 +21463,7 @@ "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-update-notifier": { "version": "1.0.7", @@ -20395,6 +21494,11 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, "socket.io": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", @@ -20445,6 +21549,25 @@ "debug": "~4.3.1" } }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, "sonic-boom": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", @@ -20535,6 +21658,21 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", + "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", + "requires": { + "minipass": "^5.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + } + } + }, "stack-utils": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", @@ -20617,6 +21755,16 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "string.prototype.trimend": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", @@ -20645,6 +21793,14 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -20791,7 +21947,6 @@ "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "optional": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -21155,6 +22310,22 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "requires": { + "unique-slug": "^4.0.0" + } + }, + "unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, "universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -21395,7 +22566,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, "requires": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -21476,9 +22646,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "shebang-command": { @@ -21523,6 +22693,16 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 578f7a297b..f304f73a26 100644 --- a/package.json +++ b/package.json @@ -160,6 +160,7 @@ "cross-env": "7.0.3", "dotenv": "8.6.0", "dotenv-flow": "3.2.0", + "duckdb": "0.8.1", "ecpair": "2.1.0", "elliptic": "6.5.4", "escape-goat": "3.0.0", diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 7a0a2062a8..6d60242b22 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -704,6 +704,7 @@ export interface DbBnsSubdomain { tx_id: string; tx_index: number; canonical: boolean; + index_block_hash?: string; } export interface DbConfigState { @@ -1219,6 +1220,11 @@ export interface StxLockEventInsertValues { contract_name: string; } +export interface RawEventRequestInsertValues { + event_path: string; + payload: string; +} + export interface Pox2EventQueryResult { event_index: number; tx_id: string; @@ -1552,3 +1558,8 @@ export interface DbChainTip { indexBlockHash: string; burnBlockHeight: number; } + +export enum IndexesState { + Off = 0, + On = 1, +} diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 07b1614060..5d843beed8 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -63,6 +63,8 @@ import { DbMempoolTxRaw, DbChainTip, DbPox3Event, + RawEventRequestInsertValues, + IndexesState, } from './common'; import { ClarityAbi } from '@stacks/transactions'; import { @@ -95,6 +97,8 @@ import { parseResolver, parseZoneFileTxt } from '../event-stream/bns/bns-helpers import { Pox2EventName } from '../pox-helpers'; import { logger } from '../logger'; +const MIGRATIONS_TABLE = 'pgmigrations'; + class MicroblockGapError extends Error { constructor(message: string) { super(message); @@ -552,6 +556,32 @@ export class PgWriteStore extends PgStore { return result.count; } + async insertStxEventBatch(sql: PgSqlClient, stxEvents: StxEventInsertValues[]) { + const values = stxEvents.map(s => { + const value: StxEventInsertValues = { + event_index: s.event_index, + tx_id: s.tx_id, + tx_index: s.tx_index, + block_height: s.block_height, + index_block_hash: s.index_block_hash, + parent_index_block_hash: s.parent_index_block_hash, + microblock_hash: s.microblock_hash, + microblock_sequence: s.microblock_sequence, + microblock_canonical: s.microblock_canonical, + canonical: s.canonical, + asset_event_type_id: s.asset_event_type_id, + sender: s.sender, + recipient: s.recipient, + amount: s.amount, + memo: s.memo ?? null, + }; + return value; + }); + await sql` + INSERT INTO stx_events ${sql(values)} + `; + } + async updateBurnchainRewardSlotHolders({ burnchainBlockHash, burnchainBlockHeight, @@ -1580,6 +1610,7 @@ export class PgWriteStore extends PgStore { (burn_block_hash = ${burnchainBlockHash} OR burn_block_height >= ${burnchainBlockHeight}) `; + if (existingRewards.count > 0) { logger.warn( `Invalidated ${existingRewards.count} burnchain rewards after fork detected at burnchain block ${burnchainBlockHash}` @@ -1606,6 +1637,44 @@ export class PgWriteStore extends PgStore { }); } + async insertSlotHoldersBatch(sql: PgSqlClient, slotHolders: DbRewardSlotHolder[]): Promise { + const slotValues: RewardSlotHolderInsertValues[] = slotHolders.map(slot => ({ + canonical: true, + burn_block_hash: slot.burn_block_hash, + burn_block_height: slot.burn_block_height, + address: slot.address, + slot_index: slot.slot_index, + })); + + const result = await sql` + INSERT INTO reward_slot_holders ${sql(slotValues)} + `; + + if (result.count !== slotValues.length) { + throw new Error(`Failed to insert slot holder for ${slotValues}`); + } + } + + async insertBurnchainRewardsBatch(sql: PgSqlClient, rewards: DbBurnchainReward[]): Promise { + const rewardValues: BurnchainRewardInsertValues[] = rewards.map(reward => ({ + canonical: true, + burn_block_hash: reward.burn_block_hash, + burn_block_height: reward.burn_block_height, + burn_amount: reward.burn_amount.toString(), + reward_recipient: reward.reward_recipient, + reward_amount: reward.reward_amount, + reward_index: reward.reward_index, + })); + + const res = await sql` + INSERT into burnchain_rewards ${sql(rewardValues)} + `; + + if (res.count !== rewardValues.length) { + throw new Error(`Failed to insert burnchain reward for ${rewardValues}`); + } + } + async updateTx(sql: PgSqlClient, tx: DbTxRaw): Promise { const values: TxInsertValues = { tx_id: tx.tx_id, @@ -2957,7 +3026,7 @@ export class PgWriteStore extends PgStore { } /** - * Called when a full event import is complete. + * (event-replay) Finishes DB setup after an event-replay. */ async finishEventReplay() { if (!this.isEventReplay) { @@ -2970,4 +3039,260 @@ export class PgWriteStore extends PgStore { await this.refreshMaterializedView('mempool_digest', sql, false); }); } + + /** + * batch operations (mainly for event-replay) + */ + + async insertBlockBatch(sql: PgSqlClient, blocks: DbBlock[]) { + const values: BlockInsertValues[] = blocks.map(block => ({ + block_hash: block.block_hash, + index_block_hash: block.index_block_hash, + parent_index_block_hash: block.parent_index_block_hash, + parent_block_hash: block.parent_block_hash, + parent_microblock_hash: block.parent_microblock_hash, + parent_microblock_sequence: block.parent_microblock_sequence, + block_height: block.block_height, + burn_block_time: block.burn_block_time, + burn_block_hash: block.burn_block_hash, + burn_block_height: block.burn_block_height, + miner_txid: block.miner_txid, + canonical: block.canonical, + execution_cost_read_count: block.execution_cost_read_count, + execution_cost_read_length: block.execution_cost_read_length, + execution_cost_runtime: block.execution_cost_runtime, + execution_cost_write_count: block.execution_cost_write_count, + execution_cost_write_length: block.execution_cost_write_length, + })); + await sql` + INSERT INTO blocks ${sql(values)} + `; + } + + async insertMicroblock(sql: PgSqlClient, microblocks: DbMicroblock[]): Promise { + const values: MicroblockInsertValues[] = microblocks.map(mb => ({ + canonical: mb.canonical, + microblock_canonical: mb.microblock_canonical, + microblock_hash: mb.microblock_hash, + microblock_sequence: mb.microblock_sequence, + microblock_parent_hash: mb.microblock_parent_hash, + parent_index_block_hash: mb.parent_index_block_hash, + block_height: mb.block_height, + parent_block_height: mb.parent_block_height, + parent_block_hash: mb.parent_block_hash, + index_block_hash: mb.index_block_hash, + block_hash: mb.block_hash, + parent_burn_block_height: mb.parent_burn_block_height, + parent_burn_block_hash: mb.parent_burn_block_hash, + parent_burn_block_time: mb.parent_burn_block_time, + })); + const mbResult = await sql` + INSERT INTO microblocks ${sql(values)} + `; + if (mbResult.count !== microblocks.length) { + throw new Error( + `Unexpected row count after inserting microblocks: ${mbResult.count} vs ${values.length}` + ); + } + } + + // alias to insertMicroblock + async insertMicroblockBatch(sql: PgSqlClient, microblocks: DbMicroblock[]): Promise { + return this.insertMicroblock(sql, microblocks); + } + + async insertTxBatch(sql: PgSqlClient, txs: DbTx[]): Promise { + const values: TxInsertValues[] = txs.map(tx => ({ + tx_id: tx.tx_id, + raw_tx: tx.raw_result, + tx_index: tx.tx_index, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + block_hash: tx.block_hash, + parent_block_hash: tx.parent_block_hash, + block_height: tx.block_height, + burn_block_time: tx.burn_block_time, + parent_burn_block_time: tx.parent_burn_block_time, + type_id: tx.type_id, + anchor_mode: tx.anchor_mode, + status: tx.status, + canonical: tx.canonical, + post_conditions: tx.post_conditions, + nonce: tx.nonce, + fee_rate: tx.fee_rate, + sponsored: tx.sponsored, + sponsor_nonce: tx.sponsor_nonce ?? null, + sponsor_address: tx.sponsor_address ?? null, + sender_address: tx.sender_address, + origin_hash_mode: tx.origin_hash_mode, + microblock_canonical: tx.microblock_canonical, + microblock_sequence: tx.microblock_sequence, + microblock_hash: tx.microblock_hash, + token_transfer_recipient_address: tx.token_transfer_recipient_address ?? null, + token_transfer_amount: tx.token_transfer_amount ?? null, + token_transfer_memo: tx.token_transfer_memo ?? null, + smart_contract_clarity_version: tx.smart_contract_clarity_version ?? null, + smart_contract_contract_id: tx.smart_contract_contract_id ?? null, + smart_contract_source_code: tx.smart_contract_source_code ?? null, + contract_call_contract_id: tx.contract_call_contract_id ?? null, + contract_call_function_name: tx.contract_call_function_name ?? null, + contract_call_function_args: tx.contract_call_function_args ?? null, + poison_microblock_header_1: tx.poison_microblock_header_1 ?? null, + poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, + coinbase_payload: tx.coinbase_payload ?? null, + coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, + raw_result: tx.raw_result, + event_count: tx.event_count, + execution_cost_read_count: tx.execution_cost_read_count, + execution_cost_read_length: tx.execution_cost_read_length, + execution_cost_runtime: tx.execution_cost_runtime, + execution_cost_write_count: tx.execution_cost_write_count, + execution_cost_write_length: tx.execution_cost_write_length, + })); + await sql`INSERT INTO txs ${sql(values)}`; + } + + async insertPrincipalStxTxsBatch(sql: PgSqlClient, values: PrincipalStxTxsInsertValues[]) { + await sql` + INSERT INTO principal_stx_txs ${sql(values)} + `; + } + + async insertContractEventBatch(sql: PgSqlClient, values: SmartContractEventInsertValues[]) { + await sql` + INSERT INTO contract_logs ${sql(values)} + `; + } + + async insertFtEventBatch(sql: PgSqlClient, values: FtEventInsertValues[]) { + await sql` + INSERT INTO ft_events ${sql(values)} + `; + } + + async insertNftEventBatch(sql: PgSqlClient, values: NftEventInsertValues[]) { + await sql`INSERT INTO nft_events ${sql(values)}`; + } + + async insertNameBatch(sql: PgSqlClient, values: BnsNameInsertValues[]) { + await sql` + INSERT INTO names ${sql(values)} + `; + } + + async insertNamespace( + sql: PgSqlClient, + blockData: { + index_block_hash: string; + parent_index_block_hash: string; + microblock_hash: string; + microblock_sequence: number; + microblock_canonical: boolean; + }, + bnsNamespace: DbBnsNamespace + ) { + const values: BnsNamespaceInsertValues = { + namespace_id: bnsNamespace.namespace_id, + launched_at: bnsNamespace.launched_at ?? null, + address: bnsNamespace.address, + reveal_block: bnsNamespace.reveal_block, + ready_block: bnsNamespace.ready_block, + buckets: bnsNamespace.buckets, + base: bnsNamespace.base.toString(), + coeff: bnsNamespace.coeff.toString(), + nonalpha_discount: bnsNamespace.nonalpha_discount.toString(), + no_vowel_discount: bnsNamespace.no_vowel_discount.toString(), + lifetime: bnsNamespace.lifetime, + status: bnsNamespace.status ?? null, + tx_index: bnsNamespace.tx_index, + tx_id: bnsNamespace.tx_id, + canonical: bnsNamespace.canonical, + index_block_hash: blockData.index_block_hash, + parent_index_block_hash: blockData.parent_index_block_hash, + microblock_hash: blockData.microblock_hash, + microblock_sequence: blockData.microblock_sequence, + microblock_canonical: blockData.microblock_canonical, + }; + await sql` + INSERT INTO namespaces ${sql(values)} + `; + } + + async insertZonefileBatch(sql: PgSqlClient, values: BnsZonefileInsertValues[]) { + await sql` + INSERT INTO zonefiles ${sql(values)} + `; + } + + async insertRawEventRequestBatch( + sql: PgSqlClient, + events: RawEventRequestInsertValues[] + ): Promise { + await sql` + INSERT INTO event_observer_requests ${this.sql(events)} + `; + } + + /** + * (event-replay) Enable or disable indexes for DB tables. + */ + async toggleAllTableIndexes(sql: PgSqlClient, state: IndexesState): Promise { + const enable: boolean = Boolean(state); + const dbName = sql.options.database; + const tableSchema = sql.options.connection.search_path ?? 'public'; + const tablesQuery = await sql<{ tablename: string }[]>` + SELECT tablename FROM pg_catalog.pg_tables + WHERE tablename != ${MIGRATIONS_TABLE} + AND schemaname = ${tableSchema}`; + if (tablesQuery.length === 0) { + const errorMsg = `No tables found in database '${dbName}', schema '${tableSchema}'`; + console.error(errorMsg); + throw new Error(errorMsg); + } + const tables: string[] = tablesQuery.map((r: { tablename: string }) => r.tablename); + + // Exclude subdomains table since its constraints + // are need to handle the ingestion of attachments_new events. + const filtered = tables.filter(item => item !== 'subdomains'); + + const result = await sql` + UPDATE pg_index + SET ${sql({ indisready: enable, indisvalid: enable })} + WHERE indrelid = ANY ( + SELECT oid FROM pg_class + WHERE relname IN ${sql(filtered)} + AND relnamespace = ( + SELECT oid FROM pg_namespace WHERE nspname = ${tableSchema} + ) + ) + `; + if (result.count === 0) { + throw new Error(`No updates made while toggling table indexes`); + } + } + + /** + * (event-replay) Reindex all DB tables. + */ + async reindexAllTables(sql: PgSqlClient): Promise { + const dbName = sql.options.database; + const tableSchema = sql.options.connection.search_path ?? 'public'; + const tablesQuery = await sql<{ tablename: string }[]>` + SELECT tablename FROM pg_catalog.pg_tables + WHERE tablename != ${MIGRATIONS_TABLE} + AND schemaname = ${tableSchema}`; + if (tablesQuery.length === 0) { + const errorMsg = `No tables found in database '${dbName}', schema '${tableSchema}'`; + console.error(errorMsg); + throw new Error(errorMsg); + } + const tables: string[] = tablesQuery.map((r: { tablename: string }) => r.tablename); + + for (const table of tables) { + const result = await sql`REINDEX TABLE ${sql(table)}`; + if (result.count === 0) { + throw new Error(`No updates made while toggling table indexes`); + } + } + } } diff --git a/src/event-replay/parquet-based/dataset/store.ts b/src/event-replay/parquet-based/dataset/store.ts new file mode 100644 index 0000000000..1b1c29723e --- /dev/null +++ b/src/event-replay/parquet-based/dataset/store.ts @@ -0,0 +1,162 @@ +import { loadDotEnv } from '../../../helpers'; +import { Database, QueryResult, TableData } from 'duckdb'; + +loadDotEnv(); + +const EVENTS_DIR = process.env.STACKS_EVENTS_DIR; + +export class DatasetStore { + private readonly db; + + constructor() { + this.db = new Database(':memory:'); + } + + static connect(): DatasetStore { + return new DatasetStore(); + } + + // + // NEW_BLOCK EVENTS + // + + newBlockEventsIds = (): Promise => { + const con = this.db.connect(); + return new Promise(resolve => { + con.all( + `SELECT id FROM READ_PARQUET('${EVENTS_DIR}/new_block/canonical/*.parquet')`, + (err: any, result: any) => { + if (err) { + throw err; + } + + const res: number[] = result.map((a: { id: number }) => a.id); // extract IDs as an Array + resolve(res); + } + ); + }); + }; + + newBlockEventsPayloadStream = (ids: number[]): Promise => { + return new Promise(resolve => { + const con = this.db.connect(); + const res = con.stream( + `SELECT payload FROM READ_PARQUET('${EVENTS_DIR}/new_block/canonical/*.parquet') WHERE id IN (${ids}) ORDER BY id` + ); + + resolve(res); + }); + }; + + // + // NEW_BURN_BLOCK EVENTS + // + + newBurnBlockEventsOrdered = () => { + return new Promise(resolve => { + const con = this.db.connect(); + con.all( + `SELECT * FROM READ_PARQUET('${EVENTS_DIR}/new_burn_block/canonical/*.parquet') ORDER BY id`, + (err: any, result: any) => { + if (err) { + throw err; + } + + resolve(result); + } + ); + }); + }; + + // + // ATTACHMENTS_NEW EVENTS + // + + attachmentsCanonicalEvents = (): Promise => { + const con = this.db.connect(); + return new Promise(resolve => { + const res = con.stream( + `SELECT payload FROM READ_PARQUET('${EVENTS_DIR}/attachments_new/canonical/*.parquet') ORDER BY id` + ); + + resolve(res); + }); + }; + + // + // RAW EVENTS + // + + rawEvents = (): Promise => { + return new Promise(resolve => { + const con = this.db.connect(); + con.all( + `SELECT method, payload FROM READ_PARQUET([ + '${EVENTS_DIR}/new_burn_block/canonical/*.parquet', + '${EVENTS_DIR}/attachments_new/canonical/*.parquet', + '${EVENTS_DIR}/new_microblocks/*.parquet', + '${EVENTS_DIR}/drop_mempool_tx/*.parquet', + '${EVENTS_DIR}/new_mempool_tx/*.parquet', + ]) ORDER BY id`, + (err: any, result: any) => { + if (err) { + throw err; + } + + resolve(result); + } + ); + }); + }; + + rawEventsByIds = (ids: number[]): Promise => { + return new Promise(resolve => { + const con = this.db.connect(); + const res = con.stream( + `SELECT method, payload FROM READ_PARQUET('${EVENTS_DIR}/new_block/canonical/*.parquet') WHERE id IN (${ids}) ORDER BY id` + ); + + resolve(res); + }); + }; + + // + // REMAINDER EVENTS + // + + remainderEvents = (): Promise => { + return new Promise(resolve => { + const con = this.db.connect(); + con.all( + `SELECT method, payload FROM READ_PARQUET('${EVENTS_DIR}/remainder/*.parquet') ORDER BY id`, + (err: any, res: any) => { + if (err) { + throw err; + } + + resolve(res); + } + ); + }); + }; + + // + // CANONICAL BLOCK_HASHES + // + + canonicalBlockHashes = (): Promise => { + return new Promise(resolve => { + const con = this.db.connect(); + con.all( + `SELECT * FROM READ_PARQUET('${EVENTS_DIR}/canonical/block_hashes/*.parquet')`, + (err: any, res: any) => { + if (err) { + throw err; + } + + resolve(res); + } + ); + }); + }; +} diff --git a/src/event-replay/parquet-based/helpers.ts b/src/event-replay/parquet-based/helpers.ts new file mode 100644 index 0000000000..63ccddfed9 --- /dev/null +++ b/src/event-replay/parquet-based/helpers.ts @@ -0,0 +1,107 @@ +import * as fs from 'fs'; + +import { logger } from '../../logger'; +import { DatasetStore } from './dataset/store'; + +interface TimeTracker { + track(name: string, fn: () => Promise): Promise; + trackSync(name: string, fn: () => T): T; + getDurations: ( + roundDecimals?: number + ) => { + name: string; + seconds: string; + }[]; +} + +const createTimeTracker = (): TimeTracker => { + const durations = new Map(); + return { + track(name: string, fn: () => Promise) { + let duration = durations.get(name); + if (duration === undefined) { + duration = { totalTime: 0n }; + durations.set(name, duration); + } + const start = process.hrtime.bigint(); + return fn().finally(() => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + duration!.totalTime += process.hrtime.bigint() - start; + }); + }, + trackSync(name: string, fn: () => T) { + let duration = durations.get(name); + if (duration === undefined) { + duration = { totalTime: 0n }; + durations.set(name, duration); + } + const start = process.hrtime.bigint(); + try { + return fn(); + } finally { + duration.totalTime += process.hrtime.bigint() - start; + } + }, + getDurations: (roundDecimals?: number) => { + return [...durations.entries()] + .sort((a, b) => Number(b[1].totalTime - a[1].totalTime)) + .map(entry => { + const seconds = Number(entry[1].totalTime) / 1e9; + return { + name: entry[0], + seconds: roundDecimals ? seconds.toFixed(roundDecimals) : seconds.toString(), + }; + }); + }, + }; +}; + +function* chunks(arr: T[], n: number): Generator { + for (let i = 0; i < arr.length; i += n) { + yield arr.slice(i, i + n); + } +} + +const splitIntoChunks = (data: number[], chunk_size: number) => { + return [...chunks(data, chunk_size)]; +}; + +const genIdsFiles = async (dataset: DatasetStore) => { + const args = process.argv.slice(2); + + let workers: number = 1; + if (args.length > 1) { + workers = Number(args[1].split('=')[1]); + } + + logger.info({ component: 'event-replay' }, `Generating ID files for ${workers} workers`); + + const dir = `${process.env.STACKS_EVENTS_DIR}/new_block`; + + const ids: number[] = await dataset.newBlockEventsIds(); + const batchSize = Math.ceil(ids.length / workers); + const chunks = splitIntoChunks(ids, batchSize); + + const files = fs.readdirSync(dir).filter(f => f.endsWith('txt')); + + // delete previous files + files.map(file => { + try { + fs.unlinkSync(`${dir}/${file}`); + } catch (err) { + throw err; + } + }); + + // create id files + chunks.forEach((chunk, idx) => { + const filename = `${dir}/ids_${idx + 1}.txt`; + chunk.forEach(id => { + fs.writeFileSync(filename, id.toString() + '\n', { flag: 'a' }); + }); + }); + + return fs.readdirSync(dir).filter(f => f.endsWith('txt')); +}; + +export { createTimeTracker, splitIntoChunks, genIdsFiles }; diff --git a/src/event-replay/parquet-based/importers/attachment-new-importer.ts b/src/event-replay/parquet-based/importers/attachment-new-importer.ts new file mode 100644 index 0000000000..43a5e2a0a1 --- /dev/null +++ b/src/event-replay/parquet-based/importers/attachment-new-importer.ts @@ -0,0 +1,123 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ + +import { Readable, Writable } from 'stream'; +import { pipeline } from 'stream/promises'; +import { batchIterate } from '../../../helpers'; +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { parseAttachment } from '../../../event-stream/event-server'; +import { logger } from '../../../logger'; +import { CoreNodeAttachmentMessage } from '../../../event-stream/core-node-message'; +import { DataStoreAttachmentSubdomainData } from '../../../datastore/common'; +import { DatasetStore } from '../dataset/store'; +import { I32_MAX } from '../../../helpers'; + +const batchInserters: BatchInserter[] = []; + +interface BatchInserter { + push(entries: T[]): Promise; + flush(): Promise; +} + +function createBatchInserter({ + batchSize, + insertFn, +}: { + batchSize: number; + insertFn: (entries: T[]) => Promise; +}): BatchInserter { + let entryBuffer: T[] = []; + return { + async push(entries: T[]) { + entries.length === 1 + ? entryBuffer.push(entries[0]) + : entries.forEach(e => entryBuffer.push(e)); + if (entryBuffer.length === batchSize) { + await insertFn(entryBuffer); + entryBuffer.length = 0; + } else if (entryBuffer.length > batchSize) { + for (const batch of batchIterate(entryBuffer, batchSize)) { + await insertFn(batch); + } + entryBuffer.length = 0; + } + }, + async flush() { + logger.debug({ component: 'event-replay' }, 'Flushing remaining data...'); + if (entryBuffer.length > 0) { + await insertFn(entryBuffer); + entryBuffer = []; + } + }, + }; +} + +const insertInBatch = (db: PgWriteStore, canonicalBlockHashes: any) => { + const dbAttachmentEventBatchInserter = createBatchInserter({ + batchSize: 1, + insertFn: async entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into subdomains table...'); + return await db.updateBatchSubdomains(db.sql, entries); + }, + }); + batchInserters.push(dbAttachmentEventBatchInserter); + return new Writable({ + objectMode: true, + write: async (data, _encoding, next) => { + const dataStoreAttachments: DataStoreAttachmentSubdomainData[] = []; + const attachmentMsg: CoreNodeAttachmentMessage[] = JSON.parse(data.payload); + const attachments = parseAttachment(attachmentMsg); + + for (const subdomain of attachments.subdomains) { + const dataStoreAttachment: DataStoreAttachmentSubdomainData = {}; + const indexBlockHash = subdomain.index_block_hash!; + const blockEntityData = canonicalBlockHashes[subdomain.block_height - 1]; + const parentIndexBlockHash = + canonicalBlockHashes[subdomain.block_height - 2]['index_block_hash']; + const microblocks = JSON.parse(blockEntityData['microblock']); + + const microblockIndex = microblocks.findIndex( + (mb: any, index: any) => index > 0 && mb[1].includes(subdomain.tx_id) + ); + + // derive from entity hash index + subdomain.tx_index = JSON.parse(blockEntityData['microblock']) + .flatMap((m: any) => m[1]) + .findIndex((tx: any) => tx === subdomain.tx_id); + + const blockData = { + index_block_hash: indexBlockHash, + parent_index_block_hash: parentIndexBlockHash, + microblock_hash: microblockIndex !== -1 ? microblocks[microblockIndex][0] : '', + microblock_sequence: microblockIndex !== -1 ? microblockIndex - 1 : I32_MAX, + microblock_canonical: true, + }; + + dataStoreAttachment.blockData = blockData; + dataStoreAttachment.subdomains = attachments.subdomains; + dataStoreAttachments.push(dataStoreAttachment); + } + + await dbAttachmentEventBatchInserter.push(dataStoreAttachments); + + next(); + }, + }); +}; + +export const processAttachmentNewEvents = async (db: PgWriteStore, dataset: DatasetStore) => { + logger.info({ component: 'event-replay' }, 'ATTACHMENTS_NEW events process started'); + + const canonicalEvents = await dataset.attachmentsCanonicalEvents(); + const canonicalBlockHashes: any = await dataset.canonicalBlockHashes(); + const insert = insertInBatch(db, canonicalBlockHashes); + + await pipeline( + Readable.from(canonicalEvents), + insert.on('finish', async () => { + for (const batchInserter of batchInserters) { + await batchInserter.flush(); + } + }) + ); +}; diff --git a/src/event-replay/parquet-based/importers/new-block-importer.ts b/src/event-replay/parquet-based/importers/new-block-importer.ts new file mode 100644 index 0000000000..7d00a036de --- /dev/null +++ b/src/event-replay/parquet-based/importers/new-block-importer.ts @@ -0,0 +1,473 @@ +import { Readable, Writable, Transform } from 'stream'; +import { pipeline } from 'stream/promises'; +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { parseNewBlockMessage } from '../../../event-stream/event-server'; +import { + DbBlock, + DbMicroblock, + DbTx, + SmartContractEventInsertValues, + StxEventInsertValues, + PrincipalStxTxsInsertValues, + FtEventInsertValues, + NftEventInsertValues, + BnsNameInsertValues, + BnsZonefileInsertValues, + DataStoreBlockUpdateData, +} from '../../../datastore/common'; +import { validateZonefileHash } from '../../../datastore/helpers'; +import { logger } from '../../../logger'; +import { getApiConfiguredChainID, batchIterate } from '../../../helpers'; +import { CoreNodeBlockMessage } from '../../../event-stream/core-node-message'; +import { DatasetStore } from '../dataset/store'; + +const chainID = getApiConfiguredChainID(); + +const batchInserters: BatchInserter[] = []; + +interface BatchInserter { + push(entries: T[]): Promise; + flush(): Promise; +} + +function createBatchInserter({ + batchSize, + insertFn, +}: { + batchSize: number; + insertFn: (entries: T[]) => Promise; +}): BatchInserter { + let entryBuffer: T[] = []; + return { + async push(entries: T[]) { + entries.length === 1 + ? entryBuffer.push(entries[0]) + : entries.forEach(e => entryBuffer.push(e)); + if (entryBuffer.length === batchSize) { + await insertFn(entryBuffer); + entryBuffer.length = 0; + } else if (entryBuffer.length > batchSize) { + for (const batch of batchIterate(entryBuffer, batchSize)) { + await insertFn(batch); + } + entryBuffer.length = 0; + } + }, + async flush() { + logger.debug({ component: 'event-replay' }, 'Flushing remaining data...'); + if (entryBuffer.length > 0) { + await insertFn(entryBuffer); + entryBuffer = []; + } + }, + }; +} + +const populateBatchInserters = (db: PgWriteStore) => { + const dbBlockBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into blocks table...'); + return db.insertBlockBatch(db.sql, entries); + }, + }); + batchInserters.push(dbBlockBatchInserter); + + const dbMicroblockBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into microblocks table...'); + return db.insertMicroblockBatch(db.sql, entries); + }, + }); + batchInserters.push(dbMicroblockBatchInserter); + + const dbTxBatchInserter = createBatchInserter({ + batchSize: 1400, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into txs table...'); + return db.insertTxBatch(db.sql, entries); + }, + }); + batchInserters.push(dbTxBatchInserter); + + const dbStxEventBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into stx_events table...'); + return db.insertStxEventBatch(db.sql, entries); + }, + }); + batchInserters.push(dbStxEventBatchInserter); + + const dbPrincipalStxTxBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into principal_stx_txs table...'); + return db.insertPrincipalStxTxsBatch(db.sql, entries); + }, + }); + batchInserters.push(dbPrincipalStxTxBatchInserter); + + const dbContractEventBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into contract_logs table...'); + return db.insertContractEventBatch(db.sql, entries); + }, + }); + batchInserters.push(dbContractEventBatchInserter); + + const dbFtEventBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into ft_events table...'); + return db.insertFtEventBatch(db.sql, entries); + }, + }); + batchInserters.push(dbFtEventBatchInserter); + + const dbNftEventBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into nft_events table...'); + return db.insertNftEventBatch(db.sql, entries); + }, + }); + batchInserters.push(dbNftEventBatchInserter); + + const dbNameBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into names table...'); + return db.insertNameBatch(db.sql, entries); + }, + }); + batchInserters.push(dbNameBatchInserter); + + const dbZonefileBatchInserter = createBatchInserter({ + batchSize: 500, + insertFn: entries => { + logger.debug({ component: 'event-replay' }, 'Inserting into zonefiles table...'); + return db.insertZonefileBatch(db.sql, entries); + }, + }); + batchInserters.push(dbZonefileBatchInserter); + + return new Writable({ + objectMode: true, + write: async (data: CoreNodeBlockMessage, _encoding, next) => { + let dbData: DataStoreBlockUpdateData; + try { + dbData = parseNewBlockMessage(chainID, data); + } catch (err) { + logger.error({ component: 'event-replay' }, 'Error when parsing new_block event'); + console.error(err); + + throw err; + } + + const insertTxs = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + await dbTxBatchInserter.push([entry.tx]); + } + }; + + const insertContractLogs = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + await dbContractEventBatchInserter.push( + entry.contractLogEvents.map((contractEvent: any) => ({ + event_index: contractEvent.event_index, + tx_id: contractEvent.tx_id, + tx_index: contractEvent.tx_index, + block_height: contractEvent.block_height, + index_block_hash: entry.tx.index_block_hash, + parent_index_block_hash: entry.tx.parent_index_block_hash, + microblock_hash: entry.tx.microblock_hash, + microblock_sequence: entry.tx.microblock_sequence, + microblock_canonical: entry.tx.microblock_canonical, + canonical: contractEvent.canonical, + contract_identifier: contractEvent.contract_identifier, + topic: contractEvent.topic, + value: contractEvent.value, + })) + ); + } + }; + + const insertStxEvents = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const stxEvent of entry.stxEvents) { + await dbStxEventBatchInserter.push([ + { + ...stxEvent, + index_block_hash: entry.tx.index_block_hash, + parent_index_block_hash: entry.tx.parent_index_block_hash, + microblock_hash: entry.tx.microblock_hash, + microblock_sequence: entry.tx.microblock_sequence, + microblock_canonical: entry.tx.microblock_canonical, + sender: stxEvent.sender ?? null, + recipient: stxEvent.recipient ?? null, + amount: stxEvent.amount ?? null, + memo: stxEvent.memo ?? null, + }, + ]); + } + } + }; + + const insertPrincipalStxTxs = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + // string key: `principal, tx_id, index_block_hash, microblock_hash` + const alreadyInsertedRowKeys = new Set(); + const values: PrincipalStxTxsInsertValues[] = []; + const push = (principal: string) => { + // Check if this row has already been inserted by comparing the same columns used in the + // sql unique constraint defined on the table. This prevents later errors during re-indexing + // when the table indexes/constraints are temporarily disabled during inserts. + const constraintKey = `${principal},${entry.tx.tx_id},${entry.tx.index_block_hash},${entry.tx.microblock_hash}`; + if (!alreadyInsertedRowKeys.has(constraintKey)) { + alreadyInsertedRowKeys.add(constraintKey); + values.push({ + principal: principal, + tx_id: entry.tx.tx_id, + block_height: entry.tx.block_height, + index_block_hash: entry.tx.index_block_hash, + microblock_hash: entry.tx.microblock_hash, + microblock_sequence: entry.tx.microblock_sequence, + tx_index: entry.tx.tx_index, + canonical: entry.tx.canonical, + microblock_canonical: entry.tx.microblock_canonical, + }); + } + }; + + const principals = new Set(); + + // Insert tx data + [ + entry.tx.sender_address, + entry.tx.token_transfer_recipient_address, + entry.tx.contract_call_contract_id, + entry.tx.smart_contract_contract_id, + ] + .filter((p): p is string => !!p) + .forEach(p => principals.add(p)); + + // Insert stx_event data + entry.stxEvents.forEach((event: any) => { + if (event.sender) { + principals.add(event.sender); + } + if (event.recipient) { + principals.add(event.recipient); + } + }); + + principals.forEach(principal => push(principal)); + await dbPrincipalStxTxBatchInserter.push(values); + } + }; + + const insertFTEvents = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + await dbFtEventBatchInserter.push( + entry.ftEvents.map((ftEvent: any) => ({ + event_index: ftEvent.event_index, + tx_id: ftEvent.tx_id, + tx_index: ftEvent.tx_index, + block_height: ftEvent.block_height, + index_block_hash: entry.tx.index_block_hash, + parent_index_block_hash: entry.tx.parent_index_block_hash, + microblock_hash: entry.tx.microblock_hash, + microblock_sequence: entry.tx.microblock_sequence, + microblock_canonical: entry.tx.microblock_canonical, + canonical: ftEvent.canonical, + asset_event_type_id: ftEvent.asset_event_type_id, + sender: ftEvent.sender ?? null, + recipient: ftEvent.recipient ?? null, + asset_identifier: ftEvent.asset_identifier, + amount: ftEvent.amount.toString(), + })) + ); + } + }; + + const insertNFTEvents = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + await dbNftEventBatchInserter.push( + entry.nftEvents.map((nftEvent: any) => ({ + tx_id: nftEvent.tx_id, + index_block_hash: entry.tx.index_block_hash, + parent_index_block_hash: entry.tx.parent_index_block_hash, + microblock_hash: entry.tx.microblock_hash, + microblock_sequence: entry.tx.microblock_sequence, + microblock_canonical: entry.tx.microblock_canonical, + sender: nftEvent.sender ?? null, + recipient: nftEvent.recipient ?? null, + event_index: nftEvent.event_index, + tx_index: nftEvent.tx_index, + block_height: nftEvent.block_height, + canonical: nftEvent.canonical, + asset_event_type_id: nftEvent.asset_event_type_id, + asset_identifier: nftEvent.asset_identifier, + value: nftEvent.value, + })) + ); + } + }; + + const insertNames = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + await dbNameBatchInserter.push( + entry.names.map((bnsName: any) => ({ + name: bnsName.name, + address: bnsName.address, + registered_at: bnsName.registered_at, + expire_block: bnsName.expire_block, + zonefile_hash: validateZonefileHash(bnsName.zonefile_hash), + namespace_id: bnsName.namespace_id, + grace_period: bnsName.grace_period ?? null, + renewal_deadline: bnsName.renewal_deadline ?? null, + resolver: bnsName.resolver ?? null, + tx_id: bnsName.tx_id ?? null, + tx_index: bnsName.tx_index, + event_index: bnsName.event_index ?? null, + status: bnsName.status ?? null, + canonical: bnsName.canonical, + index_block_hash: entry.tx.index_block_hash ?? null, + parent_index_block_hash: entry.tx.parent_index_block_hash, + microblock_hash: entry.tx.microblock_hash, + microblock_sequence: entry.tx.microblock_sequence, + microblock_canonical: entry.tx.microblock_canonical, + })) + ); + } + }; + + const insertZoneFiles = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + await dbZonefileBatchInserter.push( + entry.names.map((bnsName: any) => ({ + name: bnsName.name, + zonefile: bnsName.zonefile, + zonefile_hash: validateZonefileHash(bnsName.zonefile_hash), + tx_id: bnsName.tx_id, + index_block_hash: bnsName.index_block_hash ?? null, + })) + ); + } + }; + + const insertSmartContracts = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const smartContract of entry.smartContracts) { + await db.updateSmartContract(db.sql, entry.tx, smartContract); + } + } + }; + + const insertNamespaces = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const namespace of entry.namespaces) { + await db.insertNamespace(db.sql, entry.tx, namespace); + } + } + }; + + const insertStxLockEvents = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const stxLockEvent of entry.stxLockEvents) { + await db.updateStxLockEvent(db.sql, entry.tx, stxLockEvent); + } + } + }; + + const insertMinerRewards = async (dbData: DataStoreBlockUpdateData) => { + for (const minerReward of dbData.minerRewards) { + await db.updateMinerReward(db.sql, minerReward); + } + }; + + const insertPox2Events = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const pox2Event of entry.pox2Events) { + await db.updatePox2Event(db.sql, entry.tx, pox2Event); + } + } + }; + + const insertPox3Events = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const pox3Event of entry.pox3Events) { + await db.updatePox3Event(db.sql, entry.tx, pox3Event); + } + } + }; + + await Promise.all([ + // Insert blocks + dbBlockBatchInserter.push([dbData.block]), + // Insert microblocks + dbMicroblockBatchInserter.push(dbData.microblocks), + // Insert txs + insertTxs(dbData), + // Insert stx_events + insertStxEvents(dbData), + // Insert principal_stx_txs + insertPrincipalStxTxs(dbData), + // Insert contract_logs + insertContractLogs(dbData), + // Insert ft_events + insertFTEvents(dbData), + // Insert nft_events + insertNFTEvents(dbData), + // Insert names + insertNames(dbData), + // Insert zonefiles + insertZoneFiles(dbData), + // Insert smart_contracts + insertSmartContracts(dbData), + // Insert namespaces + insertNamespaces(dbData), + // Insert stx_lock_events + insertStxLockEvents(dbData), + // Insert miner_rewards + insertMinerRewards(dbData), + // Insert pox2_events + insertPox2Events(dbData), + // Insert pox3_events + insertPox3Events(dbData), + ]); + + next(); + }, + }); +}; + +const transformDataToJSON = () => { + return new Transform({ + objectMode: true, + transform: (data, _encoding, callback) => { + callback(null, JSON.parse(data.payload)); + }, + }); +}; + +export const processNewBlockEvents = async (db: PgWriteStore, dataset: DatasetStore, ids?: any) => { + logger.info({ component: 'event-replay' }, 'NEW_BLOCK events process started'); + + const payload = await dataset.newBlockEventsPayloadStream(ids); + const toJSON = transformDataToJSON(); + const insertBatchData = populateBatchInserters(db); + + await pipeline( + Readable.from(payload), + toJSON, + insertBatchData.on('finish', async () => { + for (const batchInserter of batchInserters) { + await batchInserter.flush(); + } + }) + ); +}; diff --git a/src/event-replay/parquet-based/importers/new-burn-block-importer.ts b/src/event-replay/parquet-based/importers/new-burn-block-importer.ts new file mode 100644 index 0000000000..71552eacc2 --- /dev/null +++ b/src/event-replay/parquet-based/importers/new-burn-block-importer.ts @@ -0,0 +1,72 @@ +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { DbBurnchainReward, DbRewardSlotHolder } from '../../../datastore/common'; +import { CoreNodeBurnBlockMessage } from '../../../event-stream/core-node-message'; +import { logger } from '../../../logger'; +import { splitIntoChunks } from '../helpers'; +import { DatasetStore } from '../dataset/store'; + +const INSERT_BATCH_SIZE = 500; + +const DbBurnchainRewardParse = (payload: CoreNodeBurnBlockMessage) => { + const rewards = payload.reward_recipients.map((r, index) => { + const dbReward: DbBurnchainReward = { + canonical: true, + burn_block_hash: payload.burn_block_hash, + burn_block_height: payload.burn_block_height, + burn_amount: BigInt(payload.burn_amount), + reward_recipient: r.recipient, + reward_amount: BigInt(r.amt), + reward_index: index, + }; + + return dbReward; + }); + + return rewards; +}; + +const DbRewardSlotHolderParse = (payload: CoreNodeBurnBlockMessage) => { + const slotHolders = payload.reward_slot_holders.map((r, index) => { + const slotHolder: DbRewardSlotHolder = { + canonical: true, + burn_block_hash: payload.burn_block_hash, + burn_block_height: payload.burn_block_height, + address: r, + slot_index: index, + }; + return slotHolder; + }); + + return slotHolders; +}; + +const insertBurnchainRewardsAndSlotHolders = async (db: PgWriteStore, chunks: any) => { + for (const chunk of chunks) { + const burnchainRewards: DbBurnchainReward[] = []; + const slotHolders: DbRewardSlotHolder[] = []; + for (const event of chunk) { + const payload: CoreNodeBurnBlockMessage = JSON.parse(event['payload']); + const burnchainRewardsData = DbBurnchainRewardParse(payload); + const slotHoldersData = DbRewardSlotHolderParse(payload); + burnchainRewardsData.forEach(reward => burnchainRewards.push(reward)); + slotHoldersData.forEach(slotHolder => slotHolders.push(slotHolder)); + } + + if (burnchainRewards.length !== 0) { + await db.insertBurnchainRewardsBatch(db.sql, burnchainRewards); + } + + if (slotHolders.length !== 0) { + await db.insertSlotHoldersBatch(db.sql, slotHolders); + } + } +}; + +export const processNewBurnBlockEvents = async (db: PgWriteStore, dataset: DatasetStore) => { + logger.info({ component: 'event-replay' }, 'NEW_BURN_BLOCK events process started'); + + return dataset + .newBurnBlockEventsOrdered() + .then((data: any) => splitIntoChunks(data, INSERT_BATCH_SIZE)) + .then(async (chunks: any) => await insertBurnchainRewardsAndSlotHolders(db, chunks)); +}; diff --git a/src/event-replay/parquet-based/importers/raw-importer.ts b/src/event-replay/parquet-based/importers/raw-importer.ts new file mode 100644 index 0000000000..9fc4480509 --- /dev/null +++ b/src/event-replay/parquet-based/importers/raw-importer.ts @@ -0,0 +1,106 @@ +import { Readable, Writable } from 'stream'; +import { pipeline } from 'stream/promises'; +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { RawEventRequestInsertValues } from '../../../datastore/common'; +import { logger } from '../../../logger'; +import { batchIterate } from '../../../helpers'; +import { DatasetStore } from '../dataset/store'; + +const batchInserters: BatchInserter[] = []; + +interface BatchInserter { + push(entries: T[]): Promise; + flush(): Promise; +} + +function createBatchInserter({ + batchSize, + insertFn, +}: { + batchSize: number; + insertFn: (entries: T[]) => Promise; +}): BatchInserter { + let entryBuffer: T[] = []; + return { + async push(entries: T[]) { + entries.length === 1 + ? entryBuffer.push(entries[0]) + : entries.forEach(e => entryBuffer.push(e)); + if (entryBuffer.length === batchSize) { + await insertFn(entryBuffer); + entryBuffer.length = 0; + } else if (entryBuffer.length > batchSize) { + for (const batch of batchIterate(entryBuffer, batchSize)) { + await insertFn(batch); + } + entryBuffer.length = 0; + } + }, + async flush() { + logger.debug({ component: 'event-replay' }, 'Flushing remaining data...'); + if (entryBuffer.length > 0) { + await insertFn(entryBuffer); + entryBuffer = []; + } + }, + }; +} + +const insertInBatch = (db: PgWriteStore) => { + const dbRawEventBatchInserter = createBatchInserter({ + batchSize: 200, + insertFn: async entries => { + logger.debug( + { component: 'event-replay' }, + 'Inserting into event_observer_requests table...' + ); + return await db.insertRawEventRequestBatch(db.sql, entries); + }, + }); + batchInserters.push(dbRawEventBatchInserter); + + return new Writable({ + objectMode: true, + write: async (data, _encoding, next) => { + await dbRawEventBatchInserter.push([{ event_path: data.method, payload: data.payload }]); + + next(); + }, + }); +}; + +export const processRawEvents = async (db: PgWriteStore, dataset: DatasetStore) => { + logger.info({ component: 'event-replay' }, 'RAW events process started'); + + const payload = await dataset.rawEvents(); + const insert = insertInBatch(db); + + await pipeline( + Readable.from(payload), + insert.on('finish', async () => { + for (const batchInserter of batchInserters) { + await batchInserter.flush(); + } + }) + ); +}; + +export const processRawEventsInParallel = async ( + db: PgWriteStore, + dataset: DatasetStore, + ids: any +) => { + logger.info({ component: 'event-replay' }, 'RAW events parallel processing started'); + + const payload = await dataset.rawEventsByIds(ids); + const insert = insertInBatch(db); + + await pipeline( + Readable.from(payload), + insert.on('finish', async () => { + for (const batchInserter of batchInserters) { + await batchInserter.flush(); + } + }) + ); +}; diff --git a/src/event-replay/parquet-based/importers/remainder-importer.ts b/src/event-replay/parquet-based/importers/remainder-importer.ts new file mode 100644 index 0000000000..b13f9010e3 --- /dev/null +++ b/src/event-replay/parquet-based/importers/remainder-importer.ts @@ -0,0 +1,48 @@ +import { Readable, Writable } from 'stream'; +import { pipeline } from 'stream/promises'; +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { logger } from '../../../logger'; +import { DatasetStore } from '../dataset/store'; +import { EventStreamServer, startEventServer } from '../../../event-stream/event-server'; +import { getApiConfiguredChainID, httpPostRequest } from '../../../helpers'; + +const chainID = getApiConfiguredChainID(); + +const processRequests = (eventServer: EventStreamServer) => { + return new Writable({ + objectMode: true, + write: async (data, _encoding, next) => { + await httpPostRequest({ + host: '127.0.0.1', + port: eventServer.serverAddress.port, + path: data.method, + headers: { 'Content-Type': 'application/json' }, + body: data.payload, + throwOnNotOK: true, + }); + + next(); + }, + }); +}; + +export const processRemainderEvents = async (db: PgWriteStore, dataset: DatasetStore) => { + logger.info({ component: 'event-replay' }, 'REMAINDER events processing started'); + + const eventServer = await startEventServer({ + datastore: db, + chainId: chainID, + serverHost: '127.0.0.1', + serverPort: 0, + }); + + const eventStream = await dataset.remainderEvents(); + const process = processRequests(eventServer); + + await pipeline( + Readable.from(eventStream), + process.on('finish', async () => { + await eventServer.closeAsync(); + }) + ); +}; diff --git a/src/event-replay/parquet-based/replay-controller.ts b/src/event-replay/parquet-based/replay-controller.ts new file mode 100644 index 0000000000..323f8b7260 --- /dev/null +++ b/src/event-replay/parquet-based/replay-controller.ts @@ -0,0 +1,287 @@ +import * as tty from 'tty'; + +import { PgWriteStore } from '../../datastore/pg-write-store'; +import { logger } from '../../logger'; +import { createTimeTracker, genIdsFiles } from './helpers'; +import { processNewBurnBlockEvents } from './importers/new-burn-block-importer'; +import { processAttachmentNewEvents } from './importers/attachment-new-importer'; +import { processRawEvents } from './importers/raw-importer'; +import { processRemainderEvents } from './importers/remainder-importer'; +import { DatasetStore } from './dataset/store'; +import { cycleMigrations, dangerousDropAllTables } from '../../datastore/migrations'; +import { IndexesState } from '../../datastore/common'; +import { importV1TokenOfferingData } from '../../import-v1'; + +import * as _cluster from 'cluster'; +const cluster = (_cluster as unknown) as _cluster.Cluster; // typings fix + +import { FILE_PATH as raw_worker_path } from './workers/raw-worker'; +import { FILE_PATH as new_block_worker_path } from './workers/new-block-worker'; + +/** + * This class is an entry point for the event-replay based on parquet files, + * being responsible to start the replay process (check "do" method). + * + * It also has functions to prepare and finalize the database for an event-replay. + */ +export class ReplayController { + private readonly db; + private readonly dataset; + + /** + * + */ + private constructor(db: PgWriteStore, dataset: DatasetStore) { + this.db = db; + this.dataset = dataset; + } + + /** + * + */ + static async init() { + const db = await PgWriteStore.connect({ + usageName: 'event-replay', + skipMigrations: true, + withNotifier: false, + isEventReplay: true, + }); + const dataset = DatasetStore.connect(); + + return new ReplayController(db, dataset); + } + + /** + * + */ + private ingestNewBurnBlockEvents = async () => { + const timeTracker = createTimeTracker(); + + try { + await timeTracker.track('NEW_BURN_BLOCK_EVENTS', async () => { + await processNewBurnBlockEvents(this.db, this.dataset); + }); + } catch (err) { + throw err; + } finally { + if (true || tty.isatty(1)) { + console.log('Tracked function times:'); + console.table(timeTracker.getDurations(3)); + } else { + logger.info(`Tracked function times`, timeTracker.getDurations(3)); + } + } + }; + + /** + * + */ + private ingestAttachmentNewEvents = async () => { + const timeTracker = createTimeTracker(); + + try { + await timeTracker.track('ATTACHMENTS_NEW_EVENTS', async () => { + await processAttachmentNewEvents(this.db, this.dataset); + }); + } catch (err) { + throw err; + } finally { + if (true || tty.isatty(1)) { + console.log('Tracked function times:'); + console.table(timeTracker.getDurations(3)); + } else { + logger.info(`Tracked function times`, timeTracker.getDurations(3)); + } + } + }; + + /** + * + */ + ingestRawEvents = async () => { + const timeTracker = createTimeTracker(); + + try { + await timeTracker.track('RAW_EVENTS', async () => { + await processRawEvents(this.db, this.dataset); + }); + } catch (err) { + throw err; + } finally { + if (true || tty.isatty(1)) { + console.log('Tracked function times:'); + console.table(timeTracker.getDurations(3)); + } else { + logger.info(`Tracked function times`, timeTracker.getDurations(3)); + } + } + }; + + ingestRawNewBlockEvents = async () => { + return new Promise(async resolve => { + cluster.setupPrimary({ + exec: raw_worker_path, + }); + + let workersReady = 0; + const idFiles = await genIdsFiles(this.dataset); + for (const idFile of idFiles) { + cluster.fork().send(idFile); + workersReady++; + } + + for (const id in cluster.workers) { + const worker: _cluster.Worker | undefined = cluster.workers[id]; + worker?.on('message', (msg, _handle) => { + switch (msg.msgType) { + case 'FINISH': + logger.info({ component: 'event-replay' }, `${msg.msg}`); + workersReady--; + worker.disconnect(); + break; + default: + // default action + break; + } + }); + + worker?.on('disconnect', () => { + if (workersReady === 0) { + resolve(true); + } + }); + } + }); + }; + + /** + * + */ + ingestNewBlockEvents = (): Promise => { + return new Promise(async resolve => { + cluster.setupPrimary({ + exec: new_block_worker_path, + }); + + let workersReady = 0; + const idFiles = await genIdsFiles(this.dataset); + for (const idFile of idFiles) { + cluster.fork().send(idFile); + workersReady++; + } + + for (const id in cluster.workers) { + const worker: _cluster.Worker | undefined = cluster.workers[id]; + worker?.on('message', (msg, _handle) => { + switch (msg.msgType) { + case 'FINISH': + logger.info({ component: 'event-replay' }, `${msg.msg}`); + workersReady--; + worker.disconnect(); + break; + default: + // default action + break; + } + }); + + worker?.on('disconnect', () => { + if (workersReady === 0) { + resolve(true); + } + }); + } + }); + }; + + /** + * + */ + private ingestRemainderEvents = async () => { + const timeTracker = createTimeTracker(); + + try { + await timeTracker.track('REMAINDER_EVENTS', async () => { + await processRemainderEvents(this.db, this.dataset); + }); + } catch (err) { + throw err; + } finally { + if (true || tty.isatty(1)) { + console.log('Tracked function times:'); + console.table(timeTracker.getDurations(3)); + } else { + logger.info(`Tracked function times`, timeTracker.getDurations(3)); + } + } + }; + + /** + * + */ + prepare = async () => { + logger.info({ component: 'event-replay' }, 'Cleaning up the Database'); + await dangerousDropAllTables({ acknowledgePotentialCatastrophicConsequences: 'yes' }); + + logger.info({ component: 'event-replay' }, 'Migrating tables'); + try { + await cycleMigrations({ dangerousAllowDataLoss: true, checkForEmptyData: true }); + } catch (error) { + logger.error(error); + throw new Error('DB migration cycle failed'); + } + + // Disabling indexes + logger.info( + { component: 'event-replay' }, + 'Disabling indexes and constraints to speed up insertion' + ); + await this.db.toggleAllTableIndexes(this.db.sql, IndexesState.Off); + }; + + /** + * + */ + finalize = async () => { + logger.info({ component: 'event-replay' }, 'Importing Token Offering Data'); + await importV1TokenOfferingData(this.db); + + // Re-enabling indexes + logger.info({ component: 'event-replay' }, 'Re-enabling indexes and constraints on tables'); + await this.db.toggleAllTableIndexes(this.db.sql, IndexesState.On); + + // Re-indexing tables + logger.info({ component: 'event-replay' }, 'Re-indexing tables'); + await this.db.reindexAllTables(this.db.sql); + + // Remainder events to be replayed with regular HTTP POSTs + await this.ingestRemainderEvents(); + + // Refreshing materialized views + logger.info({ component: 'event-replay' }, `Refreshing materialized views`); + await this.db.finishEventReplay(); + + // Close DB + logger.info({ component: 'event-replay' }, 'Closing DB connection'); + await this.db.close(); + + // Exit with success + logger.info({ component: 'event-replay' }, 'Finishing event-replay with success'); + process.exit(0); + }; + + /** + * This funtion is responsible to initialize the event-replay process. + */ + do = async () => { + // NEW_BLOCK events + await this.ingestNewBlockEvents(); + + // RAW events to event_observer_requests table + await this.ingestRawEvents(); + await this.ingestRawNewBlockEvents(); + + // NEW_BURN_BLOCK and ATTACHMENTS/NEW events + await Promise.all([this.ingestNewBurnBlockEvents(), this.ingestAttachmentNewEvents()]); + }; +} diff --git a/src/event-replay/parquet-based/workers/new-block-worker.ts b/src/event-replay/parquet-based/workers/new-block-worker.ts new file mode 100644 index 0000000000..a1e715ad1c --- /dev/null +++ b/src/event-replay/parquet-based/workers/new-block-worker.ts @@ -0,0 +1,51 @@ +import * as fs from 'fs'; +import * as tty from 'tty'; + +import { processNewBlockEvents } from '../importers/new-block-importer'; +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { DatasetStore } from '../dataset/store'; +import { logger } from '../../../logger'; +import { createTimeTracker } from '../helpers'; + +export const FILE_PATH = __filename; + +const ingestNewBlock = async (idFile?: string) => { + const db = await PgWriteStore.connect({ + usageName: `${idFile}`, + skipMigrations: true, + withNotifier: false, + isEventReplay: true, + }); + const dataset = DatasetStore.connect(); + + const timeTracker = createTimeTracker(); + + const dir = `${process.env.STACKS_EVENTS_DIR}/new_block`; + + try { + const idsFileContent = fs.readFileSync(`${dir}/${idFile}`, 'utf-8'); + const ids = idsFileContent.split(/\r?\n/); + + await timeTracker.track('NEW_BLOCK_EVENTS', async () => { + await processNewBlockEvents(db, dataset, ids); + }); + + // notify parent + process.send?.({ + msgType: 'FINISH', + msg: 'Worker has finished', + }); + } catch (err) { + throw err; + } finally { + if (true || tty.isatty(1)) { + console.table(timeTracker.getDurations(3)); + } else { + logger.info(`Tracked function times`, timeTracker.getDurations(3)); + } + } +}; + +process.on('message', async (msg: string) => { + await ingestNewBlock(msg); +}); diff --git a/src/event-replay/parquet-based/workers/raw-worker.ts b/src/event-replay/parquet-based/workers/raw-worker.ts new file mode 100644 index 0000000000..8262d4cbe0 --- /dev/null +++ b/src/event-replay/parquet-based/workers/raw-worker.ts @@ -0,0 +1,51 @@ +import * as fs from 'fs'; +import * as tty from 'tty'; + +import { PgWriteStore } from '../../../datastore/pg-write-store'; +import { DatasetStore } from '../dataset/store'; +import { logger } from '../../../logger'; +import { createTimeTracker } from '../helpers'; +import { processRawEventsInParallel } from '../importers/raw-importer'; + +export const FILE_PATH = __filename; + +const ingestNewBlock = async (idFile?: string) => { + const db = await PgWriteStore.connect({ + usageName: `${idFile}`, + skipMigrations: true, + withNotifier: false, + isEventReplay: true, + }); + const dataset = DatasetStore.connect(); + + const timeTracker = createTimeTracker(); + + const dir = `${process.env.STACKS_EVENTS_DIR}/new_block`; + + try { + const idsFileContent = fs.readFileSync(`${dir}/${idFile}`, 'utf-8'); + const ids = idsFileContent.split(/\r?\n/); + + await timeTracker.track('RAW_EVENTS_PARALLEL', async () => { + await processRawEventsInParallel(db, dataset, ids); + }); + + // notify parent + process.send?.({ + msgType: 'FINISH', + msg: 'Worker has finished', + }); + } catch (err) { + throw err; + } finally { + if (true || tty.isatty(1)) { + console.table(timeTracker.getDurations(3)); + } else { + logger.info(`Tracked function times`, timeTracker.getDurations(3)); + } + } +}; + +process.on('message', async (msg: string) => { + await ingestNewBlock(msg); +}); diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index 6eb837e653..263697bb84 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -36,6 +36,8 @@ import { DataStoreAttachmentData, DbPox2Event, DbTxStatus, + DbBnsSubdomain, + DataStoreBnsBlockData, } from '../datastore/common'; import { getTxSenderAddress, @@ -58,6 +60,8 @@ import { parseNameFromContractEvent, parseNameRenewalWithNoZonefileHashFromContractCall, parseNamespaceFromContractEvent, + parseZoneFileTxt, + parseResolver, } from './bns/bns-helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { @@ -69,6 +73,7 @@ import { handleBnsImport } from '../import-v1'; import { Pox2ContractIdentifer } from '../pox-helpers'; import { decodePox2PrintEvent } from './pox2-event-parsing'; import { logger, loggerMiddleware } from '../logger'; +import * as zoneFileParser from 'zone-file'; export const IBD_PRUNABLE_ROUTES = ['/new_mempool_tx', '/drop_mempool_tx', '/new_microblocks']; @@ -970,3 +975,168 @@ export async function startEventServer(opts: { }); return eventStreamServer; } + +export function parseNewBlockMessage(chainId: ChainID, msg: CoreNodeBlockMessage) { + const parsedTxs: CoreNodeParsedTxMessage[] = []; + const blockData: CoreNodeMsgBlockData = { + ...msg, + }; + msg.transactions.forEach(item => { + const parsedTx = parseMessageTransaction(chainId, item, blockData, msg.events); + if (parsedTx) { + parsedTxs.push(parsedTx); + } + }); + + // calculate total execution cost of the block + const totalCost = msg.transactions.reduce( + (prev, cur) => { + return { + execution_cost_read_count: prev.execution_cost_read_count + cur.execution_cost.read_count, + execution_cost_read_length: + prev.execution_cost_read_length + cur.execution_cost.read_length, + execution_cost_runtime: prev.execution_cost_runtime + cur.execution_cost.runtime, + execution_cost_write_count: + prev.execution_cost_write_count + cur.execution_cost.write_count, + execution_cost_write_length: + prev.execution_cost_write_length + cur.execution_cost.write_length, + }; + }, + { + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + } + ); + + const dbBlock: DbBlock = { + canonical: true, + block_hash: msg.block_hash, + index_block_hash: msg.index_block_hash, + parent_index_block_hash: msg.parent_index_block_hash, + parent_block_hash: msg.parent_block_hash, + parent_microblock_hash: msg.parent_microblock, + parent_microblock_sequence: msg.parent_microblock_sequence, + block_height: msg.block_height, + burn_block_time: msg.burn_block_time, + burn_block_hash: msg.burn_block_hash, + burn_block_height: msg.burn_block_height, + miner_txid: msg.miner_txid, + execution_cost_read_count: totalCost.execution_cost_read_count, + execution_cost_read_length: totalCost.execution_cost_read_length, + execution_cost_runtime: totalCost.execution_cost_runtime, + execution_cost_write_count: totalCost.execution_cost_write_count, + execution_cost_write_length: totalCost.execution_cost_write_length, + }; + + const dbMinerRewards: DbMinerReward[] = []; + for (const minerReward of msg.matured_miner_rewards) { + const dbMinerReward: DbMinerReward = { + canonical: true, + block_hash: minerReward.from_stacks_block_hash, + index_block_hash: msg.index_block_hash, + from_index_block_hash: minerReward.from_index_consensus_hash, + mature_block_height: msg.block_height, + recipient: minerReward.recipient, + miner_address: minerReward.miner_address ?? minerReward.recipient, + coinbase_amount: BigInt(minerReward.coinbase_amount), + tx_fees_anchored: BigInt(minerReward.tx_fees_anchored), + tx_fees_streamed_confirmed: BigInt(minerReward.tx_fees_streamed_confirmed), + tx_fees_streamed_produced: BigInt(minerReward.tx_fees_streamed_produced), + }; + dbMinerRewards.push(dbMinerReward); + } + + const dbMicroblocks = parseMicroblocksFromTxs({ + parentIndexBlockHash: msg.parent_index_block_hash, + txs: msg.transactions, + parentBurnBlock: { + height: msg.parent_burn_block_height, + hash: msg.parent_burn_block_hash, + time: msg.parent_burn_block_timestamp, + }, + }).map(mb => { + const microblock: DbMicroblock = { + ...mb, + canonical: true, + microblock_canonical: true, + block_height: msg.block_height, + parent_block_height: msg.block_height - 1, + parent_block_hash: msg.parent_block_hash, + index_block_hash: msg.index_block_hash, + block_hash: msg.block_hash, + }; + return microblock; + }); + + const dbData: DataStoreBlockUpdateData = { + block: dbBlock, + microblocks: dbMicroblocks, + minerRewards: dbMinerRewards, + txs: parseDataStoreTxEventData(parsedTxs, msg.events, msg, chainId), + }; + + return dbData; +} + +export function parseAttachment(msg: CoreNodeAttachmentMessage[]) { + const zoneFiles: { zonefile: string; zonefileHash: string; txId: string }[] = []; + const subdomains: DbBnsSubdomain[] = []; + for (const attachment of msg) { + if ( + attachment.contract_id === BnsContractIdentifier.mainnet || + attachment.contract_id === BnsContractIdentifier.testnet + ) { + const metadataCV = decodeClarityValue< + ClarityValueTuple<{ + op: ClarityValueStringAscii; + name: ClarityValueBuffer; + namespace: ClarityValueBuffer; + }> + >(attachment.metadata); + const op = metadataCV.data['op'].data; + const zonefile = Buffer.from(attachment.content.slice(2), 'hex').toString(); + const zonefileHash = attachment.content_hash; + zoneFiles.push({ + zonefile, + zonefileHash, + txId: attachment.tx_id, + }); + if (op === 'name-update') { + const name = hexToBuffer(metadataCV.data['name'].buffer).toString('utf8'); + const namespace = hexToBuffer(metadataCV.data['namespace'].buffer).toString('utf8'); + const zoneFileContents = zoneFileParser.parseZoneFile(zonefile); + const zoneFileTxt = zoneFileContents.txt; + // Case for subdomain + if (zoneFileTxt) { + for (let i = 0; i < zoneFileTxt.length; i++) { + const zoneFile = zoneFileTxt[i]; + const parsedTxt = parseZoneFileTxt(zoneFile.txt); + if (parsedTxt.owner === '') continue; //if txt has no owner , skip it + const subdomain: DbBnsSubdomain = { + name: name.concat('.', namespace), + namespace_id: namespace, + fully_qualified_subdomain: zoneFile.name.concat('.', name, '.', namespace), + owner: parsedTxt.owner, + zonefile_hash: parsedTxt.zoneFileHash, + zonefile: parsedTxt.zoneFile, + tx_id: attachment.tx_id, + tx_index: -1, + canonical: true, + parent_zonefile_hash: attachment.content_hash.slice(2), + parent_zonefile_index: 0, // TODO need to figure out this field + block_height: Number.parseInt(attachment.block_height, 10), + zonefile_offset: 1, + resolver: zoneFileContents.uri ? parseResolver(zoneFileContents.uri) : '', + index_block_hash: attachment.index_block_hash, + }; + subdomains.push(subdomain); + } + } + } + } + } + return { zoneFiles, subdomains }; +} diff --git a/src/index.ts b/src/index.ts index 26fd473062..83516e234b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,6 +27,7 @@ import { isFtMetadataEnabled, isNftMetadataEnabled } from './token-metadata/help import { TokensProcessorQueue } from './token-metadata/tokens-processor-queue'; import { registerMempoolPromStats } from './datastore/helpers'; import { logger } from './logger'; +import { ReplayController } from './event-replay/parquet-based/replay-controller'; enum StacksApiMode { /** @@ -275,6 +276,15 @@ function getProgramArgs() { ['wipe-db']?: boolean; ['force']?: boolean; }; + } + | { + operand: 'from-parquet-events'; + options: { + ['new-burn-block']?: boolean; + ['attachment-new']?: boolean; + ['new-block']?: boolean; + ['ids-path']?: string; + }; }; return { args, parsedOpts }; } @@ -290,6 +300,11 @@ async function handleProgramArgs() { args.options['wipe-db'], args.options.force ); + } else if (args.operand === 'from-parquet-events') { + const replay = await ReplayController.init(); + await replay.prepare(); + await replay.do(); + await replay.finalize(); } else if (parsedOpts._[0]) { throw new Error(`Unexpected program argument: ${parsedOpts._[0]}`); } else { diff --git a/src/tests-2.4/pox-3-delegate-aggregation.ts b/src/tests-2.4/pox-3-delegate-aggregation.ts index 2fda6c1484..504914925c 100644 --- a/src/tests-2.4/pox-3-delegate-aggregation.ts +++ b/src/tests-2.4/pox-3-delegate-aggregation.ts @@ -8,9 +8,8 @@ import { standByForNextPoxCycle, standByForPoxCycle, standByForPoxCycleEnd, - standByForTx, standByForTxSuccess, - standByUntilBurnBlock, + standByForAccountUnlock, testEnv, } from '../test-utils/test-helpers'; import { stxToMicroStx } from '../helpers'; @@ -32,7 +31,6 @@ import { decodeClarityValue, } from 'stacks-encoding-native-js'; import { AddressStxBalanceResponse } from '@stacks/stacks-blockchain-api-types'; -import { DbTxStatus } from '../datastore/common'; describe('PoX-3 - Delegate aggregation increase operations', () => { const seedKey = testnetKeys[4].secretKey; @@ -430,6 +428,8 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { }); test('Validate account balances are unlocked', async () => { + await standByForAccountUnlock(delegateeAccount.stxAddr); + // validate stacks-node balance const coreBalanceInfo = await testEnv.client.getAccount(delegateeAccount.stxAddr); expect(BigInt(coreBalanceInfo.locked)).toBe(0n);