From 61dc6b251f85168282fe77cfcb03e1ab1ab05c2c Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 29 Sep 2023 15:08:42 +0200 Subject: [PATCH 01/68] add sdk structure example --- EXAMPLE.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 EXAMPLE.md diff --git a/EXAMPLE.md b/EXAMPLE.md new file mode 100644 index 0000000..d4e970b --- /dev/null +++ b/EXAMPLE.md @@ -0,0 +1,50 @@ +# Structure example + +```ts +import { Hosting } from '@apillon/sdk'; +import { Storage } from '@apillon/sdk'; +import { Nft } from '@apillon/sdk'; + +export async function test() { + + const hosting = new Hosting({ apillonConfig }); + await hosting.listWebsites(); + await hosting.createWebsite(); + const webpage1 = hosting.website('uuid'); + await webpage1.getInfo(); + await webpage1.update({}); + await webpage1.getDeployment(id); + await webpage1.getDeployments(); + await webpage1.deployFromFolder('path', 'environment'); // can go directly to production + await webpage1.updateDeployment(from stg -> production); // tu me moti še na api levelu, kr lahko dobiš in pogledaš detajle specifičnega deploymenta, ampak deploy klic pa dela samo na zadnjem + + // or + await hosting.website('uuid').getInfo(); + + + //Naming hosting -> webpage? + + const storage = new Storage({ apillonConfig }); + await storage.listBuckets(); + await storage.createBucket(); + + const bucket = storage.bucket('uuid'); + await bucket.upload('path to files'); + await bucket.getContent({ directory, search, limit }); + await bucket.getFile(id); + await bucket.deleteFile(id); + + const nft = new Nft({ apillonConfig }); + await nft.listCollections(); + await nft.createCollection(); + + const collection = nft.collection('uuid'); + const info = collection.getInfo(); //.info? + await collection.mint(); + await collection.burn(); + await collection.transferOwnership(); + await collection.getTransactions(); + + +} +``` \ No newline at end of file From ae4526e898a9b38b337324cf2b284475a4987818 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Tue, 3 Oct 2023 13:13:31 +0200 Subject: [PATCH 02/68] Add jest --- package-lock.json | 11974 +++++++++++++++++++++++++++--------- package.json | 30 +- packages/sdk/package.json | 33 +- 3 files changed, 9124 insertions(+), 2913 deletions(-) diff --git a/package-lock.json b/package-lock.json index c706e81..26fb7d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,12 @@ "packages/*" ], "devDependencies": { + "@types/jest": "^29.5.5", "eslint-config-common": "*", + "jest": "29.7.0", "prettier": "latest", "rimraf": "^4.4.0", + "ts-jest": "29.1.1", "turbo": "latest" }, "engines": { @@ -22,6 +25,19 @@ "npm": ">=8.4.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@apillon/cli": { "resolved": "packages/cli", "link": true @@ -30,1010 +46,1190 @@ "resolved": "packages/sdk", "link": true }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", - "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "color-convert": "^1.9.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "engines": { + "node": ">=4" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=0.8.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "has-flag": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=4" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/@babel/core/node_modules/semver": { + "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" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" }, "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=10.10.0" + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "yallist": "^3.0.2" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "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" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "engines": { - "node": ">=12.22" + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" - }, - "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==", + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "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" + "@babel/types": "^7.22.15" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "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==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "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==", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "optional": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">=14" + "node": ">=4" } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" - }, - "node_modules/@types/node": { - "version": "18.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "peer": true + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", - "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/type-utils": "5.55.0", - "@typescript-eslint/utils": "5.55.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "has-flag": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", - "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", - "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "dependencies": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", - "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.55.0", - "@typescript-eslint/utils": "5.55.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "eslint": "*" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", - "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", - "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "dependencies": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", - "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", - "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, "dependencies": { - "@typescript-eslint/types": "5.55.0", - "eslint-visitor-keys": "^3.3.0" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "dev": true + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "bin": { - "acorn": "bin/acorn" + "node_modules/@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "@jridgewell/trace-mapping": "0.3.9" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", + "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", "dependencies": { - "color-convert": "^2.0.1" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", "engines": { - "node": ">= 8" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { + "node_modules/@eslint/eslintrc": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=8" + "node": "*" } }, - "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==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dependencies": { - "fill-range": "^7.0.1" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=8" + "node": ">=10.10.0" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "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==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "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": ">= 8.10.0" + "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==", + "dev": true, + "engines": { + "node": ">=12" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "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==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">= 6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "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", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, "dependencies": { - "color-name": "~1.1.4" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { - "delayed-stream": "~1.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/commander": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", - "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", - "engines": { - "node": ">=14" + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "p-locate": "^4.1.0" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "p-try": "^2.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=6" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">=8" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, "dependencies": { - "path-type": "^4.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, "dependencies": { - "esutils": "^2.0.2" + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=6.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "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==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" + "jest-get-type": "^29.6.3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-config-common": { - "resolved": "packages/eslint-config-common", - "link": true - }, - "node_modules/eslint-config-prettier": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz", - "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==", - "bin": { - "eslint-config-prettier": "bin/cli.js" + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">=12.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "eslint-config-prettier": { + "node-notifier": { "optional": true } } }, - "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", - "dependencies": { - "safe-regex": "^2.1.1" - } - }, - "node_modules/eslint-plugin-sonarjs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.15.0.tgz", - "integrity": "sha512-LuxHdAe6VqSbi1phsUvNjbmXLuvlobmryQJJNyQYbdubCfz6K8tmgoqNiJPnz0pP2AbYDbtuPm0ajOMgMrC+dQ==", - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/eslint/node_modules/brace-expansion": { + "node_modules/@jest/reporters/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint/node_modules/minimatch": { + "node_modules/@jest/reporters/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1041,1642 +1237,1771 @@ "node": "*" } }, - "node_modules/espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, "dependencies": { - "estraverse": "^5.2.0" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" - }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=8.6.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">= 6" + "node": ">=6.0.0" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dependencies": { - "reusify": "^1.0.4" + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dependencies": { - "to-regex-range": "^5.0.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 8" } }, - "node_modules/flat-cache/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "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==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "type-detect": "4.0.8" } }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@babel/types": "^7.0.0" } }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + "node_modules/@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "node_modules/@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" } }, - "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==", + "node_modules/@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "@types/node": "*" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" + "@types/istanbul-lib-coverage": "*" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/@types/jest": { + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, - "node_modules/glob": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", - "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "node_modules/@types/node": { + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.26", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz", + "integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", + "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/type-utils": "5.55.0", + "@typescript-eslint/utils": "5.55.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/@typescript-eslint/parser": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", + "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", "dependencies": { - "is-glob": "^4.0.3" + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=10.13.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", + "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", "dependencies": { - "type-fest": "^0.20.2" + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/@typescript-eslint/type-utils": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", + "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/utils": "5.55.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "node_modules/@typescript-eslint/types": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", + "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==", "engines": { - "node": ">= 4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", + "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/@typescript-eslint/utils": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", + "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, "engines": { - "node": ">=0.8.19" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", + "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@typescript-eslint/types": "5.55.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "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==", + "dev": true }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { - "is-extglob": "^2.1.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, "dependencies": { - "argparse": "^2.0.1" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 8" } }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, "engines": { - "node": "14 || >=16.14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=8.6" + "node": ">=8" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "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" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, "dependencies": { - "mime-db": "1.52.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/minimatch": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", - "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "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==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/nodemon": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.21.tgz", - "integrity": "sha512-djN/n2549DUtY33S7o1djRCd7dEm0kBnj9c7S9XVXqRUbuggN1MZH/Nqa+5RFQr63Fbefq37nFXAE9VU86yL1A==", + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" }, "bin": { - "nodemon": "bin/nodemon.js" + "browserslist": "cli.js" }, "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/nodemon/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, "dependencies": { - "ms": "^2.1.1" + "node-int64": "^0.4.0" } }, - "node_modules/nodemon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/nodemon/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">=6" } }, - "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==", + "node_modules/caniuse-lite": { + "version": "1.0.30001542", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001542.tgz", + "integrity": "sha512-UrtAXVcj1mvPBFQ4sKd38daP8dEcXXr5sQe6QNNinaPd0iA/cxg9/l3VrSdL73jgw5sKyuQ6jNgiKO12W3SsVA==", "dev": true, - "bin": { - "semver": "bin/semver" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/nodemon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "dependencies": { - "has-flag": "^3.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=4" + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" + "is-glob": "^4.0.1" }, "engines": { - "node": "*" + "node": ">= 6" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, "dependencies": { - "wrappy": "1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/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==", + "dev": true, "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/cliui/node_modules/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==", + "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "p-limit": "^3.0.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=7.0.0" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { - "callsites": "^3.0.0" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/commander": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", + "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", "engines": { - "node": ">=8" + "node": ">=14" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "dev": true, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "ms": "2.1.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, - "node_modules/prettier": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", - "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", - "bin": { - "prettier": "bin-prettier.js" - }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/prettier-linter-helpers": { + "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regexp-tree": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", - "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", - "bin": { - "regexp-tree": "bin/regexp-tree" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=0.3.1" } }, - "node_modules/rimraf": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", - "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, - "dependencies": { - "glob": "^9.2.0" - }, - "bin": { - "rimraf": "dist/cjs/src/bin.js" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", - "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", - "dependencies": { - "regexp-tree": "~0.1.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dependencies": { - "yallist": "^4.0.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/electron-to-chromium": { + "version": "1.4.537", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.537.tgz", + "integrity": "sha512-W1+g9qs9hviII0HAwOdehGYkr+zt7KKdmCcJcjH0mYg6oL8+ioT3Skjmt7BLoAQqXhjf40AXd+HlR4oAWMlXjA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { - "node": ">=14" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/simple-update-notifier": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", - "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "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==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { - "semver": "~7.0.0" - }, - "engines": { - "node": ">=8.10.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=6" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", - "dev": true, + "node_modules/eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "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==", - "dev": true, + "node_modules/eslint-config-common": { + "resolved": "packages/eslint-config-common", + "link": true + }, + "node_modules/eslint-config-prettier": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz", + "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "prettier-linter-helpers": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/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==", - "dev": true, + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/string-width/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==", - "dev": true, + "node_modules/eslint-plugin-security": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", + "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", "dependencies": { - "ansi-regex": "^6.0.1" - }, + "safe-regex": "^2.1.1" + } + }, + "node_modules/eslint-plugin-sonarjs": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.15.0.tgz", + "integrity": "sha512-LuxHdAe6VqSbi1phsUvNjbmXLuvlobmryQJJNyQYbdubCfz6K8tmgoqNiJPnz0pP2AbYDbtuPm0ajOMgMrC+dQ==", "engines": { "node": ">=12" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dependencies": { - "ansi-regex": "^5.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "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==", - "dev": true, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "ansi-regex": "^5.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "has-flag": "^4.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "dependencies": { - "is-number": "^7.0.0" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=8.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, "bin": { - "nodetouch": "bin/nodetouch.js" + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "estraverse": "^5.1.0" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "engines": { + "node": ">=0.10" } }, - "node_modules/tsconfig": { - "resolved": "packages/tsconfig", - "link": true - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dependencies": { - "tslib": "^1.8.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + "node": ">=4.0" } }, - "node_modules/turbo": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.8.3.tgz", - "integrity": "sha512-zGrkU1EuNFmkq6iky6LcMqD4h0OLE8XysVFxQWRIZbcTNnf0XAycbsbeEyiJpiWeqb7qtg2bVuY9EYcNoNhVuQ==", - "dev": true, - "hasInstallScript": true, - "bin": { - "turbo": "bin/turbo" - }, - "optionalDependencies": { - "turbo-darwin-64": "1.8.3", - "turbo-darwin-arm64": "1.8.3", - "turbo-linux-64": "1.8.3", - "turbo-linux-arm64": "1.8.3", - "turbo-windows-64": "1.8.3", - "turbo-windows-arm64": "1.8.3" + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" } }, - "node_modules/turbo-darwin-64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.8.3.tgz", - "integrity": "sha512-bLM084Wr17VAAY/EvCWj7+OwYHvI9s/NdsvlqGp8iT5HEYVimcornCHespgJS/yvZDfC+mX9EQkn3V2JmYgGGw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/turbo-darwin-arm64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.8.3.tgz", - "integrity": "sha512-4oZjXtzakopMK110kue3z/hqu3WLv+eDLZOX1NGdo49gqca9BeD8GbH+sXpAp6tqyeuzpss+PIliVYuyt7LgbA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/turbo-linux-64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.8.3.tgz", - "integrity": "sha512-uvX2VKotf5PU14FCxJA5iHItPQno2JWzerMd+g3/h/Asay6dvxvtVjc39MQeGT0H5njSvzVKFkT+3/5q8lgOEg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/turbo-linux-arm64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.8.3.tgz", - "integrity": "sha512-E1p+oH3XKMaPS4rqWhYsL4j2Pzc0d/9P5KU7Kn1kqVLo2T3iRA7n2KVULEieUNE0nTH+aIJPXYXOpqCI5wFJaA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } }, - "node_modules/turbo-windows-64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.8.3.tgz", - "integrity": "sha512-cnzAytHtoLXd0J7aNzRpZFpL/GTjcBmkvAPlbOdf/Pl1iwS4qzGrudZQ+OM1lmLgLIfBPIavsGHBknTwTNib4A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/turbo-windows-arm64": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.8.3.tgz", - "integrity": "sha512-ulIiItNm2w/zYJdD5/oAzjzNns1IjbpweRzpsE8tLXaWwo6+fnXXkyloUug0IUhcd2k6fJXfoiDZfygqpOVuXg==", - "cpu": [ - "arm64" - ], + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dependencies": { - "prelude-ls": "^1.2.1" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "node_modules/execa/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==", "dev": true }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "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==", - "dev": true, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=8.6.0" } }, - "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==", - "dev": true, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 6" } }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "node_modules/wrap-ansi-cjs/node_modules/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, - "node_modules/wrap-ansi/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==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/wrap-ansi/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==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "dependencies": { + "bser": "2.1.1" } }, - "node_modules/wrap-ansi/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==", - "dev": true, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dependencies": { - "ansi-regex": "^6.0.1" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=10" }, @@ -2684,139 +3009,198 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/cli": { - "name": "@apillon/cli", - "version": "0.1.2", - "license": "MIT", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dependencies": { - "@apillon/sdk": "*", - "axios": "^1.3.4", - "chalk": "^4.1.2", - "commander": "^10.0.0", - "dotenv": "^16.0.3" - }, - "bin": { - "apillon": "dist/index.js", - "cli": "dist/index.js" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, - "devDependencies": { - "eslint-config-common": "*", - "nodemon": "^2.0.20", - "rimraf": "^5.0.5", - "ts-node": "^10.9.1", - "tsconfig": "*" + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "packages/cli/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "packages/cli/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { - "brace-expansion": "^2.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "packages/cli/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "dev": true, + "node_modules/flat-cache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "*" } }, - "packages/cli/node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, + "node_modules/flat-cache/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": "^10.3.7" + "glob": "^7.1.3" }, "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14" + "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "packages/eslint-config-common": { - "version": "0.0.0", + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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==", + "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "^5.35.1", - "@typescript-eslint/parser": "^5.35.1", - "eslint": "^8.22.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-promise": "^6.0.1", - "eslint-plugin-security": "^1.5.0", - "eslint-plugin-sonarjs": "^0.15.0", - "tsconfig": "*" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, - "devDependencies": { - "typescript": "^4.7.4" + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "packages/sdk": { - "name": "@apillon/sdk", - "version": "0.1.2", - "license": "MIT", + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { - "axios": "^1.3.4" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, - "devDependencies": { - "eslint-config-common": "*", - "nodemon": "^2.0.20", - "rimraf": "^5.0.5", - "ts-node": "^10.9.1", - "tsconfig": "*" + "engines": { + "node": ">= 6" } }, - "packages/sdk/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", + "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^7.4.1", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -2825,784 +3209,5527 @@ "url": "https://github.com/sponsors/isaacs" } }, - "packages/sdk/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dependencies": { - "brace-expansion": "^2.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/sdk/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=10.17.0" } }, - "packages/sdk/node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { - "glob": "^10.3.7" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" }, "bin": { - "rimraf": "dist/esm/bin.mjs" + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/tsconfig": { - "version": "0.0.0" - } - }, - "dependencies": { - "@apillon/cli": { + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "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": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", + "integrity": "sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", + "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/nodemon": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.21.tgz", + "integrity": "sha512-djN/n2549DUtY33S7o1djRCd7dEm0kBnj9c7S9XVXqRUbuggN1MZH/Nqa+5RFQr63Fbefq37nFXAE9VU86yL1A==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", + "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.0.tgz", + "integrity": "sha512-X36S+qpCUR0HjXlkDe4NAOhS//aHH0Z+h8Ckf2auGJk3PTnx5rLmrHkwNdbVQuCSUhOyFrlRvFEllZOYE+yZGQ==", + "dev": true, + "dependencies": { + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", + "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", + "dependencies": { + "regexp-tree": "~0.1.1" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dev": true, + "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/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/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==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/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-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==", + "dev": true, + "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", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/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==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig": { + "resolved": "packages/tsconfig", + "link": true + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/turbo": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo/-/turbo-1.8.3.tgz", + "integrity": "sha512-zGrkU1EuNFmkq6iky6LcMqD4h0OLE8XysVFxQWRIZbcTNnf0XAycbsbeEyiJpiWeqb7qtg2bVuY9EYcNoNhVuQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "turbo": "bin/turbo" + }, + "optionalDependencies": { + "turbo-darwin-64": "1.8.3", + "turbo-darwin-arm64": "1.8.3", + "turbo-linux-64": "1.8.3", + "turbo-linux-arm64": "1.8.3", + "turbo-windows-64": "1.8.3", + "turbo-windows-arm64": "1.8.3" + } + }, + "node_modules/turbo-darwin-64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-1.8.3.tgz", + "integrity": "sha512-bLM084Wr17VAAY/EvCWj7+OwYHvI9s/NdsvlqGp8iT5HEYVimcornCHespgJS/yvZDfC+mX9EQkn3V2JmYgGGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/turbo-darwin-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-1.8.3.tgz", + "integrity": "sha512-4oZjXtzakopMK110kue3z/hqu3WLv+eDLZOX1NGdo49gqca9BeD8GbH+sXpAp6tqyeuzpss+PIliVYuyt7LgbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/turbo-linux-64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-1.8.3.tgz", + "integrity": "sha512-uvX2VKotf5PU14FCxJA5iHItPQno2JWzerMd+g3/h/Asay6dvxvtVjc39MQeGT0H5njSvzVKFkT+3/5q8lgOEg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-linux-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-1.8.3.tgz", + "integrity": "sha512-E1p+oH3XKMaPS4rqWhYsL4j2Pzc0d/9P5KU7Kn1kqVLo2T3iRA7n2KVULEieUNE0nTH+aIJPXYXOpqCI5wFJaA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/turbo-windows-64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-1.8.3.tgz", + "integrity": "sha512-cnzAytHtoLXd0J7aNzRpZFpL/GTjcBmkvAPlbOdf/Pl1iwS4qzGrudZQ+OM1lmLgLIfBPIavsGHBknTwTNib4A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/turbo-windows-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-1.8.3.tgz", + "integrity": "sha512-ulIiItNm2w/zYJdD5/oAzjzNns1IjbpweRzpsE8tLXaWwo6+fnXXkyloUug0IUhcd2k6fJXfoiDZfygqpOVuXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "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/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==", + "dev": true, + "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/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/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==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/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==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/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==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/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==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/cli": { + "name": "@apillon/cli", + "version": "0.1.2", + "license": "MIT", + "dependencies": { + "@apillon/sdk": "*", + "axios": "^1.3.4", + "chalk": "^4.1.2", + "commander": "^10.0.0", + "dotenv": "^16.0.3" + }, + "bin": { + "apillon": "dist/index.js", + "cli": "dist/index.js" + }, + "devDependencies": { + "eslint-config-common": "*", + "nodemon": "^2.0.20", + "rimraf": "^5.0.5", + "ts-node": "^10.9.1", + "tsconfig": "*" + } + }, + "packages/cli/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/cli/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/cli/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/cli/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/eslint-config-common": { + "version": "0.0.0", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.35.1", + "@typescript-eslint/parser": "^5.35.1", + "eslint": "^8.22.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.0.1", + "eslint-plugin-security": "^1.5.0", + "eslint-plugin-sonarjs": "^0.15.0", + "tsconfig": "*" + }, + "devDependencies": { + "typescript": "^4.7.4" + } + }, + "packages/sdk": { + "name": "@apillon/sdk", + "version": "0.1.2", + "license": "MIT", + "dependencies": { + "axios": "^1.3.4" + }, + "devDependencies": { + "eslint-config-common": "*", + "nodemon": "^2.0.20", + "rimraf": "^5.0.5", + "ts-node": "^10.9.1", + "tsconfig": "*" + } + }, + "packages/sdk/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/sdk/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/sdk/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "packages/sdk/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/tsconfig": { + "version": "0.0.0" + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@apillon/cli": { "version": "file:packages/cli", "requires": { - "@apillon/sdk": "*", - "axios": "^1.3.4", - "chalk": "^4.1.2", - "commander": "^10.0.0", - "dotenv": "^16.0.3", - "eslint-config-common": "*", - "nodemon": "^2.0.20", - "rimraf": "^5.0.5", - "ts-node": "^10.9.1", - "tsconfig": "*" + "@apillon/sdk": "*", + "axios": "^1.3.4", + "chalk": "^4.1.2", + "commander": "^10.0.0", + "dotenv": "^16.0.3", + "eslint-config-common": "*", + "nodemon": "^2.0.20", + "rimraf": "^5.0.5", + "ts-node": "^10.9.1", + "tsconfig": "*" + }, + "dependencies": { + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "requires": { + "glob": "^10.3.7" + } + } + } + }, + "@apillon/sdk": { + "version": "file:packages/sdk", + "requires": { + "axios": "^1.3.4", + "eslint-config-common": "*", + "nodemon": "^2.0.20", + "rimraf": "^5.0.5", + "ts-node": "^10.9.1", + "tsconfig": "*" + }, + "dependencies": { + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "requires": { + "glob": "^10.3.7" + } + } + } + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", + "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==" + }, + "@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==" + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "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==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.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", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + } + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.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==", + "dev": true, + "optional": true + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "dev": true, + "requires": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "@types/node": { + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "dev": true + }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.26", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz", + "integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", + "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/type-utils": "5.55.0", + "@typescript-eslint/utils": "5.55.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", + "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", + "requires": { + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", + "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "requires": { + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", + "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", + "requires": { + "@typescript-eslint/typescript-estree": "5.55.0", + "@typescript-eslint/utils": "5.55.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", + "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==" + }, + "@typescript-eslint/typescript-estree": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", + "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "requires": { + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/visitor-keys": "5.55.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", + "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.55.0", + "@typescript-eslint/types": "5.55.0", + "@typescript-eslint/typescript-estree": "5.55.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", + "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", + "requires": { + "@typescript-eslint/types": "5.55.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "requires": {} + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" }, "dependencies": { - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true - }, - "rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } } } }, - "@apillon/sdk": { - "version": "file:packages/sdk", + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "axios": "^1.3.4", - "eslint-config-common": "*", - "nodemon": "^2.0.20", - "rimraf": "^5.0.5", - "ts-node": "^10.9.1", - "tsconfig": "*" + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "dependencies": { - "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" } }, - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true - }, - "rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "requires": { - "glob": "^10.3.7" - } } } }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" } }, - "@eslint-community/eslint-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.2.0.tgz", - "integrity": "sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==", + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, "requires": { - "eslint-visitor-keys": "^3.3.0" + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" } }, - "@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==" + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "@eslint/eslintrc": { + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + "balanced-match": "^1.0.0" } }, - "@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==" + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } }, - "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001542", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001542.tgz", + "integrity": "sha512-UrtAXVcj1mvPBFQ4sKd38daP8dEcXXr5sQe6QNNinaPd0iA/cxg9/l3VrSdL73jgw5sKyuQ6jNgiKO12W3SsVA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "is-glob": "^4.0.1" } } } }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + "ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "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==", + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "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" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "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==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "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==", "dev": true, "requires": { - "ansi-regex": "^6.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "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==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } } } }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "color-name": "~1.1.4" } }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "delayed-stream": "~1.0.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==", - "dev": true, - "optional": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "commander": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", + "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==" }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" - }, - "@types/node": { - "version": "18.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, - "peer": true - }, - "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.55.0.tgz", - "integrity": "sha512-IZGc50rtbjk+xp5YQoJvmMPmJEYoC53SiKPXyqWfv15XoD2Y5Kju6zN0DwlmaGJp1Iw33JsWJcQ7nw0lGCGjVg==", "requires": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/type-utils": "5.55.0", - "@typescript-eslint/utils": "5.55.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" } }, - "@typescript-eslint/parser": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.55.0.tgz", - "integrity": "sha512-ppvmeF7hvdhUUZWSd2EEWfzcFkjJzgNQzVST22nzg958CR+sphy8A6K7LXQZd6V75m1VKjp+J4g/PCEfSCmzhw==", - "requires": { - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "debug": "^4.3.4" - } + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, - "@typescript-eslint/scope-manager": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.55.0.tgz", - "integrity": "sha512-OK+cIO1ZGhJYNCL//a3ROpsd83psf4dUJ4j7pdNVzd5DmIk+ffkuUIX2vcZQbEW/IR41DYsfJTB19tpCboxQuw==", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "requires": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "@typescript-eslint/type-utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.55.0.tgz", - "integrity": "sha512-ObqxBgHIXj8rBNm0yh8oORFrICcJuZPZTqtAFh0oZQyr5DnAHZWfyw54RwpEEH+fD8suZaI0YxvWu5tYE/WswA==", + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "@typescript-eslint/typescript-estree": "5.55.0", - "@typescript-eslint/utils": "5.55.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ms": "2.1.2" } }, - "@typescript-eslint/types": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.55.0.tgz", - "integrity": "sha512-M4iRh4AG1ChrOL6Y+mETEKGeDnT7Sparn6fhZ5LtVJF1909D5O4uqK+C5NPbLmpfZ0XIIxCdwzKiijpZUOvOug==" + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true }, - "@typescript-eslint/typescript-estree": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.55.0.tgz", - "integrity": "sha512-I7X4A9ovA8gdpWMpr7b1BN9eEbvlEtWhQvpxp/yogt48fy9Lj3iE3ild/1H3jKBBIYj5YYJmS2+9ystVhC7eaQ==", + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "requires": { - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/visitor-keys": "5.55.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "path-type": "^4.0.0" } }, - "@typescript-eslint/utils": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.55.0.tgz", - "integrity": "sha512-FkW+i2pQKcpDC3AY6DU54yl8Lfl14FVGYDgBTyGKB75cCwV3KpkpTMFi9d9j2WAJ4271LR2HeC5SEWF/CZmmfw==", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.55.0", - "@typescript-eslint/types": "5.55.0", - "@typescript-eslint/typescript-estree": "5.55.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "esutils": "^2.0.2" } }, - "@typescript-eslint/visitor-keys": { - "version": "5.55.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.55.0.tgz", - "integrity": "sha512-q2dlHHwWgirKh1D3acnuApXG+VNXpEY5/AwRxDVuEQpxWaB0jCDe0jFMVMALJ3ebSfuOVE8/rMS+9ZOYGg1GWw==", - "requires": { - "@typescript-eslint/types": "5.55.0", - "eslint-visitor-keys": "^3.3.0" - } + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + "electron-to-chromium": { + "version": "1.4.537", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.537.tgz", + "integrity": "sha512-W1+g9qs9hviII0HAwOdehGYkr+zt7KKdmCcJcjH0mYg6oL8+ioT3Skjmt7BLoAQqXhjf40AXd+HlR4oAWMlXjA==", + "dev": true }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "requires": {} + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "is-arrayish": "^0.2.1" } }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", "requires": { - "color-convert": "^2.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, + "eslint-config-common": { + "version": "file:packages/eslint-config-common", "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@typescript-eslint/eslint-plugin": "^5.35.1", + "@typescript-eslint/parser": "^5.35.1", + "eslint": "^8.22.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-promise": "^6.0.1", + "eslint-plugin-security": "^1.5.0", + "eslint-plugin-sonarjs": "^0.15.0", + "tsconfig": "*", + "typescript": "^4.7.4" } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "eslint-config-prettier": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz", + "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==", + "requires": {} }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "requires": { + "prettier-linter-helpers": "^1.0.0" + } }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "requires": {} + }, + "eslint-plugin-security": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", + "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "requires": { + "safe-regex": "^2.1.1" + } + }, + "eslint-plugin-sonarjs": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.15.0.tgz", + "integrity": "sha512-LuxHdAe6VqSbi1phsUvNjbmXLuvlobmryQJJNyQYbdubCfz6K8tmgoqNiJPnz0pP2AbYDbtuPm0ajOMgMrC+dQ==", + "requires": {} + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" }, - "axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "requires": { - "balanced-match": "^1.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "requires": { - "fill-range": "^7.0.1" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } } }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "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==", + "dev": true + } } }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "dependencies": { "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } } } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "requires": { - "delayed-stream": "~1.0.0" + "reusify": "^1.0.4" } }, - "commander": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", - "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "bser": "2.1.1" } }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "requires": { - "ms": "2.1.2" + "flat-cache": "^3.0.4" } }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "requires": { - "path-type": "^4.0.0" + "to-regex-range": "^5.0.1" } }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, "dependencies": { "brace-expansion": { @@ -3614,20 +8741,19 @@ "concat-map": "0.0.1" } }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3635,210 +8761,472 @@ "requires": { "brace-expansion": "^1.1.7" } + }, + "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" + } } } }, - "eslint-config-common": { - "version": "file:packages/eslint-config-common", + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "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==", + "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "^5.35.1", - "@typescript-eslint/parser": "^5.35.1", - "eslint": "^8.22.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-promise": "^6.0.1", - "eslint-plugin-security": "^1.5.0", - "eslint-plugin-sonarjs": "^0.15.0", - "tsconfig": "*", - "typescript": "^4.7.4" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" } }, - "eslint-config-prettier": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.7.0.tgz", - "integrity": "sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==", - "requires": {} + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } }, - "eslint-plugin-prettier": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", - "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", + "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "dev": true, "requires": { - "prettier-linter-helpers": "^1.0.0" + "fs.realpath": "^1.0.0", + "minimatch": "^7.4.1", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" } }, - "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "requires": {} + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } }, - "eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "requires": { - "safe-regex": "^2.1.1" + "type-fest": "^0.20.2" } }, - "eslint-plugin-sonarjs": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.15.0.tgz", - "integrity": "sha512-LuxHdAe6VqSbi1phsUvNjbmXLuvlobmryQJJNyQYbdubCfz6K8tmgoqNiJPnz0pP2AbYDbtuPm0ajOMgMrC+dQ==", - "requires": {} + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "once": "^1.3.0", + "wrappy": "1" } }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "binary-extensions": "^2.0.0" } }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - } + "has": "^1.0.3" } }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" - } + "is-extglob": "^2.1.1" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", + "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "dev": true, "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { - "is-glob": "^4.0.1" + "yallist": "^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" } } } }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, "requires": { - "reusify": "^1.0.4" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, "requires": { - "flat-cache": "^3.0.4" + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" } }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" } }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" } }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "dependencies": { "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3848,6 +9236,7 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3861,203 +9250,392 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } - }, - "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" - } } } }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, - "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==", + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "detect-newline": "^3.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + } }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, - "optional": true + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } }, - "glob": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.0.tgz", - "integrity": "sha512-EAZejC7JvnQINayvB/7BJbpZpNOJ8Lrw2OZNEvQxe0vaLn1SuwMcfV7/MNaX8L/T0wmptBFI4YMtDvSBxYDc7w==", + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "minimatch": "^7.4.1", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, "requires": { - "is-glob": "^4.0.3" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" } }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "requires": { - "type-fest": "^0.20.2" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" } }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" } }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" } }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" } }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "requires": { - "binary-extensions": "^2.0.0" + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, "requires": { - "is-extglob": "^2.1.1" + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } } }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + } + } }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + } }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "js-sdsl": { @@ -4065,6 +9643,12 @@ "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4073,6 +9657,18 @@ "argparse": "^2.0.1" } }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -4083,6 +9679,24 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -4092,6 +9706,12 @@ "type-check": "~0.4.0" } }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4100,6 +9720,12 @@ "p-locate": "^5.0.0" } }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4111,10 +9737,54 @@ "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "dev": true }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, "merge2": { @@ -4144,6 +9814,12 @@ "mime-db": "1.52.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "minimatch": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.2.tgz", @@ -4174,6 +9850,18 @@ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, "nodemon": { "version": "2.0.21", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.21.tgz", @@ -4258,6 +9946,15 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4266,6 +9963,15 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -4295,6 +10001,12 @@ "p-limit": "^3.0.2" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4303,6 +10015,18 @@ "callsites": "^3.0.0" } }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4318,6 +10042,12 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, "path-scurry": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", @@ -4341,11 +10071,71 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4364,6 +10154,35 @@ "fast-diff": "^1.1.2" } }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -4380,11 +10199,23 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, + "pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4399,11 +10230,51 @@ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==" }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4488,11 +10359,66 @@ } } }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, "string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -4557,6 +10483,18 @@ "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4570,11 +10508,75 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4592,6 +10594,42 @@ "nopt": "~1.0.10" } }, + "ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "ts-node": { "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", @@ -4693,6 +10731,12 @@ "prelude-ls": "^1.2.1" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -4709,6 +10753,16 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4723,6 +10777,44 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + } + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4805,11 +10897,75 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 1f049f2..1fc3e24 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,34 @@ "eslint-config-common": "*", "prettier": "latest", "rimraf": "^4.4.0", - "turbo": "latest" + "turbo": "latest", + "jest": "29.7.0", + "ts-jest": "29.1.1", + "@types/jest": "^29.5.5" + }, + "jest": { + "testTimeout": 1800000, + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "json" + ], + "rootDir": "src/tests", + "testPathIgnorePatterns": [ + "dist/*" + ], + "testRegex": ".*\\.test\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverage": false, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node", + "preset": "ts-jest", + "verbose": true } } diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 8c6b655..5f14ce0 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -25,7 +25,8 @@ "build": "tsc --declarationMap", "dev": "tsc --declarationMap --watch", "lint": "tsc --declarationMap && eslint \"{src,test}/**/*.ts\" --fix", - "publish-package": "npm publish" + "publish-package": "npm publish", + "test": "npx jest" }, "keywords": [ "SDK", @@ -48,6 +49,32 @@ "nodemon": "^2.0.20", "ts-node": "^10.9.1", "tsconfig": "*", - "rimraf": "^5.0.5" + "rimraf": "^5.0.5", + "dotenv": "^16.0.3" + }, + "jest": { + "testTimeout": 1800000, + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "json" + ], + "rootDir": "src", + "testPathIgnorePatterns": [ + "dist/*" + ], + "testRegex": ".*\\.test\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverage": false, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node", + "preset": "ts-jest", + "verbose": true } -} \ No newline at end of file +} From ea7339930b5b24558ee1c1a944fe6ea9f9976229 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Tue, 3 Oct 2023 13:15:14 +0200 Subject: [PATCH 03/68] Refactor structure and add comments. --- EXAMPLE.md | 7 +- packages/sdk/src/index.ts | 6 +- packages/sdk/src/{modules => lib}/apillon.ts | 0 packages/sdk/src/lib/common.ts | 2 +- packages/sdk/src/modules/hosting.ts | 99 ------------ .../src/modules/hosting/hosting-website.ts | 150 ++++++++++++++++++ packages/sdk/src/modules/hosting/hosting.ts | 17 ++ .../{nfts.ts => nft/nft-collection.ts} | 33 ++-- packages/sdk/src/modules/nft/nft.ts | 3 + .../sdk/src/modules/storage/storage-bucket.ts | 1 + packages/sdk/src/modules/storage/storage.ts | 3 + packages/sdk/src/types/hosting.ts | 5 + packages/sdk/src/types/nfts.ts | 6 +- packages/tsconfig/base.json | 6 +- 14 files changed, 211 insertions(+), 127 deletions(-) rename packages/sdk/src/{modules => lib}/apillon.ts (100%) delete mode 100644 packages/sdk/src/modules/hosting.ts create mode 100644 packages/sdk/src/modules/hosting/hosting-website.ts create mode 100644 packages/sdk/src/modules/hosting/hosting.ts rename packages/sdk/src/modules/{nfts.ts => nft/nft-collection.ts} (87%) create mode 100644 packages/sdk/src/modules/nft/nft.ts create mode 100644 packages/sdk/src/modules/storage/storage-bucket.ts create mode 100644 packages/sdk/src/modules/storage/storage.ts create mode 100644 packages/sdk/src/types/hosting.ts diff --git a/EXAMPLE.md b/EXAMPLE.md index d4e970b..8d6e0f8 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -16,13 +16,13 @@ export async function test() { await webpage1.getDeployment(id); await webpage1.getDeployments(); await webpage1.deployFromFolder('path', 'environment'); // can go directly to production - await webpage1.updateDeployment(from stg -> production); // tu me moti še na api levelu, kr lahko dobiš in pogledaš detajle specifičnega deploymenta, ampak deploy klic pa dela samo na zadnjem + await webpage1.updateDeployment(from stg -> production); // tu me moti še na api levelu, kr lahko dobiš in pogledaš detajle specifičnega deploymenta, ampak deploy klic pa dela samo na zadnjem // or await hosting.website('uuid').getInfo(); - //Naming hosting -> webpage? + //Naming hosting -> webpage? const storage = new Storage({ apillonConfig }); await storage.listBuckets(); @@ -36,7 +36,6 @@ export async function test() { const nft = new Nft({ apillonConfig }); await nft.listCollections(); - await nft.createCollection(); const collection = nft.collection('uuid'); const info = collection.getInfo(); //.info? @@ -47,4 +46,4 @@ export async function test() { } -``` \ No newline at end of file +``` diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 6f9c856..24a66f8 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,6 +1,6 @@ export * from './lib/common'; export * from './types/generic'; export * from './types/nfts'; -export * from './modules/apillon'; -export * from './modules/hosting'; -export * from './modules/nfts'; +export * from './lib/apillon'; +export * from './modules/hosting/hosting'; +export * from './modules/nft/nft'; diff --git a/packages/sdk/src/modules/apillon.ts b/packages/sdk/src/lib/apillon.ts similarity index 100% rename from packages/sdk/src/modules/apillon.ts rename to packages/sdk/src/lib/apillon.ts diff --git a/packages/sdk/src/lib/common.ts b/packages/sdk/src/lib/common.ts index 2c72d61..26acf8e 100644 --- a/packages/sdk/src/lib/common.ts +++ b/packages/sdk/src/lib/common.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import * as path from 'path'; import axios from 'axios'; -import { ApillonApiError, ApillonNetworkError } from '../modules/apillon'; +import { ApillonApiError, ApillonNetworkError } from './apillon'; /** * Convert value to boolean if defined, else return undefined. diff --git a/packages/sdk/src/modules/hosting.ts b/packages/sdk/src/modules/hosting.ts deleted file mode 100644 index b30a57b..0000000 --- a/packages/sdk/src/modules/hosting.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { listFilesRecursive, uploadFilesToS3 } from '../lib/common'; -import { ApillonModule } from './apillon'; - -export enum DeployToEnvironment { - TO_STAGING = 1, - STAGING_TO_PRODUCTION = 2, - DIRECTLY_TO_PRODUCTION = 3, -} - -export class Hosting extends ApillonModule { - public async createWebsite() { - throw Error('Not implemented'); - } - - public async getWebsite(websiteUuid) { - throw Error('Not implemented'); - } - - public async updateWebsite(websiteUuid, params) { - throw Error('Not implemented'); - } - - public async uploadFromFolder(websiteUuid: string, folderPath: string) { - console.log( - `Preparing to upload files from ${folderPath} to website ${websiteUuid} ...`, - ); - let files; - try { - files = listFilesRecursive(folderPath); - } catch (err) { - console.error(err); - throw new Error(`Error reading files in ${folderPath}`); - } - - const data = { files }; - console.log(`Files to upload: ${data.files.length}`); - - console.time('Got upload links'); - const resp = await this.api.post( - `/hosting/websites/${websiteUuid}/upload`, - data, - ); - - console.timeEnd('Got upload links'); - - // console.log(resp); - const sessionUuid = resp.data.data.sessionUuid; - - console.time('File upload complete'); - await uploadFilesToS3(resp.data.data.files, files); - console.timeEnd('File upload complete'); - - console.log('Closing session...'); - const respEndSession = await this.api.post( - `/hosting/websites/${websiteUuid}/upload/${sessionUuid}/end`, - ); - console.log('Session ended.'); - return respEndSession.data?.data; - } - - public async deployWebsite( - websiteUuid: string, - toEnvironment: DeployToEnvironment, - ) { - // - console.log( - `Deploying website ${websiteUuid} to IPFS (${ - toEnvironment === DeployToEnvironment.TO_STAGING - ? 'preview' - : 'production' - })`, - ); - - console.time('Deploy complete'); - const resp = await this.api.post( - `/hosting/websites/${websiteUuid}/deploy`, - { - environment: toEnvironment, - }, - ); - - console.timeEnd('Deploy complete'); - - return resp.data.data; - } - - public async getWebsiteDeployments( - websiteUuid: string, - deploymentId?: string, - ) { - // - console.log('Get deployments for website ', websiteUuid); - return ( - await this.api.get( - `/hosting/websites/${websiteUuid}/deployments/${deploymentId}`, - ) - ).data; - } -} diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts new file mode 100644 index 0000000..b84febe --- /dev/null +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -0,0 +1,150 @@ +import { AxiosInstance } from 'axios'; +import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; +import { DeployToEnvironment } from '../../types/hosting'; + +export class HostingWebsite { + /** + * Axios instance set to correct rootUrl with correct error handling. + */ + protected api: AxiosInstance; + + /** + * @dev API url prefix for this class. + */ + private API_PREFIX = '/hosting/websites'; + + /** + * @dev Unique identifier of the website. + */ + public uuid; + + /** + * @dev User assigned name of the website. + */ + public name: string = null; + + /** + * @dev User assigned description of the website. + */ + public description: string = null; + + /** + * @dev Domain on which this website lives. + */ + public domain: string = null; + + /** + * @dev Unique identifier of a storage bucket in which this website files reside. + */ + public bucketUuid: string = null; + + /** + * @dev IPNS CID for staging environment. + */ + public ipnsStaging: string = null; + + /** + * @dev IPNS CID for production environment. + */ + public ipnsProduction: string = null; + + /** + * @dev Constructor which should only be called via Hosting class. + * @param uuid Unique identifier of the website. + * @param api Axios instance set to correct rootUrl with correct error handling. + */ + constructor(uuid: string, api: AxiosInstance) { + this.api = api; + this.uuid = uuid; + } + + /** + * @dev Gets information about the website and fills properties with it. + * @returns An instance of HostingWebsite class with filled properties. + */ + public async get(): Promise { + const data = (await this.api.get(`${this.API_PREFIX}/${this.uuid}`)).data; + this.name = data.data?.name; + this.description = data.data?.description; + this.domain = data.data?.domain; + this.bucketUuid = data.data?.bucketUuid; + this.ipnsStaging = data.data?.ipnsStaging; + this.ipnsProduction = data.data?.ipnsProduction; + return this; + } + + /** + * @dev Uploads website files inside a folder via path. + * @param folderPath Path to the folder to upload. + */ + public async uploadFromFolder(folderPath: string): Promise { + console.log( + `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, + ); + let files; + try { + files = listFilesRecursive(folderPath); + } catch (err) { + console.error(err); + throw new Error(`Error reading files in ${folderPath}`); + } + + const data = { files }; + console.log(`Files to upload: ${data.files.length}`); + + console.time('Got upload links'); + const resp = await this.api.post( + `${this.API_PREFIX}/${this.uuid}/upload`, + data, + ); + + console.timeEnd('Got upload links'); + + // console.log(resp); + const sessionUuid = resp.data.data.sessionUuid; + + console.time('File upload complete'); + await uploadFilesToS3(resp.data.data.files, files); + console.timeEnd('File upload complete'); + + console.log('Closing session...'); + const respEndSession = await this.api.post( + `${this.API_PREFIX}/${this.uuid}/upload/${sessionUuid}/end`, + ); + console.log('Session ended.'); + + if (!respEndSession.data?.data) { + throw new Error(); + } + } + + public async deploy(toEnvironment: DeployToEnvironment): Promise { + // + console.log( + `Deploying website ${this.uuid} to IPFS (${ + toEnvironment === DeployToEnvironment.TO_STAGING + ? 'preview' + : 'production' + })`, + ); + + console.time('Deploy complete'); + const resp = await this.api.post(`${this.API_PREFIX}/${this.uuid}/deploy`, { + environment: toEnvironment, + }); + + console.timeEnd('Deploy complete'); + + return resp.data?.data; + } + + public async getDeployStatus(deploymentId: string) { + // + console.log('Get deployments for website ', this.uuid); + return ( + await this.api.get( + `${this.API_PREFIX}/${this.uuid}/deployments/${deploymentId}`, + ) + ).data; + } +} diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts new file mode 100644 index 0000000..720d3b6 --- /dev/null +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -0,0 +1,17 @@ +import { ApillonModule } from '../../lib/apillon'; +import { HostingWebsite } from './hosting-website'; + +export class Hosting extends ApillonModule { + public createWebsite() { + throw Error('Not implemented'); + } + + /** + * @dev Returns an website instance. + * @param uuid Unique website identifier. + * @returns An instance of Website.∂ + */ + public website(uuid: string): HostingWebsite { + return new HostingWebsite(uuid, this.api); + } +} diff --git a/packages/sdk/src/modules/nfts.ts b/packages/sdk/src/modules/nft/nft-collection.ts similarity index 87% rename from packages/sdk/src/modules/nfts.ts rename to packages/sdk/src/modules/nft/nft-collection.ts index 0d3e2f5..57f2900 100644 --- a/packages/sdk/src/modules/nfts.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -1,25 +1,32 @@ -import { ApillonModule } from './apillon'; -import { constructUrlWithQueryParams } from '../lib/common'; +import { AxiosInstance } from 'axios'; +import { constructUrlWithQueryParams } from '../../lib/common'; +import { + IApillonResponse, + IApillonList, + IApillonStatus, +} from '../../types/apillon'; import { - IBurnCollectionNft, - ICollection, ICollectionFilters, + ICollection, ICreateCollection, IMintCollectionNft, INestMintCollectionNft, - ITransaction, - ITransactionFilters, + IBurnCollectionNft, ITransferCollectionOwnership, -} from '../types/nfts'; -import { - IApillonList, - IApillonResponse, - IApillonStatus, -} from '../types/apillon'; + ITransactionFilters, + ITransaction, +} from '../../types/nfts'; const COLLECTIONS_ROUTE = '/nfts/collections'; -export class Nfts extends ApillonModule { +export class NftCollection { + protected api: AxiosInstance; + private uuid; + + constructor(uuid: string, api: AxiosInstance) { + this.api = api; + this.uuid = uuid; + } // COLLECTIONS public async listNftCollections(params: ICollectionFilters) { const url = constructUrlWithQueryParams(COLLECTIONS_ROUTE, params); diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts new file mode 100644 index 0000000..e8ad2ea --- /dev/null +++ b/packages/sdk/src/modules/nft/nft.ts @@ -0,0 +1,3 @@ +import { ApillonModule } from '../../lib/apillon'; + +export class Nft extends ApillonModule {} diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts new file mode 100644 index 0000000..1fbd5b3 --- /dev/null +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -0,0 +1 @@ +export class StorageBucket {} diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts new file mode 100644 index 0000000..acebc1e --- /dev/null +++ b/packages/sdk/src/modules/storage/storage.ts @@ -0,0 +1,3 @@ +import { ApillonModule } from '../../lib/apillon'; + +export class Storage extends ApillonModule {} diff --git a/packages/sdk/src/types/hosting.ts b/packages/sdk/src/types/hosting.ts new file mode 100644 index 0000000..38e6860 --- /dev/null +++ b/packages/sdk/src/types/hosting.ts @@ -0,0 +1,5 @@ +export enum DeployToEnvironment { + TO_STAGING = 1, + STAGING_TO_PRODUCTION = 2, + DIRECTLY_TO_PRODUCTION = 3, +} diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index 65ccf07..d62a35e 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -113,10 +113,10 @@ export interface ITransaction { } export interface ICollectionFilters extends IApillonPagination { - collectionStatus: CollectionStatus + collectionStatus: CollectionStatus; } export interface ITransactionFilters extends IApillonPagination { - transactionStatus: TransactionStatus - transactionType: TransactionType + transactionStatus: TransactionStatus; + transactionType: TransactionType; } diff --git a/packages/tsconfig/base.json b/packages/tsconfig/base.json index 4edd157..470daff 100644 --- a/packages/tsconfig/base.json +++ b/packages/tsconfig/base.json @@ -22,7 +22,5 @@ "sourceMap": true, "target": "es2017" }, - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "exclude": ["node_modules"] +} From 8f13522565a42415df0694454fff272aabc6c713 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Tue, 3 Oct 2023 13:15:31 +0200 Subject: [PATCH 04/68] Add hosting tests --- packages/sdk/src/tests/helpers/helper.ts | 11 ++++ .../sdk/src/tests/helpers/website/index.html | 11 ++++ .../sdk/src/tests/helpers/website/style.css | 4 ++ packages/sdk/src/tests/hosting.test.ts | 55 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 packages/sdk/src/tests/helpers/helper.ts create mode 100644 packages/sdk/src/tests/helpers/website/index.html create mode 100644 packages/sdk/src/tests/helpers/website/style.css create mode 100644 packages/sdk/src/tests/hosting.test.ts diff --git a/packages/sdk/src/tests/helpers/helper.ts b/packages/sdk/src/tests/helpers/helper.ts new file mode 100644 index 0000000..d375d16 --- /dev/null +++ b/packages/sdk/src/tests/helpers/helper.ts @@ -0,0 +1,11 @@ +import * as dotenv from 'dotenv'; +import { ApillonConfig } from '../../lib/apillon'; + +export function getConfig(): ApillonConfig { + dotenv.config({ path: '../../.env' }); + return { + apiUrl: process.env['APILLON_API_URL'], + secret: process.env['APILLON_API_SECRET'], + key: process.env['APILLON_API_KEY'], + } as ApillonConfig; +} diff --git a/packages/sdk/src/tests/helpers/website/index.html b/packages/sdk/src/tests/helpers/website/index.html new file mode 100644 index 0000000..a1a87a8 --- /dev/null +++ b/packages/sdk/src/tests/helpers/website/index.html @@ -0,0 +1,11 @@ + + + + + Page Title + + +

This is a Heading

+

This is a paragraph.

+ + diff --git a/packages/sdk/src/tests/helpers/website/style.css b/packages/sdk/src/tests/helpers/website/style.css new file mode 100644 index 0000000..406e561 --- /dev/null +++ b/packages/sdk/src/tests/helpers/website/style.css @@ -0,0 +1,4 @@ +h1 { + color: white; + text-align: center; +} diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts new file mode 100644 index 0000000..00a832e --- /dev/null +++ b/packages/sdk/src/tests/hosting.test.ts @@ -0,0 +1,55 @@ +import { ApillonConfig } from '../lib/apillon'; +import { Hosting } from '../modules/hosting/hosting'; +import { DeployToEnvironment } from '../types/hosting'; +import { getConfig } from './helpers/helper'; + +describe('Hosting tests', () => { + let config: ApillonConfig; + + beforeAll(async () => { + config = getConfig(); + }); + + test('get website info', async () => { + const hosting = new Hosting(config); + try { + const website = await hosting + .website('8e1a512d-5672-4c2f-ad5e-60333498cde2') + .get(); + console.log(website.name); + console.log(website.bucketUuid); + console.log(website.ipnsProduction); + console.log(website.ipnsStaging); + } catch (e) { + console.log(e); + } + }); + + test('upload website from folder', async () => { + const hosting = new Hosting(config); + const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + try { + await website.uploadFromFolder('./src/tests/helpers/website/'); + } catch (e) { + console.log(e); + } + const deploymentId = await website.deploy(DeployToEnvironment.TO_STAGING); + console.log(deploymentId); + }); + + test.only('get deployment status', async () => { + const hosting = new Hosting(config); + const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + + const deployStatus = await website.deploy(DeployToEnvironment.TO_STAGING); + console.log(deployStatus); + }); + + test.only('get deployment status', async () => { + const hosting = new Hosting(config); + const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + + const deployStatus = await website.getDeployStatus('201'); + console.log(deployStatus); + }); +}); From 4bc28d2bc721dd8cdadd48dd982162d9a1d919b3 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Wed, 4 Oct 2023 14:22:56 +0200 Subject: [PATCH 05/68] Basic storage logic. --- .../src/modules/hosting/hosting-website.ts | 18 ++- packages/sdk/src/modules/storage/directory.ts | 99 ++++++++++++++++ packages/sdk/src/modules/storage/file.ts | 92 ++++++++++++++ .../sdk/src/modules/storage/storage-bucket.ts | 112 +++++++++++++++++- packages/sdk/src/modules/storage/storage.ts | 12 +- .../sdk/src/tests/helpers/website/style.css | 2 +- packages/sdk/src/tests/hosting.test.ts | 16 +-- packages/sdk/src/tests/storage.test.ts | 70 +++++++++++ packages/sdk/src/types/storage.ts | 11 ++ 9 files changed, 410 insertions(+), 22 deletions(-) create mode 100644 packages/sdk/src/modules/storage/directory.ts create mode 100644 packages/sdk/src/modules/storage/file.ts create mode 100644 packages/sdk/src/tests/storage.test.ts create mode 100644 packages/sdk/src/types/storage.ts diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index b84febe..f96be9c 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -11,7 +11,7 @@ export class HostingWebsite { /** * @dev API url prefix for this class. */ - private API_PREFIX = '/hosting/websites'; + private API_PREFIX: string = null; /** * @dev Unique identifier of the website. @@ -56,6 +56,7 @@ export class HostingWebsite { constructor(uuid: string, api: AxiosInstance) { this.api = api; this.uuid = uuid; + this.API_PREFIX = `/hosting/websites/${uuid}`; } /** @@ -63,7 +64,7 @@ export class HostingWebsite { * @returns An instance of HostingWebsite class with filled properties. */ public async get(): Promise { - const data = (await this.api.get(`${this.API_PREFIX}/${this.uuid}`)).data; + const data = (await this.api.get(this.API_PREFIX)).data; this.name = data.data?.name; this.description = data.data?.description; this.domain = data.data?.domain; @@ -93,10 +94,7 @@ export class HostingWebsite { console.log(`Files to upload: ${data.files.length}`); console.time('Got upload links'); - const resp = await this.api.post( - `${this.API_PREFIX}/${this.uuid}/upload`, - data, - ); + const resp = await this.api.post(`${this.API_PREFIX}/upload`, data); console.timeEnd('Got upload links'); @@ -109,7 +107,7 @@ export class HostingWebsite { console.log('Closing session...'); const respEndSession = await this.api.post( - `${this.API_PREFIX}/${this.uuid}/upload/${sessionUuid}/end`, + `${this.API_PREFIX}/upload/${sessionUuid}/end`, ); console.log('Session ended.'); @@ -129,7 +127,7 @@ export class HostingWebsite { ); console.time('Deploy complete'); - const resp = await this.api.post(`${this.API_PREFIX}/${this.uuid}/deploy`, { + const resp = await this.api.post(`${this.API_PREFIX}/deploy`, { environment: toEnvironment, }); @@ -142,9 +140,7 @@ export class HostingWebsite { // console.log('Get deployments for website ', this.uuid); return ( - await this.api.get( - `${this.API_PREFIX}/${this.uuid}/deployments/${deploymentId}`, - ) + await this.api.get(`${this.API_PREFIX}/deployments/${deploymentId}`) ).data; } } diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts new file mode 100644 index 0000000..adef480 --- /dev/null +++ b/packages/sdk/src/modules/storage/directory.ts @@ -0,0 +1,99 @@ +import { AxiosInstance } from 'axios'; +import { StorageContentType } from '../../types/storage'; +import { File } from './file'; + +export class Directory { + /** + * Axios instance set to correct rootUrl with correct error handling. + */ + protected api: AxiosInstance; + + /** + * @dev API url prefix for this class. + */ + private API_PREFIX: string = null; + + /** + * @dev Unique identifier of the bucket. + */ + public bucketUuid; + + /** + * @dev Unique identifier of the directory. + */ + public id; + + /** + * Directory name. + */ + public name: string = null; + + /** + * Directory unique ipfs identifier. + */ + public CID: string = null; + + /** + * Id of the directory in which the file resides. + */ + public parentDirectoryId: string = null; + + /** + * Type of content. + */ + public type = StorageContentType.DIRECTORY; + + public content: (File | Directory)[] = null; + /** + * @dev Constructor which should only be called via Storage class. + * @param uuid Unique identifier of the bucket. + * @param api Axios instance set to correct rootUrl with correct error handling. + */ + constructor( + api: AxiosInstance, + bucketUuid: string, + directoryId: string, + data: any, + ) { + this.api = api; + this.bucketUuid = bucketUuid; + this.id = directoryId; + this.API_PREFIX = `/storage/${bucketUuid}`; + this.populate(data); + } + + /** + * Populates class properties via data object. + * @param data Data object. + */ + private populate(data: any) { + if (data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); + } + } + + /** + * @dev Gets contents of a directory. + */ + async get() { + this.content = []; + const postfix = `?directoryId=${this.id}`; + const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); + for (const item of resp.data?.data?.items) { + if (item.type == StorageContentType.FILE) { + this.content.push(new File(this.api, this.bucketUuid, item.id, item)); + } else { + this.content.push( + new Directory(this.api, this.bucketUuid, item.id, item), + ); + } + } + + return this.content; + } +} diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts new file mode 100644 index 0000000..d19294f --- /dev/null +++ b/packages/sdk/src/modules/storage/file.ts @@ -0,0 +1,92 @@ +import { AxiosInstance } from 'axios'; +import { FileStatus, StorageContentType } from '../../types/storage'; + +export class File { + /** + * Axios instance set to correct rootUrl with correct error handling. + */ + protected api: AxiosInstance; + + /** + * @dev API url prefix for this class. + */ + private API_PREFIX: string = null; + + /** + * @dev Unique identifier of the bucket. + */ + public bucketUuid: string; + + /** + * @dev Unique identifier of the file. + */ + public id: string; + + /** + * File name. + */ + public name: string = null; + + /** + * File unique ipfs identifier. + */ + public CID: string = null; + + /** + * File status. + */ + public status: FileStatus = null; + + /** + * Id of the directory in which the file resides. + */ + public parentDirectoryId: string = null; + + /** + * Type of content. + */ + public type = StorageContentType.FILE; + + /** + * @dev Constructor which should only be called via Storage class. + * @param uuid Unique identifier of the bucket. + * @param api Axios instance set to correct rootUrl with correct error handling. + */ + constructor( + api: AxiosInstance, + bucketUuid: string, + fileId: string, + data: any, + ) { + this.api = api; + this.bucketUuid = bucketUuid; + this.id = fileId; + this.API_PREFIX = `/storage/${bucketUuid}/file/${fileId}`; + this.populate(data); + } + + /** + * Populates class properties via data object. + * @param data Data object. + */ + private populate(data: any) { + if (data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); + } + } + + /** + * @dev Gets file details. + */ + async get() { + const resp = await this.api.get(`${this.API_PREFIX}/detail`); + this.status = resp.data?.data?.fileStatus; + this.populate(resp.data?.data?.file); + return this; + } +} diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 1fbd5b3..11a0a3d 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -1 +1,111 @@ -export class StorageBucket {} +import { AxiosInstance } from 'axios'; +import { Directory } from './directory'; +import { StorageContentType } from '../../types/storage'; +import { File } from './file'; +import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; + +export class StorageBucket { + /** + * Axios instance set to correct rootUrl with correct error handling. + */ + protected api: AxiosInstance; + + /** + * @dev API url prefix for this class. + */ + private API_PREFIX: string = null; + + /** + * @dev Unique identifier of the bucket. + */ + public uuid; + + /** + * @dev Bucket content which are files and directories. + */ + public content: (File | Directory)[] = null; + + /** + * @dev Constructor which should only be called via Storage class. + * @param uuid Unique identifier of the bucket. + * @param api Axios instance set to correct rootUrl with correct error handling. + */ + constructor(uuid: string, api: AxiosInstance) { + this.api = api; + this.uuid = uuid; + this.API_PREFIX = `/storage/${uuid}`; + } + + /** + * TODO: How to handle search etc.? + * @dev Gets contents of a bucket. + */ + async getContent(data?: any) { + this.content = []; + let postfix = ''; + if (data?.directoryId) { + postfix = `?directoryId=${data.directoryId}`; + } + const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); + for (const item of resp.data?.data?.items) { + if (item.type == StorageContentType.FILE) { + this.content.push(new File(this.api, this.uuid, item.id, item)); + } else { + this.content.push(new Directory(this.api, this.uuid, item.id, item)); + } + } + + return this.content; + } + + /** + * @dev Uploads files inside a folder via path. + * @param folderPath Path to the folder to upload. + */ + public async uploadFromFolder(folderPath: string): Promise { + console.log( + `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, + ); + let files; + try { + files = listFilesRecursive(folderPath); + } catch (err) { + console.error(err); + throw new Error(`Error reading files in ${folderPath}`); + } + + const data = { files }; + console.log(`Files to upload: ${data.files.length}`); + + console.time('Got upload links'); + const resp = await this.api.post(`${this.API_PREFIX}/upload`, data); + + console.timeEnd('Got upload links'); + + // console.log(resp); + const sessionUuid = resp.data.data.sessionUuid; + + console.time('File upload complete'); + await uploadFilesToS3(resp.data.data.files, files); + console.timeEnd('File upload complete'); + + console.log('Closing session...'); + const respEndSession = await this.api.post( + `${this.API_PREFIX}/upload/${sessionUuid}/end`, + ); + console.log('Session ended.'); + + if (!respEndSession.data?.data) { + throw new Error(); + } + } + + /** + * Gets file instance. + * @param fileId Id of the file. + * @returns Instance of file. + */ + file(fileId: string): File { + return new File(this.api, this.uuid, fileId, null); + } +} diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index acebc1e..4367dc7 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -1,3 +1,13 @@ import { ApillonModule } from '../../lib/apillon'; +import { StorageBucket } from './storage-bucket'; -export class Storage extends ApillonModule {} +export class Storage extends ApillonModule { + /** + * @dev Returns an website instance. + * @param uuid Unique website identifier. + * @returns An instance of Website.∂ + */ + public bucket(uuid: string): StorageBucket { + return new StorageBucket(uuid, this.api); + } +} diff --git a/packages/sdk/src/tests/helpers/website/style.css b/packages/sdk/src/tests/helpers/website/style.css index 406e561..35d3b60 100644 --- a/packages/sdk/src/tests/helpers/website/style.css +++ b/packages/sdk/src/tests/helpers/website/style.css @@ -1,4 +1,4 @@ h1 { - color: white; + color: blueviolet; text-align: center; } diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index 00a832e..3b2d55b 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -3,7 +3,7 @@ import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig } from './helpers/helper'; -describe('Hosting tests', () => { +describe.skip('Hosting tests', () => { let config: ApillonConfig; beforeAll(async () => { @@ -37,19 +37,19 @@ describe('Hosting tests', () => { console.log(deploymentId); }); - test.only('get deployment status', async () => { - const hosting = new Hosting(config); - const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + // test('get deployment status', async () => { + // const hosting = new Hosting(config); + // const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); - const deployStatus = await website.deploy(DeployToEnvironment.TO_STAGING); - console.log(deployStatus); - }); + // const deployStatus = await website.deploy(DeployToEnvironment.TO_STAGING); + // console.log(deployStatus); + // }); test.only('get deployment status', async () => { const hosting = new Hosting(config); const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); - const deployStatus = await website.getDeployStatus('201'); + const deployStatus = await website.getDeployStatus('208'); console.log(deployStatus); }); }); diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts new file mode 100644 index 0000000..f7c586c --- /dev/null +++ b/packages/sdk/src/tests/storage.test.ts @@ -0,0 +1,70 @@ +import { ApillonConfig } from '../lib/apillon'; +import { Storage } from '../modules/storage/storage'; +import { StorageContentType } from '../types/storage'; +import { getConfig } from './helpers/helper'; + +describe.only('Storage tests', () => { + let config: ApillonConfig; + + beforeAll(async () => { + config = getConfig(); + }); + + test('get bucket content', async () => { + const storage = new Storage(config); + try { + const content = await storage + .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') + .getContent(); + console.log(content); + } catch (e) { + console.log(e); + } + }); + + test('get bucket directory content', async () => { + const storage = new Storage(config); + try { + const content = await storage + .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') + .getContent({ directoryId: '3160' }); + + for (let i = 0; i < content.length; i++) { + if (content[i].type == StorageContentType.DIRECTORY) { + await content[i].get(); + console.log(content[i]); + } + if (content[i].type == StorageContentType.FILE) { + console.log(content[i]); + } + } + } catch (e) { + console.log(e); + } + }); + + test('get file details', async () => { + const storage = new Storage(config); + try { + const content = await storage + .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') + .file('79961') + .get(); + console.log(content); + } catch (e) { + console.log(e); + } + }); + + test('upload files', async () => { + const storage = new Storage(config); + try { + await storage + .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') + .uploadFromFolder('./src/tests/helpers/website/'); + // console.log(content); + } catch (e) { + console.log(e); + } + }); +}); diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts new file mode 100644 index 0000000..c480d3e --- /dev/null +++ b/packages/sdk/src/types/storage.ts @@ -0,0 +1,11 @@ +export enum StorageContentType { + FILE = 2, + DIRECTORY = 1, +} + +export enum FileStatus { + UPLOAD_REQUEST_GENERATED = 1, + UPLOADED = 2, + AVAILABLE_ON_IPFS = 3, + AVAILABLE_ON_IPFS_AND_REPLICATED = 4, +} From 82302a2ddd93c1c8045f1f4dcee7ceda9badd54d Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Wed, 4 Oct 2023 15:41:23 +0200 Subject: [PATCH 06/68] Start of nft refactor. --- .../sdk/src/modules/nft/nft-collection.ts | 81 +++++++------------ packages/sdk/src/modules/nft/nft.ts | 39 ++++++++- packages/sdk/src/tests/nft.test.ts | 23 ++++++ packages/sdk/src/tests/storage.test.ts | 2 +- 4 files changed, 93 insertions(+), 52 deletions(-) create mode 100644 packages/sdk/src/tests/nft.test.ts diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 57f2900..ba68462 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -6,9 +6,7 @@ import { IApillonStatus, } from '../../types/apillon'; import { - ICollectionFilters, ICollection, - ICreateCollection, IMintCollectionNft, INestMintCollectionNft, IBurnCollectionNft, @@ -17,93 +15,76 @@ import { ITransaction, } from '../../types/nfts'; -const COLLECTIONS_ROUTE = '/nfts/collections'; - export class NftCollection { + /** + * Axios instance set to correct rootUrl with correct error handling. + */ protected api: AxiosInstance; + + /** + * @dev Unique identifier of the collection. + */ private uuid; + /** + * @dev API url prefix for this class. + */ + private API_PREFIX: string = null; + constructor(uuid: string, api: AxiosInstance) { this.api = api; this.uuid = uuid; - } - // COLLECTIONS - public async listNftCollections(params: ICollectionFilters) { - const url = constructUrlWithQueryParams(COLLECTIONS_ROUTE, params); - - const resp = await this.api.get< - IApillonResponse> - >(url); - - return resp.data.data; + this.API_PREFIX = `/nfts/collections/${this.uuid}`; } - public async getCollection(uuid: string) { + public async get() { const resp = await this.api.get>( - `${COLLECTIONS_ROUTE}/${uuid}`, - ); - - return resp.data.data; - } - - public async createCollection(data: ICreateCollection) { - const resp = await this.api.post>( - COLLECTIONS_ROUTE, - data, + this.API_PREFIX, ); - return resp.data.data; + return resp.data?.data; } - public async mintCollectionNft(uuid: string, data: IMintCollectionNft) { + public async mint(data: IMintCollectionNft) { const resp = await this.api.post>( - `${COLLECTIONS_ROUTE}/${uuid}/mint`, + `${this.API_PREFIX}/mint`, data, ); - return resp.data.data; + return resp.data?.data; } - public async nestMintCollectionNft( - uuid: string, - data: INestMintCollectionNft, - ) { + public async nestMintNft(data: INestMintCollectionNft) { const resp = await this.api.post>( - `${COLLECTIONS_ROUTE}/${uuid}/nest-mint`, + `${this.API_PREFIX}/nest-mint`, data, ); - return resp.data.data; + return resp.data?.data; } - public async burnCollectionNft(uuid: string, data: IBurnCollectionNft) { + public async burnNft(data: IBurnCollectionNft) { const resp = await this.api.post>( - `${COLLECTIONS_ROUTE}/${uuid}/burn`, + `${this.API_PREFIX}/burn`, data, ); - return resp.data.data; + return resp.data?.data; } - public async transferCollectionOwnership( - uuid: string, - data: ITransferCollectionOwnership, - ) { + public async transferOwnership(data: ITransferCollectionOwnership) { const resp = await this.api.post>( - `${COLLECTIONS_ROUTE}/${uuid}/transfer`, + `${this.API_PREFIX}/transfer`, data, ); - return resp.data.data; + return resp.data?.data; } // TRANSACTIONS - public async listCollectionTransactions( - uuid: string, - params: ITransactionFilters, - ) { + public async listTransactions(uuid: string, params: ITransactionFilters) { const url = constructUrlWithQueryParams( - `${COLLECTIONS_ROUTE}/${uuid}/transactions`, + `${this.API_PREFIX}/transactions`, params, ); @@ -111,6 +92,6 @@ export class NftCollection { IApillonResponse> >(url); - return resp.data.data.items; + return resp.data?.data.items; } } diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index e8ad2ea..60faece 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -1,3 +1,40 @@ import { ApillonModule } from '../../lib/apillon'; +import { constructUrlWithQueryParams } from '../../lib/common'; +import { IApillonResponse, IApillonList } from '../../types/apillon'; +import { + ICollectionFilters, + ICollection, + ICreateCollection, +} from '../../types/nfts'; +import { NftCollection } from './nft-collection'; -export class Nft extends ApillonModule {} +export class Nft extends ApillonModule { + API_PREFIX = '/nfts/collections'; + /** + * @dev Returns a collection instance. + * @param uuid Unique collection identifier. + * @returns An instance of NFT Collection + */ + public collection(uuid: string): NftCollection { + return new NftCollection(uuid, this.api); + } + + public async list(params: ICollectionFilters) { + const url = constructUrlWithQueryParams(this.API_PREFIX, params); + + const resp = await this.api.get< + IApillonResponse> + >(url); + + return resp.data?.data; + } + + public async create(data: ICreateCollection) { + const resp = await this.api.post>( + this.API_PREFIX, + data, + ); + + return resp.data?.data; + } +} diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts new file mode 100644 index 0000000..32e4028 --- /dev/null +++ b/packages/sdk/src/tests/nft.test.ts @@ -0,0 +1,23 @@ +import { ApillonConfig } from '../lib/apillon'; +import { Nft } from '../modules/nft/nft'; +import { getConfig } from './helpers/helper'; + +describe('Nft tests', () => { + let config: ApillonConfig; + + beforeAll(async () => { + config = getConfig(); + }); + + test('get nft collection details', async () => { + const nft = new Nft(config); + try { + const collection = await nft + .collection('2ad03895-fd5d-40e7-af17-1d6daecf3b5a') + .get(); + console.log(collection); + } catch (e) { + console.log(e); + } + }); +}); diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index f7c586c..88a4254 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -3,7 +3,7 @@ import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; import { getConfig } from './helpers/helper'; -describe.only('Storage tests', () => { +describe.skip('Storage tests', () => { let config: ApillonConfig; beforeAll(async () => { From 0bc4d9775f454af6a11542059ec92ad30945c17b Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Thu, 5 Oct 2023 10:24:22 +0200 Subject: [PATCH 07/68] Basic nft logic. --- .../sdk/src/modules/nft/nft-collection.ts | 123 +++++++++++++++++- packages/sdk/src/modules/nft/nft.ts | 29 ++++- packages/sdk/src/tests/nft.test.ts | 22 ++++ 3 files changed, 167 insertions(+), 7 deletions(-) diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index ba68462..3fbf239 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -13,6 +13,9 @@ import { ITransferCollectionOwnership, ITransactionFilters, ITransaction, + CollectionType, + CollectionStatus, + EvmChain, } from '../../types/nfts'; export class NftCollection { @@ -31,18 +34,132 @@ export class NftCollection { */ private API_PREFIX: string = null; - constructor(uuid: string, api: AxiosInstance) { + /** + * @dev collection symbol. + */ + public symbol = null; + + /** + * @dev collection name + */ + public name = null; + + /** + * @dev collection description. + */ + public description: string = null; + + /** + * Collection type. Defines the smart contract used. + */ + public collectionType: CollectionType = null; + + /** + * Max amount of NFTs that can get minted in this collection. 0 represents unlimited. + */ + public maxSupply: number = null; + + /** + * Base uri from which uri for each token is calculated from: + * Base uri + token id + base extension. + */ + public baseUri: string = null; + + /** + * Base extension from which uri for each token is calculated from: + * Base uri + token id + base extension. + */ + public baseExtension: string = null; + + /** + * If nft is transferable. + */ + public isSoulbound: boolean = null; + + /** + * If collection owner can burn / destroy a NFT. + */ + public isRevokable: boolean = null; + + /** + * If this collection has drop (anyone can buy a nft directly from the smart contract) functionality enabled. + */ + public drop: boolean = null; + + /** + * Pri per NFT if drop is active. + */ + public dropPrice: number = null; + + /** + * UNIX timestamp of when general buying of NFTs start. + */ + public dropStart: number = null; + + /** + * Amount of reserved NFTs that can't be bought by general public but can get minted by the collection owner. + */ + public dropReserve: number = null; + + /** + * Procentual amount of royalties fees. + */ + public royaltiesFees: number = null; + + /** + * Address to which royalties are paid. + */ + public royaltiesAddress: string = null; + + /** + * Status of the collection. From not deployed etc. + */ + public collectionStatus: CollectionStatus = null; + + /** + * Smart contract address (available after succesfull deploy). + */ + public contractAddress: string = null; + + /** + * Transaction hash of contract deploy. + */ + public transactionHash: string = null; + + /** + * Chain on which the smart contract was deployed. + */ + public chain: EvmChain = null; + + constructor(api: AxiosInstance, uuid: string, data: any) { this.api = api; this.uuid = uuid; this.API_PREFIX = `/nfts/collections/${this.uuid}`; + this.populate(data); + } + + /** + * Populates class properties via data object. + * @param data Data object. + */ + private populate(data: any) { + if (data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); + } } public async get() { const resp = await this.api.get>( this.API_PREFIX, ); + this.populate(resp.data?.data); - return resp.data?.data; + return this; } public async mint(data: IMintCollectionNft) { @@ -82,7 +199,7 @@ export class NftCollection { } // TRANSACTIONS - public async listTransactions(uuid: string, params: ITransactionFilters) { + public async listTransactions(params?: ITransactionFilters) { const url = constructUrlWithQueryParams( `${this.API_PREFIX}/transactions`, params, diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 60faece..c4915f9 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -16,25 +16,46 @@ export class Nft extends ApillonModule { * @returns An instance of NFT Collection */ public collection(uuid: string): NftCollection { - return new NftCollection(uuid, this.api); + return new NftCollection(this.api, uuid, null); } - public async list(params: ICollectionFilters) { + /** + * Lists all nft collections available. + * @param params + * @returns Array of NftCollection. + */ + public async list(params?: ICollectionFilters): Promise { + const items: NftCollection[] = []; const url = constructUrlWithQueryParams(this.API_PREFIX, params); const resp = await this.api.get< IApillonResponse> >(url); - return resp.data?.data; + if (resp.data?.data && resp.data?.data.items) { + for (const item of resp.data?.data.items) { + items.push(new NftCollection(this.api, item.collectionUuid, item)); + } + } + + return items; } + /** + * Deploys a new NftCollection smart contract. + * @param data NFT collection data. + * @returns A NftCollection instance. + */ public async create(data: ICreateCollection) { const resp = await this.api.post>( this.API_PREFIX, data, ); - return resp.data?.data; + return new NftCollection( + this.api, + resp.data?.data.collectionUuid, + resp.data?.data, + ); } } diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index 32e4028..9d5e0de 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -9,7 +9,29 @@ describe('Nft tests', () => { config = getConfig(); }); + test.only('list nft collections', async () => { + const nft = new Nft(config); + try { + const collection = await nft.list(); + console.log(collection); + } catch (e) { + console.log(e); + } + }); + test('get nft collection details', async () => { + const nft = new Nft(config); + try { + const collection = await nft + .collection('2ad03895-fd5d-40e7-af17-1d6daecf3b5a') + .listTransactions(); + console.log(collection); + } catch (e) { + console.log(e); + } + }); + + test.only('get nft collection details', async () => { const nft = new Nft(config); try { const collection = await nft From 77a87866a017f07691c94bfda79306cfbe6473ef Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Thu, 5 Oct 2023 13:04:37 +0200 Subject: [PATCH 08/68] Fix turbo repo test cache --- turbo.json | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/turbo.json b/turbo.json index d9eff49..44a81a6 100644 --- a/turbo.json +++ b/turbo.json @@ -2,17 +2,11 @@ "$schema": "https://turborepo.org/schema.json", "pipeline": { "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "dist/**" - ] + "dependsOn": ["^build"], + "outputs": ["dist/**"] }, "cli-install": { - "dependsOn": [ - "^build" - ], + "dependsOn": ["^build"], "outputs": [] }, "dev": { @@ -20,18 +14,15 @@ "outputs": [] }, "publish-package": { - "dependsOn": [ - "^build" - ], + "dependsOn": ["^build"], "outputs": [] }, "lint": { "outputs": [] }, "test": { - "dependsOn": [ - "^build" - ], + "cache": false, + "dependsOn": ["^build"], "outputs": [] } } From 513dc8f8be4d7a632586cb1aab725a86aced08c5 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Thu, 5 Oct 2023 15:41:09 +0200 Subject: [PATCH 09/68] add typedoc --- .gitignore | 2 ++ packages/sdk/package.json | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 7f03445..a6cc1da 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ # Node artifact files node_modules/ dist/ +packages/sdk/docs/ +packages/cli/docs/ # Compiled Java class files *.class diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 5f14ce0..c57b5df 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -26,7 +26,8 @@ "dev": "tsc --declarationMap --watch", "lint": "tsc --declarationMap && eslint \"{src,test}/**/*.ts\" --fix", "publish-package": "npm publish", - "test": "npx jest" + "test": "npx jest", + "docs": "npx typedoc src/docs-index.ts" }, "keywords": [ "SDK", @@ -50,7 +51,8 @@ "ts-node": "^10.9.1", "tsconfig": "*", "rimraf": "^5.0.5", - "dotenv": "^16.0.3" + "dotenv": "^16.0.3", + "typedoc": "^0.25.1" }, "jest": { "testTimeout": 1800000, From 66cde4e05de0145d47fa3af43df55a2a5179793c Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Thu, 5 Oct 2023 15:41:18 +0200 Subject: [PATCH 10/68] type docs index --- packages/sdk/src/docs-index.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 packages/sdk/src/docs-index.ts diff --git a/packages/sdk/src/docs-index.ts b/packages/sdk/src/docs-index.ts new file mode 100644 index 0000000..c26775a --- /dev/null +++ b/packages/sdk/src/docs-index.ts @@ -0,0 +1,14 @@ +export * from './lib/common'; +export * from './types/generic'; +export * from './types/nfts'; +export * from './types/hosting'; +export * from './types/storage'; +export * from './lib/apillon'; +export * from './modules/storage/storage'; +export * from './modules/storage/storage-bucket'; +export * from './modules/storage/file'; +export * from './modules/storage/directory'; +export * from './modules/hosting/hosting'; +export * from './modules/hosting/hosting-website'; +export * from './modules/nft/nft'; +export * from './modules/nft/nft-collection'; From 91e9b92d10177b06bd3ac30843776641cf1866c9 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 6 Oct 2023 09:26:31 +0200 Subject: [PATCH 11/68] Finish nft refactor. --- packages/sdk/src/docs-index.ts | 1 - .../sdk/src/modules/nft/nft-collection.ts | 80 +++++++++++++++---- packages/sdk/src/modules/nft/nft.ts | 8 +- packages/sdk/src/types/nfts.ts | 13 --- 4 files changed, 70 insertions(+), 32 deletions(-) diff --git a/packages/sdk/src/docs-index.ts b/packages/sdk/src/docs-index.ts index c26775a..8f0d39f 100644 --- a/packages/sdk/src/docs-index.ts +++ b/packages/sdk/src/docs-index.ts @@ -1,4 +1,3 @@ -export * from './lib/common'; export * from './types/generic'; export * from './types/nfts'; export * from './types/hosting'; diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 3fbf239..e610bc7 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -7,10 +7,6 @@ import { } from '../../types/apillon'; import { ICollection, - IMintCollectionNft, - INestMintCollectionNft, - IBurnCollectionNft, - ITransferCollectionOwnership, ITransactionFilters, ITransaction, CollectionType, @@ -153,7 +149,11 @@ export class NftCollection { } } - public async get() { + /** + * Gets and populates collection information. + * @returns Collection instance. + */ + public async get(): Promise { const resp = await this.api.get>( this.API_PREFIX, ); @@ -162,44 +162,92 @@ export class NftCollection { return this; } - public async mint(data: IMintCollectionNft) { + /** + * Mints new nfts to a receiver. + * @param receiver Address of the receiver. + * @param quantity Amount of nfts to mint. + * @returns Call status. + */ + public async mint(receiver: string, quantity: number) { const resp = await this.api.post>( `${this.API_PREFIX}/mint`, - data, + { receivingAddress: receiver, quantity }, ); return resp.data?.data; } - public async nestMintNft(data: INestMintCollectionNft) { + /** + * Mints new nfts directly to an existing nft. + * @warn This method is only available for nestable collections. + * @param parentCollectionUuid UUID of the collection we want to nest mint to. + * @param parentNftId ID of the nft in the collection we want to nest mint to. + * @param quantity Amount of nfts we want to mint. + * @returns Call status. + */ + public async nestMintNft( + parentCollectionUuid: string, + parentNftId: number, + quantity: number, + ): Promise { + if ( + this.collectionType != null && + this.collectionType != CollectionType.NESTABLE + ) { + throw new Error('This method is only available on nestable collections.'); + } const resp = await this.api.post>( `${this.API_PREFIX}/nest-mint`, - data, + { parentCollectionUuid, parentNftId, quantity }, ); return resp.data?.data; } - public async burnNft(data: IBurnCollectionNft) { + /** + * Burns a nft. + * @warn Can only burn NFTs if the collection is revokable. + * @param id Id of the NFT we want to burn. + * @returns Status. + */ + public async burnNft(id: string): Promise { + if (this.isRevokable != null && !this.isRevokable) { + throw new Error('Collection is not revokable'); + } const resp = await this.api.post>( `${this.API_PREFIX}/burn`, - data, + { tokenId: id }, ); return resp.data?.data; } - public async transferOwnership(data: ITransferCollectionOwnership) { + /** + * Transfers ownership of this collection. + * @warn Once ownership is transferred you cannot call mint methods anymore since you are the + * owner and you need to the smart contracts call directly on chain. + * @param address Address to which the ownership will be transferred. + * @returns Collection data. + */ + public async transferOwnership(address: string): Promise { const resp = await this.api.post>( `${this.API_PREFIX}/transfer`, - data, + { address }, ); - return resp.data?.data; + this.populate(resp.data?.data); + + return this; } - // TRANSACTIONS - public async listTransactions(params?: ITransactionFilters) { + /** + * Gets list of transactions that occurred on this collection through Apillon. + * @param params Filters. + * @returns List of transactions. + */ + public async listTransactions( + params?: ITransactionFilters, + ): Promise { const url = constructUrlWithQueryParams( `${this.API_PREFIX}/transactions`, params, diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index c4915f9..4bf6b92 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -9,7 +9,11 @@ import { import { NftCollection } from './nft-collection'; export class Nft extends ApillonModule { - API_PREFIX = '/nfts/collections'; + /** + * @dev API url for collections. + */ + private API_PREFIX = '/nfts/collections'; + /** * @dev Returns a collection instance. * @param uuid Unique collection identifier. @@ -21,7 +25,7 @@ export class Nft extends ApillonModule { /** * Lists all nft collections available. - * @param params + * @param params Filter for listing collections. * @returns Array of NftCollection. */ public async list(params?: ICollectionFilters): Promise { diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index d62a35e..1faf766 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -56,25 +56,12 @@ export interface ICreateCollection { dropReserve: number; } -export interface ITransferCollectionOwnership { - address: string; -} - -export interface IMintCollectionNft { - receivingAddress: string; - quantity: number; -} - export interface INestMintCollectionNft { parentCollectionUuid: string; parentNftId: number; quantity: number; } -export interface IBurnCollectionNft { - tokenId: number; -} - //OUTPUTS export interface ICollection { collectionUuid: string; From 9ed522d9f60bbbc209f87e9d1096eb28c5d1107d Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 6 Oct 2023 09:33:12 +0200 Subject: [PATCH 12/68] Move uuids to env. --- packages/sdk/src/tests/helpers/helper.ts | 12 ++++++++++++ packages/sdk/src/tests/hosting.test.ts | 19 ++++++++++--------- packages/sdk/src/tests/nft.test.ts | 12 ++++++------ packages/sdk/src/tests/storage.test.ts | 19 ++++++++----------- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/packages/sdk/src/tests/helpers/helper.ts b/packages/sdk/src/tests/helpers/helper.ts index d375d16..ffefd76 100644 --- a/packages/sdk/src/tests/helpers/helper.ts +++ b/packages/sdk/src/tests/helpers/helper.ts @@ -9,3 +9,15 @@ export function getConfig(): ApillonConfig { key: process.env['APILLON_API_KEY'], } as ApillonConfig; } + +export function getBucketUUID() { + return process.env['BUCKET_UUID']; +} + +export function getCollectionUUID() { + return process.env['COLLECTION_UUID']; +} + +export function getWebsiteUUID() { + return process.env['WEBSITE_UUID']; +} diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index 3b2d55b..04e11a1 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -1,21 +1,22 @@ import { ApillonConfig } from '../lib/apillon'; import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; -import { getConfig } from './helpers/helper'; +import { getConfig, getWebsiteUUID } from './helpers/helper'; -describe.skip('Hosting tests', () => { +describe('Hosting tests', () => { let config: ApillonConfig; + let websiteUUID: string; beforeAll(async () => { config = getConfig(); + websiteUUID = getWebsiteUUID(); }); - test('get website info', async () => { + test.only('get website info', async () => { const hosting = new Hosting(config); try { - const website = await hosting - .website('8e1a512d-5672-4c2f-ad5e-60333498cde2') - .get(); + const website = await hosting.website(websiteUUID).get(); + console.log(website); console.log(website.name); console.log(website.bucketUuid); console.log(website.ipnsProduction); @@ -27,7 +28,7 @@ describe.skip('Hosting tests', () => { test('upload website from folder', async () => { const hosting = new Hosting(config); - const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + const website = hosting.website(websiteUUID); try { await website.uploadFromFolder('./src/tests/helpers/website/'); } catch (e) { @@ -39,7 +40,7 @@ describe.skip('Hosting tests', () => { // test('get deployment status', async () => { // const hosting = new Hosting(config); - // const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + // const website = hosting.website(websiteUUID); // const deployStatus = await website.deploy(DeployToEnvironment.TO_STAGING); // console.log(deployStatus); @@ -47,7 +48,7 @@ describe.skip('Hosting tests', () => { test.only('get deployment status', async () => { const hosting = new Hosting(config); - const website = hosting.website('8e1a512d-5672-4c2f-ad5e-60333498cde2'); + const website = hosting.website(websiteUUID); const deployStatus = await website.getDeployStatus('208'); console.log(deployStatus); diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index 9d5e0de..4d7cbca 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -1,15 +1,17 @@ import { ApillonConfig } from '../lib/apillon'; import { Nft } from '../modules/nft/nft'; -import { getConfig } from './helpers/helper'; +import { getCollectionUUID, getConfig } from './helpers/helper'; describe('Nft tests', () => { let config: ApillonConfig; + let collectionUUID: string; beforeAll(async () => { config = getConfig(); + collectionUUID = getCollectionUUID(); }); - test.only('list nft collections', async () => { + test('list nft collections', async () => { const nft = new Nft(config); try { const collection = await nft.list(); @@ -23,7 +25,7 @@ describe('Nft tests', () => { const nft = new Nft(config); try { const collection = await nft - .collection('2ad03895-fd5d-40e7-af17-1d6daecf3b5a') + .collection(collectionUUID) .listTransactions(); console.log(collection); } catch (e) { @@ -34,9 +36,7 @@ describe('Nft tests', () => { test.only('get nft collection details', async () => { const nft = new Nft(config); try { - const collection = await nft - .collection('2ad03895-fd5d-40e7-af17-1d6daecf3b5a') - .get(); + const collection = await nft.collection(collectionUUID).get(); console.log(collection); } catch (e) { console.log(e); diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 88a4254..71fc086 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -1,21 +1,21 @@ import { ApillonConfig } from '../lib/apillon'; import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; -import { getConfig } from './helpers/helper'; +import { getBucketUUID, getConfig } from './helpers/helper'; describe.skip('Storage tests', () => { let config: ApillonConfig; + let bucketUUID: string; beforeAll(async () => { config = getConfig(); + bucketUUID = getBucketUUID(); }); test('get bucket content', async () => { const storage = new Storage(config); try { - const content = await storage - .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') - .getContent(); + const content = await storage.bucket(bucketUUID).getObjects(); console.log(content); } catch (e) { console.log(e); @@ -26,8 +26,8 @@ describe.skip('Storage tests', () => { const storage = new Storage(config); try { const content = await storage - .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') - .getContent({ directoryId: '3160' }); + .bucket(bucketUUID) + .getObjects({ directoryId: '3160' }); for (let i = 0; i < content.length; i++) { if (content[i].type == StorageContentType.DIRECTORY) { @@ -46,10 +46,7 @@ describe.skip('Storage tests', () => { test('get file details', async () => { const storage = new Storage(config); try { - const content = await storage - .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') - .file('79961') - .get(); + const content = await storage.bucket(bucketUUID).file('79961').get(); console.log(content); } catch (e) { console.log(e); @@ -60,7 +57,7 @@ describe.skip('Storage tests', () => { const storage = new Storage(config); try { await storage - .bucket('f2df445a-ab8d-4248-b231-470cc8a18385') + .bucket(bucketUUID) .uploadFromFolder('./src/tests/helpers/website/'); // console.log(content); } catch (e) { From 9239c59825662bed7d68ca3508d64ab3edc4247c Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 6 Oct 2023 10:42:10 +0200 Subject: [PATCH 13/68] add logger --- packages/sdk/src/index.ts | 4 +- packages/sdk/src/lib/apillon.ts | 33 ++++++++++++++ .../src/modules/hosting/hosting-website.ts | 45 ++++++++++++------- packages/sdk/src/modules/hosting/hosting.ts | 2 +- .../sdk/src/modules/nft/nft-collection.ts | 14 +++++- packages/sdk/src/modules/nft/nft.ts | 7 ++- packages/sdk/src/modules/storage/file.ts | 8 ++++ .../sdk/src/modules/storage/storage-bucket.ts | 17 +++++-- packages/sdk/src/modules/storage/storage.ts | 2 +- packages/sdk/src/tests/hosting.test.ts | 5 ++- packages/sdk/src/tests/nft.test.ts | 2 +- packages/sdk/src/types/apillon.ts | 6 +++ packages/sdk/src/types/hosting.ts | 7 +++ packages/sdk/src/types/nfts.ts | 6 --- 14 files changed, 123 insertions(+), 35 deletions(-) diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 24a66f8..d8c1871 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,6 +1,8 @@ -export * from './lib/common'; export * from './types/generic'; export * from './types/nfts'; +export * from './types/hosting'; +export * from './types/storage'; export * from './lib/apillon'; +export * from './modules/storage/storage'; export * from './modules/hosting/hosting'; export * from './modules/nft/nft'; diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index d3681e9..8d7c8a5 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -1,9 +1,11 @@ import axios, { AxiosInstance } from 'axios'; +import { LogLevel } from '../types/apillon'; export interface ApillonConfig { key?: string; secret?: string; apiUrl?: string; + logLevel?: LogLevel; } export class ApillonApiError extends Error {} @@ -12,6 +14,7 @@ export class ApillonNetworkError extends Error {} export class ApillonModule { protected api: AxiosInstance; + protected logger: ApillonLogger; private config: ApillonConfig; public constructor(config?: ApillonConfig) { @@ -19,9 +22,11 @@ export class ApillonModule { key: process.env.APILLON_API_KEY, secret: process.env.APILLON_API_SECRET, apiUrl: process.env.APILLON_API_URL || 'https://api.apillon.io', + logLevel: LogLevel.NONE, }; this.config = { ...defaultOptions, ...config }; + this.logger = new ApillonLogger(this.config.logLevel); let auth = undefined; if (this.config.key && this.config.secret) { @@ -44,6 +49,7 @@ export class ApillonModule { return config; }, (error) => { + this.logger.log(error, LogLevel.ERROR); throw new ApillonRequestError(error.request); }, ); @@ -53,6 +59,7 @@ export class ApillonModule { return response; }, (error) => { + this.logger.log(error, LogLevel.ERROR); if (error.response?.data) { throw new ApillonApiError( JSON.stringify(error.response.data, null, 2), @@ -64,3 +71,29 @@ export class ApillonModule { ); } } + +export class ApillonLogger { + private logLevel: LogLevel = LogLevel.NONE; + constructor(logLevel?: LogLevel) { + this.logLevel = logLevel || LogLevel.NONE; + } + + log(message: any, logLevel: LogLevel) { + if (this.logLevel >= logLevel) { + if (message instanceof Object) { + console.log(JSON.stringify(message)); + } else { + console.log(message); + } + } + } + logWithTime(message: any, logLevel: LogLevel) { + if (this.logLevel >= logLevel) { + if (message instanceof Object) { + console.log(`${new Date().toISOString()}: `, JSON.stringify(message)); + } else { + console.log(`${new Date().toISOString()}: `, message); + } + } + } +} diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index f96be9c..afb4654 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -1,6 +1,8 @@ import { AxiosInstance } from 'axios'; import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; import { DeployToEnvironment } from '../../types/hosting'; +import { ApillonLogger } from '../../index'; +import { LogLevel } from '../../types/apillon'; export class HostingWebsite { /** @@ -8,6 +10,11 @@ export class HostingWebsite { */ protected api: AxiosInstance; + /** + * Logger. + */ + protected logger: ApillonLogger; + /** * @dev API url prefix for this class. */ @@ -53,9 +60,10 @@ export class HostingWebsite { * @param uuid Unique identifier of the website. * @param api Axios instance set to correct rootUrl with correct error handling. */ - constructor(uuid: string, api: AxiosInstance) { + constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string) { this.api = api; this.uuid = uuid; + this.logger = logger; this.API_PREFIX = `/hosting/websites/${uuid}`; } @@ -79,37 +87,39 @@ export class HostingWebsite { * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { - console.log( + this.logger.log( `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, + LogLevel.VERBOSE, ); + let files; try { files = listFilesRecursive(folderPath); } catch (err) { - console.error(err); + this.logger.log(err, LogLevel.ERROR); throw new Error(`Error reading files in ${folderPath}`); } const data = { files }; - console.log(`Files to upload: ${data.files.length}`); + this.logger.log(`Files to upload: ${data.files.length}`, LogLevel.VERBOSE); - console.time('Got upload links'); + this.logger.logWithTime('Get upload links', LogLevel.VERBOSE); const resp = await this.api.post(`${this.API_PREFIX}/upload`, data); - console.timeEnd('Got upload links'); + this.logger.logWithTime('Got upload links', LogLevel.VERBOSE); // console.log(resp); const sessionUuid = resp.data.data.sessionUuid; - console.time('File upload complete'); + this.logger.logWithTime('File upload complete', LogLevel.VERBOSE); await uploadFilesToS3(resp.data.data.files, files); - console.timeEnd('File upload complete'); + this.logger.logWithTime('File upload complete', LogLevel.VERBOSE); - console.log('Closing session...'); + this.logger.log('Closing session...', LogLevel.VERBOSE); const respEndSession = await this.api.post( `${this.API_PREFIX}/upload/${sessionUuid}/end`, ); - console.log('Session ended.'); + this.logger.log('Session ended.', LogLevel.VERBOSE); if (!respEndSession.data?.data) { throw new Error(); @@ -118,29 +128,32 @@ export class HostingWebsite { public async deploy(toEnvironment: DeployToEnvironment): Promise { // - console.log( + this.logger.log( `Deploying website ${this.uuid} to IPFS (${ toEnvironment === DeployToEnvironment.TO_STAGING ? 'preview' : 'production' })`, + LogLevel.VERBOSE, ); - console.time('Deploy complete'); + this.logger.logWithTime('Deploy start', LogLevel.VERBOSE); const resp = await this.api.post(`${this.API_PREFIX}/deploy`, { environment: toEnvironment, }); - console.timeEnd('Deploy complete'); + this.logger.logWithTime('Deploy complete', LogLevel.VERBOSE); return resp.data?.data; } public async getDeployStatus(deploymentId: string) { - // - console.log('Get deployments for website ', this.uuid); + this.logger.log( + `Get deployments for website ${this.uuid}`, + LogLevel.VERBOSE, + ); return ( await this.api.get(`${this.API_PREFIX}/deployments/${deploymentId}`) - ).data; + ).data?.data; } } diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 720d3b6..655a5ab 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -12,6 +12,6 @@ export class Hosting extends ApillonModule { * @returns An instance of Website.∂ */ public website(uuid: string): HostingWebsite { - return new HostingWebsite(uuid, this.api); + return new HostingWebsite(this.api, this.logger, uuid); } } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index e610bc7..24cb556 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -13,6 +13,7 @@ import { CollectionStatus, EvmChain, } from '../../types/nfts'; +import { ApillonLogger } from '../../docs-index'; export class NftCollection { /** @@ -20,6 +21,11 @@ export class NftCollection { */ protected api: AxiosInstance; + /** + * Logger. + */ + protected logger: ApillonLogger; + /** * @dev Unique identifier of the collection. */ @@ -127,8 +133,14 @@ export class NftCollection { */ public chain: EvmChain = null; - constructor(api: AxiosInstance, uuid: string, data: any) { + constructor( + api: AxiosInstance, + logger: ApillonLogger, + uuid: string, + data: any, + ) { this.api = api; + this.logger = logger; this.uuid = uuid; this.API_PREFIX = `/nfts/collections/${this.uuid}`; this.populate(data); diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 4bf6b92..2505216 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -20,7 +20,7 @@ export class Nft extends ApillonModule { * @returns An instance of NFT Collection */ public collection(uuid: string): NftCollection { - return new NftCollection(this.api, uuid, null); + return new NftCollection(this.api, this.logger, uuid, null); } /** @@ -38,7 +38,9 @@ export class Nft extends ApillonModule { if (resp.data?.data && resp.data?.data.items) { for (const item of resp.data?.data.items) { - items.push(new NftCollection(this.api, item.collectionUuid, item)); + items.push( + new NftCollection(this.api, this.logger, item.collectionUuid, item), + ); } } @@ -58,6 +60,7 @@ export class Nft extends ApillonModule { return new NftCollection( this.api, + this.logger, resp.data?.data.collectionUuid, resp.data?.data, ); diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index d19294f..09a2e4a 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -1,5 +1,6 @@ import { AxiosInstance } from 'axios'; import { FileStatus, StorageContentType } from '../../types/storage'; +import { ApillonLogger } from '../../lib/apillon'; export class File { /** @@ -7,6 +8,11 @@ export class File { */ protected api: AxiosInstance; + /** + * Logger. + */ + protected logger: ApillonLogger; + /** * @dev API url prefix for this class. */ @@ -54,11 +60,13 @@ export class File { */ constructor( api: AxiosInstance, + logger: ApillonLogger, bucketUuid: string, fileId: string, data: any, ) { this.api = api; + this.logger = logger; this.bucketUuid = bucketUuid; this.id = fileId; this.API_PREFIX = `/storage/${bucketUuid}/file/${fileId}`; diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 11a0a3d..e91e165 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -3,6 +3,7 @@ import { Directory } from './directory'; import { StorageContentType } from '../../types/storage'; import { File } from './file'; import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; +import { ApillonLogger } from '../../docs-index'; export class StorageBucket { /** @@ -10,6 +11,11 @@ export class StorageBucket { */ protected api: AxiosInstance; + /** + * Logger. + */ + protected logger: ApillonLogger; + /** * @dev API url prefix for this class. */ @@ -30,8 +36,9 @@ export class StorageBucket { * @param uuid Unique identifier of the bucket. * @param api Axios instance set to correct rootUrl with correct error handling. */ - constructor(uuid: string, api: AxiosInstance) { + constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string) { this.api = api; + this.logger = logger; this.uuid = uuid; this.API_PREFIX = `/storage/${uuid}`; } @@ -40,7 +47,7 @@ export class StorageBucket { * TODO: How to handle search etc.? * @dev Gets contents of a bucket. */ - async getContent(data?: any) { + async getObjects(data?: any) { this.content = []; let postfix = ''; if (data?.directoryId) { @@ -49,7 +56,9 @@ export class StorageBucket { const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { - this.content.push(new File(this.api, this.uuid, item.id, item)); + this.content.push( + new File(this.api, this.logger, this.uuid, item.id, item), + ); } else { this.content.push(new Directory(this.api, this.uuid, item.id, item)); } @@ -106,6 +115,6 @@ export class StorageBucket { * @returns Instance of file. */ file(fileId: string): File { - return new File(this.api, this.uuid, fileId, null); + return new File(this.api, this.logger, this.uuid, fileId, null); } } diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index 4367dc7..5fc0589 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -8,6 +8,6 @@ export class Storage extends ApillonModule { * @returns An instance of Website.∂ */ public bucket(uuid: string): StorageBucket { - return new StorageBucket(uuid, this.api); + return new StorageBucket(this.api, this.logger, uuid); } } diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index 04e11a1..85a037b 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -1,5 +1,6 @@ import { ApillonConfig } from '../lib/apillon'; import { Hosting } from '../modules/hosting/hosting'; +import { LogLevel } from '../types/apillon'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; @@ -12,7 +13,7 @@ describe('Hosting tests', () => { websiteUUID = getWebsiteUUID(); }); - test.only('get website info', async () => { + test('get website info', async () => { const hosting = new Hosting(config); try { const website = await hosting.website(websiteUUID).get(); @@ -50,7 +51,7 @@ describe('Hosting tests', () => { const hosting = new Hosting(config); const website = hosting.website(websiteUUID); - const deployStatus = await website.getDeployStatus('208'); + const deployStatus = await website.getDeployStatus('20'); console.log(deployStatus); }); }); diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index 4d7cbca..b4c3714 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -2,7 +2,7 @@ import { ApillonConfig } from '../lib/apillon'; import { Nft } from '../modules/nft/nft'; import { getCollectionUUID, getConfig } from './helpers/helper'; -describe('Nft tests', () => { +describe.skip('Nft tests', () => { let config: ApillonConfig; let collectionUUID: string; diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index f94bc90..a027f67 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -12,3 +12,9 @@ export interface IApillonResponse { export interface IApillonStatus { status: number; } + +export enum LogLevel { + NONE = 1, + ERROR = 2, + VERBOSE = 3, +} diff --git a/packages/sdk/src/types/hosting.ts b/packages/sdk/src/types/hosting.ts index 38e6860..0784e89 100644 --- a/packages/sdk/src/types/hosting.ts +++ b/packages/sdk/src/types/hosting.ts @@ -3,3 +3,10 @@ export enum DeployToEnvironment { STAGING_TO_PRODUCTION = 2, DIRECTLY_TO_PRODUCTION = 3, } + +export enum DeploymentStatus { + INITIATED = 0, + IN_PROCESS = 1, + SUCCESSFUL = 10, + FAILED = 100, +} diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index 1faf766..099f5df 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -56,12 +56,6 @@ export interface ICreateCollection { dropReserve: number; } -export interface INestMintCollectionNft { - parentCollectionUuid: string; - parentNftId: number; - quantity: number; -} - //OUTPUTS export interface ICollection { collectionUuid: string; From 00445a2bfe2595b12cc3feecd848f6a24952d220 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 6 Oct 2023 13:27:41 +0200 Subject: [PATCH 14/68] Add nft tests. --- .../sdk/src/modules/nft/nft-collection.ts | 15 +-- packages/sdk/src/modules/storage/directory.ts | 14 ++- .../sdk/src/modules/storage/storage-bucket.ts | 4 +- packages/sdk/src/tests/helpers/helper.ts | 4 + packages/sdk/src/tests/hosting.test.ts | 3 +- packages/sdk/src/tests/nft.test.ts | 93 ++++++++++++++----- packages/sdk/src/types/apillon.ts | 4 + 7 files changed, 102 insertions(+), 35 deletions(-) diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 24cb556..5bbcc16 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -4,6 +4,7 @@ import { IApillonResponse, IApillonList, IApillonStatus, + IApillonBoolResponse, } from '../../types/apillon'; import { ICollection, @@ -27,14 +28,14 @@ export class NftCollection { protected logger: ApillonLogger; /** - * @dev Unique identifier of the collection. + * @dev API url prefix for this class. */ - private uuid; + private API_PREFIX: string = null; /** - * @dev API url prefix for this class. + * @dev Unique identifier of the collection. */ - private API_PREFIX: string = null; + public uuid; /** * @dev collection symbol. @@ -181,7 +182,7 @@ export class NftCollection { * @returns Call status. */ public async mint(receiver: string, quantity: number) { - const resp = await this.api.post>( + const resp = await this.api.post>( `${this.API_PREFIX}/mint`, { receivingAddress: receiver, quantity }, ); @@ -206,7 +207,7 @@ export class NftCollection { this.collectionType != null && this.collectionType != CollectionType.NESTABLE ) { - throw new Error('This method is only available on nestable collections.'); + throw new Error('Collection is not nestable.'); } const resp = await this.api.post>( `${this.API_PREFIX}/nest-mint`, @@ -224,7 +225,7 @@ export class NftCollection { */ public async burnNft(id: string): Promise { if (this.isRevokable != null && !this.isRevokable) { - throw new Error('Collection is not revokable'); + throw new Error('Collection is not revokable.'); } const resp = await this.api.post>( `${this.API_PREFIX}/burn`, diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index adef480..7b89403 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -1,6 +1,7 @@ import { AxiosInstance } from 'axios'; import { StorageContentType } from '../../types/storage'; import { File } from './file'; +import { ApillonLogger } from '../../lib/apillon'; export class Directory { /** @@ -8,6 +9,11 @@ export class Directory { */ protected api: AxiosInstance; + /** + * Logger. + */ + protected logger: ApillonLogger; + /** * @dev API url prefix for this class. */ @@ -51,11 +57,13 @@ export class Directory { */ constructor( api: AxiosInstance, + logger: ApillonLogger, bucketUuid: string, directoryId: string, data: any, ) { this.api = api; + this.logger = logger; this.bucketUuid = bucketUuid; this.id = directoryId; this.API_PREFIX = `/storage/${bucketUuid}`; @@ -86,10 +94,12 @@ export class Directory { const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { - this.content.push(new File(this.api, this.bucketUuid, item.id, item)); + this.content.push( + new File(this.api, this.logger, this.bucketUuid, item.id, item), + ); } else { this.content.push( - new Directory(this.api, this.bucketUuid, item.id, item), + new Directory(this.api, this.logger, this.bucketUuid, item.id, item), ); } } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index e91e165..671154a 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -60,7 +60,9 @@ export class StorageBucket { new File(this.api, this.logger, this.uuid, item.id, item), ); } else { - this.content.push(new Directory(this.api, this.uuid, item.id, item)); + this.content.push( + new Directory(this.api, this.logger, this.uuid, item.id, item), + ); } } diff --git a/packages/sdk/src/tests/helpers/helper.ts b/packages/sdk/src/tests/helpers/helper.ts index ffefd76..cd45380 100644 --- a/packages/sdk/src/tests/helpers/helper.ts +++ b/packages/sdk/src/tests/helpers/helper.ts @@ -21,3 +21,7 @@ export function getCollectionUUID() { export function getWebsiteUUID() { return process.env['WEBSITE_UUID']; } + +export function getMintAddress() { + return process.env['MINT_ADDRESS']; +} diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index 85a037b..cd6e4e8 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -1,10 +1,9 @@ import { ApillonConfig } from '../lib/apillon'; import { Hosting } from '../modules/hosting/hosting'; -import { LogLevel } from '../types/apillon'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; -describe('Hosting tests', () => { +describe.skip('Hosting tests', () => { let config: ApillonConfig; let websiteUUID: string; diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index b4c3714..98283d7 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -1,45 +1,92 @@ +import { CollectionType, EvmChain, NftCollection } from '../docs-index'; import { ApillonConfig } from '../lib/apillon'; import { Nft } from '../modules/nft/nft'; -import { getCollectionUUID, getConfig } from './helpers/helper'; +import { getCollectionUUID, getConfig, getMintAddress } from './helpers/helper'; -describe.skip('Nft tests', () => { +describe('Nft tests', () => { let config: ApillonConfig; let collectionUUID: string; + let receiverAddress: string; beforeAll(async () => { config = getConfig(); collectionUUID = getCollectionUUID(); + receiverAddress = getMintAddress(); }); test('list nft collections', async () => { const nft = new Nft(config); - try { - const collection = await nft.list(); - console.log(collection); - } catch (e) { - console.log(e); - } + const collections = await nft.list(); + expect(collections.length).toBeGreaterThan(0); + expect(collections[0]).toBeInstanceOf(NftCollection); + }); + + test.skip('creates a new collection', async () => { + const nft = new Nft(config); + const collection = await nft.create({ + chain: EvmChain.MOONBASE, + collectionType: CollectionType.GENERIC, + name: 'created from sdk tests', + symbol: 'cfst', + royaltiesFees: 0, + royaltiesAddress: '0x0000000000000000000000000000000000000000', + baseUri: 'https://test.com/metadata/', + baseExtension: '.json', + maxSupply: 5, + isRevokable: true, + isSoulbound: false, + drop: false, + dropStart: 0, + dropPrice: 0, + dropReserve: 0, + }); + expect(collection.uuid).toBeDefined(); + }); + + test.skip('mints a new nft', async () => { + const nft = new Nft(config); + const collection = await nft.collection(collectionUUID); + const res = await collection.mint(receiverAddress, 1); + expect(res.success).toBe(true); + }); + + test.only('get nft collection transactions', async () => { + const nft = new Nft(config); + const transactions = await nft + .collection(collectionUUID) + .listTransactions(); + expect(transactions.length).toBeGreaterThan(0); + expect(transactions[0].transactionHash).toBeDefined(); }); test('get nft collection details', async () => { const nft = new Nft(config); - try { - const collection = await nft - .collection(collectionUUID) - .listTransactions(); - console.log(collection); - } catch (e) { - console.log(e); - } + const collection = await nft.collection(collectionUUID).get(); + console.log(collection); + expect(collection.name).toBe('sdk test manual'); + }); + + test('should fail nest minting for collection that is not nestable if collection populated', async () => { + const nft = new Nft(config); + const collection = await nft.collection(collectionUUID).get(); + await expect(collection.nestMintNft('', 1, 1)).rejects.toThrow( + 'Collection is not nestable.', + ); }); - test.only('get nft collection details', async () => { + // TODO: unhandled error in api + test('should fail nest minting', async () => { const nft = new Nft(config); - try { - const collection = await nft.collection(collectionUUID).get(); - console.log(collection); - } catch (e) { - console.log(e); - } + const collection = await nft.collection(collectionUUID); + await collection.nestMintNft('2ad03895-fd5d-40e7-af17-1d6daecf3b5a', 1, 1); + }); + + test('should fail revoking for collection that is not revokable if collection populated', async () => { + const nft = new Nft(config); + const collection = await nft.collection(collectionUUID).get(); + + await expect(collection.burnNft('1')).rejects.toThrow( + 'Collection is not revokable.', + ); }); }); diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index a027f67..ea87e02 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -13,6 +13,10 @@ export interface IApillonStatus { status: number; } +export interface IApillonBoolResponse { + success: boolean; +} + export enum LogLevel { NONE = 1, ERROR = 2, From 82e7abb26296275b09a91abe10e34031ceede360 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 20 Oct 2023 15:03:52 +0200 Subject: [PATCH 15/68] Update hosting --- packages/sdk/src/modules/hosting/hosting.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 655a5ab..642995d 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -2,10 +2,6 @@ import { ApillonModule } from '../../lib/apillon'; import { HostingWebsite } from './hosting-website'; export class Hosting extends ApillonModule { - public createWebsite() { - throw Error('Not implemented'); - } - /** * @dev Returns an website instance. * @param uuid Unique website identifier. From f94ad311c414282d058408da4d06195436e7d532 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 24 Oct 2023 15:02:59 +0200 Subject: [PATCH 16/68] Add test debug launch configuration --- .vscode/launch.json | 25 ++++ package-lock.json | 169 ++++++++++++++++++++++- package.json | 1 - packages/sdk/package.json | 1 + packages/sdk/src/lib/common.ts | 4 +- packages/sdk/src/tests/helpers/helper.ts | 6 +- 6 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..bbb0356 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Jest Test Current File", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": [ + "${relativeFile}", + "--config=${workspaceFolder}/package.json", + "--runInBand", + "--detectOpenHandles", + "--forceExit" + ], + "cwd": "${workspaceFolder}", + "env": { + "LOG_TARGET": "none", + "APP_ENV": "test" + }, + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen" + } + ] +} diff --git a/package-lock.json b/package-lock.json index 26fb7d1..a3a552a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1879,6 +1879,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4312,6 +4318,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -4382,6 +4394,12 @@ "node": "14 || >=16.14" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -4439,6 +4457,18 @@ "tmpl": "1.0.5" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -5244,6 +5274,18 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", + "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -5853,6 +5895,42 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedoc": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz", + "integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -5945,6 +6023,18 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -6287,11 +6377,13 @@ "axios": "^1.3.4" }, "devDependencies": { + "dotenv": "^16.0.3", "eslint-config-common": "*", "nodemon": "^2.0.20", "rimraf": "^5.0.5", "ts-node": "^10.9.1", - "tsconfig": "*" + "tsconfig": "*", + "typedoc": "^0.25.1" } }, "packages/sdk/node_modules/glob": { @@ -6431,11 +6523,13 @@ "version": "file:packages/sdk", "requires": { "axios": "^1.3.4", + "dotenv": "^16.0.3", "eslint-config-common": "*", "nodemon": "^2.0.20", "rimraf": "^5.0.5", "ts-node": "^10.9.1", - "tsconfig": "*" + "tsconfig": "*", + "typedoc": "^0.25.1" }, "dependencies": { "glob": { @@ -7886,6 +7980,12 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, + "ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9685,6 +9785,12 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -9737,6 +9843,12 @@ "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "dev": true }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -9781,6 +9893,12 @@ "tmpl": "1.0.5" } }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -10336,6 +10454,18 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, + "shiki": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", + "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", + "dev": true, + "requires": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -10742,6 +10872,29 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, + "typedoc": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.2.tgz", + "integrity": "sha512-286F7BeATBiWe/qC4PCOCKlSTwfnsLbC/4cZ68oGBbvAqb9vV33quEOXx7q176OXotD+JdEerdQ1OZGJ818lnA==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "dependencies": { + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -10806,6 +10959,18 @@ } } }, + "vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", diff --git a/package.json b/package.json index 1fc3e24..7752435 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,6 @@ "js", "json" ], - "rootDir": "src/tests", "testPathIgnorePatterns": [ "dist/*" ], diff --git a/packages/sdk/package.json b/packages/sdk/package.json index c57b5df..0ccfa99 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -3,6 +3,7 @@ "description": "▶◀ Apillon SDK for NodeJS ▶◀", "version": "0.1.2", "author": "Apillon", + "type": "module", "license": "MIT", "main": "./dist/index.js", "source": "./src/index.ts", diff --git a/packages/sdk/src/lib/common.ts b/packages/sdk/src/lib/common.ts index 26acf8e..1e27c45 100644 --- a/packages/sdk/src/lib/common.ts +++ b/packages/sdk/src/lib/common.ts @@ -36,7 +36,7 @@ export function constructUrlWithQueryParams(url: string, parameters: any) { const cleanParams = {}; for (const key in parameters) { const value = parameters[key]; - if (value !== undefined && value !== null && value !== '') { + if (value != null && value !== '') { cleanParams[key] = value; } } @@ -54,7 +54,7 @@ export function listFilesRecursive( for (const file of files) { const fullPath = path.join(folderPath, file); if (fs.statSync(fullPath).isDirectory()) { - listFilesRecursive(fullPath, fileList, relativePath + file + '/'); + listFilesRecursive(fullPath, fileList, `${relativePath + file}/`); } else { fileList.push({ fileName: file, path: relativePath, index: fullPath }); } diff --git a/packages/sdk/src/tests/helpers/helper.ts b/packages/sdk/src/tests/helpers/helper.ts index cd45380..a463862 100644 --- a/packages/sdk/src/tests/helpers/helper.ts +++ b/packages/sdk/src/tests/helpers/helper.ts @@ -1,8 +1,12 @@ import * as dotenv from 'dotenv'; import { ApillonConfig } from '../../lib/apillon'; +import { resolve } from 'path'; export function getConfig(): ApillonConfig { - dotenv.config({ path: '../../.env' }); + // Configure dotenv with the absolute path + const envPath = resolve(__dirname, '../../.env'); + dotenv.config({ path: envPath }); + return { apiUrl: process.env['APILLON_API_URL'], secret: process.env['APILLON_API_SECRET'], From 3ce1b99758f43fa8b9e5e62240088d7e0b65a96f Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 24 Oct 2023 15:03:43 +0200 Subject: [PATCH 17/68] Replace file/directory ID with UUID, add recursive list --- packages/sdk/src/modules/storage/directory.ts | 27 ++++++--- packages/sdk/src/modules/storage/file.ts | 12 ++-- .../sdk/src/modules/storage/storage-bucket.ts | 60 +++++++++++++++---- packages/sdk/src/tests/storage.test.ts | 51 +++++++++------- packages/sdk/src/types/storage.ts | 5 ++ 5 files changed, 110 insertions(+), 45 deletions(-) diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index 7b89403..d060267 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -27,7 +27,7 @@ export class Directory { /** * @dev Unique identifier of the directory. */ - public id; + public uuid; /** * Directory name. @@ -42,7 +42,7 @@ export class Directory { /** * Id of the directory in which the file resides. */ - public parentDirectoryId: string = null; + public parentDirectoryUuid: string = null; /** * Type of content. @@ -59,13 +59,13 @@ export class Directory { api: AxiosInstance, logger: ApillonLogger, bucketUuid: string, - directoryId: string, + directoryUuid: string, data: any, ) { this.api = api; this.logger = logger; this.bucketUuid = bucketUuid; - this.id = directoryId; + this.uuid = directoryUuid; this.API_PREFIX = `/storage/${bucketUuid}`; this.populate(data); } @@ -90,16 +90,29 @@ export class Directory { */ async get() { this.content = []; - const postfix = `?directoryId=${this.id}`; + const postfix = `?directoryUuid=${this.uuid}`; const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { this.content.push( - new File(this.api, this.logger, this.bucketUuid, item.id, item), + new File( + this.api, + this.logger, + this.bucketUuid, + item.uuid, + item.directoryUuid, + item, + ), ); } else { this.content.push( - new Directory(this.api, this.logger, this.bucketUuid, item.id, item), + new Directory( + this.api, + this.logger, + this.bucketUuid, + item.uuid, + item, + ), ); } } diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 09a2e4a..6feb9ec 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -26,7 +26,7 @@ export class File { /** * @dev Unique identifier of the file. */ - public id: string; + public uuid: string; /** * File name. @@ -46,7 +46,7 @@ export class File { /** * Id of the directory in which the file resides. */ - public parentDirectoryId: string = null; + public directoryUuid: string = null; /** * Type of content. @@ -62,14 +62,16 @@ export class File { api: AxiosInstance, logger: ApillonLogger, bucketUuid: string, - fileId: string, + fileUuid: string, + directoryUuid: string, data: any, ) { this.api = api; this.logger = logger; this.bucketUuid = bucketUuid; - this.id = fileId; - this.API_PREFIX = `/storage/${bucketUuid}/file/${fileId}`; + this.uuid = fileUuid; + this.directoryUuid = directoryUuid; + this.API_PREFIX = `/storage/${bucketUuid}/file/${fileUuid}`; this.populate(data); } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 671154a..83921eb 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -1,6 +1,9 @@ import { AxiosInstance } from 'axios'; import { Directory } from './directory'; -import { StorageContentType } from '../../types/storage'; +import { + IStorageBucketContentRequest, + StorageContentType, +} from '../../types/storage'; import { File } from './file'; import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; import { ApillonLogger } from '../../docs-index'; @@ -47,21 +50,28 @@ export class StorageBucket { * TODO: How to handle search etc.? * @dev Gets contents of a bucket. */ - async getObjects(data?: any) { + async getObjects(data?: IStorageBucketContentRequest) { this.content = []; - let postfix = ''; - if (data?.directoryId) { - postfix = `?directoryId=${data.directoryId}`; - } + const postfix = data?.directoryUuid + ? `?directoryUuid=${data.directoryUuid}` + : ''; + const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { this.content.push( - new File(this.api, this.logger, this.uuid, item.id, item), + new File( + this.api, + this.logger, + this.uuid, + item.uuid, + item.directoryUuid, + item, + ), ); } else { this.content.push( - new Directory(this.api, this.logger, this.uuid, item.id, item), + new Directory(this.api, this.logger, this.uuid, item.uuid, item), ); } } @@ -69,6 +79,34 @@ export class StorageBucket { return this.content; } + async getFilesRecursive(data?: IStorageBucketContentRequest) { + const content = []; + const postfix = data?.directoryUuid + ? `?directoryUuid=${data.directoryUuid}` + : ''; + + const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); + for (const item of resp.data?.data?.items) { + if (item.type == StorageContentType.FILE) { + new File( + this.api, + this.logger, + this.uuid, + item.uuid, + item.directoryUuid, + item, + ); + } else { + const files = await this.getFilesRecursive({ + directoryUuid: item.uuid, + }); + content.push(...files); + } + } + + return (this.content = [...content]); + } + /** * @dev Uploads files inside a folder via path. * @param folderPath Path to the folder to upload. @@ -113,10 +151,10 @@ export class StorageBucket { /** * Gets file instance. - * @param fileId Id of the file. + * @param fileUuid Uuid of the file. * @returns Instance of file. */ - file(fileId: string): File { - return new File(this.api, this.logger, this.uuid, fileId, null); + file(fileUuid: string): File { + return new File(this.api, this.logger, this.uuid, fileUuid, null, null); } } diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 71fc086..7a35522 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -3,7 +3,7 @@ import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; import { getBucketUUID, getConfig } from './helpers/helper'; -describe.skip('Storage tests', () => { +describe('Storage tests', () => { let config: ApillonConfig; let bucketUUID: string; @@ -14,36 +14,43 @@ describe.skip('Storage tests', () => { test('get bucket content', async () => { const storage = new Storage(config); - try { - const content = await storage.bucket(bucketUUID).getObjects(); - console.log(content); - } catch (e) { - console.log(e); + const content = await storage.bucket(bucketUUID).getObjects(); + for (const item of content) { + if (item.type == StorageContentType.DIRECTORY) { + await item.get(); + } + console.log(`${item.type}: ${item.name}`); + } + expect(content.length).toBeGreaterThanOrEqual(0); + }); + + test('get bucket files recursively', async () => { + const storage = new Storage(config); + const content = await storage.bucket(bucketUUID).getFilesRecursive(); + for (const item of content) { + if (item.type == StorageContentType.DIRECTORY) { + await item.get(); + } + console.log(`${item.type}: ${item.name}`); } + expect(content.length).toBeGreaterThanOrEqual(0); }); test('get bucket directory content', async () => { const storage = new Storage(config); - try { - const content = await storage - .bucket(bucketUUID) - .getObjects({ directoryId: '3160' }); + const content = await storage + .bucket(bucketUUID) + .getObjects({ directoryUuid: '6c9c6ab1-801d-4915-a63e-120eed21fee0' }); - for (let i = 0; i < content.length; i++) { - if (content[i].type == StorageContentType.DIRECTORY) { - await content[i].get(); - console.log(content[i]); - } - if (content[i].type == StorageContentType.FILE) { - console.log(content[i]); - } + for (const item of content) { + if (item.type == StorageContentType.DIRECTORY) { + await item.get(); } - } catch (e) { - console.log(e); + console.log(`${item.type}: ${item.name}`); } }); - test('get file details', async () => { + test.skip('get file details', async () => { const storage = new Storage(config); try { const content = await storage.bucket(bucketUUID).file('79961').get(); @@ -53,7 +60,7 @@ describe.skip('Storage tests', () => { } }); - test('upload files', async () => { + test.skip('upload files', async () => { const storage = new Storage(config); try { await storage diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index c480d3e..eb7cac6 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -9,3 +9,8 @@ export enum FileStatus { AVAILABLE_ON_IPFS = 3, AVAILABLE_ON_IPFS_AND_REPLICATED = 4, } + +export interface IStorageBucketContentRequest { + directoryUuid?: string; + markedForDeletion?: string; +} From 79912f051a525b1f3140e133d27f56c0d79a38f6 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 24 Oct 2023 15:39:12 +0200 Subject: [PATCH 18/68] Add URL parameters for markedForDeletion search --- packages/sdk/src/lib/common.ts | 2 +- packages/sdk/src/modules/storage/file.ts | 7 +++--- .../sdk/src/modules/storage/storage-bucket.ts | 22 +++++++++---------- packages/sdk/src/tests/storage.test.ts | 21 +++++++++--------- packages/sdk/src/types/storage.ts | 2 +- 5 files changed, 28 insertions(+), 26 deletions(-) diff --git a/packages/sdk/src/lib/common.ts b/packages/sdk/src/lib/common.ts index 1e27c45..0bf87d2 100644 --- a/packages/sdk/src/lib/common.ts +++ b/packages/sdk/src/lib/common.ts @@ -32,7 +32,7 @@ export function toInteger(value: string) { * @param url url without query parameters * @param parameters query parameters */ -export function constructUrlWithQueryParams(url: string, parameters: any) { +export function constructUrlWithQueryParams(url: string, parameters: object) { const cleanParams = {}; for (const key in parameters) { const value = parameters[key]; diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 6feb9ec..6548f19 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -72,6 +72,7 @@ export class File { this.uuid = fileUuid; this.directoryUuid = directoryUuid; this.API_PREFIX = `/storage/${bucketUuid}/file/${fileUuid}`; + this.status = data.fileStatus; this.populate(data); } @@ -94,9 +95,9 @@ export class File { * @dev Gets file details. */ async get() { - const resp = await this.api.get(`${this.API_PREFIX}/detail`); - this.status = resp.data?.data?.fileStatus; - this.populate(resp.data?.data?.file); + const { data } = await this.api.get(`${this.API_PREFIX}/detail`); + this.status = data.data.fileStatus; + this.populate(data.data); return this; } } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 83921eb..db5e125 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -5,7 +5,7 @@ import { StorageContentType, } from '../../types/storage'; import { File } from './file'; -import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; +import { constructUrlWithQueryParams, listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; import { ApillonLogger } from '../../docs-index'; export class StorageBucket { @@ -52,11 +52,11 @@ export class StorageBucket { */ async getObjects(data?: IStorageBucketContentRequest) { this.content = []; - const postfix = data?.directoryUuid - ? `?directoryUuid=${data.directoryUuid}` - : ''; - - const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); + const url = constructUrlWithQueryParams( + `${this.API_PREFIX}/content`, + data, + ); + const resp = await this.api.get(url); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { this.content.push( @@ -81,11 +81,11 @@ export class StorageBucket { async getFilesRecursive(data?: IStorageBucketContentRequest) { const content = []; - const postfix = data?.directoryUuid - ? `?directoryUuid=${data.directoryUuid}` - : ''; - - const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); + const url = constructUrlWithQueryParams( + `${this.API_PREFIX}/content`, + data, + ); + const resp = await this.api.get(url); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { new File( diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 7a35522..167b808 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -2,7 +2,6 @@ import { ApillonConfig } from '../lib/apillon'; import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; import { getBucketUUID, getConfig } from './helpers/helper'; - describe('Storage tests', () => { let config: ApillonConfig; let bucketUUID: string; @@ -12,7 +11,7 @@ describe('Storage tests', () => { bucketUUID = getBucketUUID(); }); - test('get bucket content', async () => { + test.skip('get bucket content', async () => { const storage = new Storage(config); const content = await storage.bucket(bucketUUID).getObjects(); for (const item of content) { @@ -24,7 +23,7 @@ describe('Storage tests', () => { expect(content.length).toBeGreaterThanOrEqual(0); }); - test('get bucket files recursively', async () => { + test.skip('get bucket files recursively', async () => { const storage = new Storage(config); const content = await storage.bucket(bucketUUID).getFilesRecursive(); for (const item of content) { @@ -36,7 +35,13 @@ describe('Storage tests', () => { expect(content.length).toBeGreaterThanOrEqual(0); }); - test('get bucket directory content', async () => { + test.skip('get bucket files markedForDeletion=true', async () => { + const storage = new Storage(config); + const content = await storage.bucket(bucketUUID).getObjects({ markedForDeletion: true }); + expect(content.some(file => file['status'] == 8)) + }); + + test.skip('get bucket directory content', async () => { const storage = new Storage(config); const content = await storage .bucket(bucketUUID) @@ -52,12 +57,8 @@ describe('Storage tests', () => { test.skip('get file details', async () => { const storage = new Storage(config); - try { - const content = await storage.bucket(bucketUUID).file('79961').get(); - console.log(content); - } catch (e) { - console.log(e); - } + const file = await storage.bucket(bucketUUID).file('cad1e0ef-29c5-4ae1-b9de-1065e8ec1e68').get(); + expect(file.name).toBeTruthy(); }); test.skip('upload files', async () => { diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index eb7cac6..188baa9 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -12,5 +12,5 @@ export enum FileStatus { export interface IStorageBucketContentRequest { directoryUuid?: string; - markedForDeletion?: string; + markedForDeletion?: boolean; } From 9b1f856c9738a36b8253bb35c1e102f41b4e017c Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Wed, 25 Oct 2023 08:54:54 +0200 Subject: [PATCH 19/68] Divide file upload sessions into chunks --- packages/sdk/src/lib/common.ts | 2 +- packages/sdk/src/modules/storage/directory.ts | 2 +- packages/sdk/src/modules/storage/file.ts | 2 +- .../sdk/src/modules/storage/storage-bucket.ts | 30 ++++++++++--------- packages/sdk/src/tests/storage.test.ts | 19 +++++++----- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/sdk/src/lib/common.ts b/packages/sdk/src/lib/common.ts index 0bf87d2..ccb9151 100644 --- a/packages/sdk/src/lib/common.ts +++ b/packages/sdk/src/lib/common.ts @@ -59,7 +59,7 @@ export function listFilesRecursive( fileList.push({ fileName: file, path: relativePath, index: fullPath }); } } - return fileList; + return fileList.sort((a, b) => a.fileName.localeCompare(b.fileName)); } export async function uploadFilesToS3(uploadLinks: any[], files: any[]) { diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index d060267..9265c2b 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -27,7 +27,7 @@ export class Directory { /** * @dev Unique identifier of the directory. */ - public uuid; + public uuid: string; /** * Directory name. diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 6548f19..d5d553f 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -72,7 +72,7 @@ export class File { this.uuid = fileUuid; this.directoryUuid = directoryUuid; this.API_PREFIX = `/storage/${bucketUuid}/file/${fileUuid}`; - this.status = data.fileStatus; + this.status = data?.fileStatus; this.populate(data); } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index db5e125..7a299f6 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -27,7 +27,7 @@ export class StorageBucket { /** * @dev Unique identifier of the bucket. */ - public uuid; + public uuid: string; /** * @dev Bucket content which are files and directories. @@ -123,29 +123,31 @@ export class StorageBucket { throw new Error(`Error reading files in ${folderPath}`); } - const data = { files }; - console.log(`Files to upload: ${data.files.length}`); + console.log(`Files to upload: ${files.length}`); console.time('Got upload links'); - const resp = await this.api.post(`${this.API_PREFIX}/upload`, data); - + const { data } = await this.api.post(`${this.API_PREFIX}/upload`, { files }); console.timeEnd('Got upload links'); - // console.log(resp); - const sessionUuid = resp.data.data.sessionUuid; - - console.time('File upload complete'); - await uploadFilesToS3(resp.data.data.files, files); - console.timeEnd('File upload complete'); + const uploadLinks = data.data.files.sort((a, b) => a.fileName.localeCompare(b.fileName)); + // Divide files into chunks for parallel processing and uploading + const chunkSize = 10; + const fileChunks = []; + for (let i = 0; i < files.length; i += chunkSize) { + const chunkFiles = files.slice(i, i + chunkSize); + const chunkLinks = uploadLinks.slice(i, i + chunkSize); + fileChunks.push({ chunkFiles, chunkLinks }); + } + await Promise.all(fileChunks.map(({ chunkFiles, chunkLinks }) => uploadFilesToS3(chunkLinks, chunkFiles))); console.log('Closing session...'); const respEndSession = await this.api.post( - `${this.API_PREFIX}/upload/${sessionUuid}/end`, + `${this.API_PREFIX}/upload/${data.data.sessionUuid}/end`, ); console.log('Session ended.'); if (!respEndSession.data?.data) { - throw new Error(); + throw new Error('Failure when trying to end file upload session'); } } @@ -155,6 +157,6 @@ export class StorageBucket { * @returns Instance of file. */ file(fileUuid: string): File { - return new File(this.api, this.logger, this.uuid, fileUuid, null, null); + return new File(this.api, this.logger, this.uuid, fileUuid, null, {}); } } diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 167b808..1850d31 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -1,3 +1,4 @@ +import { resolve } from 'path'; import { ApillonConfig } from '../lib/apillon'; import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; @@ -11,7 +12,7 @@ describe('Storage tests', () => { bucketUUID = getBucketUUID(); }); - test.skip('get bucket content', async () => { + test('get bucket content', async () => { const storage = new Storage(config); const content = await storage.bucket(bucketUUID).getObjects(); for (const item of content) { @@ -23,7 +24,7 @@ describe('Storage tests', () => { expect(content.length).toBeGreaterThanOrEqual(0); }); - test.skip('get bucket files recursively', async () => { + test('get bucket files recursively', async () => { const storage = new Storage(config); const content = await storage.bucket(bucketUUID).getFilesRecursive(); for (const item of content) { @@ -35,13 +36,13 @@ describe('Storage tests', () => { expect(content.length).toBeGreaterThanOrEqual(0); }); - test.skip('get bucket files markedForDeletion=true', async () => { + test('get bucket files markedForDeletion=true', async () => { const storage = new Storage(config); const content = await storage.bucket(bucketUUID).getObjects({ markedForDeletion: true }); expect(content.some(file => file['status'] == 8)) }); - test.skip('get bucket directory content', async () => { + test('get bucket directory content', async () => { const storage = new Storage(config); const content = await storage .bucket(bucketUUID) @@ -55,18 +56,22 @@ describe('Storage tests', () => { } }); - test.skip('get file details', async () => { + test('get file details', async () => { const storage = new Storage(config); - const file = await storage.bucket(bucketUUID).file('cad1e0ef-29c5-4ae1-b9de-1065e8ec1e68').get(); + const file = await storage.bucket(bucketUUID).file('cf6a0d3d-2abd-4a0d-85c1-10b8f04cd4fc').get(); expect(file.name).toBeTruthy(); }); test.skip('upload files', async () => { const storage = new Storage(config); try { + const uploadDir = resolve(__dirname, './helpers/website/'); + console.time('File upload complete'); await storage .bucket(bucketUUID) - .uploadFromFolder('./src/tests/helpers/website/'); + .uploadFromFolder(uploadDir); + console.timeEnd('File upload complete'); + // console.log(content); } catch (e) { console.log(e); From 4a31fe82657d57234704c6dd8be3c672aade4480 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Wed, 25 Oct 2023 13:05:32 +0200 Subject: [PATCH 20/68] Hosting module updates --- .../src/modules/hosting/hosting-website.ts | 51 +++++++++++-------- packages/sdk/src/modules/hosting/hosting.ts | 22 +++++++- packages/sdk/src/tests/hosting.test.ts | 43 ++++++++-------- packages/sdk/src/tests/storage.test.ts | 3 ++ packages/sdk/src/types/hosting.ts | 6 +++ 5 files changed, 81 insertions(+), 44 deletions(-) diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index afb4654..5a97685 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -23,7 +23,7 @@ export class HostingWebsite { /** * @dev Unique identifier of the website. */ - public uuid; + public uuid: string; /** * @dev User assigned name of the website. @@ -60,25 +60,36 @@ export class HostingWebsite { * @param uuid Unique identifier of the website. * @param api Axios instance set to correct rootUrl with correct error handling. */ - constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string) { + constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string, data?: Partial) { this.api = api; this.uuid = uuid; this.logger = logger; + this.populate(data); this.API_PREFIX = `/hosting/websites/${uuid}`; } + /** + * Populates class properties via data object. + * @param data Data object. + */ + private populate(data: any) { + if (!data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); + } + } + /** * @dev Gets information about the website and fills properties with it. * @returns An instance of HostingWebsite class with filled properties. */ public async get(): Promise { - const data = (await this.api.get(this.API_PREFIX)).data; - this.name = data.data?.name; - this.description = data.data?.description; - this.domain = data.data?.domain; - this.bucketUuid = data.data?.bucketUuid; - this.ipnsStaging = data.data?.ipnsStaging; - this.ipnsProduction = data.data?.ipnsProduction; + const { data } = (await this.api.get(this.API_PREFIX)).data; + this.populate(data); return this; } @@ -121,39 +132,37 @@ export class HostingWebsite { ); this.logger.log('Session ended.', LogLevel.VERBOSE); - if (!respEndSession.data?.data) { + if (!respEndSession.data.data) { throw new Error(); } } public async deploy(toEnvironment: DeployToEnvironment): Promise { - // this.logger.log( - `Deploying website ${this.uuid} to IPFS (${ - toEnvironment === DeployToEnvironment.TO_STAGING - ? 'preview' - : 'production' + `Deploying website ${this.uuid} to IPFS (${toEnvironment === DeployToEnvironment.TO_STAGING + ? 'preview' + : 'production' })`, LogLevel.VERBOSE, ); this.logger.logWithTime('Deploy start', LogLevel.VERBOSE); - const resp = await this.api.post(`${this.API_PREFIX}/deploy`, { + const { data } = await this.api.post(`${this.API_PREFIX}/deploy`, { environment: toEnvironment, }); this.logger.logWithTime('Deploy complete', LogLevel.VERBOSE); - return resp.data?.data; + return data.data; } - public async getDeployStatus(deploymentId: string) { + public async getDeployment(deploymentUuid: string) { this.logger.log( - `Get deployments for website ${this.uuid}`, + `Get deployment for website ${this.uuid}`, LogLevel.VERBOSE, ); return ( - await this.api.get(`${this.API_PREFIX}/deployments/${deploymentId}`) - ).data?.data; + await this.api.get(`${this.API_PREFIX}/deployments/${deploymentUuid}`) + ).data.data; } } diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 642995d..7b5aa7f 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -1,11 +1,31 @@ +import { IWebsiteFilters } from '../../docs-index'; import { ApillonModule } from '../../lib/apillon'; +import { constructUrlWithQueryParams } from '../../lib/common'; +import { IApillonList, IApillonResponse } from '../../types/apillon'; import { HostingWebsite } from './hosting-website'; export class Hosting extends ApillonModule { + /** + * @dev Base API url for hosting. + */ + private API_PREFIX = '/hosting'; + + /** + * @dev Returns an list of websites. + * @param {IWebsiteFilters} params Query filters for listing websites + * @returns A list of HostingWebsite instances. + */ + public async listWebsites(params?: IWebsiteFilters): Promise { + const url = constructUrlWithQueryParams(`${this.API_PREFIX}/websites`, params); + + const { data } = await this.api.get>>(url); + + return data.data.items.map(website => new HostingWebsite(this.api, this.logger, website['websiteUuid'], website)); + } /** * @dev Returns an website instance. * @param uuid Unique website identifier. - * @returns An instance of Website.∂ + * @returns An instance of HostingWebsite. */ public website(uuid: string): HostingWebsite { return new HostingWebsite(this.api, this.logger, uuid); diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index cd6e4e8..becec74 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -1,9 +1,10 @@ +import { resolve } from 'path'; import { ApillonConfig } from '../lib/apillon'; import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; -describe.skip('Hosting tests', () => { +describe('Hosting tests', () => { let config: ApillonConfig; let websiteUUID: string; @@ -12,30 +13,28 @@ describe.skip('Hosting tests', () => { websiteUUID = getWebsiteUUID(); }); + test('get all websites', async () => { + const hosting = new Hosting(config); + const websites = await hosting.listWebsites(); + expect(websites.length).toBeGreaterThan(0); + expect(websites[0].name).toBeTruthy(); + }); + test('get website info', async () => { const hosting = new Hosting(config); - try { - const website = await hosting.website(websiteUUID).get(); - console.log(website); - console.log(website.name); - console.log(website.bucketUuid); - console.log(website.ipnsProduction); - console.log(website.ipnsStaging); - } catch (e) { - console.log(e); - } + const website = await hosting.website(websiteUUID).get(); + expect(website.name).toBeTruthy(); + expect(website.uuid).toBeTruthy(); }); - test('upload website from folder', async () => { + test.skip('upload website from folder', async () => { const hosting = new Hosting(config); const website = hosting.website(websiteUUID); - try { - await website.uploadFromFolder('./src/tests/helpers/website/'); - } catch (e) { - console.log(e); - } - const deploymentId = await website.deploy(DeployToEnvironment.TO_STAGING); - console.log(deploymentId); + + const uploadDir = resolve(__dirname, './helpers/website/'); + await website.uploadFromFolder(uploadDir); + const deployment = await website.deploy(DeployToEnvironment.TO_STAGING); + expect(deployment.environment).toEqual(DeployToEnvironment.TO_STAGING); }); // test('get deployment status', async () => { @@ -46,11 +45,11 @@ describe.skip('Hosting tests', () => { // console.log(deployStatus); // }); - test.only('get deployment status', async () => { + test('get deployment status', async () => { const hosting = new Hosting(config); const website = hosting.website(websiteUUID); - const deployStatus = await website.getDeployStatus('20'); - console.log(deployStatus); + const deployment = await website.getDeployment('e21a8e4e-bfce-4e63-b65b-59404d4fc6b4'); + expect(deployment.environment).toEqual(DeployToEnvironment.TO_STAGING); }); }); diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 1850d31..43b2866 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -22,6 +22,7 @@ describe('Storage tests', () => { console.log(`${item.type}: ${item.name}`); } expect(content.length).toBeGreaterThanOrEqual(0); + content.forEach(item => expect(item.name).toBeTruthy()); }); test('get bucket files recursively', async () => { @@ -34,6 +35,7 @@ describe('Storage tests', () => { console.log(`${item.type}: ${item.name}`); } expect(content.length).toBeGreaterThanOrEqual(0); + content.forEach(item => expect(item.name).toBeTruthy()); }); test('get bucket files markedForDeletion=true', async () => { @@ -54,6 +56,7 @@ describe('Storage tests', () => { } console.log(`${item.type}: ${item.name}`); } + content.forEach(item => expect(item.name).toBeTruthy()); }); test('get file details', async () => { diff --git a/packages/sdk/src/types/hosting.ts b/packages/sdk/src/types/hosting.ts index 0784e89..fffa72d 100644 --- a/packages/sdk/src/types/hosting.ts +++ b/packages/sdk/src/types/hosting.ts @@ -1,3 +1,5 @@ +import { IApillonPagination } from "./generic"; + export enum DeployToEnvironment { TO_STAGING = 1, STAGING_TO_PRODUCTION = 2, @@ -10,3 +12,7 @@ export enum DeploymentStatus { SUCCESSFUL = 10, FAILED = 100, } + +export interface IWebsiteFilters extends IApillonPagination { + status?: number; +} \ No newline at end of file From 92df399b18ca590195fd787ceadd54ec9fe3cf3e Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Wed, 25 Oct 2023 14:23:43 +0200 Subject: [PATCH 21/68] NFTs module & tests updates --- packages/sdk/src/modules/hosting/hosting.ts | 4 +-- .../sdk/src/modules/nft/nft-collection.ts | 28 +++++++++---------- packages/sdk/src/modules/nft/nft.ts | 25 +++++------------ packages/sdk/src/tests/hosting.test.ts | 3 ++ packages/sdk/src/tests/nft.test.ts | 6 ++-- packages/sdk/src/types/apillon.ts | 2 ++ 6 files changed, 31 insertions(+), 37 deletions(-) diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 7b5aa7f..99185be 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -1,7 +1,7 @@ import { IWebsiteFilters } from '../../docs-index'; import { ApillonModule } from '../../lib/apillon'; import { constructUrlWithQueryParams } from '../../lib/common'; -import { IApillonList, IApillonResponse } from '../../types/apillon'; +import { IApillonListResponse } from '../../types/apillon'; import { HostingWebsite } from './hosting-website'; export class Hosting extends ApillonModule { @@ -18,7 +18,7 @@ export class Hosting extends ApillonModule { public async listWebsites(params?: IWebsiteFilters): Promise { const url = constructUrlWithQueryParams(`${this.API_PREFIX}/websites`, params); - const { data } = await this.api.get>>(url); + const { data } = await this.api.get>(url); return data.data.items.map(website => new HostingWebsite(this.api, this.logger, website['websiteUuid'], website)); } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 5bbcc16..9da4b6c 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -35,7 +35,7 @@ export class NftCollection { /** * @dev Unique identifier of the collection. */ - public uuid; + public uuid: string; /** * @dev collection symbol. @@ -138,7 +138,7 @@ export class NftCollection { api: AxiosInstance, logger: ApillonLogger, uuid: string, - data: any, + data?: Partial, ) { this.api = api; this.logger = logger; @@ -167,10 +167,10 @@ export class NftCollection { * @returns Collection instance. */ public async get(): Promise { - const resp = await this.api.get>( + const { data } = await this.api.get>( this.API_PREFIX, ); - this.populate(resp.data?.data); + this.populate(data?.data); return this; } @@ -182,12 +182,12 @@ export class NftCollection { * @returns Call status. */ public async mint(receiver: string, quantity: number) { - const resp = await this.api.post>( + const { data } = await this.api.post>( `${this.API_PREFIX}/mint`, { receivingAddress: receiver, quantity }, ); - return resp.data?.data; + return data?.data; } /** @@ -209,12 +209,12 @@ export class NftCollection { ) { throw new Error('Collection is not nestable.'); } - const resp = await this.api.post>( + const { data } = await this.api.post>( `${this.API_PREFIX}/nest-mint`, { parentCollectionUuid, parentNftId, quantity }, ); - return resp.data?.data; + return data?.data; } /** @@ -227,12 +227,12 @@ export class NftCollection { if (this.isRevokable != null && !this.isRevokable) { throw new Error('Collection is not revokable.'); } - const resp = await this.api.post>( + const { data } = await this.api.post>( `${this.API_PREFIX}/burn`, { tokenId: id }, ); - return resp.data?.data; + return data?.data; } /** @@ -243,12 +243,12 @@ export class NftCollection { * @returns Collection data. */ public async transferOwnership(address: string): Promise { - const resp = await this.api.post>( + const { data } = await this.api.post>( `${this.API_PREFIX}/transfer`, { address }, ); - this.populate(resp.data?.data); + this.populate(data?.data); return this; } @@ -266,10 +266,10 @@ export class NftCollection { params, ); - const resp = await this.api.get< + const { data } = await this.api.get< IApillonResponse> >(url); - return resp.data?.data.items; + return data?.data.items; } } diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 2505216..9df56c9 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -1,6 +1,6 @@ import { ApillonModule } from '../../lib/apillon'; import { constructUrlWithQueryParams } from '../../lib/common'; -import { IApillonResponse, IApillonList } from '../../types/apillon'; +import { IApillonResponse, IApillonList, IApillonListResponse } from '../../types/apillon'; import { ICollectionFilters, ICollection, @@ -25,26 +25,15 @@ export class Nft extends ApillonModule { /** * Lists all nft collections available. - * @param params Filter for listing collections. + * @param {ICollectionFilters} params Filter for listing collections. * @returns Array of NftCollection. */ public async list(params?: ICollectionFilters): Promise { - const items: NftCollection[] = []; const url = constructUrlWithQueryParams(this.API_PREFIX, params); - const resp = await this.api.get< - IApillonResponse> - >(url); + const { data } = await this.api.get>(url); - if (resp.data?.data && resp.data?.data.items) { - for (const item of resp.data?.data.items) { - items.push( - new NftCollection(this.api, this.logger, item.collectionUuid, item), - ); - } - } - - return items; + return data.data.items.map(nft => new NftCollection(this.api, this.logger, nft.collectionUuid, nft)); } /** @@ -53,7 +42,7 @@ export class Nft extends ApillonModule { * @returns A NftCollection instance. */ public async create(data: ICreateCollection) { - const resp = await this.api.post>( + const { data: response } = await this.api.post>( this.API_PREFIX, data, ); @@ -61,8 +50,8 @@ export class Nft extends ApillonModule { return new NftCollection( this.api, this.logger, - resp.data?.data.collectionUuid, - resp.data?.data, + response?.data.collectionUuid, + response?.data, ); } } diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index becec74..203d258 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -3,6 +3,7 @@ import { ApillonConfig } from '../lib/apillon'; import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; +import { HostingWebsite } from '../modules/hosting/hosting-website'; describe('Hosting tests', () => { let config: ApillonConfig; @@ -17,12 +18,14 @@ describe('Hosting tests', () => { const hosting = new Hosting(config); const websites = await hosting.listWebsites(); expect(websites.length).toBeGreaterThan(0); + expect(websites[0]).toBeInstanceOf(HostingWebsite); expect(websites[0].name).toBeTruthy(); }); test('get website info', async () => { const hosting = new Hosting(config); const website = await hosting.website(websiteUUID).get(); + expect(website).toBeInstanceOf(HostingWebsite); expect(website.name).toBeTruthy(); expect(website.uuid).toBeTruthy(); }); diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index 98283d7..d1672c9 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -45,12 +45,12 @@ describe('Nft tests', () => { test.skip('mints a new nft', async () => { const nft = new Nft(config); - const collection = await nft.collection(collectionUUID); + const collection = nft.collection(collectionUUID); const res = await collection.mint(receiverAddress, 1); expect(res.success).toBe(true); }); - test.only('get nft collection transactions', async () => { + test('get nft collection transactions', async () => { const nft = new Nft(config); const transactions = await nft .collection(collectionUUID) @@ -77,7 +77,7 @@ describe('Nft tests', () => { // TODO: unhandled error in api test('should fail nest minting', async () => { const nft = new Nft(config); - const collection = await nft.collection(collectionUUID); + const collection = nft.collection(collectionUUID); await collection.nestMintNft('2ad03895-fd5d-40e7-af17-1d6daecf3b5a', 1, 1); }); diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index ea87e02..9a822ca 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -13,6 +13,8 @@ export interface IApillonStatus { status: number; } +export interface IApillonListResponse extends IApillonResponse> { } + export interface IApillonBoolResponse { success: boolean; } From 5a4089ee55cce7b021c76b57ba63c9f56a394805 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 26 Oct 2023 10:50:22 +0200 Subject: [PATCH 22/68] Implement pagination for storage endpoints --- packages/sdk/src/modules/storage/directory.ts | 13 ++-- packages/sdk/src/modules/storage/file.ts | 2 +- .../sdk/src/modules/storage/storage-bucket.ts | 66 +++++++++---------- packages/sdk/src/tests/storage.test.ts | 32 +++++---- packages/sdk/src/types/storage.ts | 8 ++- 5 files changed, 62 insertions(+), 59 deletions(-) diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index 9265c2b..a04349b 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -1,7 +1,8 @@ import { AxiosInstance } from 'axios'; -import { StorageContentType } from '../../types/storage'; +import { IStorageBucketContentRequest, StorageContentType } from '../../types/storage'; import { File } from './file'; import { ApillonLogger } from '../../lib/apillon'; +import { constructUrlWithQueryParams } from '../../lib/common'; export class Directory { /** @@ -88,10 +89,14 @@ export class Directory { /** * @dev Gets contents of a directory. */ - async get() { + async get(params: IStorageBucketContentRequest = {}): Promise<(Directory | File)[]> { this.content = []; - const postfix = `?directoryUuid=${this.uuid}`; - const resp = await this.api.get(`${this.API_PREFIX}/content${postfix}`); + params.directoryUuid = this.uuid; + const url = constructUrlWithQueryParams( + `${this.API_PREFIX}/content`, + params, + ); + const resp = await this.api.get(url); for (const item of resp.data?.data?.items) { if (item.type == StorageContentType.FILE) { this.content.push( diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index d5d553f..b0faa34 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -94,7 +94,7 @@ export class File { /** * @dev Gets file details. */ - async get() { + async get(): Promise { const { data } = await this.api.get(`${this.API_PREFIX}/detail`); this.status = data.data.fileStatus; this.populate(data.data); diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 7a299f6..b33664d 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -1,12 +1,14 @@ import { AxiosInstance } from 'axios'; import { Directory } from './directory'; import { + IBucketFilesRequest, IStorageBucketContentRequest, StorageContentType, } from '../../types/storage'; import { File } from './file'; import { constructUrlWithQueryParams, listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; import { ApillonLogger } from '../../docs-index'; +import { IApillonList, IApillonListResponse } from '../../types/apillon'; export class StorageBucket { /** @@ -47,19 +49,18 @@ export class StorageBucket { } /** - * TODO: How to handle search etc.? * @dev Gets contents of a bucket. */ - async getObjects(data?: IStorageBucketContentRequest) { - this.content = []; + async getObjects(params?: IStorageBucketContentRequest): Promise> { + const content = []; const url = constructUrlWithQueryParams( `${this.API_PREFIX}/content`, - data, + params, ); - const resp = await this.api.get(url); - for (const item of resp.data?.data?.items) { + const { data } = await this.api.get(url); + for (const item of data.data.items) { if (item.type == StorageContentType.FILE) { - this.content.push( + content.push( new File( this.api, this.logger, @@ -67,44 +68,37 @@ export class StorageBucket { item.uuid, item.directoryUuid, item, - ), - ); + )); } else { - this.content.push( - new Directory(this.api, this.logger, this.uuid, item.uuid, item), - ); + const directory = new Directory(this.api, this.logger, this.uuid, item.uuid, item); + content.push(directory, ...await directory.get()); } } - return this.content; + return { total: data.data.total, items: content }; } - async getFilesRecursive(data?: IStorageBucketContentRequest) { - const content = []; + /** + * @dev Gets all files in a bucket. + */ + async getFiles(params?: IBucketFilesRequest): Promise> { const url = constructUrlWithQueryParams( - `${this.API_PREFIX}/content`, - data, + `/storage/buckets/${this.uuid}/files`, + params, ); - const resp = await this.api.get(url); - for (const item of resp.data?.data?.items) { - if (item.type == StorageContentType.FILE) { - new File( - this.api, - this.logger, - this.uuid, - item.uuid, - item.directoryUuid, - item, - ); - } else { - const files = await this.getFilesRecursive({ - directoryUuid: item.uuid, - }); - content.push(...files); - } + const { data } = await this.api.get>(url); + + return { + total: data.data.total, + items: data.data.items.map(file => new File( + this.api, + this.logger, + this.uuid, + file.uuid, + file.directoryUuid, + file, + )) } - - return (this.content = [...content]); } /** diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 43b2866..12aa63b 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -3,6 +3,7 @@ import { ApillonConfig } from '../lib/apillon'; import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; import { getBucketUUID, getConfig } from './helpers/helper'; + describe('Storage tests', () => { let config: ApillonConfig; let bucketUUID: string; @@ -14,49 +15,46 @@ describe('Storage tests', () => { test('get bucket content', async () => { const storage = new Storage(config); - const content = await storage.bucket(bucketUUID).getObjects(); - for (const item of content) { + const { items } = await storage.bucket(bucketUUID).getObjects(); + for (const item of items) { if (item.type == StorageContentType.DIRECTORY) { await item.get(); } console.log(`${item.type}: ${item.name}`); } - expect(content.length).toBeGreaterThanOrEqual(0); - content.forEach(item => expect(item.name).toBeTruthy()); + expect(items.length).toBeGreaterThanOrEqual(0); + items.forEach(item => expect(item.name).toBeTruthy()); }); - test('get bucket files recursively', async () => { + test('get bucket files', async () => { const storage = new Storage(config); - const content = await storage.bucket(bucketUUID).getFilesRecursive(); - for (const item of content) { - if (item.type == StorageContentType.DIRECTORY) { - await item.get(); - } + const { items } = await storage.bucket(bucketUUID).getFiles(); + for (const item of items) { console.log(`${item.type}: ${item.name}`); } - expect(content.length).toBeGreaterThanOrEqual(0); - content.forEach(item => expect(item.name).toBeTruthy()); + expect(items.length).toBeGreaterThanOrEqual(0); + items.forEach(item => expect(item.name).toBeTruthy()); }); test('get bucket files markedForDeletion=true', async () => { const storage = new Storage(config); - const content = await storage.bucket(bucketUUID).getObjects({ markedForDeletion: true }); - expect(content.some(file => file['status'] == 8)) + const { items } = await storage.bucket(bucketUUID).getObjects({ markedForDeletion: true }); + expect(items.some(file => file['status'] == 8)) }); test('get bucket directory content', async () => { const storage = new Storage(config); - const content = await storage + const { items } = await storage .bucket(bucketUUID) .getObjects({ directoryUuid: '6c9c6ab1-801d-4915-a63e-120eed21fee0' }); - for (const item of content) { + for (const item of items) { if (item.type == StorageContentType.DIRECTORY) { await item.get(); } console.log(`${item.type}: ${item.name}`); } - content.forEach(item => expect(item.name).toBeTruthy()); + items.forEach(item => expect(item.name).toBeTruthy()); }); test('get file details', async () => { diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index 188baa9..1a7b898 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -1,3 +1,5 @@ +import { IApillonPagination } from "./generic"; + export enum StorageContentType { FILE = 2, DIRECTORY = 1, @@ -10,7 +12,11 @@ export enum FileStatus { AVAILABLE_ON_IPFS_AND_REPLICATED = 4, } -export interface IStorageBucketContentRequest { +export interface IStorageBucketContentRequest extends IApillonPagination { directoryUuid?: string; markedForDeletion?: boolean; } + +export interface IBucketFilesRequest extends IApillonPagination { + fileStatus?: FileStatus; +} From 469d0cfde64a9e8af2e7ccdd5474af30f9aee707 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 26 Oct 2023 11:17:26 +0200 Subject: [PATCH 23/68] Add missing storage endpoints --- .../sdk/src/modules/storage/storage-bucket.ts | 44 ++++++++++++++++++- packages/sdk/src/modules/storage/storage.ts | 26 +++++++++++ packages/sdk/src/tests/storage.test.ts | 11 +++++ 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index b33664d..4d3e5b8 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -31,6 +31,21 @@ export class StorageBucket { */ public uuid: string; + /** + * @dev Name of the bucket. + */ + public name: string = null; + + /** + * @dev Bucket description. + */ + public description: string = null; + + /** + * @dev Size of the bucket in bytes. + */ + public size: number = null; + /** * @dev Bucket content which are files and directories. */ @@ -40,12 +55,29 @@ export class StorageBucket { * @dev Constructor which should only be called via Storage class. * @param uuid Unique identifier of the bucket. * @param api Axios instance set to correct rootUrl with correct error handling. + * @param data Data to populate storage bucket */ - constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string) { + constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string, data?: Partial) { this.api = api; this.logger = logger; this.uuid = uuid; this.API_PREFIX = `/storage/${uuid}`; + this.populate(data); + } + + /** + * Populates class properties via data object. + * @param data Data object. + */ + private populate(data: any) { + if (data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); + } } /** @@ -74,7 +106,7 @@ export class StorageBucket { content.push(directory, ...await directory.get()); } } - + this.content = content; return { total: data.data.total, items: content }; } @@ -153,4 +185,12 @@ export class StorageBucket { file(fileUuid: string): File { return new File(this.api, this.logger, this.uuid, fileUuid, null, {}); } + + /** + * Deletes a file from the bucket. + * @param fileUuid Uuid of the file. + */ + async deleteFile(fileUuid: string): Promise { + await this.api.delete(`/storage/buckets/${this.uuid}/files/${fileUuid}`); + } } diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index 5fc0589..ebf44f6 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -1,7 +1,33 @@ +import { IApillonPagination } from '../../docs-index'; import { ApillonModule } from '../../lib/apillon'; +import { constructUrlWithQueryParams } from '../../lib/common'; +import { IApillonList, IApillonListResponse } from '../../types/apillon'; import { StorageBucket } from './storage-bucket'; export class Storage extends ApillonModule { + /** + * @dev API url for storage. + */ + private API_PREFIX = '/storage/buckets'; + + /** + * Lists all buckets. + * @param {ICollectionFilters} params Filter for listing collections. + * @returns Array of NftCollection. + */ + public async listBuckets(params?: IApillonPagination): Promise> { + const url = constructUrlWithQueryParams(this.API_PREFIX, params); + + const { data } = await this.api.get>(url); + + return { + items: data.data.items.map( + bucket => new StorageBucket(this.api, this.logger, bucket.bucketUuid, bucket) + ), + total: data.data.total + }; + } + /** * @dev Returns an website instance. * @param uuid Unique website identifier. diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 12aa63b..d3f6cde 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -13,6 +13,12 @@ describe('Storage tests', () => { bucketUUID = getBucketUUID(); }); + test('List buckets', async () => { + const { items } = await new Storage(config).listBuckets({ limit: 1 }); + expect(items.length).toBeGreaterThanOrEqual(0); + items.forEach(item => expect(item.name).toBeTruthy()); + }); + test('get bucket content', async () => { const storage = new Storage(config); const { items } = await storage.bucket(bucketUUID).getObjects(); @@ -78,4 +84,9 @@ describe('Storage tests', () => { console.log(e); } }); + + test.skip('delete a file', async () => { + const storage = new Storage(config); + await storage.bucket(bucketUUID).deleteFile('cf6a0d3d-2abd-4a0d-85c1-10b8f04cd4fc'); + }); }); From 3993046cb372ef66bbacfe5fedca888e0f03965b Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 26 Oct 2023 11:49:30 +0200 Subject: [PATCH 24/68] Implement deployment class and endpoints --- .../sdk/src/modules/hosting/deployment.ts | 110 ++++++++++++++++++ .../src/modules/hosting/hosting-website.ts | 49 +++++--- packages/sdk/src/modules/hosting/hosting.ts | 18 ++- .../sdk/src/modules/nft/nft-collection.ts | 5 +- packages/sdk/src/modules/storage/directory.ts | 2 +- packages/sdk/src/modules/storage/file.ts | 6 +- packages/sdk/src/tests/hosting.test.ts | 19 ++- packages/sdk/src/types/hosting.ts | 5 + 8 files changed, 183 insertions(+), 31 deletions(-) create mode 100644 packages/sdk/src/modules/hosting/deployment.ts diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts new file mode 100644 index 0000000..f50dff5 --- /dev/null +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -0,0 +1,110 @@ +import { AxiosInstance } from 'axios'; +import { ApillonLogger } from '../../lib/apillon'; +import { DeployToEnvironment, DeploymentStatus } from '../../docs-index'; +import { LogLevel } from '../../types/apillon'; + +export class Deployment { + /** + * Axios instance set to correct rootUrl with correct error handling. + */ + protected api: AxiosInstance; + + /** + * Logger. + */ + protected logger: ApillonLogger; + + /** + * @dev API url prefix for this class. + */ + private API_PREFIX: string = null; + + /** + * @dev Unique identifier of the website. + */ + public websiteUuid: string = null; + + /** + * @dev Unique identifier of the deployment. + */ + public uuid: string = null; + + /** + * IPFS CID for the deployment. + */ + public cid: string = null; + + /** + * IPFS V1 CID for the deployment. + */ + public cidv1: string = null; + + /** + * Environment of the deployment + */ + public environment: DeployToEnvironment = null; + + /** + * Status of the deployment + */ + public deploymentStatus: DeploymentStatus = null; + + /** + * Size of the website in bytes + */ + public size: number = null; + + /** + * Serial number of the deployment for this environment + */ + public number: number = null; + + + /** + * @dev Constructor which should only be called via HostingWebsite class. + * @param uuid Unique identifier of the deployment. + * @param api Axios instance set to correct rootUrl with correct error handling. + */ + constructor( + api: AxiosInstance, + logger: ApillonLogger, + websiteUuid: string, + deploymentUuid: string, + data: any, + ) { + this.api = api; + this.logger = logger; + this.websiteUuid = websiteUuid; + this.uuid = deploymentUuid; + this.API_PREFIX = `/hosting/websites/${websiteUuid}/deployments/${deploymentUuid}`; + this.populate(data); + } + + /** + * Populates class properties via data object. + * @param data Data object. + */ + private populate(data: any) { + if (data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); + } + return this; + } + + /** + * @dev Gets deployment details. + */ + async get(): Promise { + this.logger.log( + `Get deployment for website ${this.uuid}`, + LogLevel.VERBOSE, + ); + const { data } = await this.api.get(this.API_PREFIX); + return this.populate(data.data); + } +} diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index 5a97685..b442913 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -1,8 +1,9 @@ import { AxiosInstance } from 'axios'; -import { listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; -import { DeployToEnvironment } from '../../types/hosting'; +import { constructUrlWithQueryParams, listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; +import { DeployToEnvironment, IDeploymentFilters } from '../../types/hosting'; import { ApillonLogger } from '../../index'; -import { LogLevel } from '../../types/apillon'; +import { IApillonList, LogLevel } from '../../types/apillon'; +import { Deployment } from './deployment'; export class HostingWebsite { /** @@ -81,6 +82,7 @@ export class HostingWebsite { } }); } + return this; } /** @@ -89,8 +91,7 @@ export class HostingWebsite { */ public async get(): Promise { const { data } = (await this.api.get(this.API_PREFIX)).data; - this.populate(data); - return this; + return this.populate(data); } /** @@ -137,6 +138,11 @@ export class HostingWebsite { } } + /** + * @dev Deploy a website to a new environment. + * @param {DeployToEnvironment} toEnvironment The environment to deploy to + * @returns The new deployment instance + */ public async deploy(toEnvironment: DeployToEnvironment): Promise { this.logger.log( `Deploying website ${this.uuid} to IPFS (${toEnvironment === DeployToEnvironment.TO_STAGING @@ -156,13 +162,30 @@ export class HostingWebsite { return data.data; } - public async getDeployment(deploymentUuid: string) { - this.logger.log( - `Get deployment for website ${this.uuid}`, - LogLevel.VERBOSE, - ); - return ( - await this.api.get(`${this.API_PREFIX}/deployments/${deploymentUuid}`) - ).data.data; + /** + * @dev Returns an list of websites. + * @param {IWebsiteFilters} params Query filters for listing websites + * @returns A list of all deployments instances. + */ + public async listDeployments(params?: IDeploymentFilters): Promise> { + const url = constructUrlWithQueryParams(`${this.API_PREFIX}/deployments`, params); + + const { data } = await this.api.get(url); + + return { + items: data.data.items.map( + item => new Deployment(this.api, this.logger, item.websiteUuid, item.deploymentUuid, item) + ), + total: data.data.total + } + } + + /** + * Gets a deployment instance. + * @param deploymentUuid Uuid of the deployment. + * @returns Instance of a deployment. + */ + deployment(deploymentUuid: string): Deployment { + return new Deployment(this.api, this.logger, this.uuid, deploymentUuid, {}); } } diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 99185be..2ef978e 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -1,27 +1,33 @@ import { IWebsiteFilters } from '../../docs-index'; import { ApillonModule } from '../../lib/apillon'; import { constructUrlWithQueryParams } from '../../lib/common'; -import { IApillonListResponse } from '../../types/apillon'; +import { IApillonList, IApillonListResponse } from '../../types/apillon'; import { HostingWebsite } from './hosting-website'; export class Hosting extends ApillonModule { /** * @dev Base API url for hosting. */ - private API_PREFIX = '/hosting'; + private API_PREFIX = '/hosting/websites'; /** - * @dev Returns an list of websites. + * @dev Returns a list of websites. * @param {IWebsiteFilters} params Query filters for listing websites * @returns A list of HostingWebsite instances. */ - public async listWebsites(params?: IWebsiteFilters): Promise { - const url = constructUrlWithQueryParams(`${this.API_PREFIX}/websites`, params); + public async listWebsites(params?: IWebsiteFilters): Promise> { + const url = constructUrlWithQueryParams(this.API_PREFIX, params); const { data } = await this.api.get>(url); - return data.data.items.map(website => new HostingWebsite(this.api, this.logger, website['websiteUuid'], website)); + return { + items: data.data.items.map( + website => new HostingWebsite(this.api, this.logger, website['websiteUuid'], website) + ), + total: data.data.total + }; } + /** * @dev Returns an website instance. * @param uuid Unique website identifier. diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 9da4b6c..bb7a0d3 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -160,6 +160,7 @@ export class NftCollection { } }); } + return this; } /** @@ -170,9 +171,7 @@ export class NftCollection { const { data } = await this.api.get>( this.API_PREFIX, ); - this.populate(data?.data); - - return this; + return this.populate(data.data); } /** diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index a04349b..d8cb012 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -53,7 +53,7 @@ export class Directory { public content: (File | Directory)[] = null; /** * @dev Constructor which should only be called via Storage class. - * @param uuid Unique identifier of the bucket. + * @param uuid Unique identifier of the directory. * @param api Axios instance set to correct rootUrl with correct error handling. */ constructor( diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index b0faa34..3c67ad6 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -55,7 +55,7 @@ export class File { /** * @dev Constructor which should only be called via Storage class. - * @param uuid Unique identifier of the bucket. + * @param uuid Unique identifier of the file. * @param api Axios instance set to correct rootUrl with correct error handling. */ constructor( @@ -89,6 +89,7 @@ export class File { } }); } + return this; } /** @@ -97,7 +98,6 @@ export class File { async get(): Promise { const { data } = await this.api.get(`${this.API_PREFIX}/detail`); this.status = data.data.fileStatus; - this.populate(data.data); - return this; + return this.populate(data.data); } } diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index 203d258..693be75 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -4,6 +4,7 @@ import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; import { HostingWebsite } from '../modules/hosting/hosting-website'; +import { Deployment } from '../modules/hosting/deployment'; describe('Hosting tests', () => { let config: ApillonConfig; @@ -16,10 +17,10 @@ describe('Hosting tests', () => { test('get all websites', async () => { const hosting = new Hosting(config); - const websites = await hosting.listWebsites(); - expect(websites.length).toBeGreaterThan(0); - expect(websites[0]).toBeInstanceOf(HostingWebsite); - expect(websites[0].name).toBeTruthy(); + const { items } = await hosting.listWebsites(); + expect(items.length).toBeGreaterThan(0); + expect(items[0]).toBeInstanceOf(HostingWebsite); + expect(items[0].name).toBeTruthy(); }); test('get website info', async () => { @@ -48,11 +49,19 @@ describe('Hosting tests', () => { // console.log(deployStatus); // }); + test('list all deployments', async () => { + const hosting = new Hosting(config); + const website = hosting.website(websiteUUID); + + const { items } = await website.listDeployments({ environment: DeployToEnvironment.TO_STAGING }); + expect(items.every(d => d.environment === DeployToEnvironment.TO_STAGING)); + }); + test('get deployment status', async () => { const hosting = new Hosting(config); const website = hosting.website(websiteUUID); - const deployment = await website.getDeployment('e21a8e4e-bfce-4e63-b65b-59404d4fc6b4'); + const deployment = await website.deployment('e21a8e4e-bfce-4e63-b65b-59404d4fc6b4').get(); expect(deployment.environment).toEqual(DeployToEnvironment.TO_STAGING); }); }); diff --git a/packages/sdk/src/types/hosting.ts b/packages/sdk/src/types/hosting.ts index fffa72d..d516fed 100644 --- a/packages/sdk/src/types/hosting.ts +++ b/packages/sdk/src/types/hosting.ts @@ -15,4 +15,9 @@ export enum DeploymentStatus { export interface IWebsiteFilters extends IApillonPagination { status?: number; +} + +export interface IDeploymentFilters extends IApillonPagination { + deploymentStatus?: DeploymentStatus; + environment?: DeployToEnvironment; } \ No newline at end of file From cb4f8733a0a13d649e1987519d201a0e054bcab4 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 26 Oct 2023 13:41:49 +0200 Subject: [PATCH 25/68] Fix NFT CLI SDK method references --- packages/cli/src/config.ts | 7 +- packages/cli/src/lib/types.ts | 4 +- packages/cli/src/modules/nfts/nft.service.ts | 91 +++++++++---------- .../cli/src/modules/nfts/nfts.commands.ts | 14 +-- packages/sdk/src/index.ts | 1 + 5 files changed, 54 insertions(+), 63 deletions(-) diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index c7c22f0..4558830 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -4,16 +4,15 @@ import * as dotenv from 'dotenv'; dotenv.config(); function getVersion(rollback: string) { - let ver = rollback; try { - ver = require('./package.json').version; + return require('./package.json').version; } catch (err) { try { - ver = require('../package.json').version; + return require('../package.json').version; } catch (e) {} } - return ver; + return rollback; } export default { diff --git a/packages/cli/src/lib/types.ts b/packages/cli/src/lib/types.ts index 5dc2edb..7265fe8 100644 --- a/packages/cli/src/lib/types.ts +++ b/packages/cli/src/lib/types.ts @@ -1,8 +1,8 @@ -export interface Params { +export interface Options { [Key: string]: string; } -export interface GlobalParams { +export interface GlobalOptions { key: string; secret: string; apiUrl?: string; diff --git a/packages/cli/src/modules/nfts/nft.service.ts b/packages/cli/src/modules/nfts/nft.service.ts index e4c7f77..0850c77 100644 --- a/packages/cli/src/modules/nfts/nft.service.ts +++ b/packages/cli/src/modules/nfts/nft.service.ts @@ -1,30 +1,22 @@ import { exceptionHandler, ICreateCollection, - Nfts, + Nft, toBoolean, toInteger, } from '@apillon/sdk'; import { readAndParseJson } from '../../lib/files'; -import { GlobalParams, Params } from '../../lib/types'; - -function initNftService(options: GlobalParams) { - return new Nfts({ - key: options.key, - secret: options.secret, - apiUrl: options?.apiUrl || undefined, - }); -} +import { GlobalOptions, Options } from '../../lib/types'; // COLLECTIONS export async function listCollections( - options: Params, - optsWithGlobals: GlobalParams, + options: Options, + optsWithGlobals: GlobalOptions, ) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.listNftCollections({ + const data = await nftService.list({ collectionStatus: toInteger(options.status), page: toInteger(options.page), limit: toInteger(options.limit), @@ -38,10 +30,10 @@ export async function listCollections( } export async function getCollection(uuid: string, optsWithGlobals) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.getCollection(uuid); + const data = await nftService.collection(uuid).get(); console.log(data); } catch (e: any) { exceptionHandler(e); @@ -50,7 +42,7 @@ export async function getCollection(uuid: string, optsWithGlobals) { export async function createCollection( filePath: string, - optsWithGlobals: GlobalParams, + optsWithGlobals: GlobalOptions, ) { let createCollectionData; try { @@ -74,10 +66,10 @@ export async function createCollection( return; } - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.createCollection(createCollectionData); + const data = await nftService.create(createCollectionData); console.log(data); } catch (e: any) { exceptionHandler(e); @@ -86,16 +78,15 @@ export async function createCollection( export async function mintCollectionNft( uuid: string, - options: Params, - optsWithGlobals: GlobalParams, + options: Options, + optsWithGlobals: GlobalOptions, ) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.mintCollectionNft(uuid, { - receivingAddress: options.address, - quantity: toInteger(options.quantity), - }); + const data = await nftService + .collection(uuid) + .mint(options.address, toInteger(options.quantity)); console.log(data); } catch (e: any) { exceptionHandler(e); @@ -104,17 +95,19 @@ export async function mintCollectionNft( export async function nestMintCollectionNft( uuid: string, - options: Params, - optsWithGlobals: GlobalParams, + options: Options, + optsWithGlobals: GlobalOptions, ) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.nestMintCollectionNft(uuid, { - parentCollectionUuid: options.parentCollectionUuid, - parentNftId: toInteger(options.parentNftId), - quantity: toInteger(options.quantity), - }); + const data = await nftService + .collection(uuid) + .nestMintNft( + options.parentCollectionUuid, + toInteger(options.parentNftId), + toInteger(options.quantity), + ); console.log(data); } catch (e: any) { exceptionHandler(e); @@ -123,15 +116,13 @@ export async function nestMintCollectionNft( export async function burnCollectionNft( uuid: string, - options: Params, - optsWithGlobals: GlobalParams, + options: Options, + optsWithGlobals: GlobalOptions, ) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.burnCollectionNft(uuid, { - tokenId: toInteger(options.tokenId), - }); + const data = await nftService.collection(uuid).burnNft(options.tokenId); console.log(data); } catch (e: any) { exceptionHandler(e); @@ -140,15 +131,15 @@ export async function burnCollectionNft( export async function transferCollectionOwnership( uuid: string, - options: Params, - optsWithGlobals: GlobalParams, + options: Options, + optsWithGlobals: GlobalOptions, ) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.transferCollectionOwnership(uuid, { - address: options.address, - }); + const data = await nftService + .collection(uuid) + .transferOwnership(options.address); console.log(data); } catch (e: any) { exceptionHandler(e); @@ -158,13 +149,13 @@ export async function transferCollectionOwnership( // TRANSACTIONS export async function listCollectionTransactions( uuid: string, - options: Params, - optsWithGlobals: GlobalParams, + options: Options, + optsWithGlobals: GlobalOptions, ) { - const nftService = initNftService(optsWithGlobals); + const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.listCollectionTransactions(uuid, { + const data = await nftService.collection(uuid).listTransactions({ transactionStatus: toInteger(options.status), transactionType: toInteger(options.type), page: toInteger(options.page), diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index 3f950bf..0cdc205 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -9,7 +9,7 @@ import { nestMintCollectionNft, transferCollectionOwnership, } from './nft.service'; -import { Params } from '../../lib/types'; +import { Options } from '../../lib/types'; import { addPaginationOptions } from '../../lib/options'; export function createNftsCommands(cli: Command) { @@ -20,7 +20,7 @@ export function createNftsCommands(cli: Command) { .command('list-collections') .description('List NFT collections owned by project related to API key.') .addOption(new Option('-s, --status ', 'Collection status')) - .action(async function (options: Params) { + .action(async function (options: Options) { await listCollections(options, this.optsWithGlobals()); }); addPaginationOptions(listCollectionsCommand); @@ -49,7 +49,7 @@ export function createNftsCommands(cli: Command) { 'Address which will receive minted NFTs.', ) .requiredOption('-n, --number ', 'Number of NFTs to mint.') - .action(async function (uuid: string, options: Params) { + .action(async function (uuid: string, options: Options) { await mintCollectionNft(uuid, options, this.optsWithGlobals()); }); @@ -68,7 +68,7 @@ export function createNftsCommands(cli: Command) { 'Parent collection NFT id to which child NFTs will be minted to.', ) .requiredOption('-n, --number ', 'Number of child NFTs to mint.') - .action(async function (uuid: string, options: Params) { + .action(async function (uuid: string, options: Options) { await nestMintCollectionNft(uuid, options, this.optsWithGlobals()); }); @@ -77,7 +77,7 @@ export function createNftsCommands(cli: Command) { .description('Burn NFT for collection with UUID.') .argument('', 'Collection UUID') .requiredOption('-t, --token-id ', 'NFT id which will be burned.') - .action(async function (uuid: string, options: Params) { + .action(async function (uuid: string, options: Options) { await burnCollectionNft(uuid, options, this.optsWithGlobals()); }); @@ -89,7 +89,7 @@ export function createNftsCommands(cli: Command) { '-a, --address ', 'Address which you want to transferred collection ownership to.', ) - .action(async function (uuid: string, options: Params) { + .action(async function (uuid: string, options: Options) { await transferCollectionOwnership(uuid, options, this.optsWithGlobals()); }); @@ -100,7 +100,7 @@ export function createNftsCommands(cli: Command) { .argument('', 'Collection UUID') .addOption(new Option('-s, --status ', 'Transaction status')) .addOption(new Option('-t, --type ', 'Transaction type')) - .action(async function (uuid: string, options: Params) { + .action(async function (uuid: string, options: Options) { await listCollectionTransactions(uuid, options, this.optsWithGlobals()); }); addPaginationOptions(listCollectionTransactionsCommand); diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index d8c1871..4cdcd58 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -3,6 +3,7 @@ export * from './types/nfts'; export * from './types/hosting'; export * from './types/storage'; export * from './lib/apillon'; +export * from './lib/common'; export * from './modules/storage/storage'; export * from './modules/hosting/hosting'; export * from './modules/nft/nft'; From a54ebc1a892fdafa858efdb890565621f1a29ebe Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 26 Oct 2023 14:26:56 +0200 Subject: [PATCH 26/68] Fix SDK file formatting --- packages/sdk/package.json | 1 - .../sdk/src/modules/hosting/deployment.ts | 5 +- .../src/modules/hosting/hosting-website.ts | 42 +++++++++--- packages/sdk/src/modules/hosting/hosting.ts | 18 +++-- .../sdk/src/modules/nft/nft-collection.ts | 7 +- packages/sdk/src/modules/nft/nft.ts | 14 ++-- packages/sdk/src/modules/storage/directory.ts | 9 ++- .../sdk/src/modules/storage/storage-bucket.ts | 65 ++++++++++++++----- packages/sdk/src/modules/storage/storage.ts | 13 ++-- packages/sdk/src/tests/hosting.test.ts | 13 ++-- packages/sdk/src/tests/storage.test.ts | 27 ++++---- packages/sdk/src/types/apillon.ts | 4 +- packages/sdk/src/types/hosting.ts | 4 +- packages/sdk/src/types/storage.ts | 2 +- 14 files changed, 152 insertions(+), 72 deletions(-) diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 0ccfa99..c57b5df 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -3,7 +3,6 @@ "description": "▶◀ Apillon SDK for NodeJS ▶◀", "version": "0.1.2", "author": "Apillon", - "type": "module", "license": "MIT", "main": "./dist/index.js", "source": "./src/index.ts", diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index f50dff5..86fa285 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -45,8 +45,8 @@ export class Deployment { public environment: DeployToEnvironment = null; /** - * Status of the deployment - */ + * Status of the deployment + */ public deploymentStatus: DeploymentStatus = null; /** @@ -59,7 +59,6 @@ export class Deployment { */ public number: number = null; - /** * @dev Constructor which should only be called via HostingWebsite class. * @param uuid Unique identifier of the deployment. diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index b442913..b5bf7a6 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -1,5 +1,9 @@ import { AxiosInstance } from 'axios'; -import { constructUrlWithQueryParams, listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; +import { + constructUrlWithQueryParams, + listFilesRecursive, + uploadFilesToS3, +} from '../../lib/common'; import { DeployToEnvironment, IDeploymentFilters } from '../../types/hosting'; import { ApillonLogger } from '../../index'; import { IApillonList, LogLevel } from '../../types/apillon'; @@ -61,7 +65,12 @@ export class HostingWebsite { * @param uuid Unique identifier of the website. * @param api Axios instance set to correct rootUrl with correct error handling. */ - constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string, data?: Partial) { + constructor( + api: AxiosInstance, + logger: ApillonLogger, + uuid: string, + data?: Partial, + ) { this.api = api; this.uuid = uuid; this.logger = logger; @@ -145,9 +154,10 @@ export class HostingWebsite { */ public async deploy(toEnvironment: DeployToEnvironment): Promise { this.logger.log( - `Deploying website ${this.uuid} to IPFS (${toEnvironment === DeployToEnvironment.TO_STAGING - ? 'preview' - : 'production' + `Deploying website ${this.uuid} to IPFS (${ + toEnvironment === DeployToEnvironment.TO_STAGING + ? 'preview' + : 'production' })`, LogLevel.VERBOSE, ); @@ -167,17 +177,29 @@ export class HostingWebsite { * @param {IWebsiteFilters} params Query filters for listing websites * @returns A list of all deployments instances. */ - public async listDeployments(params?: IDeploymentFilters): Promise> { - const url = constructUrlWithQueryParams(`${this.API_PREFIX}/deployments`, params); + public async listDeployments( + params?: IDeploymentFilters, + ): Promise> { + const url = constructUrlWithQueryParams( + `${this.API_PREFIX}/deployments`, + params, + ); const { data } = await this.api.get(url); return { items: data.data.items.map( - item => new Deployment(this.api, this.logger, item.websiteUuid, item.deploymentUuid, item) + (item) => + new Deployment( + this.api, + this.logger, + item.websiteUuid, + item.deploymentUuid, + item, + ), ), - total: data.data.total - } + total: data.data.total, + }; } /** diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 2ef978e..1100031 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -15,16 +15,26 @@ export class Hosting extends ApillonModule { * @param {IWebsiteFilters} params Query filters for listing websites * @returns A list of HostingWebsite instances. */ - public async listWebsites(params?: IWebsiteFilters): Promise> { + public async listWebsites( + params?: IWebsiteFilters, + ): Promise> { const url = constructUrlWithQueryParams(this.API_PREFIX, params); - const { data } = await this.api.get>(url); + const { data } = await this.api.get>( + url, + ); return { items: data.data.items.map( - website => new HostingWebsite(this.api, this.logger, website['websiteUuid'], website) + (website) => + new HostingWebsite( + this.api, + this.logger, + website['websiteUuid'], + website, + ), ), - total: data.data.total + total: data.data.total, }; } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index bb7a0d3..3413599 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -181,10 +181,9 @@ export class NftCollection { * @returns Call status. */ public async mint(receiver: string, quantity: number) { - const { data } = await this.api.post>( - `${this.API_PREFIX}/mint`, - { receivingAddress: receiver, quantity }, - ); + const { data } = await this.api.post< + IApillonResponse + >(`${this.API_PREFIX}/mint`, { receivingAddress: receiver, quantity }); return data?.data; } diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 9df56c9..9dc7f4d 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -1,6 +1,6 @@ import { ApillonModule } from '../../lib/apillon'; import { constructUrlWithQueryParams } from '../../lib/common'; -import { IApillonResponse, IApillonList, IApillonListResponse } from '../../types/apillon'; +import { IApillonResponse, IApillonListResponse } from '../../types/apillon'; import { ICollectionFilters, ICollection, @@ -33,7 +33,10 @@ export class Nft extends ApillonModule { const { data } = await this.api.get>(url); - return data.data.items.map(nft => new NftCollection(this.api, this.logger, nft.collectionUuid, nft)); + return data.data.items.map( + (nft) => + new NftCollection(this.api, this.logger, nft.collectionUuid, nft), + ); } /** @@ -42,10 +45,9 @@ export class Nft extends ApillonModule { * @returns A NftCollection instance. */ public async create(data: ICreateCollection) { - const { data: response } = await this.api.post>( - this.API_PREFIX, - data, - ); + const { data: response } = await this.api.post< + IApillonResponse + >(this.API_PREFIX, data); return new NftCollection( this.api, diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index d8cb012..5673689 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -1,5 +1,8 @@ import { AxiosInstance } from 'axios'; -import { IStorageBucketContentRequest, StorageContentType } from '../../types/storage'; +import { + IStorageBucketContentRequest, + StorageContentType, +} from '../../types/storage'; import { File } from './file'; import { ApillonLogger } from '../../lib/apillon'; import { constructUrlWithQueryParams } from '../../lib/common'; @@ -89,7 +92,9 @@ export class Directory { /** * @dev Gets contents of a directory. */ - async get(params: IStorageBucketContentRequest = {}): Promise<(Directory | File)[]> { + async get( + params: IStorageBucketContentRequest = {}, + ): Promise<(Directory | File)[]> { this.content = []; params.directoryUuid = this.uuid; const url = constructUrlWithQueryParams( diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 4d3e5b8..357cda5 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -6,7 +6,11 @@ import { StorageContentType, } from '../../types/storage'; import { File } from './file'; -import { constructUrlWithQueryParams, listFilesRecursive, uploadFilesToS3 } from '../../lib/common'; +import { + constructUrlWithQueryParams, + listFilesRecursive, + uploadFilesToS3, +} from '../../lib/common'; import { ApillonLogger } from '../../docs-index'; import { IApillonList, IApillonListResponse } from '../../types/apillon'; @@ -57,7 +61,12 @@ export class StorageBucket { * @param api Axios instance set to correct rootUrl with correct error handling. * @param data Data to populate storage bucket */ - constructor(api: AxiosInstance, logger: ApillonLogger, uuid: string, data?: Partial) { + constructor( + api: AxiosInstance, + logger: ApillonLogger, + uuid: string, + data?: Partial, + ) { this.api = api; this.logger = logger; this.uuid = uuid; @@ -83,7 +92,9 @@ export class StorageBucket { /** * @dev Gets contents of a bucket. */ - async getObjects(params?: IStorageBucketContentRequest): Promise> { + async getObjects( + params?: IStorageBucketContentRequest, + ): Promise> { const content = []; const url = constructUrlWithQueryParams( `${this.API_PREFIX}/content`, @@ -100,10 +111,17 @@ export class StorageBucket { item.uuid, item.directoryUuid, item, - )); + ), + ); } else { - const directory = new Directory(this.api, this.logger, this.uuid, item.uuid, item); - content.push(directory, ...await directory.get()); + const directory = new Directory( + this.api, + this.logger, + this.uuid, + item.uuid, + item, + ); + content.push(directory, ...(await directory.get())); } } this.content = content; @@ -122,15 +140,18 @@ export class StorageBucket { return { total: data.data.total, - items: data.data.items.map(file => new File( - this.api, - this.logger, - this.uuid, - file.uuid, - file.directoryUuid, - file, - )) - } + items: data.data.items.map( + (file) => + new File( + this.api, + this.logger, + this.uuid, + file.uuid, + file.directoryUuid, + file, + ), + ), + }; } /** @@ -152,10 +173,14 @@ export class StorageBucket { console.log(`Files to upload: ${files.length}`); console.time('Got upload links'); - const { data } = await this.api.post(`${this.API_PREFIX}/upload`, { files }); + const { data } = await this.api.post(`${this.API_PREFIX}/upload`, { + files, + }); console.timeEnd('Got upload links'); - const uploadLinks = data.data.files.sort((a, b) => a.fileName.localeCompare(b.fileName)); + const uploadLinks = data.data.files.sort((a, b) => + a.fileName.localeCompare(b.fileName), + ); // Divide files into chunks for parallel processing and uploading const chunkSize = 10; const fileChunks = []; @@ -164,7 +189,11 @@ export class StorageBucket { const chunkLinks = uploadLinks.slice(i, i + chunkSize); fileChunks.push({ chunkFiles, chunkLinks }); } - await Promise.all(fileChunks.map(({ chunkFiles, chunkLinks }) => uploadFilesToS3(chunkLinks, chunkFiles))); + await Promise.all( + fileChunks.map(({ chunkFiles, chunkLinks }) => + uploadFilesToS3(chunkLinks, chunkFiles), + ), + ); console.log('Closing session...'); const respEndSession = await this.api.post( diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index ebf44f6..006182d 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -6,8 +6,8 @@ import { StorageBucket } from './storage-bucket'; export class Storage extends ApillonModule { /** - * @dev API url for storage. - */ + * @dev API url for storage. + */ private API_PREFIX = '/storage/buckets'; /** @@ -15,16 +15,19 @@ export class Storage extends ApillonModule { * @param {ICollectionFilters} params Filter for listing collections. * @returns Array of NftCollection. */ - public async listBuckets(params?: IApillonPagination): Promise> { + public async listBuckets( + params?: IApillonPagination, + ): Promise> { const url = constructUrlWithQueryParams(this.API_PREFIX, params); const { data } = await this.api.get>(url); return { items: data.data.items.map( - bucket => new StorageBucket(this.api, this.logger, bucket.bucketUuid, bucket) + (bucket) => + new StorageBucket(this.api, this.logger, bucket.bucketUuid, bucket), ), - total: data.data.total + total: data.data.total, }; } diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index 693be75..c7051d2 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -4,7 +4,6 @@ import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; import { HostingWebsite } from '../modules/hosting/hosting-website'; -import { Deployment } from '../modules/hosting/deployment'; describe('Hosting tests', () => { let config: ApillonConfig; @@ -53,15 +52,21 @@ describe('Hosting tests', () => { const hosting = new Hosting(config); const website = hosting.website(websiteUUID); - const { items } = await website.listDeployments({ environment: DeployToEnvironment.TO_STAGING }); - expect(items.every(d => d.environment === DeployToEnvironment.TO_STAGING)); + const { items } = await website.listDeployments({ + environment: DeployToEnvironment.TO_STAGING, + }); + expect( + items.every((d) => d.environment === DeployToEnvironment.TO_STAGING), + ); }); test('get deployment status', async () => { const hosting = new Hosting(config); const website = hosting.website(websiteUUID); - const deployment = await website.deployment('e21a8e4e-bfce-4e63-b65b-59404d4fc6b4').get(); + const deployment = await website + .deployment('e21a8e4e-bfce-4e63-b65b-59404d4fc6b4') + .get(); expect(deployment.environment).toEqual(DeployToEnvironment.TO_STAGING); }); }); diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index d3f6cde..bc04b1e 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -16,7 +16,7 @@ describe('Storage tests', () => { test('List buckets', async () => { const { items } = await new Storage(config).listBuckets({ limit: 1 }); expect(items.length).toBeGreaterThanOrEqual(0); - items.forEach(item => expect(item.name).toBeTruthy()); + items.forEach((item) => expect(item.name).toBeTruthy()); }); test('get bucket content', async () => { @@ -29,7 +29,7 @@ describe('Storage tests', () => { console.log(`${item.type}: ${item.name}`); } expect(items.length).toBeGreaterThanOrEqual(0); - items.forEach(item => expect(item.name).toBeTruthy()); + items.forEach((item) => expect(item.name).toBeTruthy()); }); test('get bucket files', async () => { @@ -39,13 +39,15 @@ describe('Storage tests', () => { console.log(`${item.type}: ${item.name}`); } expect(items.length).toBeGreaterThanOrEqual(0); - items.forEach(item => expect(item.name).toBeTruthy()); + items.forEach((item) => expect(item.name).toBeTruthy()); }); test('get bucket files markedForDeletion=true', async () => { const storage = new Storage(config); - const { items } = await storage.bucket(bucketUUID).getObjects({ markedForDeletion: true }); - expect(items.some(file => file['status'] == 8)) + const { items } = await storage + .bucket(bucketUUID) + .getObjects({ markedForDeletion: true }); + expect(items.some((file) => file['status'] == 8)); }); test('get bucket directory content', async () => { @@ -60,12 +62,15 @@ describe('Storage tests', () => { } console.log(`${item.type}: ${item.name}`); } - items.forEach(item => expect(item.name).toBeTruthy()); + items.forEach((item) => expect(item.name).toBeTruthy()); }); test('get file details', async () => { const storage = new Storage(config); - const file = await storage.bucket(bucketUUID).file('cf6a0d3d-2abd-4a0d-85c1-10b8f04cd4fc').get(); + const file = await storage + .bucket(bucketUUID) + .file('cf6a0d3d-2abd-4a0d-85c1-10b8f04cd4fc') + .get(); expect(file.name).toBeTruthy(); }); @@ -74,9 +79,7 @@ describe('Storage tests', () => { try { const uploadDir = resolve(__dirname, './helpers/website/'); console.time('File upload complete'); - await storage - .bucket(bucketUUID) - .uploadFromFolder(uploadDir); + await storage.bucket(bucketUUID).uploadFromFolder(uploadDir); console.timeEnd('File upload complete'); // console.log(content); @@ -87,6 +90,8 @@ describe('Storage tests', () => { test.skip('delete a file', async () => { const storage = new Storage(config); - await storage.bucket(bucketUUID).deleteFile('cf6a0d3d-2abd-4a0d-85c1-10b8f04cd4fc'); + await storage + .bucket(bucketUUID) + .deleteFile('cf6a0d3d-2abd-4a0d-85c1-10b8f04cd4fc'); }); }); diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index 9a822ca..2233ffe 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -13,7 +13,9 @@ export interface IApillonStatus { status: number; } -export interface IApillonListResponse extends IApillonResponse> { } +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface IApillonListResponse + extends IApillonResponse> {} export interface IApillonBoolResponse { success: boolean; diff --git a/packages/sdk/src/types/hosting.ts b/packages/sdk/src/types/hosting.ts index d516fed..2481f1c 100644 --- a/packages/sdk/src/types/hosting.ts +++ b/packages/sdk/src/types/hosting.ts @@ -1,4 +1,4 @@ -import { IApillonPagination } from "./generic"; +import { IApillonPagination } from './generic'; export enum DeployToEnvironment { TO_STAGING = 1, @@ -20,4 +20,4 @@ export interface IWebsiteFilters extends IApillonPagination { export interface IDeploymentFilters extends IApillonPagination { deploymentStatus?: DeploymentStatus; environment?: DeployToEnvironment; -} \ No newline at end of file +} diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index 1a7b898..26a9fe3 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -1,4 +1,4 @@ -import { IApillonPagination } from "./generic"; +import { IApillonPagination } from './generic'; export enum StorageContentType { FILE = 2, From 736fba49e62ae82898f931c48432909bb08253ef Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 27 Oct 2023 09:42:42 +0200 Subject: [PATCH 27/68] Implement hosting CLI commands --- packages/cli/src/lib/types.ts | 3 +- .../src/modules/hosting/hosting.commands.ts | 74 +++++++++++++++++-- .../src/modules/hosting/hosting.service.ts | 73 +++++++++++------- 3 files changed, 116 insertions(+), 34 deletions(-) diff --git a/packages/cli/src/lib/types.ts b/packages/cli/src/lib/types.ts index 7265fe8..3b636a8 100644 --- a/packages/cli/src/lib/types.ts +++ b/packages/cli/src/lib/types.ts @@ -1,9 +1,10 @@ export interface Options { - [Key: string]: string; + [key: string]: string; } export interface GlobalOptions { key: string; secret: string; apiUrl?: string; + [key: string]: string; } diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index e9636e5..580e88d 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -1,15 +1,75 @@ -import { Command } from 'commander'; -import { deployWebsite } from './hosting.service'; +import { Command, Option } from 'commander'; +import { addPaginationOptions } from '../../lib/options'; +import { + deployToEnvironment, + getDeployment, + getWebsite, + listDeployments, + listWebsites, + uploadWebsiteFiles, +} from './hosting.service'; export function createHostingCommands(cli: Command) { const hosting = cli.command('hosting'); - const hostingDeploy = hosting - .command('deploy-website') + const hostingList = hosting + .command('list-websites') + .action(async function () { + await listWebsites(this.optsWithGlobals()); + }); + addPaginationOptions(hostingList); + + hosting + .command('get-website') + .requiredOption('--uuid ', 'UUID of website to get') + .action(async function () { + await getWebsite(this.optsWithGlobals()); + }); + + hosting + .command('upload-files') .argument('', 'path to folder with website files') + .requiredOption( + '--uuid ', + 'UUID of website to upload files to', + ) + .action(async function (path: string) { + await uploadWebsiteFiles(path, this.optsWithGlobals()); + }); + + hosting + .command('deploy') .requiredOption('--uuid ', 'UUID of website to deploy') - .option('-p, --preview', 'deploys to staging environment') - .action(async function (path) { - await deployWebsite(path, this.optsWithGlobals()); + .addOption( + new Option('--env ', 'Environment to deploy to') + .choices(['1', '2', '3']) + .makeOptionMandatory(true), + ) + .action(async function () { + await deployToEnvironment(this.optsWithGlobals()); + }); + + const hostingListDeployments = hosting + .command('list-deployments') + .requiredOption( + '--uuid ', + 'UUID of website to list deployments for', + ) + .option('--env ', 'deployment status') + .action(async function () { + await listDeployments(this.optsWithGlobals()); + }); + addPaginationOptions(hostingListDeployments); + + hosting + .command('get-deployment') + .requiredOption('--uuid ', 'UUID of website') + .requiredOption( + '--deployment-uuid ', + 'UUID of deployment to get', + ) + .action(async function () { + await getDeployment(this.optsWithGlobals()); }); } diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index a8570a9..5b8068f 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -1,31 +1,52 @@ -import { DeployToEnvironment, Hosting } from '@apillon/sdk'; +import { Hosting } from '@apillon/sdk'; +import { GlobalOptions } from '../../lib/types'; -export async function deployWebsite( +export async function listWebsites(optsWithGlobals: GlobalOptions) { + const hosting = new Hosting(optsWithGlobals); + const { items: websites } = await hosting.listWebsites(); + console.log(websites); +} + +export async function getWebsite(optsWithGlobals: GlobalOptions) { + const hosting = new Hosting(optsWithGlobals); + const website = await hosting.website(optsWithGlobals.uuid).get(); + console.log(website); +} + +export async function uploadWebsiteFiles( path: string, - options: { - uuid: string; - preview?: boolean; - key: string; - secret: string; - apiUrl?: string; - }, + optsWithGlobals: GlobalOptions, ) { - const hosting = new Hosting({ - key: options.key, - secret: options.secret, - apiUrl: options?.apiUrl || undefined, - }); + const hosting = new Hosting(optsWithGlobals); + console.log(optsWithGlobals.uuid); + await hosting.website(optsWithGlobals.uuid).uploadFromFolder(path); +} + +export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { + const hosting = new Hosting(optsWithGlobals); + await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); +} + +export async function listDeployments(optsWithGlobals: GlobalOptions) { + const hosting = new Hosting(optsWithGlobals); + const params = + optsWithGlobals.env || optsWithGlobals.status + ? { + environment: +optsWithGlobals.env, + deploymentStatus: +optsWithGlobals.status, + } + : null; + const { items: deployments } = await hosting + .website(optsWithGlobals.uuid) + .listDeployments(params); + console.log(deployments); +} - await hosting.uploadFromFolder(options.uuid, path); - const deployment = await hosting.deployWebsite( - options.uuid, - options.preview - ? DeployToEnvironment.TO_STAGING - : DeployToEnvironment.DIRECTLY_TO_PRODUCTION, - ); - const deploymentData = await hosting.getWebsiteDeployments( - options.uuid, - deployment.id, - ); - console.log(deploymentData); +export async function getDeployment(optsWithGlobals: GlobalOptions) { + const hosting = new Hosting(optsWithGlobals); + const deployment = await hosting + .website(optsWithGlobals.uuid) + .deployment(optsWithGlobals.deploymentUuid) + .get(); + console.log(deployment); } From 03480387cdfcbab4a57c3f5fe67ef9705ef29219 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 27 Oct 2023 10:19:01 +0200 Subject: [PATCH 28/68] Implement storage CLI commands --- packages/cli/src/index.ts | 3 +- .../src/modules/hosting/hosting.service.ts | 2 +- .../src/modules/storage/storage.commands.ts | 74 +++++++++++++------ .../src/modules/storage/storage.service.ts | 49 ++++++++++++ 4 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 packages/cli/src/modules/storage/storage.service.ts diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 24f6772..76fcf22 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -5,6 +5,7 @@ import { Command, Option } from 'commander'; import config from './config'; import { createHostingCommands } from './modules/hosting/hosting.commands'; import { createNftsCommands } from './modules/nfts/nfts.commands'; +import { createStorageCommands } from './modules/storage/storage.commands'; const cli = new Command('apillon').version(config.VERSION); cli.addHelpText( @@ -41,8 +42,8 @@ cli.configureHelp({ cli.showHelpAfterError('Run with --help for additional information!'); +createStorageCommands(cli); createHostingCommands(cli); -// const storage = createStorageCommands(cli); createNftsCommands(cli); cli.parse(); diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index 5b8068f..d96513b 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -18,13 +18,13 @@ export async function uploadWebsiteFiles( optsWithGlobals: GlobalOptions, ) { const hosting = new Hosting(optsWithGlobals); - console.log(optsWithGlobals.uuid); await hosting.website(optsWithGlobals.uuid).uploadFromFolder(path); } export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); + console.log('Deploy successful'); } export async function listDeployments(optsWithGlobals: GlobalOptions) { diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index daa4d1d..410f6ed 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -1,32 +1,60 @@ import { Command } from 'commander'; +import { addPaginationOptions } from '../../lib/options'; +import { + listBuckets, + getObjects, + getFiles, + uploadFromFolder, + file, + deleteFile, +} from './storage.service'; export function createStorageCommands(cli: Command) { const storage = cli.command('storage'); - const storageUploadFolder = storage - .command('upload-folder') - // .requiredOption('-d , --dir ', 'folder with website files') - .argument('[path]', 'path to folder with website files', '.') - .option('-p, --preview', 'deploys to staging environment') - .action(uploadFolder); + storage.command('list-buckets').action(async function () { + await listBuckets(this.optsWithGlobals()); + }); + addPaginationOptions(storage); - const storageUploadFiles = storage - .command('upload-files') - // .requiredOption('-d , --dir ', 'folder with website files') - .argument('[path]', 'path to folder with website files', '.') - .option('-p, --preview', 'deploys to staging environment') - .action(uploadFiles); -} + storage + .command('get-objects') + .requiredOption( + '--uuid ', + 'UUID of bucket to get objects from', + ) + .action(async function () { + await getObjects(this.optsWithGlobals()); + }); -function uploadFolder(path: string) { - console.log(path); - console.log(this.opts().preview); - throw Error('Command not implemented!'); -} + storage + .command('get-files') + .requiredOption('--uuid ', 'UUID of bucket to get files from') + .action(async function () { + await getFiles(this.optsWithGlobals()); + }); + + storage + .command('upload') + .argument('', 'path to folder with files') + .requiredOption('--uuid ', 'UUID of bucket to upload files to') + .action(async function (path: string) { + await uploadFromFolder(path, this.optsWithGlobals()); + }); + + storage + .command('file') + .requiredOption('--uuid ', 'UUID of bucket') + .requiredOption('--file-uuid ', 'UUID of file to get') + .action(async function () { + await file(this.optsWithGlobals()); + }); -// eslint-disable-next-line sonarjs/no-identical-functions -function uploadFiles(path: string) { - console.log(path); - console.log(this.opts().preview); - throw Error('Command not implemented!'); + storage + .command('delete-file') + .requiredOption('--uuid ', 'UUID of bucket') + .requiredOption('--file-uuid ', 'UUID of file to delete') + .action(async function () { + await deleteFile(this.optsWithGlobals()); + }); } diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts new file mode 100644 index 0000000..3441d30 --- /dev/null +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -0,0 +1,49 @@ +import { Storage } from '@apillon/sdk'; +import { GlobalOptions } from '../../lib/types'; + +export async function listBuckets(optsWithGlobals: GlobalOptions) { + const storage = new Storage(optsWithGlobals); + const { items: buckets } = await storage.listBuckets(); + console.log(buckets); +} + +export async function getObjects(optsWithGlobals: GlobalOptions) { + const storage = new Storage(optsWithGlobals); + const { items: objects } = await storage + .bucket(optsWithGlobals.uuid) + .getObjects(); + console.log(objects); +} + +export async function getFiles(optsWithGlobals: GlobalOptions) { + const storage = new Storage(optsWithGlobals); + const { items: files } = await storage + .bucket(optsWithGlobals.uuid) + .getFiles(); + console.log(files); +} + +export async function uploadFromFolder( + path: string, + optsWithGlobals: GlobalOptions, +) { + const storage = new Storage(optsWithGlobals); + await storage.bucket(optsWithGlobals.uuid).uploadFromFolder(path); +} + +export async function file(optsWithGlobals: GlobalOptions) { + const storage = new Storage(optsWithGlobals); + const file = await storage + .bucket(optsWithGlobals.uuid) + .file(optsWithGlobals.fileUuid) + .get(); + console.log(file); +} + +export async function deleteFile(optsWithGlobals: GlobalOptions) { + const storage = new Storage(optsWithGlobals); + await storage + .bucket(optsWithGlobals.uuid) + .deleteFile(optsWithGlobals.fileUuid); + console.log('File deleted successfully'); +} From aeba74c25c8611cc3aea9678b83dcfc6e0ed6776 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 27 Oct 2023 10:20:32 +0200 Subject: [PATCH 29/68] Add CLI storage/hosting exception handling --- .../src/modules/hosting/hosting.service.ts | 58 +++++++++++----- .../src/modules/storage/storage.service.ts | 66 +++++++++++++------ 2 files changed, 86 insertions(+), 38 deletions(-) diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index d96513b..42fd1c1 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -1,16 +1,24 @@ -import { Hosting } from '@apillon/sdk'; +import { Hosting, exceptionHandler } from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; export async function listWebsites(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); - const { items: websites } = await hosting.listWebsites(); - console.log(websites); + try { + const { items: websites } = await hosting.listWebsites(); + console.log(websites); + } catch (err) { + exceptionHandler(err); + } } export async function getWebsite(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); - const website = await hosting.website(optsWithGlobals.uuid).get(); - console.log(website); + try { + const website = await hosting.website(optsWithGlobals.uuid).get(); + console.log(website); + } catch (err) { + exceptionHandler(err); + } } export async function uploadWebsiteFiles( @@ -18,13 +26,21 @@ export async function uploadWebsiteFiles( optsWithGlobals: GlobalOptions, ) { const hosting = new Hosting(optsWithGlobals); - await hosting.website(optsWithGlobals.uuid).uploadFromFolder(path); + try { + await hosting.website(optsWithGlobals.uuid).uploadFromFolder(path); + } catch (err) { + exceptionHandler(err); + } } export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); - await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); - console.log('Deploy successful'); + try { + await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); + console.log('Deploy successful'); + } catch (err) { + exceptionHandler(err); + } } export async function listDeployments(optsWithGlobals: GlobalOptions) { @@ -36,17 +52,25 @@ export async function listDeployments(optsWithGlobals: GlobalOptions) { deploymentStatus: +optsWithGlobals.status, } : null; - const { items: deployments } = await hosting - .website(optsWithGlobals.uuid) - .listDeployments(params); - console.log(deployments); + try { + const { items: deployments } = await hosting + .website(optsWithGlobals.uuid) + .listDeployments(params); + console.log(deployments); + } catch (err) { + exceptionHandler(err); + } } export async function getDeployment(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); - const deployment = await hosting - .website(optsWithGlobals.uuid) - .deployment(optsWithGlobals.deploymentUuid) - .get(); - console.log(deployment); + try { + const deployment = await hosting + .website(optsWithGlobals.uuid) + .deployment(optsWithGlobals.deploymentUuid) + .get(); + console.log(deployment); + } catch (err) { + exceptionHandler(err); + } } diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index 3441d30..ebe7d18 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -1,26 +1,38 @@ -import { Storage } from '@apillon/sdk'; +import { Storage, exceptionHandler } from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; export async function listBuckets(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); - const { items: buckets } = await storage.listBuckets(); - console.log(buckets); + try { + const { items: buckets } = await storage.listBuckets(); + console.log(buckets); + } catch (err) { + exceptionHandler(err); + } } export async function getObjects(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); - const { items: objects } = await storage - .bucket(optsWithGlobals.uuid) - .getObjects(); - console.log(objects); + try { + const { items: objects } = await storage + .bucket(optsWithGlobals.uuid) + .getObjects(); + console.log(objects); + } catch (err) { + exceptionHandler(err); + } } export async function getFiles(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); - const { items: files } = await storage - .bucket(optsWithGlobals.uuid) - .getFiles(); - console.log(files); + try { + const { items: files } = await storage + .bucket(optsWithGlobals.uuid) + .getFiles(); + console.log(files); + } catch (err) { + exceptionHandler(err); + } } export async function uploadFromFolder( @@ -28,22 +40,34 @@ export async function uploadFromFolder( optsWithGlobals: GlobalOptions, ) { const storage = new Storage(optsWithGlobals); - await storage.bucket(optsWithGlobals.uuid).uploadFromFolder(path); + try { + await storage.bucket(optsWithGlobals.uuid).uploadFromFolder(path); + } catch (err) { + exceptionHandler(err); + } } export async function file(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); - const file = await storage - .bucket(optsWithGlobals.uuid) - .file(optsWithGlobals.fileUuid) - .get(); - console.log(file); + try { + const file = await storage + .bucket(optsWithGlobals.uuid) + .file(optsWithGlobals.fileUuid) + .get(); + console.log(file); + } catch (err) { + exceptionHandler(err); + } } export async function deleteFile(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); - await storage - .bucket(optsWithGlobals.uuid) - .deleteFile(optsWithGlobals.fileUuid); - console.log('File deleted successfully'); + try { + await storage + .bucket(optsWithGlobals.uuid) + .deleteFile(optsWithGlobals.fileUuid); + console.log('File deleted successfully'); + } catch (err) { + exceptionHandler(err); + } } From bdf7186646423b173ac243554de1ed143196d87e Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 27 Oct 2023 12:09:42 +0200 Subject: [PATCH 30/68] Refactor/cleanup: API and Logger singleton instances --- packages/sdk/src/lib/apillon-api.ts | 82 +++++++++++ packages/sdk/src/lib/apillon-logger.ts | 29 ++++ packages/sdk/src/lib/apillon.ts | 105 +++++--------- packages/sdk/src/lib/common.ts | 5 +- .../sdk/src/modules/hosting/deployment.ts | 64 ++------- .../src/modules/hosting/hosting-website.ts | 128 +++++++----------- packages/sdk/src/modules/hosting/hosting.ts | 13 +- .../sdk/src/modules/nft/nft-collection.ts | 70 +++------- packages/sdk/src/modules/nft/nft.ts | 19 ++- packages/sdk/src/modules/storage/directory.ts | 84 +++--------- packages/sdk/src/modules/storage/file.ts | 34 ++--- .../sdk/src/modules/storage/storage-bucket.ts | 117 +++++----------- packages/sdk/src/modules/storage/storage.ts | 14 +- packages/sdk/src/tests/storage.test.ts | 2 +- 14 files changed, 307 insertions(+), 459 deletions(-) create mode 100644 packages/sdk/src/lib/apillon-api.ts create mode 100644 packages/sdk/src/lib/apillon-logger.ts diff --git a/packages/sdk/src/lib/apillon-api.ts b/packages/sdk/src/lib/apillon-api.ts new file mode 100644 index 0000000..2553834 --- /dev/null +++ b/packages/sdk/src/lib/apillon-api.ts @@ -0,0 +1,82 @@ +import axios, { AxiosInstance, AxiosResponse } from 'axios'; +import { ApillonConfig } from './apillon'; +import { LogLevel } from '../types/apillon'; +import { ApillonLogger } from './apillon-logger'; +import { + ApillonApiError, + ApillonNetworkError, + ApillonRequestError, +} from './common'; + +export class ApillonApi { + private static instance: AxiosInstance; + + public static initialize(apiConfig?: ApillonConfig) { + const defaultOptions: ApillonConfig = { + key: process.env.APILLON_API_KEY, + secret: process.env.APILLON_API_SECRET, + apiUrl: process.env.APILLON_API_URL || 'https://api.apillon.io', + logLevel: LogLevel.NONE, + }; + + const config = { ...defaultOptions, ...apiConfig }; + + const auth = + config.key && config.secret + ? { + username: config.key, + password: config.secret, + } + : undefined; + + this.instance = axios.create({ + baseURL: config.apiUrl, + headers: { 'content-type': 'application/json' }, + auth, + }); + + this.instance.interceptors.request.use( + (request) => request, + (error) => { + ApillonLogger.log(error, LogLevel.ERROR); + throw new ApillonRequestError(error.request); + }, + ); + + this.instance.interceptors.response.use( + (response) => response, + (error) => { + ApillonLogger.log(error, LogLevel.ERROR); + if (error.response?.data) { + throw new ApillonApiError( + JSON.stringify(error.response.data, null, 2), + ); + } else { + throw new ApillonNetworkError(error.message); + } + }, + ); + } + + public static async get( + url: string, + config?: any, + ): Promise> { + return this.instance.get(url, config); + } + + public static async post( + url: string, + data?: any, + config?: any, + ): Promise> { + return this.instance.post(url, data, config); + } + + public static async delete( + url: string, + config?: any, + ): Promise> { + return this.instance.delete(url, config); + } +} diff --git a/packages/sdk/src/lib/apillon-logger.ts b/packages/sdk/src/lib/apillon-logger.ts new file mode 100644 index 0000000..1f42ff4 --- /dev/null +++ b/packages/sdk/src/lib/apillon-logger.ts @@ -0,0 +1,29 @@ +import { LogLevel } from '../types/apillon'; + +export class ApillonLogger { + private static logLevel: LogLevel = LogLevel.NONE; + + public static initialize(logLevel?: LogLevel) { + this.logLevel = logLevel || LogLevel.NONE; + } + + static log(message: any, logLevel: LogLevel) { + if (this.logLevel >= logLevel) { + if (message instanceof Object) { + console.log(JSON.stringify(message)); + } else { + console.log(message); + } + } + } + + static logWithTime(message: any, logLevel: LogLevel) { + if (this.logLevel >= logLevel) { + if (message instanceof Object) { + console.log(`${new Date().toISOString()}: `, JSON.stringify(message)); + } else { + console.log(`${new Date().toISOString()}: `, message); + } + } + } +} diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 8d7c8a5..d5d05fc 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -1,5 +1,6 @@ -import axios, { AxiosInstance } from 'axios'; import { LogLevel } from '../types/apillon'; +import { ApillonApi } from './apillon-api'; +import { ApillonLogger } from './apillon-logger'; export interface ApillonConfig { key?: string; @@ -8,92 +9,50 @@ export interface ApillonConfig { logLevel?: LogLevel; } -export class ApillonApiError extends Error {} -export class ApillonRequestError extends Error {} -export class ApillonNetworkError extends Error {} - export class ApillonModule { - protected api: AxiosInstance; - protected logger: ApillonLogger; - private config: ApillonConfig; - public constructor(config?: ApillonConfig) { - const defaultOptions: ApillonConfig = { + const defaultConfig: ApillonConfig = { key: process.env.APILLON_API_KEY, secret: process.env.APILLON_API_SECRET, apiUrl: process.env.APILLON_API_URL || 'https://api.apillon.io', logLevel: LogLevel.NONE, }; - this.config = { ...defaultOptions, ...config }; - this.logger = new ApillonLogger(this.config.logLevel); - - let auth = undefined; - if (this.config.key && this.config.secret) { - auth = { - username: this.config.key, - password: this.config.secret, - }; - } - - this.api = axios.create({ - baseURL: this.config.apiUrl, - headers: { - 'content-type': 'application/json', - }, - auth, - }); - - this.api.interceptors.request.use( - (config) => { - return config; - }, - (error) => { - this.logger.log(error, LogLevel.ERROR); - throw new ApillonRequestError(error.request); - }, - ); + const mergedConfig = { ...defaultConfig, ...config }; - this.api.interceptors.response.use( - (response) => { - return response; - }, - (error) => { - this.logger.log(error, LogLevel.ERROR); - if (error.response?.data) { - throw new ApillonApiError( - JSON.stringify(error.response.data, null, 2), - ); - } else { - throw new ApillonNetworkError(error.message); - } - }, - ); + ApillonApi.initialize(mergedConfig); + ApillonLogger.initialize(mergedConfig.logLevel); } } -export class ApillonLogger { - private logLevel: LogLevel = LogLevel.NONE; - constructor(logLevel?: LogLevel) { - this.logLevel = logLevel || LogLevel.NONE; - } +export class ApillonModel { + /** + * @dev API url prefix for this class. + */ + protected API_PREFIX: string = null; - log(message: any, logLevel: LogLevel) { - if (this.logLevel >= logLevel) { - if (message instanceof Object) { - console.log(JSON.stringify(message)); - } else { - console.log(message); - } - } + /** + * @dev Unique identifier of the model. + */ + public uuid: string; + + constructor(uuid: string) { + this.uuid = uuid; } - logWithTime(message: any, logLevel: LogLevel) { - if (this.logLevel >= logLevel) { - if (message instanceof Object) { - console.log(`${new Date().toISOString()}: `, JSON.stringify(message)); - } else { - console.log(`${new Date().toISOString()}: `, message); - } + + /** + * Populates class properties via data object. + * @param data Data object. + */ + protected populate(data: any) { + if (data != null) { + Object.keys(data || {}).forEach((key) => { + const prop = this[key]; + if (prop === null) { + this[key] = data[key]; + } + }); } + return this; } } diff --git a/packages/sdk/src/lib/common.ts b/packages/sdk/src/lib/common.ts index ccb9151..ba90205 100644 --- a/packages/sdk/src/lib/common.ts +++ b/packages/sdk/src/lib/common.ts @@ -2,7 +2,10 @@ import * as fs from 'fs'; import * as path from 'path'; import axios from 'axios'; -import { ApillonApiError, ApillonNetworkError } from './apillon'; + +export class ApillonApiError extends Error {} +export class ApillonRequestError extends Error {} +export class ApillonNetworkError extends Error {} /** * Convert value to boolean if defined, else return undefined. diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index 86fa285..100898f 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -1,34 +1,15 @@ -import { AxiosInstance } from 'axios'; -import { ApillonLogger } from '../../lib/apillon'; +import { ApillonModel } from '../../lib/apillon'; import { DeployToEnvironment, DeploymentStatus } from '../../docs-index'; -import { LogLevel } from '../../types/apillon'; - -export class Deployment { - /** - * Axios instance set to correct rootUrl with correct error handling. - */ - protected api: AxiosInstance; - - /** - * Logger. - */ - protected logger: ApillonLogger; - - /** - * @dev API url prefix for this class. - */ - private API_PREFIX: string = null; +import { IApillonResponse, LogLevel } from '../../types/apillon'; +import { ApillonApi } from '../../lib/apillon-api'; +import { ApillonLogger } from '../../lib/apillon-logger'; +export class Deployment extends ApillonModel { /** * @dev Unique identifier of the website. */ public websiteUuid: string = null; - /** - * @dev Unique identifier of the deployment. - */ - public uuid: string = null; - /** * IPFS CID for the deployment. */ @@ -61,49 +42,32 @@ export class Deployment { /** * @dev Constructor which should only be called via HostingWebsite class. - * @param uuid Unique identifier of the deployment. - * @param api Axios instance set to correct rootUrl with correct error handling. + * @param websiteUuid Unique identifier of the deployment's website. + * @param deploymentUuid Unique identifier of the deployment. + * @param data Data to populate the deployment with. */ constructor( - api: AxiosInstance, - logger: ApillonLogger, websiteUuid: string, deploymentUuid: string, - data: any, + data: Partial, ) { - this.api = api; - this.logger = logger; + super(deploymentUuid); this.websiteUuid = websiteUuid; - this.uuid = deploymentUuid; this.API_PREFIX = `/hosting/websites/${websiteUuid}/deployments/${deploymentUuid}`; this.populate(data); } - /** - * Populates class properties via data object. - * @param data Data object. - */ - private populate(data: any) { - if (data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - return this; - } - /** * @dev Gets deployment details. */ async get(): Promise { - this.logger.log( + ApillonLogger.log( `Get deployment for website ${this.uuid}`, LogLevel.VERBOSE, ); - const { data } = await this.api.get(this.API_PREFIX); + const { data } = await ApillonApi.get>( + this.API_PREFIX, + ); return this.populate(data.data); } } diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index b5bf7a6..0397ea1 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -1,35 +1,21 @@ -import { AxiosInstance } from 'axios'; import { constructUrlWithQueryParams, listFilesRecursive, uploadFilesToS3, } from '../../lib/common'; import { DeployToEnvironment, IDeploymentFilters } from '../../types/hosting'; -import { ApillonLogger } from '../../index'; -import { IApillonList, LogLevel } from '../../types/apillon'; +import { + IApillonList, + IApillonListResponse, + IApillonResponse, + LogLevel, +} from '../../types/apillon'; import { Deployment } from './deployment'; +import { ApillonModel } from '../../docs-index'; +import { ApillonApi } from '../../lib/apillon-api'; +import { ApillonLogger } from '../../lib/apillon-logger'; -export class HostingWebsite { - /** - * Axios instance set to correct rootUrl with correct error handling. - */ - protected api: AxiosInstance; - - /** - * Logger. - */ - protected logger: ApillonLogger; - - /** - * @dev API url prefix for this class. - */ - private API_PREFIX: string = null; - - /** - * @dev Unique identifier of the website. - */ - public uuid: string; - +export class HostingWebsite extends ApillonModel { /** * @dev User assigned name of the website. */ @@ -63,35 +49,12 @@ export class HostingWebsite { /** * @dev Constructor which should only be called via Hosting class. * @param uuid Unique identifier of the website. - * @param api Axios instance set to correct rootUrl with correct error handling. + * @param data Data to populate the website with. */ - constructor( - api: AxiosInstance, - logger: ApillonLogger, - uuid: string, - data?: Partial, - ) { - this.api = api; - this.uuid = uuid; - this.logger = logger; - this.populate(data); + constructor(uuid: string, data?: Partial) { + super(uuid); this.API_PREFIX = `/hosting/websites/${uuid}`; - } - - /** - * Populates class properties via data object. - * @param data Data object. - */ - private populate(data: any) { - if (!data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - return this; + this.populate(data); } /** @@ -99,7 +62,9 @@ export class HostingWebsite { * @returns An instance of HostingWebsite class with filled properties. */ public async get(): Promise { - const { data } = (await this.api.get(this.API_PREFIX)).data; + const { data } = ( + await ApillonApi.get>(this.API_PREFIX) + ).data; return this.populate(data); } @@ -108,7 +73,7 @@ export class HostingWebsite { * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { - this.logger.log( + ApillonLogger.log( `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, LogLevel.VERBOSE, ); @@ -117,33 +82,39 @@ export class HostingWebsite { try { files = listFilesRecursive(folderPath); } catch (err) { - this.logger.log(err, LogLevel.ERROR); + ApillonLogger.log(err, LogLevel.ERROR); throw new Error(`Error reading files in ${folderPath}`); } const data = { files }; - this.logger.log(`Files to upload: ${data.files.length}`, LogLevel.VERBOSE); + ApillonLogger.log( + `Files to upload: ${data.files.length}`, + LogLevel.VERBOSE, + ); - this.logger.logWithTime('Get upload links', LogLevel.VERBOSE); - const resp = await this.api.post(`${this.API_PREFIX}/upload`, data); + ApillonLogger.logWithTime('Get upload links', LogLevel.VERBOSE); + const { data: session } = await ApillonApi.post( + `${this.API_PREFIX}/upload`, + data, + ); - this.logger.logWithTime('Got upload links', LogLevel.VERBOSE); + ApillonLogger.logWithTime('Got upload links', LogLevel.VERBOSE); // console.log(resp); - const sessionUuid = resp.data.data.sessionUuid; + const sessionUuid = session.data.sessionUuid; - this.logger.logWithTime('File upload complete', LogLevel.VERBOSE); - await uploadFilesToS3(resp.data.data.files, files); - this.logger.logWithTime('File upload complete', LogLevel.VERBOSE); + ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); + await uploadFilesToS3(session.data.files, files); + ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); - this.logger.log('Closing session...', LogLevel.VERBOSE); - const respEndSession = await this.api.post( + ApillonLogger.log('Closing session...', LogLevel.VERBOSE); + const { data: endSession } = await ApillonApi.post( `${this.API_PREFIX}/upload/${sessionUuid}/end`, ); - this.logger.log('Session ended.', LogLevel.VERBOSE); + ApillonLogger.log('Session ended.', LogLevel.VERBOSE); - if (!respEndSession.data.data) { - throw new Error(); + if (!endSession.data) { + throw new Error('Upload session did not end'); } } @@ -153,7 +124,7 @@ export class HostingWebsite { * @returns The new deployment instance */ public async deploy(toEnvironment: DeployToEnvironment): Promise { - this.logger.log( + ApillonLogger.log( `Deploying website ${this.uuid} to IPFS (${ toEnvironment === DeployToEnvironment.TO_STAGING ? 'preview' @@ -162,12 +133,12 @@ export class HostingWebsite { LogLevel.VERBOSE, ); - this.logger.logWithTime('Deploy start', LogLevel.VERBOSE); - const { data } = await this.api.post(`${this.API_PREFIX}/deploy`, { + ApillonLogger.logWithTime('Deploy start', LogLevel.VERBOSE); + const { data } = await ApillonApi.post(`${this.API_PREFIX}/deploy`, { environment: toEnvironment, }); - this.logger.logWithTime('Deploy complete', LogLevel.VERBOSE); + ApillonLogger.logWithTime('Deploy complete', LogLevel.VERBOSE); return data.data; } @@ -185,18 +156,13 @@ export class HostingWebsite { params, ); - const { data } = await this.api.get(url); + const { data } = await ApillonApi.get< + IApillonListResponse + >(url); return { items: data.data.items.map( - (item) => - new Deployment( - this.api, - this.logger, - item.websiteUuid, - item.deploymentUuid, - item, - ), + (item) => new Deployment(item.websiteUuid, item.deploymentUuid, item), ), total: data.data.total, }; @@ -208,6 +174,6 @@ export class HostingWebsite { * @returns Instance of a deployment. */ deployment(deploymentUuid: string): Deployment { - return new Deployment(this.api, this.logger, this.uuid, deploymentUuid, {}); + return new Deployment(this.uuid, deploymentUuid, {}); } } diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 1100031..c7bf581 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -1,5 +1,6 @@ import { IWebsiteFilters } from '../../docs-index'; import { ApillonModule } from '../../lib/apillon'; +import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonList, IApillonListResponse } from '../../types/apillon'; import { HostingWebsite } from './hosting-website'; @@ -20,19 +21,13 @@ export class Hosting extends ApillonModule { ): Promise> { const url = constructUrlWithQueryParams(this.API_PREFIX, params); - const { data } = await this.api.get>( + const { data } = await ApillonApi.get>( url, ); return { items: data.data.items.map( - (website) => - new HostingWebsite( - this.api, - this.logger, - website['websiteUuid'], - website, - ), + (website) => new HostingWebsite(website['websiteUuid'], website), ), total: data.data.total, }; @@ -44,6 +39,6 @@ export class Hosting extends ApillonModule { * @returns An instance of HostingWebsite. */ public website(uuid: string): HostingWebsite { - return new HostingWebsite(this.api, this.logger, uuid); + return new HostingWebsite(uuid); } } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 3413599..5ebf9df 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -1,4 +1,5 @@ -import { AxiosInstance } from 'axios'; +import { ApillonModel } from '../../docs-index'; +import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonResponse, @@ -14,29 +15,8 @@ import { CollectionStatus, EvmChain, } from '../../types/nfts'; -import { ApillonLogger } from '../../docs-index'; - -export class NftCollection { - /** - * Axios instance set to correct rootUrl with correct error handling. - */ - protected api: AxiosInstance; - - /** - * Logger. - */ - protected logger: ApillonLogger; - - /** - * @dev API url prefix for this class. - */ - private API_PREFIX: string = null; - - /** - * @dev Unique identifier of the collection. - */ - public uuid: string; +export class NftCollection extends ApillonModel { /** * @dev collection symbol. */ @@ -134,33 +114,15 @@ export class NftCollection { */ public chain: EvmChain = null; - constructor( - api: AxiosInstance, - logger: ApillonLogger, - uuid: string, - data?: Partial, - ) { - this.api = api; - this.logger = logger; - this.uuid = uuid; - this.API_PREFIX = `/nfts/collections/${this.uuid}`; - this.populate(data); - } - /** - * Populates class properties via data object. - * @param data Data object. + * @dev Constructor which should only be called via Nft class. + * @param uuid Unique identifier of the NFT collection. + * @param data Data to populate the collection with. */ - private populate(data: any) { - if (data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - return this; + constructor(uuid: string, data?: Partial) { + super(uuid); + this.API_PREFIX = `/nfts/collections/${this.uuid}`; + this.populate(data); } /** @@ -168,7 +130,7 @@ export class NftCollection { * @returns Collection instance. */ public async get(): Promise { - const { data } = await this.api.get>( + const { data } = await ApillonApi.get>( this.API_PREFIX, ); return this.populate(data.data); @@ -181,7 +143,7 @@ export class NftCollection { * @returns Call status. */ public async mint(receiver: string, quantity: number) { - const { data } = await this.api.post< + const { data } = await ApillonApi.post< IApillonResponse >(`${this.API_PREFIX}/mint`, { receivingAddress: receiver, quantity }); @@ -207,7 +169,7 @@ export class NftCollection { ) { throw new Error('Collection is not nestable.'); } - const { data } = await this.api.post>( + const { data } = await ApillonApi.post>( `${this.API_PREFIX}/nest-mint`, { parentCollectionUuid, parentNftId, quantity }, ); @@ -225,7 +187,7 @@ export class NftCollection { if (this.isRevokable != null && !this.isRevokable) { throw new Error('Collection is not revokable.'); } - const { data } = await this.api.post>( + const { data } = await ApillonApi.post>( `${this.API_PREFIX}/burn`, { tokenId: id }, ); @@ -241,7 +203,7 @@ export class NftCollection { * @returns Collection data. */ public async transferOwnership(address: string): Promise { - const { data } = await this.api.post>( + const { data } = await ApillonApi.post>( `${this.API_PREFIX}/transfer`, { address }, ); @@ -264,7 +226,7 @@ export class NftCollection { params, ); - const { data } = await this.api.get< + const { data } = await ApillonApi.get< IApillonResponse> >(url); diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 9dc7f4d..b18de14 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -1,4 +1,5 @@ import { ApillonModule } from '../../lib/apillon'; +import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonResponse, IApillonListResponse } from '../../types/apillon'; import { @@ -20,7 +21,7 @@ export class Nft extends ApillonModule { * @returns An instance of NFT Collection */ public collection(uuid: string): NftCollection { - return new NftCollection(this.api, this.logger, uuid, null); + return new NftCollection(uuid, null); } /** @@ -31,11 +32,12 @@ export class Nft extends ApillonModule { public async list(params?: ICollectionFilters): Promise { const url = constructUrlWithQueryParams(this.API_PREFIX, params); - const { data } = await this.api.get>(url); + const { data } = await ApillonApi.get>( + url, + ); return data.data.items.map( - (nft) => - new NftCollection(this.api, this.logger, nft.collectionUuid, nft), + (nft) => new NftCollection(nft.collectionUuid, nft), ); } @@ -45,15 +47,10 @@ export class Nft extends ApillonModule { * @returns A NftCollection instance. */ public async create(data: ICreateCollection) { - const { data: response } = await this.api.post< + const { data: response } = await ApillonApi.post< IApillonResponse >(this.API_PREFIX, data); - return new NftCollection( - this.api, - this.logger, - response?.data.collectionUuid, - response?.data, - ); + return new NftCollection(response?.data.collectionUuid, response?.data); } } diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index 5673689..35f86b2 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -1,38 +1,19 @@ -import { AxiosInstance } from 'axios'; import { IStorageBucketContentRequest, StorageContentType, } from '../../types/storage'; import { File } from './file'; -import { ApillonLogger } from '../../lib/apillon'; import { constructUrlWithQueryParams } from '../../lib/common'; +import { ApillonApi } from '../../lib/apillon-api'; +import { IApillonListResponse } from '../../types/apillon'; +import { ApillonModel } from '../../docs-index'; -export class Directory { - /** - * Axios instance set to correct rootUrl with correct error handling. - */ - protected api: AxiosInstance; - - /** - * Logger. - */ - protected logger: ApillonLogger; - - /** - * @dev API url prefix for this class. - */ - private API_PREFIX: string = null; - +export class Directory extends ApillonModel { /** * @dev Unique identifier of the bucket. */ public bucketUuid; - /** - * @dev Unique identifier of the directory. - */ - public uuid: string; - /** * Directory name. */ @@ -53,42 +34,25 @@ export class Directory { */ public type = StorageContentType.DIRECTORY; - public content: (File | Directory)[] = null; + public content: (File | Directory)[] = []; + /** - * @dev Constructor which should only be called via Storage class. - * @param uuid Unique identifier of the directory. - * @param api Axios instance set to correct rootUrl with correct error handling. + * @dev Constructor which should only be called via HostingWebsite class. + * @param bucketUuid Unique identifier of the directory's bucket. + * @param directoryUuid Unique identifier of the directory. + * @param data Data to populate the directory with. */ constructor( - api: AxiosInstance, - logger: ApillonLogger, bucketUuid: string, directoryUuid: string, - data: any, + data: Partial, ) { - this.api = api; - this.logger = logger; + super(directoryUuid); this.bucketUuid = bucketUuid; - this.uuid = directoryUuid; this.API_PREFIX = `/storage/${bucketUuid}`; this.populate(data); } - /** - * Populates class properties via data object. - * @param data Data object. - */ - private populate(data: any) { - if (data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - } - /** * @dev Gets contents of a directory. */ @@ -101,28 +65,18 @@ export class Directory { `${this.API_PREFIX}/content`, params, ); - const resp = await this.api.get(url); - for (const item of resp.data?.data?.items) { + const { data } = await ApillonApi.get< + IApillonListResponse + >(url); + for (const item of data?.data?.items) { if (item.type == StorageContentType.FILE) { + const file = item as File; this.content.push( - new File( - this.api, - this.logger, - this.bucketUuid, - item.uuid, - item.directoryUuid, - item, - ), + new File(this.bucketUuid, file.directoryUuid, file.uuid, file), ); } else { this.content.push( - new Directory( - this.api, - this.logger, - this.bucketUuid, - item.uuid, - item, - ), + new Directory(this.bucketUuid, item.uuid, item as Directory), ); } } diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 3c67ad6..9486c66 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -1,18 +1,8 @@ -import { AxiosInstance } from 'axios'; +import { AxiosResponse } from 'axios'; +import { ApillonApi } from '../../lib/apillon-api'; import { FileStatus, StorageContentType } from '../../types/storage'; -import { ApillonLogger } from '../../lib/apillon'; export class File { - /** - * Axios instance set to correct rootUrl with correct error handling. - */ - protected api: AxiosInstance; - - /** - * Logger. - */ - protected logger: ApillonLogger; - /** * @dev API url prefix for this class. */ @@ -54,20 +44,18 @@ export class File { public type = StorageContentType.FILE; /** - * @dev Constructor which should only be called via Storage class. - * @param uuid Unique identifier of the file. - * @param api Axios instance set to correct rootUrl with correct error handling. + * @dev Constructor which should only be called via HostingWebsite class. + * @param bucketUuid Unique identifier of the file's bucket. + * @param directoryUuid Unique identifier of the file's directory. + * @param fileUuid Unique identifier of the file. + * @param data Data to populate the directory with. */ constructor( - api: AxiosInstance, - logger: ApillonLogger, bucketUuid: string, - fileUuid: string, directoryUuid: string, - data: any, + fileUuid: string, + data: Partial, ) { - this.api = api; - this.logger = logger; this.bucketUuid = bucketUuid; this.uuid = fileUuid; this.directoryUuid = directoryUuid; @@ -96,7 +84,9 @@ export class File { * @dev Gets file details. */ async get(): Promise { - const { data } = await this.api.get(`${this.API_PREFIX}/detail`); + const { data } = await ApillonApi.get< + AxiosResponse + >(`${this.API_PREFIX}/detail`); this.status = data.data.fileStatus; return this.populate(data.data); } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 357cda5..543e312 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -1,4 +1,3 @@ -import { AxiosInstance } from 'axios'; import { Directory } from './directory'; import { IBucketFilesRequest, @@ -11,30 +10,16 @@ import { listFilesRecursive, uploadFilesToS3, } from '../../lib/common'; -import { ApillonLogger } from '../../docs-index'; -import { IApillonList, IApillonListResponse } from '../../types/apillon'; - -export class StorageBucket { - /** - * Axios instance set to correct rootUrl with correct error handling. - */ - protected api: AxiosInstance; - - /** - * Logger. - */ - protected logger: ApillonLogger; - - /** - * @dev API url prefix for this class. - */ - private API_PREFIX: string = null; - - /** - * @dev Unique identifier of the bucket. - */ - public uuid: string; - +import { + IApillonList, + IApillonListResponse, + LogLevel, +} from '../../types/apillon'; +import { ApillonApi } from '../../lib/apillon-api'; +import { ApillonModel } from '../../docs-index'; +import { ApillonLogger } from '../../lib/apillon-logger'; + +export class StorageBucket extends ApillonModel { /** * @dev Name of the bucket. */ @@ -53,42 +38,19 @@ export class StorageBucket { /** * @dev Bucket content which are files and directories. */ - public content: (File | Directory)[] = null; + public content: (File | Directory)[] = []; /** * @dev Constructor which should only be called via Storage class. * @param uuid Unique identifier of the bucket. - * @param api Axios instance set to correct rootUrl with correct error handling. - * @param data Data to populate storage bucket + * @param data Data to populate storage bucket with. */ - constructor( - api: AxiosInstance, - logger: ApillonLogger, - uuid: string, - data?: Partial, - ) { - this.api = api; - this.logger = logger; - this.uuid = uuid; + constructor(uuid: string, data?: Partial) { + super(uuid); this.API_PREFIX = `/storage/${uuid}`; this.populate(data); } - /** - * Populates class properties via data object. - * @param data Data object. - */ - private populate(data: any) { - if (data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - } - /** * @dev Gets contents of a bucket. */ @@ -100,26 +62,20 @@ export class StorageBucket { `${this.API_PREFIX}/content`, params, ); - const { data } = await this.api.get(url); + const { data } = await ApillonApi.get< + IApillonListResponse + >(url); for (const item of data.data.items) { if (item.type == StorageContentType.FILE) { - content.push( - new File( - this.api, - this.logger, - this.uuid, - item.uuid, - item.directoryUuid, - item, - ), + const file = item as File; + this.content.push( + new File(this.uuid, file.directoryUuid, file.uuid, file), ); } else { const directory = new Directory( - this.api, - this.logger, this.uuid, item.uuid, - item, + item as Directory, ); content.push(directory, ...(await directory.get())); } @@ -136,20 +92,12 @@ export class StorageBucket { `/storage/buckets/${this.uuid}/files`, params, ); - const { data } = await this.api.get>(url); + const { data } = await ApillonApi.get>(url); return { total: data.data.total, items: data.data.items.map( - (file) => - new File( - this.api, - this.logger, - this.uuid, - file.uuid, - file.directoryUuid, - file, - ), + (file) => new File(this.uuid, file.directoryUuid, file.uuid, file), ), }; } @@ -159,8 +107,9 @@ export class StorageBucket { * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { - console.log( + ApillonLogger.log( `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, + LogLevel.VERBOSE, ); let files; try { @@ -170,13 +119,11 @@ export class StorageBucket { throw new Error(`Error reading files in ${folderPath}`); } - console.log(`Files to upload: ${files.length}`); + ApillonLogger.log(`Files to upload: ${files.length}`, LogLevel.VERBOSE); - console.time('Got upload links'); - const { data } = await this.api.post(`${this.API_PREFIX}/upload`, { + const { data } = await ApillonApi.post(`${this.API_PREFIX}/upload`, { files, }); - console.timeEnd('Got upload links'); const uploadLinks = data.data.files.sort((a, b) => a.fileName.localeCompare(b.fileName), @@ -195,11 +142,11 @@ export class StorageBucket { ), ); - console.log('Closing session...'); - const respEndSession = await this.api.post( + ApillonLogger.log('Closing upload session...', LogLevel.VERBOSE); + const respEndSession = await ApillonApi.post( `${this.API_PREFIX}/upload/${data.data.sessionUuid}/end`, ); - console.log('Session ended.'); + ApillonLogger.log('Session ended.', LogLevel.VERBOSE); if (!respEndSession.data?.data) { throw new Error('Failure when trying to end file upload session'); @@ -212,7 +159,7 @@ export class StorageBucket { * @returns Instance of file. */ file(fileUuid: string): File { - return new File(this.api, this.logger, this.uuid, fileUuid, null, {}); + return new File(this.uuid, null, fileUuid, {}); } /** @@ -220,6 +167,6 @@ export class StorageBucket { * @param fileUuid Uuid of the file. */ async deleteFile(fileUuid: string): Promise { - await this.api.delete(`/storage/buckets/${this.uuid}/files/${fileUuid}`); + await ApillonApi.delete(`/storage/buckets/${this.uuid}/files/${fileUuid}`); } } diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index 006182d..fb7a4a2 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -1,5 +1,6 @@ import { IApillonPagination } from '../../docs-index'; import { ApillonModule } from '../../lib/apillon'; +import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonList, IApillonListResponse } from '../../types/apillon'; import { StorageBucket } from './storage-bucket'; @@ -20,23 +21,22 @@ export class Storage extends ApillonModule { ): Promise> { const url = constructUrlWithQueryParams(this.API_PREFIX, params); - const { data } = await this.api.get>(url); + const { data } = await ApillonApi.get>(url); return { items: data.data.items.map( - (bucket) => - new StorageBucket(this.api, this.logger, bucket.bucketUuid, bucket), + (bucket) => new StorageBucket(bucket.bucketUuid, bucket), ), total: data.data.total, }; } /** - * @dev Returns an website instance. - * @param uuid Unique website identifier. - * @returns An instance of Website.∂ + * @dev Returns a bucket instance. + * @param uuid Unique bucket identifier. + * @returns An instance of StorageBucket. */ public bucket(uuid: string): StorageBucket { - return new StorageBucket(this.api, this.logger, uuid); + return new StorageBucket(uuid); } } diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index bc04b1e..4fbebf3 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -14,7 +14,7 @@ describe('Storage tests', () => { }); test('List buckets', async () => { - const { items } = await new Storage(config).listBuckets({ limit: 1 }); + const { items } = await new Storage(config).listBuckets(); expect(items.length).toBeGreaterThanOrEqual(0); items.forEach((item) => expect(item.name).toBeTruthy()); }); From 0eeef5daef5e0813828e1923fcea244012ed12a6 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 27 Oct 2023 12:22:32 +0200 Subject: [PATCH 31/68] Wrap AxiosResponse data object --- packages/sdk/src/lib/apillon-api.ts | 25 ++++++++----------- packages/sdk/src/lib/apillon.ts | 2 +- .../sdk/src/modules/hosting/deployment.ts | 4 +-- .../src/modules/hosting/hosting-website.ts | 18 ++++++------- packages/sdk/src/modules/hosting/hosting.ts | 4 +-- .../sdk/src/modules/nft/nft-collection.ts | 12 ++++----- packages/sdk/src/modules/nft/nft.ts | 6 ++--- packages/sdk/src/modules/storage/directory.ts | 5 ++-- packages/sdk/src/modules/storage/file.ts | 6 ++--- .../sdk/src/modules/storage/storage-bucket.ts | 16 ++++++------ packages/sdk/src/modules/storage/storage.ts | 4 +-- 11 files changed, 49 insertions(+), 53 deletions(-) diff --git a/packages/sdk/src/lib/apillon-api.ts b/packages/sdk/src/lib/apillon-api.ts index 2553834..c0682a8 100644 --- a/packages/sdk/src/lib/apillon-api.ts +++ b/packages/sdk/src/lib/apillon-api.ts @@ -1,4 +1,4 @@ -import axios, { AxiosInstance, AxiosResponse } from 'axios'; +import axios, { AxiosInstance } from 'axios'; import { ApillonConfig } from './apillon'; import { LogLevel } from '../types/apillon'; import { ApillonLogger } from './apillon-logger'; @@ -58,25 +58,22 @@ export class ApillonApi { ); } - public static async get( - url: string, - config?: any, - ): Promise> { - return this.instance.get(url, config); + public static async get(url: string, config?: any): Promise { + const { data } = await this.instance.get(url, config); + return data; } public static async post( url: string, - data?: any, + body?: any, config?: any, - ): Promise> { - return this.instance.post(url, data, config); + ): Promise { + const { data } = await this.instance.post(url, body, config); + return data; } - public static async delete( - url: string, - config?: any, - ): Promise> { - return this.instance.delete(url, config); + public static async delete(url: string, config?: any): Promise { + const { data } = await this.instance.delete(url, config); + return data; } } diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index d5d05fc..5b85fee 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -44,7 +44,7 @@ export class ApillonModel { * Populates class properties via data object. * @param data Data object. */ - protected populate(data: any) { + protected populate(data: object) { if (data != null) { Object.keys(data || {}).forEach((key) => { const prop = this[key]; diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index 100898f..5afb361 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -49,7 +49,7 @@ export class Deployment extends ApillonModel { constructor( websiteUuid: string, deploymentUuid: string, - data: Partial, + data?: Partial, ) { super(deploymentUuid); this.websiteUuid = websiteUuid; @@ -68,6 +68,6 @@ export class Deployment extends ApillonModel { const { data } = await ApillonApi.get>( this.API_PREFIX, ); - return this.populate(data.data); + return this.populate(data); } } diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index 0397ea1..9141f7c 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -62,9 +62,9 @@ export class HostingWebsite extends ApillonModel { * @returns An instance of HostingWebsite class with filled properties. */ public async get(): Promise { - const { data } = ( - await ApillonApi.get>(this.API_PREFIX) - ).data; + const { data } = await ApillonApi.get>( + this.API_PREFIX, + ); return this.populate(data); } @@ -101,10 +101,10 @@ export class HostingWebsite extends ApillonModel { ApillonLogger.logWithTime('Got upload links', LogLevel.VERBOSE); // console.log(resp); - const sessionUuid = session.data.sessionUuid; + const sessionUuid = session.sessionUuid; ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); - await uploadFilesToS3(session.data.files, files); + await uploadFilesToS3(session.files, files); ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); ApillonLogger.log('Closing session...', LogLevel.VERBOSE); @@ -113,7 +113,7 @@ export class HostingWebsite extends ApillonModel { ); ApillonLogger.log('Session ended.', LogLevel.VERBOSE); - if (!endSession.data) { + if (!endSession) { throw new Error('Upload session did not end'); } } @@ -140,7 +140,7 @@ export class HostingWebsite extends ApillonModel { ApillonLogger.logWithTime('Deploy complete', LogLevel.VERBOSE); - return data.data; + return data; } /** @@ -161,10 +161,10 @@ export class HostingWebsite extends ApillonModel { >(url); return { - items: data.data.items.map( + items: data.items.map( (item) => new Deployment(item.websiteUuid, item.deploymentUuid, item), ), - total: data.data.total, + total: data.total, }; } diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index c7bf581..1f86033 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -26,10 +26,10 @@ export class Hosting extends ApillonModule { ); return { - items: data.data.items.map( + items: data.items.map( (website) => new HostingWebsite(website['websiteUuid'], website), ), - total: data.data.total, + total: data.total, }; } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 5ebf9df..95ffe87 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -133,7 +133,7 @@ export class NftCollection extends ApillonModel { const { data } = await ApillonApi.get>( this.API_PREFIX, ); - return this.populate(data.data); + return this.populate(data); } /** @@ -147,7 +147,7 @@ export class NftCollection extends ApillonModel { IApillonResponse >(`${this.API_PREFIX}/mint`, { receivingAddress: receiver, quantity }); - return data?.data; + return data; } /** @@ -174,7 +174,7 @@ export class NftCollection extends ApillonModel { { parentCollectionUuid, parentNftId, quantity }, ); - return data?.data; + return data; } /** @@ -192,7 +192,7 @@ export class NftCollection extends ApillonModel { { tokenId: id }, ); - return data?.data; + return data; } /** @@ -208,7 +208,7 @@ export class NftCollection extends ApillonModel { { address }, ); - this.populate(data?.data); + this.populate(data); return this; } @@ -230,6 +230,6 @@ export class NftCollection extends ApillonModel { IApillonResponse> >(url); - return data?.data.items; + return data.items; } } diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index b18de14..01cbf42 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -36,9 +36,7 @@ export class Nft extends ApillonModule { url, ); - return data.data.items.map( - (nft) => new NftCollection(nft.collectionUuid, nft), - ); + return data.items.map((nft) => new NftCollection(nft.collectionUuid, nft)); } /** @@ -51,6 +49,6 @@ export class Nft extends ApillonModule { IApillonResponse >(this.API_PREFIX, data); - return new NftCollection(response?.data.collectionUuid, response?.data); + return new NftCollection(response.collectionUuid, response); } } diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index 35f86b2..7efa16d 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -45,7 +45,7 @@ export class Directory extends ApillonModel { constructor( bucketUuid: string, directoryUuid: string, - data: Partial, + data?: Partial, ) { super(directoryUuid); this.bucketUuid = bucketUuid; @@ -68,7 +68,8 @@ export class Directory extends ApillonModel { const { data } = await ApillonApi.get< IApillonListResponse >(url); - for (const item of data?.data?.items) { + + for (const item of data.items) { if (item.type == StorageContentType.FILE) { const file = item as File; this.content.push( diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 9486c66..8c91d94 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -54,7 +54,7 @@ export class File { bucketUuid: string, directoryUuid: string, fileUuid: string, - data: Partial, + data?: Partial, ) { this.bucketUuid = bucketUuid; this.uuid = fileUuid; @@ -87,7 +87,7 @@ export class File { const { data } = await ApillonApi.get< AxiosResponse >(`${this.API_PREFIX}/detail`); - this.status = data.data.fileStatus; - return this.populate(data.data); + this.status = data.fileStatus; + return this.populate(data); } } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 543e312..8938fe8 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -65,7 +65,7 @@ export class StorageBucket extends ApillonModel { const { data } = await ApillonApi.get< IApillonListResponse >(url); - for (const item of data.data.items) { + for (const item of data.items) { if (item.type == StorageContentType.FILE) { const file = item as File; this.content.push( @@ -81,7 +81,7 @@ export class StorageBucket extends ApillonModel { } } this.content = content; - return { total: data.data.total, items: content }; + return { total: data.total, items: content }; } /** @@ -95,8 +95,8 @@ export class StorageBucket extends ApillonModel { const { data } = await ApillonApi.get>(url); return { - total: data.data.total, - items: data.data.items.map( + total: data.total, + items: data.items.map( (file) => new File(this.uuid, file.directoryUuid, file.uuid, file), ), }; @@ -125,7 +125,7 @@ export class StorageBucket extends ApillonModel { files, }); - const uploadLinks = data.data.files.sort((a, b) => + const uploadLinks = data.files.sort((a, b) => a.fileName.localeCompare(b.fileName), ); // Divide files into chunks for parallel processing and uploading @@ -143,12 +143,12 @@ export class StorageBucket extends ApillonModel { ); ApillonLogger.log('Closing upload session...', LogLevel.VERBOSE); - const respEndSession = await ApillonApi.post( - `${this.API_PREFIX}/upload/${data.data.sessionUuid}/end`, + const { data: endSession } = await ApillonApi.post( + `${this.API_PREFIX}/upload/${data.sessionUuid}/end`, ); ApillonLogger.log('Session ended.', LogLevel.VERBOSE); - if (!respEndSession.data?.data) { + if (!endSession) { throw new Error('Failure when trying to end file upload session'); } } diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index fb7a4a2..bf4b08e 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -24,10 +24,10 @@ export class Storage extends ApillonModule { const { data } = await ApillonApi.get>(url); return { - items: data.data.items.map( + items: data.items.map( (bucket) => new StorageBucket(bucket.bucketUuid, bucket), ), - total: data.data.total, + total: data.total, }; } From d774230463c157e3da55d1a49a0d8199988e7f10 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 2 Nov 2023 12:12:03 +0100 Subject: [PATCH 32/68] Update EXAMPLE.md --- EXAMPLE.md | 57 ++++++++----------- packages/cli/src/modules/nfts/nft.service.ts | 6 +- .../sdk/src/modules/nft/nft-collection.ts | 4 +- packages/sdk/src/modules/nft/nft.ts | 4 +- packages/sdk/src/tests/nft.test.ts | 8 +-- 5 files changed, 37 insertions(+), 42 deletions(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index 8d6e0f8..91b5df0 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -1,49 +1,42 @@ # Structure example ```ts -import { Hosting } from '@apillon/sdk'; -import { Storage } from '@apillon/sdk'; -import { Nft } from '@apillon/sdk'; +import { Hosting, Storage, Nft, DeployToEnvironment, FileStatus } from '@apillon/sdk'; export async function test() { - + // Hosting example const hosting = new Hosting({ apillonConfig }); await hosting.listWebsites(); - await hosting.createWebsite(); const webpage1 = hosting.website('uuid'); - await webpage1.getInfo(); - await webpage1.update({}); - await webpage1.getDeployment(id); - await webpage1.getDeployments(); - await webpage1.deployFromFolder('path', 'environment'); // can go directly to production - await webpage1.updateDeployment(from stg -> production); // tu me moti še na api levelu, kr lahko dobiš in pogledaš detajle specifičnega deploymenta, ampak deploy klic pa dela samo na zadnjem - - // or - await hosting.website('uuid').getInfo(); + await webpage1.get(); + await webpage1.uploadFromFolder('folder_path'); + await webpage1.deploy(DeployToEnvironment.STAGING_TO_PRODUCTION); + await webpage1.listDeployments(); + const deployment = await webpage1.deployment(deployment_uuid).get(); - //Naming hosting -> webpage? - + // Storage example const storage = new Storage({ apillonConfig }); await storage.listBuckets(); - await storage.createBucket(); - const bucket = storage.bucket('uuid'); - await bucket.upload('path to files'); - await bucket.getContent({ directory, search, limit }); - await bucket.getFile(id); - await bucket.deleteFile(id); - + await bucket.uploadFromFolder('folder_path'); + await bucket.getObjects({ + directoryUuid, + markedForDeletion: false, + limit: 5, + }); + await bucket.getFiles({ fileStatus: FileStatus.UPLOADED }); + const file = await bucket.file(file_uuid).get(); + await bucket.deleteFile(file_uuid); + + // NFT example const nft = new Nft({ apillonConfig }); await nft.listCollections(); - - const collection = nft.collection('uuid'); - const info = collection.getInfo(); //.info? - await collection.mint(); - await collection.burn(); - await collection.transferOwnership(); - await collection.getTransactions(); - - + const collection = await nft.collection('uuid').get(); + await collection.mint(receiver, quantity); + await collection.nestMint(collection.uuid, 1, quantity); + await collection.burn(quantity); + await collection.listTransactions(); + await collection.transferOwnership(to_address); } ``` diff --git a/packages/cli/src/modules/nfts/nft.service.ts b/packages/cli/src/modules/nfts/nft.service.ts index 0850c77..a8345d9 100644 --- a/packages/cli/src/modules/nfts/nft.service.ts +++ b/packages/cli/src/modules/nfts/nft.service.ts @@ -16,7 +16,7 @@ export async function listCollections( const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.list({ + const data = await nftService.listCollections({ collectionStatus: toInteger(options.status), page: toInteger(options.page), limit: toInteger(options.limit), @@ -103,7 +103,7 @@ export async function nestMintCollectionNft( try { const data = await nftService .collection(uuid) - .nestMintNft( + .nestMint( options.parentCollectionUuid, toInteger(options.parentNftId), toInteger(options.quantity), @@ -122,7 +122,7 @@ export async function burnCollectionNft( const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.collection(uuid).burnNft(options.tokenId); + const data = await nftService.collection(uuid).burn(options.tokenId); console.log(data); } catch (e: any) { exceptionHandler(e); diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index 95ffe87..e3fd794 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -158,7 +158,7 @@ export class NftCollection extends ApillonModel { * @param quantity Amount of nfts we want to mint. * @returns Call status. */ - public async nestMintNft( + public async nestMint( parentCollectionUuid: string, parentNftId: number, quantity: number, @@ -183,7 +183,7 @@ export class NftCollection extends ApillonModel { * @param id Id of the NFT we want to burn. * @returns Status. */ - public async burnNft(id: string): Promise { + public async burn(id: string): Promise { if (this.isRevokable != null && !this.isRevokable) { throw new Error('Collection is not revokable.'); } diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 01cbf42..835b0b4 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -29,7 +29,9 @@ export class Nft extends ApillonModule { * @param {ICollectionFilters} params Filter for listing collections. * @returns Array of NftCollection. */ - public async list(params?: ICollectionFilters): Promise { + public async listCollections( + params?: ICollectionFilters, + ): Promise { const url = constructUrlWithQueryParams(this.API_PREFIX, params); const { data } = await ApillonApi.get>( diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index d1672c9..c9f3d07 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -16,7 +16,7 @@ describe('Nft tests', () => { test('list nft collections', async () => { const nft = new Nft(config); - const collections = await nft.list(); + const collections = await nft.listCollections(); expect(collections.length).toBeGreaterThan(0); expect(collections[0]).toBeInstanceOf(NftCollection); }); @@ -69,7 +69,7 @@ describe('Nft tests', () => { test('should fail nest minting for collection that is not nestable if collection populated', async () => { const nft = new Nft(config); const collection = await nft.collection(collectionUUID).get(); - await expect(collection.nestMintNft('', 1, 1)).rejects.toThrow( + await expect(collection.nestMint('', 1, 1)).rejects.toThrow( 'Collection is not nestable.', ); }); @@ -78,14 +78,14 @@ describe('Nft tests', () => { test('should fail nest minting', async () => { const nft = new Nft(config); const collection = nft.collection(collectionUUID); - await collection.nestMintNft('2ad03895-fd5d-40e7-af17-1d6daecf3b5a', 1, 1); + await collection.nestMint('2ad03895-fd5d-40e7-af17-1d6daecf3b5a', 1, 1); }); test('should fail revoking for collection that is not revokable if collection populated', async () => { const nft = new Nft(config); const collection = await nft.collection(collectionUUID).get(); - await expect(collection.burnNft('1')).rejects.toThrow( + await expect(collection.burn('1')).rejects.toThrow( 'Collection is not revokable.', ); }); From 4481d02fd03db0f3bf7653089b03f98503605c35 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 2 Nov 2023 12:20:43 +0100 Subject: [PATCH 33/68] Update method and property JSDoc --- .gitignore | 4 ++-- packages/sdk/package.json | 2 +- packages/sdk/src/lib/apillon.ts | 4 ++-- .../sdk/src/modules/hosting/deployment.ts | 6 +++--- .../src/modules/hosting/hosting-website.ts | 21 +++++++++---------- packages/sdk/src/modules/hosting/hosting.ts | 4 +--- .../sdk/src/modules/nft/nft-collection.ts | 12 +++++------ packages/sdk/src/modules/nft/nft.ts | 3 +-- packages/sdk/src/modules/storage/directory.ts | 6 +++--- packages/sdk/src/modules/storage/file.ts | 10 ++++----- .../sdk/src/modules/storage/storage-bucket.ts | 16 +++++++------- packages/sdk/src/modules/storage/storage.ts | 3 +-- packages/sdk/tsconfig.json | 3 ++- 13 files changed, 45 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index a6cc1da..2fce56b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,8 @@ # Node artifact files node_modules/ dist/ -packages/sdk/docs/ -packages/cli/docs/ +docs/ +.turbo # Compiled Java class files *.class diff --git a/packages/sdk/package.json b/packages/sdk/package.json index c57b5df..dffada2 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -27,7 +27,7 @@ "lint": "tsc --declarationMap && eslint \"{src,test}/**/*.ts\" --fix", "publish-package": "npm publish", "test": "npx jest", - "docs": "npx typedoc src/docs-index.ts" + "generate-docs": "npx typedoc src/docs-index.ts" }, "keywords": [ "SDK", diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 5b85fee..df66feb 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -27,12 +27,12 @@ export class ApillonModule { export class ApillonModel { /** - * @dev API url prefix for this class. + * API url prefix for this class. */ protected API_PREFIX: string = null; /** - * @dev Unique identifier of the model. + * Unique identifier of the model. */ public uuid: string; diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index 5afb361..de9c2e2 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -6,7 +6,7 @@ import { ApillonLogger } from '../../lib/apillon-logger'; export class Deployment extends ApillonModel { /** - * @dev Unique identifier of the website. + * Unique identifier of the website. */ public websiteUuid: string = null; @@ -41,7 +41,7 @@ export class Deployment extends ApillonModel { public number: number = null; /** - * @dev Constructor which should only be called via HostingWebsite class. + * Constructor which should only be called via HostingWebsite class. * @param websiteUuid Unique identifier of the deployment's website. * @param deploymentUuid Unique identifier of the deployment. * @param data Data to populate the deployment with. @@ -58,7 +58,7 @@ export class Deployment extends ApillonModel { } /** - * @dev Gets deployment details. + * Gets deployment details. */ async get(): Promise { ApillonLogger.log( diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index 9141f7c..4728c18 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -17,37 +17,37 @@ import { ApillonLogger } from '../../lib/apillon-logger'; export class HostingWebsite extends ApillonModel { /** - * @dev User assigned name of the website. + * User assigned name of the website. */ public name: string = null; /** - * @dev User assigned description of the website. + * User assigned description of the website. */ public description: string = null; /** - * @dev Domain on which this website lives. + * Domain on which this website lives. */ public domain: string = null; /** - * @dev Unique identifier of a storage bucket in which this website files reside. + * Unique identifier of a storage bucket in which this website files reside. */ public bucketUuid: string = null; /** - * @dev IPNS CID for staging environment. + * IPNS CID for staging environment. */ public ipnsStaging: string = null; /** - * @dev IPNS CID for production environment. + * IPNS CID for production environment. */ public ipnsProduction: string = null; /** - * @dev Constructor which should only be called via Hosting class. + * Constructor which should only be called via Hosting class. * @param uuid Unique identifier of the website. * @param data Data to populate the website with. */ @@ -58,7 +58,7 @@ export class HostingWebsite extends ApillonModel { } /** - * @dev Gets information about the website and fills properties with it. + * Gets information about the website and fills properties with it. * @returns An instance of HostingWebsite class with filled properties. */ public async get(): Promise { @@ -69,7 +69,7 @@ export class HostingWebsite extends ApillonModel { } /** - * @dev Uploads website files inside a folder via path. + * Uploads website files inside a folder via path. * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { @@ -119,7 +119,7 @@ export class HostingWebsite extends ApillonModel { } /** - * @dev Deploy a website to a new environment. + * Deploy a website to a new environment. * @param {DeployToEnvironment} toEnvironment The environment to deploy to * @returns The new deployment instance */ @@ -144,7 +144,6 @@ export class HostingWebsite extends ApillonModel { } /** - * @dev Returns an list of websites. * @param {IWebsiteFilters} params Query filters for listing websites * @returns A list of all deployments instances. */ diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index 1f86033..f031e5c 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -7,12 +7,11 @@ import { HostingWebsite } from './hosting-website'; export class Hosting extends ApillonModule { /** - * @dev Base API url for hosting. + * Base API url for hosting. */ private API_PREFIX = '/hosting/websites'; /** - * @dev Returns a list of websites. * @param {IWebsiteFilters} params Query filters for listing websites * @returns A list of HostingWebsite instances. */ @@ -34,7 +33,6 @@ export class Hosting extends ApillonModule { } /** - * @dev Returns an website instance. * @param uuid Unique website identifier. * @returns An instance of HostingWebsite. */ diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index e3fd794..e91255f 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -18,17 +18,17 @@ import { export class NftCollection extends ApillonModel { /** - * @dev collection symbol. + * Collection symbol. */ public symbol = null; /** - * @dev collection name + * Collection name */ public name = null; /** - * @dev collection description. + * collection description. */ public description: string = null; @@ -70,7 +70,7 @@ export class NftCollection extends ApillonModel { public drop: boolean = null; /** - * Pri per NFT if drop is active. + * Price per NFT if drop is active. */ public dropPrice: number = null; @@ -85,7 +85,7 @@ export class NftCollection extends ApillonModel { public dropReserve: number = null; /** - * Procentual amount of royalties fees. + * Percentage amount of royalties fees. */ public royaltiesFees: number = null; @@ -115,7 +115,7 @@ export class NftCollection extends ApillonModel { public chain: EvmChain = null; /** - * @dev Constructor which should only be called via Nft class. + * Constructor which should only be called via Nft class. * @param uuid Unique identifier of the NFT collection. * @param data Data to populate the collection with. */ diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 835b0b4..79842fb 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -11,12 +11,11 @@ import { NftCollection } from './nft-collection'; export class Nft extends ApillonModule { /** - * @dev API url for collections. + * API url for collections. */ private API_PREFIX = '/nfts/collections'; /** - * @dev Returns a collection instance. * @param uuid Unique collection identifier. * @returns An instance of NFT Collection */ diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index 7efa16d..c6c7e1e 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -10,7 +10,7 @@ import { ApillonModel } from '../../docs-index'; export class Directory extends ApillonModel { /** - * @dev Unique identifier of the bucket. + * Unique identifier of the bucket. */ public bucketUuid; @@ -37,7 +37,7 @@ export class Directory extends ApillonModel { public content: (File | Directory)[] = []; /** - * @dev Constructor which should only be called via HostingWebsite class. + * Constructor which should only be called via HostingWebsite class. * @param bucketUuid Unique identifier of the directory's bucket. * @param directoryUuid Unique identifier of the directory. * @param data Data to populate the directory with. @@ -54,7 +54,7 @@ export class Directory extends ApillonModel { } /** - * @dev Gets contents of a directory. + * Gets contents of a directory. */ async get( params: IStorageBucketContentRequest = {}, diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 8c91d94..d3650f6 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -4,17 +4,17 @@ import { FileStatus, StorageContentType } from '../../types/storage'; export class File { /** - * @dev API url prefix for this class. + * API url prefix for this class. */ private API_PREFIX: string = null; /** - * @dev Unique identifier of the bucket. + * Unique identifier of the file's bucket. */ public bucketUuid: string; /** - * @dev Unique identifier of the file. + * Unique identifier of the file. */ public uuid: string; @@ -44,7 +44,7 @@ export class File { public type = StorageContentType.FILE; /** - * @dev Constructor which should only be called via HostingWebsite class. + * Constructor which should only be called via HostingWebsite class. * @param bucketUuid Unique identifier of the file's bucket. * @param directoryUuid Unique identifier of the file's directory. * @param fileUuid Unique identifier of the file. @@ -81,7 +81,7 @@ export class File { } /** - * @dev Gets file details. + * Gets file details. */ async get(): Promise { const { data } = await ApillonApi.get< diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 8938fe8..47e6851 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -21,27 +21,27 @@ import { ApillonLogger } from '../../lib/apillon-logger'; export class StorageBucket extends ApillonModel { /** - * @dev Name of the bucket. + * Name of the bucket. */ public name: string = null; /** - * @dev Bucket description. + * Bucket description. */ public description: string = null; /** - * @dev Size of the bucket in bytes. + * Size of the bucket in bytes. */ public size: number = null; /** - * @dev Bucket content which are files and directories. + * Bucket content which are files and directories. */ public content: (File | Directory)[] = []; /** - * @dev Constructor which should only be called via Storage class. + * Constructor which should only be called via Storage class. * @param uuid Unique identifier of the bucket. * @param data Data to populate storage bucket with. */ @@ -52,7 +52,7 @@ export class StorageBucket extends ApillonModel { } /** - * @dev Gets contents of a bucket. + * Gets contents of a bucket. */ async getObjects( params?: IStorageBucketContentRequest, @@ -85,7 +85,7 @@ export class StorageBucket extends ApillonModel { } /** - * @dev Gets all files in a bucket. + * Gets all files in a bucket. */ async getFiles(params?: IBucketFilesRequest): Promise> { const url = constructUrlWithQueryParams( @@ -103,7 +103,7 @@ export class StorageBucket extends ApillonModel { } /** - * @dev Uploads files inside a folder via path. + * Uploads files inside a folder via path. * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index bf4b08e..043e380 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -7,7 +7,7 @@ import { StorageBucket } from './storage-bucket'; export class Storage extends ApillonModule { /** - * @dev API url for storage. + * API url for storage. */ private API_PREFIX = '/storage/buckets'; @@ -32,7 +32,6 @@ export class Storage extends ApillonModule { } /** - * @dev Returns a bucket instance. * @param uuid Unique bucket identifier. * @returns An instance of StorageBucket. */ diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index 400541d..46c102e 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -10,6 +10,7 @@ ], "exclude": [ "node_modules", - "dist" + "dist", + "docs" ] } From 08067670de54a8b841001d8e73b4b7ee0427127f Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 3 Nov 2023 13:03:12 +0100 Subject: [PATCH 34/68] Move file-utils to new util file --- packages/sdk/src/lib/common.ts | 54 --------- .../src/modules/hosting/hosting-website.ts | 51 +------- .../sdk/src/modules/storage/storage-bucket.ts | 59 +-------- packages/sdk/src/types/storage.ts | 2 +- packages/sdk/src/util/file-utils.ts | 113 ++++++++++++++++++ 5 files changed, 121 insertions(+), 158 deletions(-) create mode 100644 packages/sdk/src/util/file-utils.ts diff --git a/packages/sdk/src/lib/common.ts b/packages/sdk/src/lib/common.ts index ba90205..dcd87f5 100644 --- a/packages/sdk/src/lib/common.ts +++ b/packages/sdk/src/lib/common.ts @@ -1,8 +1,3 @@ -/* eslint-disable security/detect-non-literal-fs-filename */ -import * as fs from 'fs'; -import * as path from 'path'; -import axios from 'axios'; - export class ApillonApiError extends Error {} export class ApillonRequestError extends Error {} export class ApillonNetworkError extends Error {} @@ -48,55 +43,6 @@ export function constructUrlWithQueryParams(url: string, parameters: object) { return queryParams ? `${url}?${queryParams}` : url; } -export function listFilesRecursive( - folderPath, - fileList = [], - relativePath = '', -) { - const files = fs.readdirSync(folderPath); - for (const file of files) { - const fullPath = path.join(folderPath, file); - if (fs.statSync(fullPath).isDirectory()) { - listFilesRecursive(fullPath, fileList, `${relativePath + file}/`); - } else { - fileList.push({ fileName: file, path: relativePath, index: fullPath }); - } - } - return fileList.sort((a, b) => a.fileName.localeCompare(b.fileName)); -} - -export async function uploadFilesToS3(uploadLinks: any[], files: any[]) { - const s3Api = axios.create(); - const uploadWorkers = []; - - for (const link of uploadLinks) { - // console.log(link.url); - const file = files.find( - (x) => x.fileName === link.fileName && x.path === link.path, - ); - if (!file) { - throw new Error(`Cant find file ${link.path}${link.fileName}!`); - } - uploadWorkers.push( - new Promise((resolve, reject) => { - fs.readFile(file.index, async (err, data) => { - if (err) { - reject(err.message); - } - // const respS3 = - await s3Api.put(link.url, data); - // console.log(respS3); - - console.log(`File uploaded: ${file.fileName} `); - resolve(); - }); - }), - ); - } - - await Promise.all(uploadWorkers); -} - /** * Exception handler for requests sent by CLI service. * @param e exception diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index 4728c18..f0b01ba 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -1,8 +1,4 @@ -import { - constructUrlWithQueryParams, - listFilesRecursive, - uploadFilesToS3, -} from '../../lib/common'; +import { constructUrlWithQueryParams } from '../../lib/common'; import { DeployToEnvironment, IDeploymentFilters } from '../../types/hosting'; import { IApillonList, @@ -14,6 +10,7 @@ import { Deployment } from './deployment'; import { ApillonModel } from '../../docs-index'; import { ApillonApi } from '../../lib/apillon-api'; import { ApillonLogger } from '../../lib/apillon-logger'; +import { uploadFilesFromFolder } from '../../util/file-utils'; export class HostingWebsite extends ApillonModel { /** @@ -73,49 +70,7 @@ export class HostingWebsite extends ApillonModel { * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { - ApillonLogger.log( - `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, - LogLevel.VERBOSE, - ); - - let files; - try { - files = listFilesRecursive(folderPath); - } catch (err) { - ApillonLogger.log(err, LogLevel.ERROR); - throw new Error(`Error reading files in ${folderPath}`); - } - - const data = { files }; - ApillonLogger.log( - `Files to upload: ${data.files.length}`, - LogLevel.VERBOSE, - ); - - ApillonLogger.logWithTime('Get upload links', LogLevel.VERBOSE); - const { data: session } = await ApillonApi.post( - `${this.API_PREFIX}/upload`, - data, - ); - - ApillonLogger.logWithTime('Got upload links', LogLevel.VERBOSE); - - // console.log(resp); - const sessionUuid = session.sessionUuid; - - ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); - await uploadFilesToS3(session.files, files); - ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); - - ApillonLogger.log('Closing session...', LogLevel.VERBOSE); - const { data: endSession } = await ApillonApi.post( - `${this.API_PREFIX}/upload/${sessionUuid}/end`, - ); - ApillonLogger.log('Session ended.', LogLevel.VERBOSE); - - if (!endSession) { - throw new Error('Upload session did not end'); - } + await uploadFilesFromFolder(folderPath, this.API_PREFIX); } /** diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 47e6851..2341659 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -5,19 +5,11 @@ import { StorageContentType, } from '../../types/storage'; import { File } from './file'; -import { - constructUrlWithQueryParams, - listFilesRecursive, - uploadFilesToS3, -} from '../../lib/common'; -import { - IApillonList, - IApillonListResponse, - LogLevel, -} from '../../types/apillon'; +import { constructUrlWithQueryParams } from '../../lib/common'; +import { IApillonList, IApillonListResponse } from '../../types/apillon'; import { ApillonApi } from '../../lib/apillon-api'; import { ApillonModel } from '../../docs-index'; -import { ApillonLogger } from '../../lib/apillon-logger'; +import { uploadFilesFromFolder } from '../../util/file-utils'; export class StorageBucket extends ApillonModel { /** @@ -107,50 +99,7 @@ export class StorageBucket extends ApillonModel { * @param folderPath Path to the folder to upload. */ public async uploadFromFolder(folderPath: string): Promise { - ApillonLogger.log( - `Preparing to upload files from ${folderPath} to website ${this.uuid} ...`, - LogLevel.VERBOSE, - ); - let files; - try { - files = listFilesRecursive(folderPath); - } catch (err) { - console.error(err); - throw new Error(`Error reading files in ${folderPath}`); - } - - ApillonLogger.log(`Files to upload: ${files.length}`, LogLevel.VERBOSE); - - const { data } = await ApillonApi.post(`${this.API_PREFIX}/upload`, { - files, - }); - - const uploadLinks = data.files.sort((a, b) => - a.fileName.localeCompare(b.fileName), - ); - // Divide files into chunks for parallel processing and uploading - const chunkSize = 10; - const fileChunks = []; - for (let i = 0; i < files.length; i += chunkSize) { - const chunkFiles = files.slice(i, i + chunkSize); - const chunkLinks = uploadLinks.slice(i, i + chunkSize); - fileChunks.push({ chunkFiles, chunkLinks }); - } - await Promise.all( - fileChunks.map(({ chunkFiles, chunkLinks }) => - uploadFilesToS3(chunkLinks, chunkFiles), - ), - ); - - ApillonLogger.log('Closing upload session...', LogLevel.VERBOSE); - const { data: endSession } = await ApillonApi.post( - `${this.API_PREFIX}/upload/${data.sessionUuid}/end`, - ); - ApillonLogger.log('Session ended.', LogLevel.VERBOSE); - - if (!endSession) { - throw new Error('Failure when trying to end file upload session'); - } + await uploadFilesFromFolder(folderPath, this.API_PREFIX); } /** diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index 26a9fe3..55580f7 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -1,8 +1,8 @@ import { IApillonPagination } from './generic'; export enum StorageContentType { - FILE = 2, DIRECTORY = 1, + FILE = 2, } export enum FileStatus { diff --git a/packages/sdk/src/util/file-utils.ts b/packages/sdk/src/util/file-utils.ts new file mode 100644 index 0000000..2a5a41c --- /dev/null +++ b/packages/sdk/src/util/file-utils.ts @@ -0,0 +1,113 @@ +/* eslint-disable security/detect-non-literal-fs-filename */ +import * as fs from 'fs'; +import * as path from 'path'; +import axios from 'axios'; +import { ApillonLogger } from '../lib/apillon-logger'; +import { LogLevel } from '../types/apillon'; +import { ApillonApi } from '../lib/apillon-api'; + +export function listFilesRecursive( + folderPath: string, + fileList = [], + relativePath = '', +) { + const files = fs.readdirSync(folderPath); + for (const file of files) { + const fullPath = path.join(folderPath, file); + if (fs.statSync(fullPath).isDirectory()) { + listFilesRecursive(fullPath, fileList, `${relativePath + file}/`); + } else { + fileList.push({ fileName: file, path: relativePath, index: fullPath }); + } + } + return fileList.sort((a, b) => a.fileName.localeCompare(b.fileName)); +} + +export async function uploadFilesToS3(uploadLinks: any[], files: any[]) { + const s3Api = axios.create(); + const uploadWorkers = []; + + for (const link of uploadLinks) { + // console.log(link.url); + const file = files.find( + (x) => x.fileName === link.fileName && x.path === link.path, + ); + if (!file) { + throw new Error(`Cant find file ${link.path}${link.fileName}!`); + } + uploadWorkers.push( + new Promise((resolve, reject) => { + fs.readFile(file.index, async (err, data) => { + if (err) { + reject(err.message); + } + // const respS3 = + await s3Api.put(link.url, data); + // console.log(respS3); + + console.log(`File uploaded: ${file.fileName} `); + resolve(); + }); + }), + ); + } + + await Promise.all(uploadWorkers); +} + +export async function uploadFilesFromFolder( + folderPath: string, + apiPrefix: string, +): Promise { + ApillonLogger.log( + `Preparing to upload files from ${folderPath}...`, + LogLevel.VERBOSE, + ); + let files; + try { + files = listFilesRecursive(folderPath); + } catch (err) { + console.error(err); + throw new Error(`Error reading files in ${folderPath}`); + } + + ApillonLogger.log(`Files to upload: ${files.length}`, LogLevel.VERBOSE); + + const { data } = await ApillonApi.post(`${apiPrefix}/upload`, { + files, + }); + + const fileChunks = chunkify( + files, + data.files.sort((a, b) => a.fileName.localeCompare(b.fileName)), + ); + + await Promise.all( + fileChunks.map(({ chunkFiles, chunkLinks }) => + uploadFilesToS3(chunkLinks, chunkFiles), + ), + ); + ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); + + ApillonLogger.log('Closing upload session...', LogLevel.VERBOSE); + const { data: endSession } = await ApillonApi.post( + `${apiPrefix}/upload/${data.sessionUuid}/end`, + ); + ApillonLogger.logWithTime('Session ended.', LogLevel.VERBOSE); + + if (!endSession) { + throw new Error('Failure when trying to end file upload session'); + } +} + +function chunkify(files: any[], links: any[], chunkSize = 10) { + // Divide files into chunks for parallel processing and uploading + const fileChunks = []; + for (let i = 0; i < files.length; i += chunkSize) { + const chunkFiles = files.slice(i, i + chunkSize); + const chunkLinks = links.slice(i, i + chunkSize); + fileChunks.push({ chunkFiles, chunkLinks }); + } + + return fileChunks; +} From 5d3b08251b63edd45cd053fec002a0f7fa8f84a6 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 3 Nov 2023 13:15:30 +0100 Subject: [PATCH 35/68] CLI global option updates --- packages/cli/src/index.ts | 25 +++++++++++++++---- .../src/modules/hosting/hosting.commands.ts | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 76fcf22..9453125 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -6,6 +6,7 @@ import config from './config'; import { createHostingCommands } from './modules/hosting/hosting.commands'; import { createNftsCommands } from './modules/nfts/nfts.commands'; import { createStorageCommands } from './modules/storage/storage.commands'; +import { LogLevel } from '@apillon/sdk/dist/types/apillon'; const cli = new Command('apillon').version(config.VERSION); cli.addHelpText( @@ -22,18 +23,32 @@ Find more help at wiki.apillon.io! ); cli.addOption( - new Option('--key ', 'Apillon API key').env('APILLON_API_KEY'), + new Option('--key ', 'Apillon API key') + .env('APILLON_API_KEY') + .makeOptionMandatory(), ); cli.addOption( - new Option('--secret ', 'Apillon API secret').env( - 'APILLON_API_SECRET', - ), + new Option('--secret ', 'Apillon API secret') + .env('APILLON_API_SECRET') + .makeOptionMandatory(), ); cli.addOption( new Option('--api-url ', 'Apillon API secret') .env('APILLON_API_URL') - .default('https://api.apillon.io', 'Production API url'), + .default('https://api.apillon.io', 'Production API url') + .makeOptionMandatory(), ); +cli.addOption( + new Option('--log-level ', 'Level of output logging') + .env('APILLON_LOG_LEVEL') + .default(LogLevel.VERBOSE, 'Verbose logging (3)') + .choices([ + LogLevel.NONE.toString(), + LogLevel.ERROR.toString(), + LogLevel.VERBOSE.toString(), + ]), +); + cli.configureHelp({ showGlobalOptions: true, sortOptions: true, diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index 580e88d..7a3b8ca 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -27,7 +27,7 @@ export function createHostingCommands(cli: Command) { }); hosting - .command('upload-files') + .command('upload') .argument('', 'path to folder with website files') .requiredOption( '--uuid ', From 378578d61abc17702df2be21fd378700d3d8cc5b Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 3 Nov 2023 13:15:43 +0100 Subject: [PATCH 36/68] Push package versions to 1.0.0 --- package.json | 2 +- packages/cli/package.json | 2 +- packages/sdk/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 7752435..1ccffd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "apillon-web3-tools", - "version": "0.1.0", + "version": "1.0.0", "description": "Monorepo for Apillon tools", "author": "Apillon", "license": "MIT", diff --git a/packages/cli/package.json b/packages/cli/package.json index 56c5ef3..cf529c0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@apillon/cli", "description": "▶◀ Apillon CLI tools ▶◀", - "version": "0.1.2", + "version": "1.0.0", "author": "Apillon", "license": "MIT", "main": "./dist/index.js", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index dffada2..4b09cc1 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,7 +1,7 @@ { "name": "@apillon/sdk", "description": "▶◀ Apillon SDK for NodeJS ▶◀", - "version": "0.1.2", + "version": "1.0.0", "author": "Apillon", "license": "MIT", "main": "./dist/index.js", From bba57e7d181805ae2d96527c8b1d433374132222 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 9 Nov 2023 16:08:22 +0100 Subject: [PATCH 37/68] Update option choices description --- packages/cli/src/index.ts | 10 ++++++++-- packages/cli/src/modules/hosting/hosting.commands.ts | 9 ++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 9453125..8330594 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -6,7 +6,7 @@ import config from './config'; import { createHostingCommands } from './modules/hosting/hosting.commands'; import { createNftsCommands } from './modules/nfts/nfts.commands'; import { createStorageCommands } from './modules/storage/storage.commands'; -import { LogLevel } from '@apillon/sdk/dist/types/apillon'; +import { LogLevel } from '@apillon/sdk'; const cli = new Command('apillon').version(config.VERSION); cli.addHelpText( @@ -39,7 +39,13 @@ cli.addOption( .makeOptionMandatory(), ); cli.addOption( - new Option('--log-level ', 'Level of output logging') + new Option( + '--log-level ', + 'Sets the verbosity level for output logs. Choose from:\n' + + ` - ${LogLevel.NONE}: No logging.\n` + + ` - ${LogLevel.ERROR}: Log only error messages.\n` + + ` - ${LogLevel.VERBOSE}: Log all messages including errors, warnings, and informational messages.`, + ) .env('APILLON_LOG_LEVEL') .default(LogLevel.VERBOSE, 'Verbose logging (3)') .choices([ diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index 7a3b8ca..c2fe4e0 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -8,6 +8,7 @@ import { listWebsites, uploadWebsiteFiles, } from './hosting.service'; +import { DeployToEnvironment } from '@apillon/sdk'; export function createHostingCommands(cli: Command) { const hosting = cli.command('hosting'); @@ -41,7 +42,13 @@ export function createHostingCommands(cli: Command) { .command('deploy') .requiredOption('--uuid ', 'UUID of website to deploy') .addOption( - new Option('--env ', 'Environment to deploy to') + new Option( + '--env ', + 'Sets the environment to deploy the files to. Choose from:\n' + + ` - ${DeployToEnvironment.TO_STAGING}: To staging.\n` + + ` - ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production.\n` + + ` - ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production.`, + ) .choices(['1', '2', '3']) .makeOptionMandatory(true), ) From e1c25a7745be2b8ece9a74907ba66a51ffb22833 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 9 Nov 2023 16:08:40 +0100 Subject: [PATCH 38/68] Update SDK exports --- packages/sdk/src/docs-index.ts | 2 +- packages/sdk/src/index.ts | 2 +- packages/sdk/src/lib/apillon-api.ts | 2 +- packages/sdk/src/types/apillon.ts | 7 +++++++ packages/sdk/src/types/generic.ts | 6 ------ packages/sdk/src/types/hosting.ts | 2 +- packages/sdk/src/types/nfts.ts | 2 +- packages/sdk/src/types/storage.ts | 2 +- 8 files changed, 13 insertions(+), 12 deletions(-) delete mode 100644 packages/sdk/src/types/generic.ts diff --git a/packages/sdk/src/docs-index.ts b/packages/sdk/src/docs-index.ts index 8f0d39f..a55b873 100644 --- a/packages/sdk/src/docs-index.ts +++ b/packages/sdk/src/docs-index.ts @@ -1,4 +1,4 @@ -export * from './types/generic'; +export * from './types/apillon'; export * from './types/nfts'; export * from './types/hosting'; export * from './types/storage'; diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index 4cdcd58..87307e0 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,4 +1,4 @@ -export * from './types/generic'; +export * from './types/apillon'; export * from './types/nfts'; export * from './types/hosting'; export * from './types/storage'; diff --git a/packages/sdk/src/lib/apillon-api.ts b/packages/sdk/src/lib/apillon-api.ts index c0682a8..0880f1f 100644 --- a/packages/sdk/src/lib/apillon-api.ts +++ b/packages/sdk/src/lib/apillon-api.ts @@ -46,7 +46,7 @@ export class ApillonApi { this.instance.interceptors.response.use( (response) => response, (error) => { - ApillonLogger.log(error, LogLevel.ERROR); + // ApillonLogger.log(error, LogLevel.ERROR); if (error.response?.data) { throw new ApillonApiError( JSON.stringify(error.response.data, null, 2), diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index 2233ffe..be758b2 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -13,6 +13,13 @@ export interface IApillonStatus { status: number; } +export interface IApillonPagination { + page?: number; + limit?: number; + orderBy?: string; + desc?: boolean; +} + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface IApillonListResponse extends IApillonResponse> {} diff --git a/packages/sdk/src/types/generic.ts b/packages/sdk/src/types/generic.ts deleted file mode 100644 index ff89206..0000000 --- a/packages/sdk/src/types/generic.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IApillonPagination { - page?: number; - limit?: number; - orderBy?: string; - desc?: boolean; -} diff --git a/packages/sdk/src/types/hosting.ts b/packages/sdk/src/types/hosting.ts index 2481f1c..7540918 100644 --- a/packages/sdk/src/types/hosting.ts +++ b/packages/sdk/src/types/hosting.ts @@ -1,4 +1,4 @@ -import { IApillonPagination } from './generic'; +import { IApillonPagination } from './apillon'; export enum DeployToEnvironment { TO_STAGING = 1, diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index 099f5df..e4971de 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -1,4 +1,4 @@ -import { IApillonPagination } from './generic'; +import { IApillonPagination } from './apillon'; export enum EvmChain { MOONBEAM = 1284, diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index 55580f7..ddecc4c 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -1,4 +1,4 @@ -import { IApillonPagination } from './generic'; +import { IApillonPagination } from './apillon'; export enum StorageContentType { DIRECTORY = 1, From 59ede0a54eb7ed9e935af9b579bee816893b2852 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 14 Nov 2023 13:13:00 +0100 Subject: [PATCH 39/68] Implement upload-deploy CLI command --- .../src/modules/hosting/hosting.commands.ts | 23 +++++++++++++++++++ .../src/modules/hosting/hosting.service.ts | 14 +++++++++++ 2 files changed, 37 insertions(+) diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index c2fe4e0..b2bcdc0 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -6,6 +6,7 @@ import { getWebsite, listDeployments, listWebsites, + uploadAndDeploy, uploadWebsiteFiles, } from './hosting.service'; import { DeployToEnvironment } from '@apillon/sdk'; @@ -56,6 +57,28 @@ export function createHostingCommands(cli: Command) { await deployToEnvironment(this.optsWithGlobals()); }); + hosting + .command('upload-deploy') + .argument('', 'path to folder with website files') + .requiredOption( + '--uuid ', + 'UUID of website to upload files to and deploy', + ) + .addOption( + new Option( + '--env ', + 'Sets the environment to deploy the files to. Choose from:\n' + + ` - ${DeployToEnvironment.TO_STAGING}: To staging.\n` + + ` - ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production.\n` + + ` - ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production.`, + ) + .choices(['1', '2', '3']) + .makeOptionMandatory(true), + ) + .action(async function (path: string) { + await uploadAndDeploy(path, this.optsWithGlobals()); + }); + const hostingListDeployments = hosting .command('list-deployments') .requiredOption( diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index 42fd1c1..f688638 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -43,6 +43,20 @@ export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { } } +export async function uploadAndDeploy( + path: string, + optsWithGlobals: GlobalOptions, +) { + const hosting = new Hosting(optsWithGlobals); + try { + await hosting.website(optsWithGlobals.uuid).uploadFromFolder(path); + await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); + console.log('Deploy successful'); + } catch (err) { + exceptionHandler(err); + } +} + export async function listDeployments(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); const params = From a3da47153293d6c671f8deb5a2bc432ac73a6b97 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 14 Nov 2023 13:25:32 +0100 Subject: [PATCH 40/68] SDK logging updates --- packages/sdk/src/lib/apillon-logger.ts | 4 +- .../sdk/src/modules/hosting/deployment.ts | 7 +--- .../src/modules/hosting/hosting-website.ts | 6 +-- .../sdk/src/modules/nft/nft-collection.ts | 12 ++++-- packages/sdk/src/modules/storage/directory.ts | 2 +- packages/sdk/src/modules/storage/file.ts | 37 +++---------------- packages/sdk/src/util/file-utils.ts | 14 +++---- 7 files changed, 26 insertions(+), 56 deletions(-) diff --git a/packages/sdk/src/lib/apillon-logger.ts b/packages/sdk/src/lib/apillon-logger.ts index 1f42ff4..0bffef8 100644 --- a/packages/sdk/src/lib/apillon-logger.ts +++ b/packages/sdk/src/lib/apillon-logger.ts @@ -7,7 +7,7 @@ export class ApillonLogger { this.logLevel = logLevel || LogLevel.NONE; } - static log(message: any, logLevel: LogLevel) { + static log(message: any, logLevel: LogLevel = LogLevel.VERBOSE) { if (this.logLevel >= logLevel) { if (message instanceof Object) { console.log(JSON.stringify(message)); @@ -17,7 +17,7 @@ export class ApillonLogger { } } - static logWithTime(message: any, logLevel: LogLevel) { + static logWithTime(message: any, logLevel: LogLevel = LogLevel.VERBOSE) { if (this.logLevel >= logLevel) { if (message instanceof Object) { console.log(`${new Date().toISOString()}: `, JSON.stringify(message)); diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index de9c2e2..1fff6e5 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -1,8 +1,7 @@ import { ApillonModel } from '../../lib/apillon'; import { DeployToEnvironment, DeploymentStatus } from '../../docs-index'; -import { IApillonResponse, LogLevel } from '../../types/apillon'; +import { IApillonResponse } from '../../types/apillon'; import { ApillonApi } from '../../lib/apillon-api'; -import { ApillonLogger } from '../../lib/apillon-logger'; export class Deployment extends ApillonModel { /** @@ -61,10 +60,6 @@ export class Deployment extends ApillonModel { * Gets deployment details. */ async get(): Promise { - ApillonLogger.log( - `Get deployment for website ${this.uuid}`, - LogLevel.VERBOSE, - ); const { data } = await ApillonApi.get>( this.API_PREFIX, ); diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index f0b01ba..c5d5550 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -4,7 +4,6 @@ import { IApillonList, IApillonListResponse, IApillonResponse, - LogLevel, } from '../../types/apillon'; import { Deployment } from './deployment'; import { ApillonModel } from '../../docs-index'; @@ -85,15 +84,14 @@ export class HostingWebsite extends ApillonModel { ? 'preview' : 'production' })`, - LogLevel.VERBOSE, ); - ApillonLogger.logWithTime('Deploy start', LogLevel.VERBOSE); + ApillonLogger.logWithTime('Deploy start'); const { data } = await ApillonApi.post(`${this.API_PREFIX}/deploy`, { environment: toEnvironment, }); - ApillonLogger.logWithTime('Deploy complete', LogLevel.VERBOSE); + ApillonLogger.logWithTime('Deploy complete'); return data; } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index e91255f..7d82c32 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -1,5 +1,6 @@ import { ApillonModel } from '../../docs-index'; import { ApillonApi } from '../../lib/apillon-api'; +import { ApillonLogger } from '../../lib/apillon-logger'; import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonResponse, @@ -147,6 +148,8 @@ export class NftCollection extends ApillonModel { IApillonResponse >(`${this.API_PREFIX}/mint`, { receivingAddress: receiver, quantity }); + ApillonLogger.log(`NFT minted successfully to ${receiver}`); + return data; } @@ -174,24 +177,26 @@ export class NftCollection extends ApillonModel { { parentCollectionUuid, parentNftId, quantity }, ); + ApillonLogger.log(`NFT nest minted successfully on NFT ${parentNftId}`); return data; } /** * Burns a nft. * @warn Can only burn NFTs if the collection is revokable. - * @param id Id of the NFT we want to burn. + * @param tokenId Token ID of the NFT we want to burn. * @returns Status. */ - public async burn(id: string): Promise { + public async burn(tokenId: string): Promise { if (this.isRevokable != null && !this.isRevokable) { throw new Error('Collection is not revokable.'); } const { data } = await ApillonApi.post>( `${this.API_PREFIX}/burn`, - { tokenId: id }, + { tokenId }, ); + ApillonLogger.log(`NFT ${tokenId} burned successfully`); return data; } @@ -210,6 +215,7 @@ export class NftCollection extends ApillonModel { this.populate(data); + ApillonLogger.log(`NFT collection transferred successfully to ${address}`); return this; } diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index c6c7e1e..16e289f 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -12,7 +12,7 @@ export class Directory extends ApillonModel { /** * Unique identifier of the bucket. */ - public bucketUuid; + public bucketUuid: string = null; /** * Directory name. diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index d3650f6..460a0da 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -1,22 +1,18 @@ import { AxiosResponse } from 'axios'; import { ApillonApi } from '../../lib/apillon-api'; import { FileStatus, StorageContentType } from '../../types/storage'; +import { ApillonModel } from '../../docs-index'; -export class File { - /** - * API url prefix for this class. - */ - private API_PREFIX: string = null; - +export class File extends ApillonModel { /** * Unique identifier of the file's bucket. */ - public bucketUuid: string; + public bucketUuid: string = null; /** - * Unique identifier of the file. + * Id of the directory in which the file resides. */ - public uuid: string; + public directoryUuid: string = null; /** * File name. @@ -33,11 +29,6 @@ export class File { */ public status: FileStatus = null; - /** - * Id of the directory in which the file resides. - */ - public directoryUuid: string = null; - /** * Type of content. */ @@ -56,30 +47,14 @@ export class File { fileUuid: string, data?: Partial, ) { + super(fileUuid); this.bucketUuid = bucketUuid; - this.uuid = fileUuid; this.directoryUuid = directoryUuid; this.API_PREFIX = `/storage/${bucketUuid}/file/${fileUuid}`; this.status = data?.fileStatus; this.populate(data); } - /** - * Populates class properties via data object. - * @param data Data object. - */ - private populate(data: any) { - if (data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - return this; - } - /** * Gets file details. */ diff --git a/packages/sdk/src/util/file-utils.ts b/packages/sdk/src/util/file-utils.ts index 2a5a41c..4a73438 100644 --- a/packages/sdk/src/util/file-utils.ts +++ b/packages/sdk/src/util/file-utils.ts @@ -3,7 +3,6 @@ import * as fs from 'fs'; import * as path from 'path'; import axios from 'axios'; import { ApillonLogger } from '../lib/apillon-logger'; -import { LogLevel } from '../types/apillon'; import { ApillonApi } from '../lib/apillon-api'; export function listFilesRecursive( @@ -59,10 +58,7 @@ export async function uploadFilesFromFolder( folderPath: string, apiPrefix: string, ): Promise { - ApillonLogger.log( - `Preparing to upload files from ${folderPath}...`, - LogLevel.VERBOSE, - ); + ApillonLogger.log(`Preparing to upload files from ${folderPath}...`); let files; try { files = listFilesRecursive(folderPath); @@ -71,7 +67,7 @@ export async function uploadFilesFromFolder( throw new Error(`Error reading files in ${folderPath}`); } - ApillonLogger.log(`Files to upload: ${files.length}`, LogLevel.VERBOSE); + ApillonLogger.log(`Total files to upload: ${files.length}`); const { data } = await ApillonApi.post(`${apiPrefix}/upload`, { files, @@ -87,13 +83,13 @@ export async function uploadFilesFromFolder( uploadFilesToS3(chunkLinks, chunkFiles), ), ); - ApillonLogger.logWithTime('File upload complete', LogLevel.VERBOSE); + ApillonLogger.logWithTime('File upload complete'); - ApillonLogger.log('Closing upload session...', LogLevel.VERBOSE); + ApillonLogger.log('Closing upload session...'); const { data: endSession } = await ApillonApi.post( `${apiPrefix}/upload/${data.sessionUuid}/end`, ); - ApillonLogger.logWithTime('Session ended.', LogLevel.VERBOSE); + ApillonLogger.logWithTime('Session ended.'); if (!endSession) { throw new Error('Failure when trying to end file upload session'); From fc117601ec440c8e3dac441d3a5ef3b4c96f8db1 Mon Sep 17 00:00:00 2001 From: Tine Mlakar Date: Wed, 15 Nov 2023 08:54:21 +0100 Subject: [PATCH 41/68] cli hosting refactored --- packages/cli/src/index.ts | 6 ++-- .../src/modules/hosting/hosting.commands.ts | 31 ++++++++++++++++--- .../src/modules/hosting/hosting.service.ts | 23 +++++++++++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 8330594..7eafbb5 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -42,9 +42,9 @@ cli.addOption( new Option( '--log-level ', 'Sets the verbosity level for output logs. Choose from:\n' + - ` - ${LogLevel.NONE}: No logging.\n` + - ` - ${LogLevel.ERROR}: Log only error messages.\n` + - ` - ${LogLevel.VERBOSE}: Log all messages including errors, warnings, and informational messages.`, + ` ${LogLevel.NONE}: No logging.\n` + + ` ${LogLevel.ERROR}: Log only error messages.\n` + + ` ${LogLevel.VERBOSE}: Log all messages including errors, warnings, and informational messages.\n`, ) .env('APILLON_LOG_LEVEL') .default(LogLevel.VERBOSE, 'Verbose logging (3)') diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index c2fe4e0..21bc04f 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -7,14 +7,28 @@ import { listDeployments, listWebsites, uploadWebsiteFiles, + deployWebsite, } from './hosting.service'; import { DeployToEnvironment } from '@apillon/sdk'; export function createHostingCommands(cli: Command) { const hosting = cli.command('hosting'); + hosting + .command('deploy-website') + .description( + 'Deploys website directly from local folder to Apillon hosting production environment', + ) + .argument('', 'path to folder with website files') + .requiredOption('--uuid ', 'UUID of website to deploy') + .option('-p, --preview', 'deploys to staging environment') + .action(async function (path) { + await deployWebsite(path, this.optsWithGlobals()); + }); + const hostingList = hosting .command('list-websites') + .description('List websites on Apillon hosting') .action(async function () { await listWebsites(this.optsWithGlobals()); }); @@ -22,13 +36,15 @@ export function createHostingCommands(cli: Command) { hosting .command('get-website') + .description('Returns website data') .requiredOption('--uuid ', 'UUID of website to get') .action(async function () { await getWebsite(this.optsWithGlobals()); }); hosting - .command('upload') + .command('upload-files') + .description('Uploads files from local folder to deployment bucket') .argument('', 'path to folder with website files') .requiredOption( '--uuid ', @@ -39,15 +55,18 @@ export function createHostingCommands(cli: Command) { }); hosting - .command('deploy') + .command('start-deployment') + .description( + 'Starts deployment of website from uploaded files in deployment bucket', + ) .requiredOption('--uuid ', 'UUID of website to deploy') .addOption( new Option( '--env ', 'Sets the environment to deploy the files to. Choose from:\n' + - ` - ${DeployToEnvironment.TO_STAGING}: To staging.\n` + - ` - ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production.\n` + - ` - ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production.`, + ` ${DeployToEnvironment.TO_STAGING}: To Staging.\n` + + ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production.\n` + + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production.`, ) .choices(['1', '2', '3']) .makeOptionMandatory(true), @@ -58,6 +77,7 @@ export function createHostingCommands(cli: Command) { const hostingListDeployments = hosting .command('list-deployments') + .description('Returns list of started deployments') .requiredOption( '--uuid ', 'UUID of website to list deployments for', @@ -71,6 +91,7 @@ export function createHostingCommands(cli: Command) { hosting .command('get-deployment') + .description('Returns deployment data') .requiredOption('--uuid ', 'UUID of website') .requiredOption( '--deployment-uuid ', diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index 42fd1c1..2b25eea 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -1,4 +1,4 @@ -import { Hosting, exceptionHandler } from '@apillon/sdk'; +import { Hosting, exceptionHandler, DeployToEnvironment } from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; export async function listWebsites(optsWithGlobals: GlobalOptions) { @@ -21,6 +21,27 @@ export async function getWebsite(optsWithGlobals: GlobalOptions) { } } +export async function deployWebsite( + path: string, + optsWithGlobals: GlobalOptions, +) { + const hosting = new Hosting(optsWithGlobals); + try { + const website = hosting.website(optsWithGlobals.uuid); + await website.uploadFromFolder(path); + const deployment = await website.deploy( + optsWithGlobals.preview + ? DeployToEnvironment.TO_STAGING + : DeployToEnvironment.DIRECTLY_TO_PRODUCTION, + ); + const deploymentData = await website.deployment(deployment.deployment_uuid); + console.log(`Deployment started!`); + console.log(deploymentData); + } catch (err) { + exceptionHandler(err); + } +} + export async function uploadWebsiteFiles( path: string, optsWithGlobals: GlobalOptions, From 989916b922f0fdeb8fd5404d796adb49f0b816fc Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 14 Nov 2023 14:40:08 +0100 Subject: [PATCH 42/68] Update CLI documentation --- EXAMPLE.md | 3 + packages/cli/README.md | 222 ++++++++++++++++++----- packages/sdk/src/lib/apillon-api.ts | 2 +- packages/sdk/src/tests/helpers/helper.ts | 2 + 4 files changed, 185 insertions(+), 44 deletions(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index 91b5df0..7c24390 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -14,6 +14,9 @@ export async function test() { await webpage1.deploy(DeployToEnvironment.STAGING_TO_PRODUCTION); await webpage1.listDeployments(); const deployment = await webpage1.deployment(deployment_uuid).get(); + if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { + // done + } // Storage example const storage = new Storage({ apillonConfig }); diff --git a/packages/cli/README.md b/packages/cli/README.md index 214f636..9f04bf1 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -31,72 +31,208 @@ npx @apillon/cli [options] > Note that when running without installation, you have to use `@apillon/cli` instead of `apillon` execution command. -## Commands -The Apillon CLI currently supports the following command: +### Global Options -### `hosting` +- `--api-url `: Apillon API URL (default: Production API URL, can be set via the `APILLON_API_URL` environment + variable). +- `--key `: Apillon API key (can be set via the `APILLON_API_KEY` environment variable). +- `--secret `: Apillon API secret (can be set via the `APILLON_API_SECRET` environment variable). +- `-- log-level `: Sets the verbosity level for output logs. Choose from: 1: No logging, 2: Log only error messages and 3: Log all messages including errors, warnings, and informational messages. +- `-V`, `--version`: Output the version number. -To be able to deploy a website with Apillon CLI, you have to create a website deployment inside your project on [Apillon Developer dashboard](https://app.apillon.io/dashboard/service/hosting). Upon creating a website deployment, you will get the website UUID number, that you will need to run CLI hosting commands. +### Environment Variables -#### `hosting deploy-website` +You can use environment variables to set the API URL, API key, and API secret: -Deploy your website to with Apillon Web3 platform to decentralized storage (IPFS) and pin it with Crust blockchain protocol. +- `APILLON_API_URL`: Apillon API URL. +- `APILLON_API_KEY`: Apillon API key. +- `APILLON_API_SECRET`: Apillon API secret. -#### Arguments +If you have these variables set, you do not need to use the global options each time. -- `path`: Path to the folder containing your website files. +### Help -#### Options +To display the help information for the CLI or a specific command, use the `-h` or `--help` option: -- `-h`, `--help`: Display help for the command. -- `-p`, `--preview`: Deploy to the staging environment. -- `--uuid `: UUID of the website to deploy. +```sh +apillon -h +apillon hosting -h +npx @apillon/cli hosting deploy-website --help +``` +# Commands -#### Global Options +The Apillon CLI currently supports the following commands: -- `--api-url `: Apillon API URL (default: Production API URL, can be set via the `APILLON_API_URL` environment - variable). -- `--key `: Apillon API key (can be set via the `APILLON_API_KEY` environment variable). -- `--secret `: Apillon API secret (can be set via the `APILLON_API_SECRET` environment variable). -- `-V`, `--version`: Output the version number. +## `Hosting` -#### Example +To be able to deploy a website with Apillon CLI, you have to create a website deployment inside your project on [Apillon Developer dashboard](https://app.apillon.io/dashboard/service/hosting). Upon creating a website deployment, you will get the website UUID number, that you will need to run CLI hosting commands. -To deploy a website located in the ./dist folder with a specific UUID, API key, and API secret, run: +#### `hosting list-websites` -```bash -apillon hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret -# or -npx @apillon/cli hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret +This command lists all websites associated with your project. + +```sh +apillon hosting list-websites ``` -To deploy the website to the staging environment, use the --preview flag: +#### `hosting get-website` +This command retrieves information about a specific website. -```bash -apillon hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret --preview -# or -npx @apillon/cli hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret --preview +#### `hosting upload` +This command uploads website files to a specified website. + +**Arguments** +- ``: Path to the folder containing your website files. +- --uuid ``: UUID of the website to upload files to. + +**Example** +```sh +apillon hosting upload --uuid your-website-uuid ./public_html ``` -## Environment Variables +#### `hosting deploy` +This command deploys a website to the specified environment. -You can use environment variables to set the API URL, API key, and API secret: +**Arguments** +- --uuid ``:: UUID of the website to deploy. +- --env ``: The environment to deploy to. Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. -- `APILLON_API_URL`: Apillon API URL. -- `APILLON_API_KEY`: Apillon API key. -- `APILLON_API_SECRET`: Apillon API secret. +**Example** +```sh +apillon hosting deploy --uuid your-website-uuid production +``` -## Help +#### `hosting upload-deploy` +This command uploads website files and immediately deploys them to the specified environment. -To display the help information for the CLI or a specific command, use the `-h` or `--help` option: +**Arguments** +- ``: Path to the folder containing your website files. +- --uuid ``:: UUID of the website to upload files to and deploy. +- -- env ``: The environment to deploy to. Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. +**Example** ```sh -apillon -h -apillon hosting -h -npx @apillon/cli hosting deploy-website --help +apillon hosting upload-deploy ./public_html --uuid your-website-uuid --env 2 ``` + +#### `hosting list-deployments` +This command lists all deployments for a specific website. + +**Arguments** +- --uuid ``: UUID of the website to upload list deployments for. + +#### `hosting get-deployment` +This command retrieves information about a specific deployment. + +**Arguments** +- --uuid ``: UUID of the website. +- -- deployment-uuid ``: UUID of the deployment + + +## `Storage` +#### `storage list-buckets` + +This command lists all storage buckets associated with your project. + +#### `storage get-objects` + +This command retrieves objects (files and directories) recursively from a specific bucket. + +**Arguments** +- --uuid ``: UUID of the bucket to retrieve objects from. + +#### `storage get-files` +This command retrieves files from a specific bucket. + +**Arguments** +- --uuid ``: UUID of the bucket to retrieve files from. + +#### `storage upload` +This command uploads files to a specified bucket. + +**Arguments** +- ``: Path to the folder containing your files. +- --uuid ``: UUID of the bucket to upload files to. + +**Example** +```sh +apillon storage upload --uuid your-bucket-uuid ./my_folder +``` +#### `storage file` + +This command retrieves information about a specific file in a bucket. + +**Arguments** +- --uuid ``: UUID of the bucket. +- --file-uuid ``: UUID of the file to retrieve. + +#### `storage delete-file` + +This command deletes a specific file from a bucket. + +**Arguments** +- --uuid ``: UUID of the bucket. +- --file-uuid ``: UUID of the file to delete. + +## `NFTs` + +#### `nfts list-collections` +This command lists all NFT collections owned by the project related to the API key. + +#### `nfts get-collection` +This command retrieves information about a specific NFT collection. + +**Arguments** +- ``: UUID of the collection to retrieve. + +#### `nfts create-collection` +This command creates a new NFT collection. The JSON file needs to have the property structure as type `ICreateCollection`, which can be found in the SDK docs. + +**Arguments** +- ``: Path to the JSON data file for the new collection. + +#### `nfts mint-nft` +This command mints NFTs for a collection with a specific UUID. + +**Arguments** +- ``: UUID of the collection to mint NFTs to. +- --address ``: Address which will receive minted NFTs. + +- --number ``: Number of NFTs to mint. +#### `nfts nest-mint-nft` +This command nest mints NFT child collection to a parent collection with a specific UUID and parent NFT with id. + +**Arguments** +- ``: Child collection UUID. +- --parent-collection-uuid ``: Parent collection UUID to which child NFTs will be minted to. +- --parent-nft-id ``: Parent collection NFT id to which child NFTs will be minted to. +- --number ``: Number of child NFTs to mint. + +#### `nfts burn-nft` +This command burns NFT for a collection with a specific UUID. + +**Arguments** +- ``: Collection UUID. +- --token-id ````: NFT id which will be burned. + +#### `nfts transfer-collection` +This command transfers NFT collection ownership to a new wallet address. + +**Arguments** +- ``: Collection UUID. +- --address ``: Address which you want to transfer collection ownership to. + +#### `nfts list-transactions` +This command lists NFT transactions for a specific collection UUID. + +**Arguments** +- ``: Collection UUID. +- --status ``: Transaction status (optional). +- --type ``: Transaction type (optional). + + ## Using in CI/CD tools CLI is particularly useful for CI/CD builds and pipelines. @@ -125,10 +261,10 @@ jobs: uses: actions/setup-node@v3 with: node-version: 16 - + - name: Create dist folder run: mkdir -p dist - + - name: Copy files run: | cp *.html dist/ @@ -137,9 +273,9 @@ jobs: cp -r js dist/ #### -## if you are using a framework for building web app, you can replace previous two step with the +## if you are using a framework for building web app, you can replace previous two step with the ## appropriate command for generating static webpage, like an example bellow. -## Find the correct command in your framework documentation. You may need to to change the +## Find the correct command in your framework documentation. You may need to to change the ## name of the source folder in the last step (CLI call) #### diff --git a/packages/sdk/src/lib/apillon-api.ts b/packages/sdk/src/lib/apillon-api.ts index 0880f1f..f93ad9d 100644 --- a/packages/sdk/src/lib/apillon-api.ts +++ b/packages/sdk/src/lib/apillon-api.ts @@ -38,7 +38,7 @@ export class ApillonApi { this.instance.interceptors.request.use( (request) => request, (error) => { - ApillonLogger.log(error, LogLevel.ERROR); + ApillonLogger.log(error.message, LogLevel.ERROR); throw new ApillonRequestError(error.request); }, ); diff --git a/packages/sdk/src/tests/helpers/helper.ts b/packages/sdk/src/tests/helpers/helper.ts index a463862..8bfe789 100644 --- a/packages/sdk/src/tests/helpers/helper.ts +++ b/packages/sdk/src/tests/helpers/helper.ts @@ -1,6 +1,7 @@ import * as dotenv from 'dotenv'; import { ApillonConfig } from '../../lib/apillon'; import { resolve } from 'path'; +import { LogLevel } from '../../types/apillon'; export function getConfig(): ApillonConfig { // Configure dotenv with the absolute path @@ -11,6 +12,7 @@ export function getConfig(): ApillonConfig { apiUrl: process.env['APILLON_API_URL'], secret: process.env['APILLON_API_SECRET'], key: process.env['APILLON_API_KEY'], + logLevel: LogLevel.VERBOSE, } as ApillonConfig; } From bcdafabfd4395826978743e977e80a94c8272f70 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Wed, 15 Nov 2023 14:34:46 +0100 Subject: [PATCH 43/68] Fix file UUID reference --- packages/sdk/src/modules/storage/storage-bucket.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 2341659..d8b5537 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -84,12 +84,14 @@ export class StorageBucket extends ApillonModel { `/storage/buckets/${this.uuid}/files`, params, ); - const { data } = await ApillonApi.get>(url); + const { data } = await ApillonApi.get< + IApillonListResponse + >(url); return { total: data.total, items: data.items.map( - (file) => new File(this.uuid, file.directoryUuid, file.uuid, file), + (file) => new File(this.uuid, file.directoryUuid, file.fileUuid, file), ), }; } From f0122620878d5aece21595db13a8695903fe0b5d Mon Sep 17 00:00:00 2001 From: Tine Mlakar Date: Thu, 16 Nov 2023 10:33:47 +0100 Subject: [PATCH 44/68] refactoring - work in progress --- packages/cli/package.json | 2 +- packages/cli/src/config.ts | 2 +- packages/cli/src/index.ts | 16 +---- .../src/modules/hosting/hosting.commands.ts | 10 +-- .../cli/src/modules/nfts/nfts.commands.ts | 35 ++++++---- .../src/modules/storage/storage.commands.ts | 65 ++++++++++++------- .../src/modules/storage/storage.service.ts | 22 +++---- packages/sdk/src/lib/apillon.ts | 17 ++++- packages/sdk/src/modules/storage/directory.ts | 13 ++++ packages/sdk/src/modules/storage/file.ts | 37 ++++------- 10 files changed, 126 insertions(+), 93 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index cf529c0..a7ef38e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,7 +24,7 @@ "build": "tsc --declarationMap", "dev": "tsc --declarationMap --watch", "lint": "tsc --declarationMap && eslint \"{src,test}/**/*.ts\" --fix", - "cli-install": "tsc && npm i -g", + "cli-install": "tsc && npm uninstall -g ; npm i -g", "publish-package": "npm publish" }, "bin": { diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index 4558830..75b3a79 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -16,7 +16,7 @@ function getVersion(rollback: string) { } export default { - VERSION: getVersion('0.0.1'), + VERSION: getVersion('1.0.0'), APILLON_API_KEY: process.env.APILLON_API_KEY, APILLON_API_SECRET: process.env.APILLON_API_SECRET, APILLON_API_URL: process.env.APILLON_API_URL || 'https://api.apillon.io', diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 7eafbb5..1b6e95e 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -38,21 +38,9 @@ cli.addOption( .default('https://api.apillon.io', 'Production API url') .makeOptionMandatory(), ); + cli.addOption( - new Option( - '--log-level ', - 'Sets the verbosity level for output logs. Choose from:\n' + - ` ${LogLevel.NONE}: No logging.\n` + - ` ${LogLevel.ERROR}: Log only error messages.\n` + - ` ${LogLevel.VERBOSE}: Log all messages including errors, warnings, and informational messages.\n`, - ) - .env('APILLON_LOG_LEVEL') - .default(LogLevel.VERBOSE, 'Verbose logging (3)') - .choices([ - LogLevel.NONE.toString(), - LogLevel.ERROR.toString(), - LogLevel.VERBOSE.toString(), - ]), + new Option('--debug', 'Output debug messages').env('APILLON_DEBUG'), ); cli.configureHelp({ diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index 21bc04f..e72c289 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -12,7 +12,9 @@ import { import { DeployToEnvironment } from '@apillon/sdk'; export function createHostingCommands(cli: Command) { - const hosting = cli.command('hosting'); + const hosting = cli + .command('hosting') + .description('Commands for managing websites on Apillon hosting'); hosting .command('deploy-website') @@ -64,9 +66,9 @@ export function createHostingCommands(cli: Command) { new Option( '--env ', 'Sets the environment to deploy the files to. Choose from:\n' + - ` ${DeployToEnvironment.TO_STAGING}: To Staging.\n` + - ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production.\n` + - ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production.`, + ` ${DeployToEnvironment.TO_STAGING}: To Staging\n` + + ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production\n` + + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production`, ) .choices(['1', '2', '3']) .makeOptionMandatory(true), diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index 0cdc205..4d643ed 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -13,12 +13,16 @@ import { Options } from '../../lib/types'; import { addPaginationOptions } from '../../lib/options'; export function createNftsCommands(cli: Command) { - const nfts = cli.command('nfts'); + const nfts = cli + .command('nfts') + .description( + 'Commands for managing NFT collections and tokens on Apillon platform', + ); // COLLECTIONS const listCollectionsCommand = nfts .command('list-collections') - .description('List NFT collections owned by project related to API key.') + .description('List NFT collections owned by project') .addOption(new Option('-s, --status ', 'Collection status')) .action(async function (options: Options) { await listCollections(options, this.optsWithGlobals()); @@ -27,7 +31,7 @@ export function createNftsCommands(cli: Command) { nfts .command('get-collection') - .description('Get NFT collection for specific UUID.') + .description('Get NFT collection details.') .argument('', 'Collection UUID') .action(async function (uuid: string) { await getCollection(uuid, this.optsWithGlobals()); @@ -35,6 +39,7 @@ export function createNftsCommands(cli: Command) { nfts .command('create-collection') + .description('Create NFT collection from JSON file') .argument('', 'path to JSON data file') .action(async function (filePath: string) { await createCollection(filePath, this.optsWithGlobals()); @@ -42,7 +47,7 @@ export function createNftsCommands(cli: Command) { nfts .command('mint-nft') - .description('Mint NFT for collection with UUID.') + .description('Mint NFT from collection') .argument('', 'Collection UUID') .requiredOption( '-a, --address ', @@ -55,9 +60,7 @@ export function createNftsCommands(cli: Command) { nfts .command('nest-mint-nft') - .description( - 'Nest mint NFT child collection to parent collection with UUID and NFT with id.', - ) + .description('Nest mint NFT child collection to parent NFT') .argument('', 'Child collection UUID') .requiredOption( '-c, --parent-collection-uuid ', @@ -65,29 +68,33 @@ export function createNftsCommands(cli: Command) { ) .requiredOption( '-i, --parent-nft-id ', - 'Parent collection NFT id to which child NFTs will be minted to.', + 'Parent NFT id to which child NFTs will be minted to', + ) + .requiredOption( + '-n, --number ', + 'Number of child NFTs to mint', + '1', ) - .requiredOption('-n, --number ', 'Number of child NFTs to mint.') .action(async function (uuid: string, options: Options) { await nestMintCollectionNft(uuid, options, this.optsWithGlobals()); }); nfts .command('burn-nft') - .description('Burn NFT for collection with UUID.') + .description('Burn NFT token') .argument('', 'Collection UUID') - .requiredOption('-t, --token-id ', 'NFT id which will be burned.') + .requiredOption('-t, --token-id ', 'NFT id which will be burned') .action(async function (uuid: string, options: Options) { await burnCollectionNft(uuid, options, this.optsWithGlobals()); }); nfts .command('transfer-collection') - .description('Transfer NFT collection ownership to a new wallet address.') + .description('Transfer NFT collection ownership to a new wallet address') .argument('', 'Collection UUID') .requiredOption( '-a, --address ', - 'Address which you want to transferred collection ownership to.', + 'Address which you want to transferred collection ownership to', ) .action(async function (uuid: string, options: Options) { await transferCollectionOwnership(uuid, options, this.optsWithGlobals()); @@ -96,7 +103,7 @@ export function createNftsCommands(cli: Command) { // TRANSACTIONS const listCollectionTransactionsCommand = nfts .command('list-transactions') - .description('List NFT transactions for specific collection UUID.') + .description('List NFT transactions for specific collection') .argument('', 'Collection UUID') .addOption(new Option('-s, --status ', 'Transaction status')) .addOption(new Option('-t, --type ', 'Transaction type')) diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index 410f6ed..4d9ec44 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -2,59 +2,78 @@ import { Command } from 'commander'; import { addPaginationOptions } from '../../lib/options'; import { listBuckets, - getObjects, - getFiles, + listObjects, + listFiles, uploadFromFolder, - file, + getFile, deleteFile, } from './storage.service'; export function createStorageCommands(cli: Command) { - const storage = cli.command('storage'); + const storage = cli + .command('storage') + .description( + 'Commands for manipulating buckets and files on Apillon storage.', + ); + + storage + .command('list-buckets') + .description('List project buckets') + .action(async function () { + await listBuckets(this.optsWithGlobals()); + }); - storage.command('list-buckets').action(async function () { - await listBuckets(this.optsWithGlobals()); - }); addPaginationOptions(storage); storage - .command('get-objects') - .requiredOption( - '--uuid ', - 'UUID of bucket to get objects from', - ) + .command('list-objects') + .description('List files and folders in directory') + .requiredOption('--bucket-uuid ', 'UUID of bucket') + .option('-d, --dir', 'Directory path', '/') .action(async function () { - await getObjects(this.optsWithGlobals()); + await listObjects(this.optsWithGlobals()); }); storage - .command('get-files') - .requiredOption('--uuid ', 'UUID of bucket to get files from') + .command('list-files') + .description('List all files from a bucket') + .requiredOption('--bucket-uuid ', 'UUID of bucket') + .option('-p, --path', 'Filter by file path') .action(async function () { - await getFiles(this.optsWithGlobals()); + await listFiles(this.optsWithGlobals()); }); storage .command('upload') - .argument('', 'path to folder with files') - .requiredOption('--uuid ', 'UUID of bucket to upload files to') + .description('Upload files and folders to bucket') + .argument('', 'path to source') + .requiredOption('--bucket-uuid ', 'UUID of destination bucket') .action(async function (path: string) { await uploadFromFolder(path, this.optsWithGlobals()); }); storage - .command('file') - .requiredOption('--uuid ', 'UUID of bucket') - .requiredOption('--file-uuid ', 'UUID of file to get') + .command('get-file') + .description('Get file info') + .requiredOption('--bucket-uuid ', 'UUID of bucket') + .requiredOption('--file-uuid ', 'UUID of file to get') .action(async function () { - await file(this.optsWithGlobals()); + await getFile(this.optsWithGlobals()); }); storage .command('delete-file') - .requiredOption('--uuid ', 'UUID of bucket') + .description('Mark file for removal from IPFS storage') + .requiredOption('--bucket-uuid ', 'UUID of bucket') .requiredOption('--file-uuid ', 'UUID of file to delete') .action(async function () { await deleteFile(this.optsWithGlobals()); }); + + /* + TODO: + - download file + - upload folder + - ipns methods + */ } diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index ebe7d18..8fb808c 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -5,31 +5,31 @@ export async function listBuckets(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { const { items: buckets } = await storage.listBuckets(); - console.log(buckets); + console.log(buckets.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); } } -export async function getObjects(optsWithGlobals: GlobalOptions) { +export async function listObjects(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { const { items: objects } = await storage - .bucket(optsWithGlobals.uuid) + .bucket(optsWithGlobals.bucketUuid) .getObjects(); - console.log(objects); + console.log(objects.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); } } -export async function getFiles(optsWithGlobals: GlobalOptions) { +export async function listFiles(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { const { items: files } = await storage - .bucket(optsWithGlobals.uuid) + .bucket(optsWithGlobals.bucketUuid) .getFiles(); - console.log(files); + console.log(files.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); } @@ -47,14 +47,14 @@ export async function uploadFromFolder( } } -export async function file(optsWithGlobals: GlobalOptions) { +export async function getFile(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { const file = await storage - .bucket(optsWithGlobals.uuid) + .bucket(optsWithGlobals.bucketUuid) .file(optsWithGlobals.fileUuid) .get(); - console.log(file); + console.log(file.serialize()); } catch (err) { exceptionHandler(err); } @@ -64,7 +64,7 @@ export async function deleteFile(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { await storage - .bucket(optsWithGlobals.uuid) + .bucket(optsWithGlobals.bucketUuid) .deleteFile(optsWithGlobals.fileUuid); console.log('File deleted successfully'); } catch (err) { diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index df66feb..8abbd80 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -7,6 +7,7 @@ export interface ApillonConfig { secret?: string; apiUrl?: string; logLevel?: LogLevel; + debug?: boolean; } export class ApillonModule { @@ -15,13 +16,16 @@ export class ApillonModule { key: process.env.APILLON_API_KEY, secret: process.env.APILLON_API_SECRET, apiUrl: process.env.APILLON_API_URL || 'https://api.apillon.io', - logLevel: LogLevel.NONE, + logLevel: LogLevel.ERROR, + debug: false, }; const mergedConfig = { ...defaultConfig, ...config }; ApillonApi.initialize(mergedConfig); - ApillonLogger.initialize(mergedConfig.logLevel); + ApillonLogger.initialize( + mergedConfig.debug ? LogLevel.VERBOSE : mergedConfig.logLevel, + ); } } @@ -55,4 +59,13 @@ export class ApillonModel { } return this; } + + public serialize() { + return JSON.parse(JSON.stringify(this, this.serializeFilter)); + } + + protected serializeFilter(key, value) { + const excludedKeys = ['API_PREFIX']; + return excludedKeys.includes(key) ? undefined : value; + } } diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index c6c7e1e..4fc02ff 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -84,4 +84,17 @@ export class Directory extends ApillonModel { return this.content; } + + protected serializeFilter(key, value) { + const enums = { + type: StorageContentType[value], + }; + if (super.serializeFilter(key, value) && Object.keys(enums).includes(key)) { + return enums[key]; + } + const excludedKeys = ['content']; + return excludedKeys.includes(key) + ? undefined + : super.serializeFilter(key, value); + } } diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index d3650f6..e9498e4 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -1,13 +1,9 @@ import { AxiosResponse } from 'axios'; +import { ApillonModel } from '../../lib/apillon'; import { ApillonApi } from '../../lib/apillon-api'; import { FileStatus, StorageContentType } from '../../types/storage'; -export class File { - /** - * API url prefix for this class. - */ - private API_PREFIX: string = null; - +export class File extends ApillonModel { /** * Unique identifier of the file's bucket. */ @@ -56,30 +52,14 @@ export class File { fileUuid: string, data?: Partial, ) { + super(fileUuid); this.bucketUuid = bucketUuid; - this.uuid = fileUuid; this.directoryUuid = directoryUuid; this.API_PREFIX = `/storage/${bucketUuid}/file/${fileUuid}`; this.status = data?.fileStatus; this.populate(data); } - /** - * Populates class properties via data object. - * @param data Data object. - */ - private populate(data: any) { - if (data != null) { - Object.keys(data || {}).forEach((key) => { - const prop = this[key]; - if (prop === null) { - this[key] = data[key]; - } - }); - } - return this; - } - /** * Gets file details. */ @@ -90,4 +70,15 @@ export class File { this.status = data.fileStatus; return this.populate(data); } + + protected serializeFilter(key, value) { + const enums = { + status: FileStatus[value], + type: StorageContentType[value], + }; + if (super.serializeFilter(key, value) && Object.keys(enums).includes(key)) { + return enums[key]; + } + return super.serializeFilter(key, value); + } } From 60a88b36f489794b9adc9d7aa97f4878a9d18bef Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 17 Nov 2023 09:25:31 +0100 Subject: [PATCH 45/68] Revert "Implement upload-deploy CLI command" This reverts commit 59ede0a54eb7ed9e935af9b579bee816893b2852. --- .../src/modules/hosting/hosting.commands.ts | 23 ------------------- .../src/modules/hosting/hosting.service.ts | 14 ----------- 2 files changed, 37 deletions(-) diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index b2bcdc0..c2fe4e0 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -6,7 +6,6 @@ import { getWebsite, listDeployments, listWebsites, - uploadAndDeploy, uploadWebsiteFiles, } from './hosting.service'; import { DeployToEnvironment } from '@apillon/sdk'; @@ -57,28 +56,6 @@ export function createHostingCommands(cli: Command) { await deployToEnvironment(this.optsWithGlobals()); }); - hosting - .command('upload-deploy') - .argument('', 'path to folder with website files') - .requiredOption( - '--uuid ', - 'UUID of website to upload files to and deploy', - ) - .addOption( - new Option( - '--env ', - 'Sets the environment to deploy the files to. Choose from:\n' + - ` - ${DeployToEnvironment.TO_STAGING}: To staging.\n` + - ` - ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production.\n` + - ` - ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production.`, - ) - .choices(['1', '2', '3']) - .makeOptionMandatory(true), - ) - .action(async function (path: string) { - await uploadAndDeploy(path, this.optsWithGlobals()); - }); - const hostingListDeployments = hosting .command('list-deployments') .requiredOption( diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index f688638..42fd1c1 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -43,20 +43,6 @@ export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { } } -export async function uploadAndDeploy( - path: string, - optsWithGlobals: GlobalOptions, -) { - const hosting = new Hosting(optsWithGlobals); - try { - await hosting.website(optsWithGlobals.uuid).uploadFromFolder(path); - await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); - console.log('Deploy successful'); - } catch (err) { - exceptionHandler(err); - } -} - export async function listDeployments(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); const params = From 8001a2a986cf7d5128090e49c8bbd290c671de90 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 17 Nov 2023 14:24:05 +0100 Subject: [PATCH 46/68] Add github action for docs deploy --- .github/workflows/deploy-sdk-docs.yml | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/deploy-sdk-docs.yml diff --git a/.github/workflows/deploy-sdk-docs.yml b/.github/workflows/deploy-sdk-docs.yml new file mode 100644 index 0000000..64f1936 --- /dev/null +++ b/.github/workflows/deploy-sdk-docs.yml @@ -0,0 +1,38 @@ +name: Deploy Website + +on: + push: + branches: + - master + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Generate docs + run: | + cd packages/sdk + npm run generate-docs + + - name: Copy files + run: | + cp *.html dist/ + cp -r images dist/ + cp -r style dist/ + cp -r js dist/ + + - name: Deploy docs + env: + APILLON_API_KEY: ${{ secrets.APILLON_API_KEY }} + APILLON_API_SECRET: ${{ secrets.APILLON_API_SECRET }} + WEBSITE_UUID: ${{ secrets.WEBSITE_UUID }} + run: npx --yes @apillon/cli hosting deploy-website ./packages/sdk/docs --uuid $WEBSITE_UUID --key $APILLON_API_KEY --secret $APILLON_API_SECRET From 0d4e255fe1134bd68fd634e7695f285375701083 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 17 Nov 2023 14:25:46 +0100 Subject: [PATCH 47/68] update workflow --- .github/workflows/deploy-sdk-docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy-sdk-docs.yml b/.github/workflows/deploy-sdk-docs.yml index 64f1936..1d7222b 100644 --- a/.github/workflows/deploy-sdk-docs.yml +++ b/.github/workflows/deploy-sdk-docs.yml @@ -20,6 +20,7 @@ jobs: - name: Generate docs run: | + npm i cd packages/sdk npm run generate-docs From e86f8144efe5a621962f7c030871f955f583e15a Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 17 Nov 2023 14:26:52 +0100 Subject: [PATCH 48/68] fix workflow --- .github/workflows/deploy-sdk-docs.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/deploy-sdk-docs.yml b/.github/workflows/deploy-sdk-docs.yml index 1d7222b..1ce0b81 100644 --- a/.github/workflows/deploy-sdk-docs.yml +++ b/.github/workflows/deploy-sdk-docs.yml @@ -24,13 +24,6 @@ jobs: cd packages/sdk npm run generate-docs - - name: Copy files - run: | - cp *.html dist/ - cp -r images dist/ - cp -r style dist/ - cp -r js dist/ - - name: Deploy docs env: APILLON_API_KEY: ${{ secrets.APILLON_API_KEY }} From 3bb919cd54962a2dd29ddcd42fc7bfff28e68b41 Mon Sep 17 00:00:00 2001 From: Tadej Vengust Date: Fri, 17 Nov 2023 14:39:05 +0100 Subject: [PATCH 49/68] update workflow --- .github/workflows/deploy-sdk-docs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-sdk-docs.yml b/.github/workflows/deploy-sdk-docs.yml index 1ce0b81..f84135b 100644 --- a/.github/workflows/deploy-sdk-docs.yml +++ b/.github/workflows/deploy-sdk-docs.yml @@ -29,4 +29,6 @@ jobs: APILLON_API_KEY: ${{ secrets.APILLON_API_KEY }} APILLON_API_SECRET: ${{ secrets.APILLON_API_SECRET }} WEBSITE_UUID: ${{ secrets.WEBSITE_UUID }} - run: npx --yes @apillon/cli hosting deploy-website ./packages/sdk/docs --uuid $WEBSITE_UUID --key $APILLON_API_KEY --secret $APILLON_API_SECRET + run: | + npm i -g @apillon/cli + apillon hosting deploy-website ./packages/sdk/docs --uuid $WEBSITE_UUID --key $APILLON_API_KEY --secret $APILLON_API_SECRET From caacff1660c260f3b6c838098d195184468cb930 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 17 Nov 2023 14:57:21 +0100 Subject: [PATCH 50/68] Add pagination options to cli commands, storage CLI --- packages/cli/src/index.ts | 1 - packages/cli/src/lib/options.ts | 21 +++++++++- .../src/modules/storage/storage.commands.ts | 40 ++++++++++++------- .../src/modules/storage/storage.service.ts | 18 ++++++--- packages/sdk/src/lib/apillon.ts | 10 +++++ packages/sdk/src/types/apillon.ts | 1 + packages/sdk/src/types/nfts.ts | 4 +- 7 files changed, 70 insertions(+), 25 deletions(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 1b6e95e..8ece861 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -6,7 +6,6 @@ import config from './config'; import { createHostingCommands } from './modules/hosting/hosting.commands'; import { createNftsCommands } from './modules/nfts/nfts.commands'; import { createStorageCommands } from './modules/storage/storage.commands'; -import { LogLevel } from '@apillon/sdk'; const cli = new Command('apillon').version(config.VERSION); cli.addHelpText( diff --git a/packages/cli/src/lib/options.ts b/packages/cli/src/lib/options.ts index b134b1a..1b22cbd 100644 --- a/packages/cli/src/lib/options.ts +++ b/packages/cli/src/lib/options.ts @@ -1,9 +1,28 @@ import { Command, Option } from 'commander'; +import { GlobalOptions } from './types'; +import { IApillonPagination } from '@apillon/sdk'; export function addPaginationOptions(command: Command) { return command + .addOption( + new Option( + '-s, --search ', + 'Search by name or other object identifier', + ), + ) .addOption(new Option('-p, --page ', 'Page number')) .addOption(new Option('-l, --limit ', 'Page limit')) .addOption(new Option('-o, --order-by ', 'Page order by')) - .addOption(new Option('-d --desc ', 'Page order descending')); + .addOption(new Option('-d --desc ', 'Page order descending')); +} + +export function paginate(opts: GlobalOptions): IApillonPagination { + return { + search: opts.search, + page: +opts.page, + limit: +opts.limit, + orderBy: opts.orderBy, + desc: !!opts.desc, + ...opts, + }; } diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index 4d9ec44..0536073 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -8,6 +8,7 @@ import { getFile, deleteFile, } from './storage.service'; +import { FileStatus } from '@apillon/sdk'; export function createStorageCommands(cli: Command) { const storage = cli @@ -16,38 +17,47 @@ export function createStorageCommands(cli: Command) { 'Commands for manipulating buckets and files on Apillon storage.', ); - storage + const listBucketsCommand = storage .command('list-buckets') .description('List project buckets') .action(async function () { await listBuckets(this.optsWithGlobals()); }); + addPaginationOptions(listBucketsCommand); - addPaginationOptions(storage); - - storage + const listObjectsCommand = storage .command('list-objects') .description('List files and folders in directory') - .requiredOption('--bucket-uuid ', 'UUID of bucket') - .option('-d, --dir', 'Directory path', '/') + .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') + .option('-d, --directory-uuid ', 'Directory UUID') + .option('-del, --deleted', 'Include deleted objects') .action(async function () { await listObjects(this.optsWithGlobals()); }); + addPaginationOptions(listObjectsCommand); - storage + const listFilesCommand = storage .command('list-files') .description('List all files from a bucket') - .requiredOption('--bucket-uuid ', 'UUID of bucket') - .option('-p, --path', 'Filter by file path') + .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') + .option( + '-fs, --file-status ', + 'Filter by file status. Choose from:\n' + + ` ${FileStatus.UPLOAD_REQUEST_GENERATED}: Upload request generated\n` + + ` ${FileStatus.UPLOADED}: Uploaded\n` + + ` ${FileStatus.AVAILABLE_ON_IPFS}: Available on IPFS\n` + + ` ${FileStatus.AVAILABLE_ON_IPFS_AND_REPLICATED}: Available on IPFS and replicated\n`, + ) .action(async function () { await listFiles(this.optsWithGlobals()); }); + addPaginationOptions(listFilesCommand); storage .command('upload') .description('Upload files and folders to bucket') .argument('', 'path to source') - .requiredOption('--bucket-uuid ', 'UUID of destination bucket') + .requiredOption('-b, --bucket-uuid ', 'UUID of destination bucket') .action(async function (path: string) { await uploadFromFolder(path, this.optsWithGlobals()); }); @@ -55,8 +65,8 @@ export function createStorageCommands(cli: Command) { storage .command('get-file') .description('Get file info') - .requiredOption('--bucket-uuid ', 'UUID of bucket') - .requiredOption('--file-uuid ', 'UUID of file to get') + .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') + .requiredOption('--uuid ', 'UUID of file to get') .action(async function () { await getFile(this.optsWithGlobals()); }); @@ -64,14 +74,14 @@ export function createStorageCommands(cli: Command) { storage .command('delete-file') .description('Mark file for removal from IPFS storage') - .requiredOption('--bucket-uuid ', 'UUID of bucket') - .requiredOption('--file-uuid ', 'UUID of file to delete') + .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') + .requiredOption('--uuid ', 'UUID of file to delete') .action(async function () { await deleteFile(this.optsWithGlobals()); }); /* - TODO: + TODO: - download file - upload folder - ipns methods diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index 8fb808c..11f3a4e 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -1,10 +1,13 @@ import { Storage, exceptionHandler } from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; +import { paginate } from '../../lib/options'; export async function listBuckets(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { - const { items: buckets } = await storage.listBuckets(); + const { items: buckets } = await storage.listBuckets( + paginate(optsWithGlobals), + ); console.log(buckets.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); @@ -16,7 +19,10 @@ export async function listObjects(optsWithGlobals: GlobalOptions) { try { const { items: objects } = await storage .bucket(optsWithGlobals.bucketUuid) - .getObjects(); + .getObjects({ + ...paginate(optsWithGlobals), + markedForDeletion: !!optsWithGlobals.deleted, + }); console.log(objects.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); @@ -28,7 +34,7 @@ export async function listFiles(optsWithGlobals: GlobalOptions) { try { const { items: files } = await storage .bucket(optsWithGlobals.bucketUuid) - .getFiles(); + .getFiles(paginate(optsWithGlobals)); console.log(files.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); @@ -41,7 +47,7 @@ export async function uploadFromFolder( ) { const storage = new Storage(optsWithGlobals); try { - await storage.bucket(optsWithGlobals.uuid).uploadFromFolder(path); + await storage.bucket(optsWithGlobals.bucketUuid).uploadFromFolder(path); } catch (err) { exceptionHandler(err); } @@ -52,7 +58,7 @@ export async function getFile(optsWithGlobals: GlobalOptions) { try { const file = await storage .bucket(optsWithGlobals.bucketUuid) - .file(optsWithGlobals.fileUuid) + .file(optsWithGlobals.uuid) .get(); console.log(file.serialize()); } catch (err) { @@ -65,7 +71,7 @@ export async function deleteFile(optsWithGlobals: GlobalOptions) { try { await storage .bucket(optsWithGlobals.bucketUuid) - .deleteFile(optsWithGlobals.fileUuid); + .deleteFile(optsWithGlobals.uuid); console.log('File deleted successfully'); } catch (err) { exceptionHandler(err); diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 8abbd80..4122186 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -40,6 +40,16 @@ export class ApillonModel { */ public uuid: string; + /** + * The object's creation date + */ + public createTime: Date = null; + + /** + * The date when the object was last updated + */ + public updateTime: Date = null; + constructor(uuid: string) { this.uuid = uuid; } diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index be758b2..a26e258 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -14,6 +14,7 @@ export interface IApillonStatus { } export interface IApillonPagination { + search?: string; page?: number; limit?: number; orderBy?: string; diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index e4971de..a80bb1c 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -80,8 +80,8 @@ export interface ICollection { dropStart: number; dropPrice: number; dropReserve: number; - updateTime: string; - createTime: string; + updateTime: Date; + createTime: Date; } export interface ITransaction { From 8a0558686f21a946890a252e137da60dd350c4bf Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Fri, 17 Nov 2023 15:32:31 +0100 Subject: [PATCH 51/68] Update hosting commands --- packages/cli/src/lib/options.ts | 1 - .../src/modules/hosting/hosting.commands.ts | 2 +- .../src/modules/hosting/hosting.service.ts | 33 ++++++++++--------- packages/sdk/src/lib/apillon.ts | 2 +- .../sdk/src/modules/hosting/deployment.ts | 11 +++++++ .../src/modules/hosting/hosting-website.ts | 2 +- packages/sdk/src/modules/storage/file.ts | 2 +- 7 files changed, 33 insertions(+), 20 deletions(-) diff --git a/packages/cli/src/lib/options.ts b/packages/cli/src/lib/options.ts index 1b22cbd..34017fd 100644 --- a/packages/cli/src/lib/options.ts +++ b/packages/cli/src/lib/options.ts @@ -23,6 +23,5 @@ export function paginate(opts: GlobalOptions): IApillonPagination { limit: +opts.limit, orderBy: opts.orderBy, desc: !!opts.desc, - ...opts, }; } diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index e72c289..83640a0 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -94,7 +94,7 @@ export function createHostingCommands(cli: Command) { hosting .command('get-deployment') .description('Returns deployment data') - .requiredOption('--uuid ', 'UUID of website') + .requiredOption('--website-uuid ', 'UUID of website') .requiredOption( '--deployment-uuid ', 'UUID of deployment to get', diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index 2b25eea..b241415 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -1,11 +1,14 @@ import { Hosting, exceptionHandler, DeployToEnvironment } from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; +import { paginate } from '../../lib/options'; export async function listWebsites(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); try { - const { items: websites } = await hosting.listWebsites(); - console.log(websites); + const { items: websites } = await hosting.listWebsites( + paginate(optsWithGlobals), + ); + console.log(websites.map((w) => w.serialize())); } catch (err) { exceptionHandler(err); } @@ -15,7 +18,7 @@ export async function getWebsite(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); try { const website = await hosting.website(optsWithGlobals.uuid).get(); - console.log(website); + console.log(website.serialize()); } catch (err) { exceptionHandler(err); } @@ -34,9 +37,11 @@ export async function deployWebsite( ? DeployToEnvironment.TO_STAGING : DeployToEnvironment.DIRECTLY_TO_PRODUCTION, ); - const deploymentData = await website.deployment(deployment.deployment_uuid); console.log(`Deployment started!`); - console.log(deploymentData); + const deploymentData = await website + .deployment(deployment.deploymentUuid) + .get(); + console.log(deploymentData.serialize()); } catch (err) { exceptionHandler(err); } @@ -66,18 +71,16 @@ export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { export async function listDeployments(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); - const params = - optsWithGlobals.env || optsWithGlobals.status - ? { - environment: +optsWithGlobals.env, - deploymentStatus: +optsWithGlobals.status, - } - : null; + const params = { + ...paginate(optsWithGlobals), + environment: +optsWithGlobals.env || undefined, + deploymentStatus: +optsWithGlobals.status || undefined, + }; try { const { items: deployments } = await hosting .website(optsWithGlobals.uuid) .listDeployments(params); - console.log(deployments); + console.log(deployments.map((d) => d.serialize())); } catch (err) { exceptionHandler(err); } @@ -87,10 +90,10 @@ export async function getDeployment(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); try { const deployment = await hosting - .website(optsWithGlobals.uuid) + .website(optsWithGlobals.websiteUuid) .deployment(optsWithGlobals.deploymentUuid) .get(); - console.log(deployment); + console.log(deployment.serialize()); } catch (err) { exceptionHandler(err); } diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 4122186..4ee5933 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -74,7 +74,7 @@ export class ApillonModel { return JSON.parse(JSON.stringify(this, this.serializeFilter)); } - protected serializeFilter(key, value) { + protected serializeFilter(key: string, value: any) { const excludedKeys = ['API_PREFIX']; return excludedKeys.includes(key) ? undefined : value; } diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index de9c2e2..3b86be6 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -70,4 +70,15 @@ export class Deployment extends ApillonModel { ); return this.populate(data); } + + protected override serializeFilter(key: string, value: any) { + const enums = { + environment: DeployToEnvironment[value], + deploymentStatus: DeploymentStatus[value], + }; + if (super.serializeFilter(key, value) && Object.keys(enums).includes(key)) { + return enums[key]; + } + return super.serializeFilter(key, value); + } } diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index f0b01ba..96d5bc6 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -104,7 +104,7 @@ export class HostingWebsite extends ApillonModel { */ public async listDeployments( params?: IDeploymentFilters, - ): Promise> { + ): Promise> { const url = constructUrlWithQueryParams( `${this.API_PREFIX}/deployments`, params, diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index e9498e4..9495b14 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -71,7 +71,7 @@ export class File extends ApillonModel { return this.populate(data); } - protected serializeFilter(key, value) { + protected override serializeFilter(key: string, value: any) { const enums = { status: FileStatus[value], type: StorageContentType[value], From fffa6f62dfe0e34353593995673caf61d2c04661 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Mon, 20 Nov 2023 10:32:13 +0100 Subject: [PATCH 52/68] Refactor NFT commands --- packages/cli/src/lib/options.ts | 8 +- packages/cli/src/modules/nfts/nft.service.ts | 109 ++++++++---------- .../cli/src/modules/nfts/nfts.commands.ts | 51 ++++---- .../sdk/src/modules/nft/nft-collection.ts | 14 +++ 4 files changed, 89 insertions(+), 93 deletions(-) diff --git a/packages/cli/src/lib/options.ts b/packages/cli/src/lib/options.ts index 34017fd..b6260d2 100644 --- a/packages/cli/src/lib/options.ts +++ b/packages/cli/src/lib/options.ts @@ -1,6 +1,6 @@ import { Command, Option } from 'commander'; import { GlobalOptions } from './types'; -import { IApillonPagination } from '@apillon/sdk'; +import { IApillonPagination, toBoolean, toInteger } from '@apillon/sdk'; export function addPaginationOptions(command: Command) { return command @@ -19,9 +19,9 @@ export function addPaginationOptions(command: Command) { export function paginate(opts: GlobalOptions): IApillonPagination { return { search: opts.search, - page: +opts.page, - limit: +opts.limit, + page: toInteger(opts.page), + limit: toInteger(opts.limit), orderBy: opts.orderBy, - desc: !!opts.desc, + desc: toBoolean(opts.desc), }; } diff --git a/packages/cli/src/modules/nfts/nft.service.ts b/packages/cli/src/modules/nfts/nft.service.ts index a8345d9..1b9c69c 100644 --- a/packages/cli/src/modules/nfts/nft.service.ts +++ b/packages/cli/src/modules/nfts/nft.service.ts @@ -2,39 +2,33 @@ import { exceptionHandler, ICreateCollection, Nft, - toBoolean, toInteger, } from '@apillon/sdk'; import { readAndParseJson } from '../../lib/files'; -import { GlobalOptions, Options } from '../../lib/types'; +import { GlobalOptions } from '../../lib/types'; +import { paginate } from '../../lib/options'; // COLLECTIONS -export async function listCollections( - options: Options, - optsWithGlobals: GlobalOptions, -) { +export async function listCollections(optsWithGlobals: GlobalOptions) { const nftService = new Nft(optsWithGlobals); try { const data = await nftService.listCollections({ - collectionStatus: toInteger(options.status), - page: toInteger(options.page), - limit: toInteger(options.limit), - orderBy: options.orderBy, - desc: toBoolean(options.desc), + ...paginate(optsWithGlobals), + collectionStatus: toInteger(optsWithGlobals.status), }); - console.log(data); + console.log(data.map((d) => d.serialize())); } catch (e: any) { exceptionHandler(e); } } -export async function getCollection(uuid: string, optsWithGlobals) { +export async function getCollection(optsWithGlobals: GlobalOptions) { const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.collection(uuid).get(); - console.log(data); + const data = await nftService.collection(optsWithGlobals.uuid).get(); + console.log(data.serialize()); } catch (e: any) { exceptionHandler(e); } @@ -49,17 +43,14 @@ export async function createCollection( createCollectionData = readAndParseJson(filePath) as ICreateCollection; } catch (e) { if (e.code === 'ENOENT') { - console.error(`Error: File not found (${filePath}).`); - return; + return console.error(`Error: File not found (${filePath}).`); } else if ( e.name === 'SyntaxError' && e.message.includes('Unexpected end of JSON input') ) { - console.error(`Error: Failed to parse JSON file (${filePath}).`); - return; + return console.error(`Error: Failed to parse JSON file (${filePath}).`); } else { - console.error(e); - return; + return console.error(e); } } if (!createCollectionData) { @@ -70,77 +61,72 @@ export async function createCollection( try { const data = await nftService.create(createCollectionData); - console.log(data); + console.log(data.serialize()); + console.log('NFT collection created successfully!'); } catch (e: any) { exceptionHandler(e); } } -export async function mintCollectionNft( - uuid: string, - options: Options, - optsWithGlobals: GlobalOptions, -) { +export async function mintCollectionNft(optsWithGlobals: GlobalOptions) { const nftService = new Nft(optsWithGlobals); try { const data = await nftService - .collection(uuid) - .mint(options.address, toInteger(options.quantity)); - console.log(data); + .collection(optsWithGlobals.uuid) + .mint(optsWithGlobals.address, toInteger(optsWithGlobals.quantity)); + if (data.success) { + console.log('NFT minted successfully'); + } } catch (e: any) { exceptionHandler(e); } } -export async function nestMintCollectionNft( - uuid: string, - options: Options, - optsWithGlobals: GlobalOptions, -) { +export async function nestMintCollectionNft(optsWithGlobals: GlobalOptions) { const nftService = new Nft(optsWithGlobals); try { const data = await nftService - .collection(uuid) + .collection(optsWithGlobals.uuid) .nestMint( - options.parentCollectionUuid, - toInteger(options.parentNftId), - toInteger(options.quantity), + optsWithGlobals.parentCollectionUuid, + toInteger(optsWithGlobals.parentNftId), + toInteger(optsWithGlobals.quantity), ); - console.log(data); + if (data.status === 5) { + console.log('NFT nest minted successfully'); + } } catch (e: any) { exceptionHandler(e); } } -export async function burnCollectionNft( - uuid: string, - options: Options, - optsWithGlobals: GlobalOptions, -) { +export async function burnCollectionNft(optsWithGlobals: GlobalOptions) { const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.collection(uuid).burn(options.tokenId); - console.log(data); + const data = await nftService + .collection(optsWithGlobals.uuid) + .burn(optsWithGlobals.tokenId); + if (data.status === 5) { + console.log('NFT burned successfully'); + } } catch (e: any) { exceptionHandler(e); } } export async function transferCollectionOwnership( - uuid: string, - options: Options, optsWithGlobals: GlobalOptions, ) { const nftService = new Nft(optsWithGlobals); try { - const data = await nftService - .collection(uuid) - .transferOwnership(options.address); - console.log(data); + await nftService + .collection(optsWithGlobals.uuid) + .transferOwnership(optsWithGlobals.address); + console.log('NFT ownership transfered successfully'); } catch (e: any) { exceptionHandler(e); } @@ -148,21 +134,18 @@ export async function transferCollectionOwnership( // TRANSACTIONS export async function listCollectionTransactions( - uuid: string, - options: Options, optsWithGlobals: GlobalOptions, ) { const nftService = new Nft(optsWithGlobals); try { - const data = await nftService.collection(uuid).listTransactions({ - transactionStatus: toInteger(options.status), - transactionType: toInteger(options.type), - page: toInteger(options.page), - limit: toInteger(options.limit), - orderBy: options.orderBy, - desc: toBoolean(options.desc), - }); + const data = await nftService + .collection(optsWithGlobals.uuid) + .listTransactions({ + ...paginate(optsWithGlobals), + transactionStatus: toInteger(optsWithGlobals.status), + transactionType: toInteger(optsWithGlobals.type), + }); console.log(data); } catch (e: any) { exceptionHandler(e); diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index 4d643ed..12b866c 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -9,7 +9,6 @@ import { nestMintCollectionNft, transferCollectionOwnership, } from './nft.service'; -import { Options } from '../../lib/types'; import { addPaginationOptions } from '../../lib/options'; export function createNftsCommands(cli: Command) { @@ -24,23 +23,23 @@ export function createNftsCommands(cli: Command) { .command('list-collections') .description('List NFT collections owned by project') .addOption(new Option('-s, --status ', 'Collection status')) - .action(async function (options: Options) { - await listCollections(options, this.optsWithGlobals()); + .action(async function () { + await listCollections(this.optsWithGlobals()); }); addPaginationOptions(listCollectionsCommand); nfts .command('get-collection') .description('Get NFT collection details.') - .argument('', 'Collection UUID') - .action(async function (uuid: string) { - await getCollection(uuid, this.optsWithGlobals()); + .requiredOption('--uuid ', 'Collection UUID') + .action(async function () { + await getCollection(this.optsWithGlobals()); }); nfts .command('create-collection') .description('Create NFT collection from JSON file') - .argument('', 'path to JSON data file') + .argument('', 'path to JSON data file of type ICreateCollection') .action(async function (filePath: string) { await createCollection(filePath, this.optsWithGlobals()); }); @@ -48,67 +47,67 @@ export function createNftsCommands(cli: Command) { nfts .command('mint-nft') .description('Mint NFT from collection') - .argument('', 'Collection UUID') + .requiredOption('--uuid ', 'Collection UUID') .requiredOption( '-a, --address ', 'Address which will receive minted NFTs.', ) - .requiredOption('-n, --number ', 'Number of NFTs to mint.') - .action(async function (uuid: string, options: Options) { - await mintCollectionNft(uuid, options, this.optsWithGlobals()); + .requiredOption('-q, --quantity ', 'Number of NFTs to mint.') + .action(async function () { + await mintCollectionNft(this.optsWithGlobals()); }); nfts .command('nest-mint-nft') .description('Nest mint NFT child collection to parent NFT') - .argument('', 'Child collection UUID') + .requiredOption('--uuid ', 'Child collection UUID') .requiredOption( '-c, --parent-collection-uuid ', 'Parent collection UUID to which child NFTs will be minted to.', ) .requiredOption( - '-i, --parent-nft-id ', + '-pid, --parent-nft-id ', 'Parent NFT id to which child NFTs will be minted to', ) .requiredOption( - '-n, --number ', + '-q, --quantity ', 'Number of child NFTs to mint', '1', ) - .action(async function (uuid: string, options: Options) { - await nestMintCollectionNft(uuid, options, this.optsWithGlobals()); + .action(async function () { + await nestMintCollectionNft(this.optsWithGlobals()); }); nfts .command('burn-nft') .description('Burn NFT token') - .argument('', 'Collection UUID') - .requiredOption('-t, --token-id ', 'NFT id which will be burned') - .action(async function (uuid: string, options: Options) { - await burnCollectionNft(uuid, options, this.optsWithGlobals()); + .requiredOption('--uuid ', 'Collection UUID') + .requiredOption('-tid, --token-id ', 'NFT ID which will be burned') + .action(async function () { + await burnCollectionNft(this.optsWithGlobals()); }); nfts .command('transfer-collection') .description('Transfer NFT collection ownership to a new wallet address') - .argument('', 'Collection UUID') + .requiredOption('--uuid ', 'Collection UUID') .requiredOption( '-a, --address ', 'Address which you want to transferred collection ownership to', ) - .action(async function (uuid: string, options: Options) { - await transferCollectionOwnership(uuid, options, this.optsWithGlobals()); + .action(async function () { + await transferCollectionOwnership(this.optsWithGlobals()); }); // TRANSACTIONS const listCollectionTransactionsCommand = nfts .command('list-transactions') .description('List NFT transactions for specific collection') - .argument('', 'Collection UUID') + .requiredOption('--uuid ', 'Collection UUID') .addOption(new Option('-s, --status ', 'Transaction status')) .addOption(new Option('-t, --type ', 'Transaction type')) - .action(async function (uuid: string, options: Options) { - await listCollectionTransactions(uuid, options, this.optsWithGlobals()); + .action(async function () { + await listCollectionTransactions(this.optsWithGlobals()); }); addPaginationOptions(listCollectionTransactionsCommand); } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index e91255f..ceda1e8 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -109,6 +109,11 @@ export class NftCollection extends ApillonModel { */ public transactionHash: string = null; + /** + * Wallet address of deployer. + */ + public deployerAddress: string = null; + /** * Chain on which the smart contract was deployed. */ @@ -232,4 +237,13 @@ export class NftCollection extends ApillonModel { return data.items; } + + protected override serializeFilter(key: string, value: any) { + const serialized = super.serializeFilter(key, value); + const enums = { + collectionType: CollectionType[serialized], + collectionStatus: CollectionStatus[serialized], + }; + return Object.keys(enums).includes(key) ? enums[key] : serialized; + } } From fddff48dd85702103f61bc8bc22f02fe7c438b67 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Mon, 20 Nov 2023 15:20:12 +0100 Subject: [PATCH 53/68] Hosting and Storage CLI/SDK updates --- .../src/modules/hosting/hosting.service.ts | 15 ++++++++--- .../src/modules/storage/storage.commands.ts | 6 ++--- .../src/modules/storage/storage.service.ts | 5 ++-- .../sdk/src/modules/hosting/deployment.ts | 6 ++--- packages/sdk/src/modules/storage/directory.ts | 16 +++++++----- packages/sdk/src/modules/storage/file.ts | 26 ++++++++++++------- .../sdk/src/modules/storage/storage-bucket.ts | 4 +-- 7 files changed, 47 insertions(+), 31 deletions(-) diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index b241415..9ef3a10 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -1,4 +1,9 @@ -import { Hosting, exceptionHandler, DeployToEnvironment } from '@apillon/sdk'; +import { + Hosting, + exceptionHandler, + DeployToEnvironment, + toInteger, +} from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; import { paginate } from '../../lib/options'; @@ -62,7 +67,9 @@ export async function uploadWebsiteFiles( export async function deployToEnvironment(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); try { - await hosting.website(optsWithGlobals.uuid).deploy(+optsWithGlobals.env); + await hosting + .website(optsWithGlobals.uuid) + .deploy(toInteger(optsWithGlobals.env)); console.log('Deploy successful'); } catch (err) { exceptionHandler(err); @@ -73,8 +80,8 @@ export async function listDeployments(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); const params = { ...paginate(optsWithGlobals), - environment: +optsWithGlobals.env || undefined, - deploymentStatus: +optsWithGlobals.status || undefined, + environment: toInteger(optsWithGlobals.env), + deploymentStatus: toInteger(optsWithGlobals.status), }; try { const { items: deployments } = await hosting diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index 0536073..bf2d9de 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -29,7 +29,7 @@ export function createStorageCommands(cli: Command) { .command('list-objects') .description('List files and folders in directory') .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') - .option('-d, --directory-uuid ', 'Directory UUID') + .option('-dir, --directory-uuid ', 'Directory UUID') .option('-del, --deleted', 'Include deleted objects') .action(async function () { await listObjects(this.optsWithGlobals()); @@ -66,7 +66,7 @@ export function createStorageCommands(cli: Command) { .command('get-file') .description('Get file info') .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') - .requiredOption('--uuid ', 'UUID of file to get') + .requiredOption('-f, --file-uuid ', 'UUID or CID of file to get') .action(async function () { await getFile(this.optsWithGlobals()); }); @@ -75,7 +75,7 @@ export function createStorageCommands(cli: Command) { .command('delete-file') .description('Mark file for removal from IPFS storage') .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') - .requiredOption('--uuid ', 'UUID of file to delete') + .requiredOption('-f, --file-uuid ', 'UUID or CID of file to delete') .action(async function () { await deleteFile(this.optsWithGlobals()); }); diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index 11f3a4e..b2bd843 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -21,6 +21,7 @@ export async function listObjects(optsWithGlobals: GlobalOptions) { .bucket(optsWithGlobals.bucketUuid) .getObjects({ ...paginate(optsWithGlobals), + directoryUuid: optsWithGlobals.directoryUuid, markedForDeletion: !!optsWithGlobals.deleted, }); console.log(objects.map((x) => x.serialize())); @@ -58,7 +59,7 @@ export async function getFile(optsWithGlobals: GlobalOptions) { try { const file = await storage .bucket(optsWithGlobals.bucketUuid) - .file(optsWithGlobals.uuid) + .file(optsWithGlobals.fileUuid) .get(); console.log(file.serialize()); } catch (err) { @@ -71,7 +72,7 @@ export async function deleteFile(optsWithGlobals: GlobalOptions) { try { await storage .bucket(optsWithGlobals.bucketUuid) - .deleteFile(optsWithGlobals.uuid); + .deleteFile(optsWithGlobals.fileUuid); console.log('File deleted successfully'); } catch (err) { exceptionHandler(err); diff --git a/packages/sdk/src/modules/hosting/deployment.ts b/packages/sdk/src/modules/hosting/deployment.ts index 3b86be6..a50d00f 100644 --- a/packages/sdk/src/modules/hosting/deployment.ts +++ b/packages/sdk/src/modules/hosting/deployment.ts @@ -72,13 +72,11 @@ export class Deployment extends ApillonModel { } protected override serializeFilter(key: string, value: any) { + const serialized = super.serializeFilter(key, value); const enums = { environment: DeployToEnvironment[value], deploymentStatus: DeploymentStatus[value], }; - if (super.serializeFilter(key, value) && Object.keys(enums).includes(key)) { - return enums[key]; - } - return super.serializeFilter(key, value); + return Object.keys(enums).includes(key) ? enums[key] : serialized; } } diff --git a/packages/sdk/src/modules/storage/directory.ts b/packages/sdk/src/modules/storage/directory.ts index 4fc02ff..42cca13 100644 --- a/packages/sdk/src/modules/storage/directory.ts +++ b/packages/sdk/src/modules/storage/directory.ts @@ -12,7 +12,7 @@ export class Directory extends ApillonModel { /** * Unique identifier of the bucket. */ - public bucketUuid; + public bucketUuid: string = null; /** * Directory name. @@ -34,6 +34,11 @@ export class Directory extends ApillonModel { */ public type = StorageContentType.DIRECTORY; + /** + * Link on IPFS gateway. + */ + public link: string = null; + public content: (File | Directory)[] = []; /** @@ -85,16 +90,15 @@ export class Directory extends ApillonModel { return this.content; } - protected serializeFilter(key, value) { + protected serializeFilter(key: string, value: string) { + const serialized = super.serializeFilter(key, value); const enums = { type: StorageContentType[value], }; - if (super.serializeFilter(key, value) && Object.keys(enums).includes(key)) { + if (Object.keys(enums).includes(key)) { return enums[key]; } const excludedKeys = ['content']; - return excludedKeys.includes(key) - ? undefined - : super.serializeFilter(key, value); + return excludedKeys.includes(key) ? undefined : serialized; } } diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index 9495b14..33b6e1e 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -9,11 +9,6 @@ export class File extends ApillonModel { */ public bucketUuid: string; - /** - * Unique identifier of the file. - */ - public uuid: string; - /** * File name. */ @@ -24,6 +19,11 @@ export class File extends ApillonModel { */ public CID: string = null; + /** + * File content identifier V1. + */ + public CIDv1: string = null; + /** * File status. */ @@ -39,6 +39,16 @@ export class File extends ApillonModel { */ public type = StorageContentType.FILE; + /** + * Link on IPFS gateway. + */ + public link: string = null; + + /** + * Full path to file. + */ + public path: string = null; + /** * Constructor which should only be called via HostingWebsite class. * @param bucketUuid Unique identifier of the file's bucket. @@ -72,13 +82,11 @@ export class File extends ApillonModel { } protected override serializeFilter(key: string, value: any) { + const serialized = super.serializeFilter(key, value); const enums = { status: FileStatus[value], type: StorageContentType[value], }; - if (super.serializeFilter(key, value) && Object.keys(enums).includes(key)) { - return enums[key]; - } - return super.serializeFilter(key, value); + return Object.keys(enums).includes(key) ? enums[key] : serialized; } } diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 2341659..4b79e8d 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -60,9 +60,7 @@ export class StorageBucket extends ApillonModel { for (const item of data.items) { if (item.type == StorageContentType.FILE) { const file = item as File; - this.content.push( - new File(this.uuid, file.directoryUuid, file.uuid, file), - ); + content.push(new File(this.uuid, file.directoryUuid, file.uuid, file)); } else { const directory = new Directory( this.uuid, From b379eef73a289ae872bee049b16e5b39bf2ebd42 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 21 Nov 2023 09:44:13 +0100 Subject: [PATCH 54/68] SDK options update --- packages/cli/src/index.ts | 2 +- .../src/modules/hosting/hosting.commands.ts | 16 +++++++++++++- .../cli/src/modules/nfts/nfts.commands.ts | 21 ++++++++++++++++--- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 8ece861..9fb6527 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -17,7 +17,7 @@ cli.addHelpText( cli.addHelpText( 'afterAll', chalk.yellow(` -Find more help at wiki.apillon.io! +Find more help at wiki.apillon.io/build/6-apillon-cli.html `), ); diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index 83640a0..13ac79d 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -84,7 +84,21 @@ export function createHostingCommands(cli: Command) { '--uuid ', 'UUID of website to list deployments for', ) - .option('--env ', + 'Sets the environment to deploy the files to. Choose from:\n' + + ` ${DeployToEnvironment.TO_STAGING}: To Staging\n` + + ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production\n` + + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production`, + ).choices(['1', '2', '3']), + ) + .addOption( + new Option( + '--status ', + 'Status of the deployment (DeploymentStatus enum)', + ).choices(['0', '1', '10', '100']), + ) .option('--status ', 'deployment status') .action(async function () { await listDeployments(this.optsWithGlobals()); diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index 12b866c..22f2ac2 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -22,7 +22,12 @@ export function createNftsCommands(cli: Command) { const listCollectionsCommand = nfts .command('list-collections') .description('List NFT collections owned by project') - .addOption(new Option('-s, --status ', 'Collection status')) + .addOption( + new Option( + '--status ', + 'Collection status (CollectionStatus enum)', + ), + ) .action(async function () { await listCollections(this.optsWithGlobals()); }); @@ -104,8 +109,18 @@ export function createNftsCommands(cli: Command) { .command('list-transactions') .description('List NFT transactions for specific collection') .requiredOption('--uuid ', 'Collection UUID') - .addOption(new Option('-s, --status ', 'Transaction status')) - .addOption(new Option('-t, --type ', 'Transaction type')) + .addOption( + new Option( + '--status ', + 'Transaction status (TransactionStatus enum)', + ), + ) + .addOption( + new Option( + '-t, --type ', + 'Transaction type (TransactionType enum)', + ), + ) .action(async function () { await listCollectionTransactions(this.optsWithGlobals()); }); From 0e04d8ded9e485cd7c7a7e7730246bc2a5a47930 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 21 Nov 2023 09:51:00 +0100 Subject: [PATCH 55/68] Revert dates to string type --- packages/sdk/src/lib/apillon.ts | 4 ++-- packages/sdk/src/types/nfts.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 4ee5933..5752f8a 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -43,12 +43,12 @@ export class ApillonModel { /** * The object's creation date */ - public createTime: Date = null; + public createTime: string = null; /** * The date when the object was last updated */ - public updateTime: Date = null; + public updateTime: string = null; constructor(uuid: string) { this.uuid = uuid; diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index a80bb1c..e4971de 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -80,8 +80,8 @@ export interface ICollection { dropStart: number; dropPrice: number; dropReserve: number; - updateTime: Date; - createTime: Date; + updateTime: string; + createTime: string; } export interface ITransaction { From 7ed39cfdc0799c3cafb2ddb1c1ba9d829d4477a7 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 21 Nov 2023 10:20:42 +0100 Subject: [PATCH 56/68] Update storage list methods and SDK example --- EXAMPLE.md | 108 ++++++++++++------ .../src/modules/storage/storage.service.ts | 4 +- .../sdk/src/modules/storage/storage-bucket.ts | 4 +- packages/sdk/src/tests/storage.test.ts | 8 +- 4 files changed, 84 insertions(+), 40 deletions(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index 91b5df0..6cc032f 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -1,42 +1,86 @@ -# Structure example +## Hosting + +Hosting module encapsulates functionalities for Hosting service available on Apillon dashboard. + +### Usage example ```ts -import { Hosting, Storage, Nft, DeployToEnvironment, FileStatus } from '@apillon/sdk'; - -export async function test() { - // Hosting example - const hosting = new Hosting({ apillonConfig }); - await hosting.listWebsites(); - const webpage1 = hosting.website('uuid'); - await webpage1.get(); - - await webpage1.uploadFromFolder('folder_path'); - await webpage1.deploy(DeployToEnvironment.STAGING_TO_PRODUCTION); - await webpage1.listDeployments(); - const deployment = await webpage1.deployment(deployment_uuid).get(); - - // Storage example - const storage = new Storage({ apillonConfig }); - await storage.listBuckets(); - const bucket = storage.bucket('uuid'); - await bucket.uploadFromFolder('folder_path'); - await bucket.getObjects({ - directoryUuid, - markedForDeletion: false, - limit: 5, - }); - await bucket.getFiles({ fileStatus: FileStatus.UPLOADED }); - const file = await bucket.file(file_uuid).get(); - await bucket.deleteFile(file_uuid); +import { Hosting } from "@apillon/sdk"; + +const hosting = new Hosting({ apillonConfig }); +await hosting.listWebsites({ orderBy: 'createdTime' }); +const webpage1 = hosting.website('uuid'); +await webpage1.get(); + +await webpage1.uploadFromFolder('folder_path'); +await webpage1.deploy(DeployToEnvironment.STAGING_TO_PRODUCTION); +await webpage1.listDeployments(); +const deployment = await webpage1.deployment(deployment_uuid).get(); +if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { + // done +} +``` + +## Storage + +Storage module encapsulates functionalities for Storage service available on Apillon dashboard. + +### Usage example + +```ts +import { Storage } from "@apillon/sdk"; - // NFT example - const nft = new Nft({ apillonConfig }); - await nft.listCollections(); +const storage = new Storage({ apillonConfig }); +await storage.listBuckets({ limit: 5 }); +const bucket = storage.bucket('uuid'); +await bucket.uploadFromFolder('folder_path'); +await bucket.listObjects({ + directoryUuid, + markedForDeletion: false, + limit: 5, +}); +await bucket.listFiles({ fileStatus: FileStatus.UPLOADED }); +const file = await bucket.file(file_uuid).get(); +await bucket.deleteFile(file_uuid); +``` + +## NFTs + +NFT module encapsulates functionalities for NFT service available on Apillon dashboard. + +### Usage example + +```ts +import { Nft } from "@apillon/sdk"; + +const nft = new Nft({ apillonConfig }); + await nft.create({ + collectionType: CollectionType.GENERIC, + chain: EvmChain.MOONBEAM, + name: 'SpaceExplorers', + symbol: 'SE', + description: 'A collection of unique space exploration NFTs.', + baseUri: 'https://moonbeamnfts.com/collections/spaceexplorers/', + baseExtension: 'json', + maxSupply: 1000, + isRevokable: false, + isSoulbound: false, + royaltiesAddress: '0x1234567890abcdef', + royaltiesFees: 5, + drop: true, + dropStart: 1679875200, + dropPrice: 0.05, + dropReserve: 100, + }); + await nft.listCollections({ search: 'My NFT' }); const collection = await nft.collection('uuid').get(); await collection.mint(receiver, quantity); await collection.nestMint(collection.uuid, 1, quantity); await collection.burn(quantity); await collection.listTransactions(); await collection.transferOwnership(to_address); -} ``` + +## Detailed docs + +Detailed SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io). \ No newline at end of file diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index b2bd843..ff36fc4 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -19,7 +19,7 @@ export async function listObjects(optsWithGlobals: GlobalOptions) { try { const { items: objects } = await storage .bucket(optsWithGlobals.bucketUuid) - .getObjects({ + .listObjects({ ...paginate(optsWithGlobals), directoryUuid: optsWithGlobals.directoryUuid, markedForDeletion: !!optsWithGlobals.deleted, @@ -35,7 +35,7 @@ export async function listFiles(optsWithGlobals: GlobalOptions) { try { const { items: files } = await storage .bucket(optsWithGlobals.bucketUuid) - .getFiles(paginate(optsWithGlobals)); + .listFiles(paginate(optsWithGlobals)); console.log(files.map((x) => x.serialize())); } catch (err) { exceptionHandler(err); diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 4b79e8d..18ab65d 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -46,7 +46,7 @@ export class StorageBucket extends ApillonModel { /** * Gets contents of a bucket. */ - async getObjects( + async listObjects( params?: IStorageBucketContentRequest, ): Promise> { const content = []; @@ -77,7 +77,7 @@ export class StorageBucket extends ApillonModel { /** * Gets all files in a bucket. */ - async getFiles(params?: IBucketFilesRequest): Promise> { + async listFiles(params?: IBucketFilesRequest): Promise> { const url = constructUrlWithQueryParams( `/storage/buckets/${this.uuid}/files`, params, diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 4fbebf3..89ab075 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -21,7 +21,7 @@ describe('Storage tests', () => { test('get bucket content', async () => { const storage = new Storage(config); - const { items } = await storage.bucket(bucketUUID).getObjects(); + const { items } = await storage.bucket(bucketUUID).listObjects(); for (const item of items) { if (item.type == StorageContentType.DIRECTORY) { await item.get(); @@ -34,7 +34,7 @@ describe('Storage tests', () => { test('get bucket files', async () => { const storage = new Storage(config); - const { items } = await storage.bucket(bucketUUID).getFiles(); + const { items } = await storage.bucket(bucketUUID).listFiles(); for (const item of items) { console.log(`${item.type}: ${item.name}`); } @@ -46,7 +46,7 @@ describe('Storage tests', () => { const storage = new Storage(config); const { items } = await storage .bucket(bucketUUID) - .getObjects({ markedForDeletion: true }); + .listObjects({ markedForDeletion: true }); expect(items.some((file) => file['status'] == 8)); }); @@ -54,7 +54,7 @@ describe('Storage tests', () => { const storage = new Storage(config); const { items } = await storage .bucket(bucketUUID) - .getObjects({ directoryUuid: '6c9c6ab1-801d-4915-a63e-120eed21fee0' }); + .listObjects({ directoryUuid: '6c9c6ab1-801d-4915-a63e-120eed21fee0' }); for (const item of items) { if (item.type == StorageContentType.DIRECTORY) { From ee32a2a258f99a7e61de6672c71a76ff777fc3e9 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 21 Nov 2023 10:27:21 +0100 Subject: [PATCH 57/68] Update CLI README.md --- packages/cli/README.md | 274 +++++++++++++++++++++++++++++++++++------ 1 file changed, 233 insertions(+), 41 deletions(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index 214f636..163fe11 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -31,72 +31,264 @@ npx @apillon/cli [options] > Note that when running without installation, you have to use `@apillon/cli` instead of `apillon` execution command. -## Commands -The Apillon CLI currently supports the following command: +### Global Options -### `hosting` +- `--api-url `: Apillon API URL (default: Production API URL, can be set via the `APILLON_API_URL` environment + variable). +- `--key `: Apillon API key (can be set via the `APILLON_API_KEY` environment variable). +- `--secret `: Apillon API secret (can be set via the `APILLON_API_SECRET` environment variable). +- `--debug`: Output execution logs when running commands. +- `-V`, `--version`: Output the version number. + +### Environment Variables + +You can use environment variables to set the API URL, API key, and API secret: + +- `APILLON_API_URL`: Apillon API URL. +- `APILLON_API_KEY`: Apillon API key. +- `APILLON_API_SECRET`: Apillon API secret. + +If you have these variables set, you do not need to use the global options each time. + +### Help + +To display the help information for the CLI or a specific command, use the `-h` or `--help` option: + +```sh +apillon -h +apillon hosting -h +npx @apillon/cli hosting deploy-website --help +``` + +### Global list pagination options + +For commands that return a list of results, for example `apillon storage list-files`, or `apillon hosting list-websites`, there are global list pagination options that are available to use: + +- `-l, --limit `: Page limit +- `-o, --order-by `: Page order by (can be any property from the response data) +- `-p, --page `: Page number +- `-s, --search `: Search by name or other object identifier + +> For example responses and for an overview of all properties, refer to [the Apillon API wiki](https://wiki.apillon.io/build/1-apillon-api.html) + +# Commands + +The Apillon CLI currently supports the following commands: + +## `Hosting` To be able to deploy a website with Apillon CLI, you have to create a website deployment inside your project on [Apillon Developer dashboard](https://app.apillon.io/dashboard/service/hosting). Upon creating a website deployment, you will get the website UUID number, that you will need to run CLI hosting commands. +#### `hosting list-websites` + +This command lists all websites associated with your project. + +```sh +apillon hosting list-websites --search "My-Website" --limit 1 +``` + +#### `hosting get-website` +This command retrieves information about a specific website. + +**Options** +- `--uuid `: UUID of the website to get details for. + #### `hosting deploy-website` +This command deployes website from a local folder directly to Apillon hosting production environment. -Deploy your website to with Apillon Web3 platform to decentralized storage (IPFS) and pin it with Crust blockchain protocol. +**Options** +- ``: Path to the folder containing your website files. +- `--uuid `: UUID of the website to upload files to. +- `-p, --preview`: Deploy to staging environment instead. -#### Arguments +#### `hosting upload` +Upload a file folder to a website deployment bucket. -- `path`: Path to the folder containing your website files. +**Options** +- ``: Path to the folder containing your website files. +- `--uuid `: UUID of the website to upload files to. -#### Options +**Example** +```sh +apillon hosting upload --uuid your-website-uuid ./public_html +``` -- `-h`, `--help`: Display help for the command. -- `-p`, `--preview`: Deploy to the staging environment. -- `--uuid `: UUID of the website to deploy. +#### `hosting start-deployment` +This command deploys a website to the specified environment, from files already uploaded to the hosting bucket. -#### Global Options +**Options** +- `--uuid `: UUID of the website to deploy. +- `--env `: The environment to deploy to. Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. -- `--api-url `: Apillon API URL (default: Production API URL, can be set via the `APILLON_API_URL` environment - variable). -- `--key `: Apillon API key (can be set via the `APILLON_API_KEY` environment variable). -- `--secret `: Apillon API secret (can be set via the `APILLON_API_SECRET` environment variable). -- `-V`, `--version`: Output the version number. +**Example** +```sh +apillon hosting start-deployment --uuid your-website-uuid --env 3 +``` + +#### `hosting deploy-website` +This command uploads website files and immediately deploys them to the specified environment. -#### Example +**Options** +- ``: Path to the folder containing your website files. +- `--uuid `: UUID of the website to upload files to and deploy. +- `--env `: The environment to deploy to. Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. -To deploy a website located in the ./dist folder with a specific UUID, API key, and API secret, run: +**Example** +```sh +apillon hosting deploy-website ./public_html --uuid your-website-uuid --env 2 +``` -```bash -apillon hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret -# or -npx @apillon/cli hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret +#### `hosting list-deployments` +This command lists all deployments for a specific website. + +**Options** +- `--env `: The environment of the deployments (optional). Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. +- `--status `: The status of the deployments (DeploymentStatus enum, optional) + +#### `hosting get-deployment` +This command retrieves information about a specific deployment. + +**Options** +- `--website-uuid `: UUID of the website. +- `--deployment-uuid `: UUID of the deployment + +## `Storage` +#### `storage list-buckets` + +This command lists all storage buckets associated with your project. + +#### `storage list-objects` + +This command retrieves objects (files and directories) recursively from a specific bucket. + +**Options** +- `-b, --bucket-uuid `: UUID of the bucket to retrieve objects from. +- `-dir, --directory-uuid `: UUID of the directory to retreive objects from (optional, default root folder) +- `-del, --deleted`: Include objects deleted from the bucket + +#### `storage list-files` +This command retrieves files from a specific bucket. + +**Options** +- `-b, --bucket-uuid `: UUID of the bucket to retrieve files from. +- `-fs, --file-status `: Filter by file status (FileStatus enum, optional) + +**Example response** +```json +[ + { + "createTime": "2023-11-15T09:58:04.000Z", + "updateTime": "2023-11-15T09:58:10.000Z", + "name": "style.css", + "CID": "QmR6nTwU4V1rRFAd7rqANmVTEYe6rPV3nwRWxVyq2K24ud", + "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", + "type": "FILE", + "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" + }, + { + "createTime": "2023-11-15T09:58:04.000Z", + "updateTime": "2023-11-15T09:58:09.000Z", + "name": "index.html", + "CID": "QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH", + "status": "AVAILABLE_ON_IPFS", + "type": "FILE", + "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" + } +] ``` -To deploy the website to the staging environment, use the --preview flag: +#### `storage upload` +This command uploads files to a specified bucket. -```bash -apillon hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret --preview -# or -npx @apillon/cli hosting deploy-website ./dist --uuid your-website-uuid --key your-api-key --secret your-api-secret --preview +**Options** +- ``: Path to the folder containing your files. +- `-b, --bucket-uuid `: UUID of the bucket to upload files to. + +**Example** +```sh +apillon storage upload --uuid your-bucket-uuid ./my_folder ``` +#### `storage get-file` -## Environment Variables +This command retrieves information about a specific file in a bucket. -You can use environment variables to set the API URL, API key, and API secret: +**Options** +- `-b, --bucket-uuid `: UUID of the bucket. +- `--file-uuid `: UUID or CID of the file to retrieve. -- `APILLON_API_URL`: Apillon API URL. -- `APILLON_API_KEY`: Apillon API key. -- `APILLON_API_SECRET`: Apillon API secret. +#### `storage delete-file` -## Help +This command deletes a specific file from a bucket. -To display the help information for the CLI or a specific command, use the `-h` or `--help` option: +**Options** +- `-b, --bucket-uuid `: UUID of the bucket. +- `--file-uuid `: UUID or CID of the file to delete. + +## `NFTs` + +#### `nfts list-collections` +This command lists all NFT collections owned by the project related to the API key. + +**Options** +- `--status `: UUID of the collection to retrieve (CollectionStatus enum, optional). +#### `nfts get-collection` +This command retrieves information about a specific NFT collection. + +**Options** +- `--uuid `: UUID of the collection to retrieve. + +#### `nfts create-collection` +This command creates a new NFT collection. The JSON file needs to have the property structure as type `ICreateCollection`, which can be found in the SDK docs. + +**Options** +- ``: Path to the JSON data file for the new collection. + +**Example** ```sh -apillon -h -apillon hosting -h -npx @apillon/cli hosting deploy-website --help +apillon nfts create-collection ./nft-data.json ``` +#### `nfts mint-nft` +This command mints NFTs for a collection with a specific UUID. + +**Options** +- `--uuid `: UUID of the collection to mint NFTs to. +- `-a, --address `: Address which will receive minted NFTs. +- `-q --quantity `: Number of NFTs to mint. + +#### `nfts nest-mint-nft` +This command nest mints NFT child collection to a parent collection with a specific UUID and parent NFT with id. + +**Options** +- `-c, --parent-colleciton-uuid `: Parent collection UUID to which child NFTs will be minted to. +- `-pid, --parent-nft-id `: Parent collection NFT id to which child NFTs will be minted to. +- `-q, --quantity `: Number of child NFTs to mint. + +#### `nfts burn-nft` +This command burns NFT for a collection with a specific UUID. + +**Options** +- `--uuid `: Collection UUID. +- `-tid, --token-id `: NFT id which will be burned. + +#### `nfts transfer-collection` +This command transfers NFT collection ownership to a new wallet address. + +**Options** +- `--uuid `: Collection UUID. +- `-a, --address `: Address which you want to transfer collection ownership to. + +#### `nfts list-transactions` +This command lists NFT transactions for a specific collection UUID. + +**Options** +- `--uuid `: Collection UUID. +- `--status `: Transaction status (TransactionStatus enum, optional). +- `--type `: Transaction type (TransactionType enum, optional). + + ## Using in CI/CD tools CLI is particularly useful for CI/CD builds and pipelines. @@ -125,10 +317,10 @@ jobs: uses: actions/setup-node@v3 with: node-version: 16 - + - name: Create dist folder run: mkdir -p dist - + - name: Copy files run: | cp *.html dist/ @@ -137,9 +329,9 @@ jobs: cp -r js dist/ #### -## if you are using a framework for building web app, you can replace previous two step with the +## if you are using a framework for building web app, you can replace previous two step with the ## appropriate command for generating static webpage, like an example bellow. -## Find the correct command in your framework documentation. You may need to to change the +## Find the correct command in your framework documentation. You may need to to change the ## name of the source folder in the last step (CLI call) #### From 7be10cf6f25857890170c21f9b74e41ab222baa4 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 21 Nov 2023 15:31:07 +0100 Subject: [PATCH 58/68] Update typedoc config --- EXAMPLE.md | 12 ++++++++++-- packages/sdk/package.json | 2 +- packages/sdk/src/docs-index.ts | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index 6cc032f..f9fc1ef 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -21,6 +21,10 @@ if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { } ``` +### Detailed Hosting docs + +Detailed hosting SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Hosting.html). + ## Storage Storage module encapsulates functionalities for Storage service available on Apillon dashboard. @@ -44,6 +48,10 @@ const file = await bucket.file(file_uuid).get(); await bucket.deleteFile(file_uuid); ``` +### Detailed Storage docs + +Detailed Storage SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Storage.html). + ## NFTs NFT module encapsulates functionalities for NFT service available on Apillon dashboard. @@ -81,6 +89,6 @@ const nft = new Nft({ apillonConfig }); await collection.transferOwnership(to_address); ``` -## Detailed docs +### Detailed NFT docs -Detailed SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io). \ No newline at end of file +Detailed NFT SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Nft.html). \ No newline at end of file diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 4b09cc1..869873a 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -27,7 +27,7 @@ "lint": "tsc --declarationMap && eslint \"{src,test}/**/*.ts\" --fix", "publish-package": "npm publish", "test": "npx jest", - "generate-docs": "npx typedoc src/docs-index.ts" + "generate-docs": "npx typedoc src/docs-index.ts --sort enum-value-ascending" }, "keywords": [ "SDK", diff --git a/packages/sdk/src/docs-index.ts b/packages/sdk/src/docs-index.ts index a55b873..73d064a 100644 --- a/packages/sdk/src/docs-index.ts +++ b/packages/sdk/src/docs-index.ts @@ -8,6 +8,7 @@ export * from './modules/storage/storage-bucket'; export * from './modules/storage/file'; export * from './modules/storage/directory'; export * from './modules/hosting/hosting'; +export * from './modules/hosting/deployment'; export * from './modules/hosting/hosting-website'; export * from './modules/nft/nft'; export * from './modules/nft/nft-collection'; From c333449a326e69bfcbaadbb8a84210a7d3749a62 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Wed, 22 Nov 2023 10:04:56 +0100 Subject: [PATCH 59/68] CLI commands options and description updates --- EXAMPLE.md | 14 ++- packages/cli/README.md | 94 ++++++++++++++----- packages/cli/src/lib/options.ts | 10 +- .../src/modules/hosting/hosting.commands.ts | 17 ++-- packages/cli/src/modules/nfts/nft.service.ts | 4 +- .../cli/src/modules/nfts/nfts.commands.ts | 47 +++++++--- .../src/modules/storage/storage.commands.ts | 6 +- 7 files changed, 136 insertions(+), 56 deletions(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index f9fc1ef..8e7bb3a 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -2,6 +2,18 @@ Hosting module encapsulates functionalities for Hosting service available on Apillon dashboard. +::: tip +You can only create a new webpage through the [dashboard hosting service](https://app.apillon.io/dashboard/service/hosting). +::: + +The flow of deploying a new website looks like this: + +1. upload new website files +2. trigger deploy to staging +3. trigger deploy from staging to production + +You can also directly deploy uploaded files to production. + ### Usage example ```ts @@ -13,7 +25,7 @@ const webpage1 = hosting.website('uuid'); await webpage1.get(); await webpage1.uploadFromFolder('folder_path'); -await webpage1.deploy(DeployToEnvironment.STAGING_TO_PRODUCTION); +await webpage1.deploy(DeployToEnvironment.TO_STAGING); await webpage1.listDeployments(); const deployment = await webpage1.deployment(deployment_uuid).get(); if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { diff --git a/packages/cli/README.md b/packages/cli/README.md index 163fe11..a4bcd30 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -70,7 +70,7 @@ For commands that return a list of results, for example `apillon storage list-fi - `-p, --page `: Page number - `-s, --search `: Search by name or other object identifier -> For example responses and for an overview of all properties, refer to [the Apillon API wiki](https://wiki.apillon.io/build/1-apillon-api.html) +> For example responses and for an overview of all properties, refer to [the Apillon API wiki](https://wiki.apillon.io/build/1-apillon-api.html). Note: CLI responses may be dfferent from API responses. # Commands @@ -102,6 +102,11 @@ This command deployes website from a local folder directly to Apillon hosting pr - `--uuid `: UUID of the website to upload files to. - `-p, --preview`: Deploy to staging environment instead. +**Example** +```sh +apillon hosting deploy-website ./public_html --uuid your-website-uuid -p +``` + #### `hosting upload` Upload a file folder to a website deployment bucket. @@ -111,7 +116,7 @@ Upload a file folder to a website deployment bucket. **Example** ```sh -apillon hosting upload --uuid your-website-uuid ./public_html +apillon hosting upload ./public_html --uuid your-website-uuid ``` #### `hosting start-deployment` @@ -126,32 +131,34 @@ This command deploys a website to the specified environment, from files already apillon hosting start-deployment --uuid your-website-uuid --env 3 ``` -#### `hosting deploy-website` -This command uploads website files and immediately deploys them to the specified environment. +#### `hosting list-deployments` +This command lists all deployments for a specific website. **Options** -- ``: Path to the folder containing your website files. -- `--uuid `: UUID of the website to upload files to and deploy. -- `--env `: The environment to deploy to. Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. +- `--status `: The status of the deployments (DeploymentStatus enum, optional). -**Example** -```sh -apillon hosting deploy-website ./public_html --uuid your-website-uuid --env 2 +Available choices: ``` +TO_STAGING = 1 +STAGING_TO_PRODUCTION = 2 +DIRECTLY_TO_PRODUCTION = 3 +``` +- `--env `: The environment of the deployments (DeploymentStatus enum, optional). -#### `hosting list-deployments` -This command lists all deployments for a specific website. - -**Options** -- `--env `: The environment of the deployments (optional). Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. -- `--status `: The status of the deployments (DeploymentStatus enum, optional) +Available choices: +``` +INITIATED = 0 +IN_PROCESS = 1 +SUCCESSFUL = 10 +FAILED = 100 +``` #### `hosting get-deployment` This command retrieves information about a specific deployment. **Options** -- `--website-uuid `: UUID of the website. -- `--deployment-uuid `: UUID of the deployment +- `-w, --website-uuid `: UUID of the website. +- `-d, --deployment-uuid `: UUID of the deployment ## `Storage` #### `storage list-buckets` @@ -164,15 +171,23 @@ This command retrieves objects (files and directories) recursively from a specif **Options** - `-b, --bucket-uuid `: UUID of the bucket to retrieve objects from. -- `-dir, --directory-uuid `: UUID of the directory to retreive objects from (optional, default root folder) -- `-del, --deleted`: Include objects deleted from the bucket +- `-d, --directory-uuid `: UUID of the directory to retreive objects from (optional, default root folder) +- `--deleted`: Include objects deleted from the bucket #### `storage list-files` This command retrieves files from a specific bucket. **Options** - `-b, --bucket-uuid `: UUID of the bucket to retrieve files from. -- `-fs, --file-status `: Filter by file status (FileStatus enum, optional) +- `-s, --file-status `: Filter by file status (FileStatus enum, optional). + +Available choices: +``` +UPLOAD_REQUEST_GENERATED = 1 +UPLOADED = 2 +AVAILABLE_ON_IPFS = 3 +AVAILABLE_ON_IPFS_AND_REPLICATED = 4 +``` **Example response** ```json @@ -207,7 +222,7 @@ This command uploads files to a specified bucket. **Example** ```sh -apillon storage upload --uuid your-bucket-uuid ./my_folder +apillon storage upload ./my_folder --bucket-uuid your-bucket-uuid ``` #### `storage get-file` @@ -215,7 +230,7 @@ This command retrieves information about a specific file in a bucket. **Options** - `-b, --bucket-uuid `: UUID of the bucket. -- `--file-uuid `: UUID or CID of the file to retrieve. +- `-f, --file-uuid `: UUID or CID of the file to retrieve. #### `storage delete-file` @@ -223,7 +238,7 @@ This command deletes a specific file from a bucket. **Options** - `-b, --bucket-uuid `: UUID of the bucket. -- `--file-uuid `: UUID or CID of the file to delete. +- `-f, --file-uuid `: UUID or CID of the file to delete. ## `NFTs` @@ -233,6 +248,16 @@ This command lists all NFT collections owned by the project related to the API k **Options** - `--status `: UUID of the collection to retrieve (CollectionStatus enum, optional). +Available choices: +``` +CREATED = 0 +DEPLOY_INITIATED = 1 +DEPLOYING = 2 +DEPLOYED = 3 +TRANSFERRED = 4 +FAILED = 5 +``` + #### `nfts get-collection` This command retrieves information about a specific NFT collection. @@ -263,7 +288,7 @@ This command nest mints NFT child collection to a parent collection with a speci **Options** - `-c, --parent-colleciton-uuid `: Parent collection UUID to which child NFTs will be minted to. -- `-pid, --parent-nft-id `: Parent collection NFT id to which child NFTs will be minted to. +- `-p, --parent-nft-id `: Parent collection NFT id to which child NFTs will be minted to. - `-q, --quantity `: Number of child NFTs to mint. #### `nfts burn-nft` @@ -271,7 +296,7 @@ This command burns NFT for a collection with a specific UUID. **Options** - `--uuid `: Collection UUID. -- `-tid, --token-id `: NFT id which will be burned. +- `-t, --token-id `: NFT id which will be burned. #### `nfts transfer-collection` This command transfers NFT collection ownership to a new wallet address. @@ -286,8 +311,25 @@ This command lists NFT transactions for a specific collection UUID. **Options** - `--uuid `: Collection UUID. - `--status `: Transaction status (TransactionStatus enum, optional). + +Available choices: +``` +PENDING = 1 +CONFIRMED = 2 +FAILED = 3 +ERROR = 4 +``` - `--type `: Transaction type (TransactionType enum, optional). +Available choices: +``` +DEPLOY_CONTRACT = 1 +TRANSFER_CONTRACT_OWNERSHIP = 2 +MINT_NFT = 3 +SET_COLLECTION_BASE_URI = 4 +BURN_NFT = 5 +NEST_MINT_NFT = 6 +``` ## Using in CI/CD tools diff --git a/packages/cli/src/lib/options.ts b/packages/cli/src/lib/options.ts index b6260d2..d84d308 100644 --- a/packages/cli/src/lib/options.ts +++ b/packages/cli/src/lib/options.ts @@ -10,10 +10,12 @@ export function addPaginationOptions(command: Command) { 'Search by name or other object identifier', ), ) - .addOption(new Option('-p, --page ', 'Page number')) - .addOption(new Option('-l, --limit ', 'Page limit')) - .addOption(new Option('-o, --order-by ', 'Page order by')) - .addOption(new Option('-d --desc ', 'Page order descending')); + .addOption(new Option('--page ', 'Page number').default(1)) + .addOption( + new Option('--limit ', 'Page limit (page size)').default(20), + ) + .addOption(new Option('--order-by ', 'Page order by any property')) + .addOption(new Option('--desc ', 'Page order descending')); } export function paginate(opts: GlobalOptions): IApillonPagination { diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index 13ac79d..d398de2 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -9,7 +9,7 @@ import { uploadWebsiteFiles, deployWebsite, } from './hosting.service'; -import { DeployToEnvironment } from '@apillon/sdk'; +import { DeployToEnvironment, DeploymentStatus } from '@apillon/sdk'; export function createHostingCommands(cli: Command) { const hosting = cli @@ -91,15 +91,18 @@ export function createHostingCommands(cli: Command) { ` ${DeployToEnvironment.TO_STAGING}: To Staging\n` + ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production\n` + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production`, - ).choices(['1', '2', '3']), + ).choices(Object.values(DeployToEnvironment).map((x) => `${x}`)), ) .addOption( new Option( '--status ', - 'Status of the deployment (DeploymentStatus enum)', - ).choices(['0', '1', '10', '100']), + 'Status of the deployment (optional) Choose from:\n' + + ` ${DeploymentStatus.INITIATED}: Initiated\n` + + ` ${DeploymentStatus.IN_PROCESS}: In process\n` + + ` ${DeploymentStatus.SUCCESSFUL}: Successful\n` + + ` ${DeploymentStatus.FAILED}: Failed`, + ).choices(Object.values(DeploymentStatus).map((x) => `${x}`)), ) - .option('--status ', 'deployment status') .action(async function () { await listDeployments(this.optsWithGlobals()); }); @@ -108,9 +111,9 @@ export function createHostingCommands(cli: Command) { hosting .command('get-deployment') .description('Returns deployment data') - .requiredOption('--website-uuid ', 'UUID of website') + .requiredOption('-w, --website-uuid ', 'UUID of website') .requiredOption( - '--deployment-uuid ', + '-d, --deployment-uuid ', 'UUID of deployment to get', ) .action(async function () { diff --git a/packages/cli/src/modules/nfts/nft.service.ts b/packages/cli/src/modules/nfts/nft.service.ts index 1b9c69c..b6a66a9 100644 --- a/packages/cli/src/modules/nfts/nft.service.ts +++ b/packages/cli/src/modules/nfts/nft.service.ts @@ -90,8 +90,8 @@ export async function nestMintCollectionNft(optsWithGlobals: GlobalOptions) { const data = await nftService .collection(optsWithGlobals.uuid) .nestMint( - optsWithGlobals.parentCollectionUuid, - toInteger(optsWithGlobals.parentNftId), + optsWithGlobals.parentCollection, + toInteger(optsWithGlobals.parentNft), toInteger(optsWithGlobals.quantity), ); if (data.status === 5) { diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index 22f2ac2..f76af2e 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -10,6 +10,11 @@ import { transferCollectionOwnership, } from './nft.service'; import { addPaginationOptions } from '../../lib/options'; +import { + CollectionStatus, + TransactionStatus, + TransactionType, +} from '@apillon/sdk'; export function createNftsCommands(cli: Command) { const nfts = cli @@ -24,9 +29,15 @@ export function createNftsCommands(cli: Command) { .description('List NFT collections owned by project') .addOption( new Option( - '--status ', - 'Collection status (CollectionStatus enum)', - ), + '--status ', + 'Status of the collection (optional) Choose from:\n' + + ` ${CollectionStatus.CREATED}: Created\n` + + ` ${CollectionStatus.DEPLOY_INITIATED}: Deploy Initiated\n` + + ` ${CollectionStatus.DEPLOYING}: Deploying\n` + + ` ${CollectionStatus.DEPLOYED}: Deployed\n` + + ` ${CollectionStatus.TRANSFERRED}: Transferred\n` + + ` ${CollectionStatus.FAILED}: Failed`, + ).choices(Object.values(CollectionStatus).map((x) => `${x}`)), ) .action(async function () { await listCollections(this.optsWithGlobals()); @@ -67,12 +78,12 @@ export function createNftsCommands(cli: Command) { .description('Nest mint NFT child collection to parent NFT') .requiredOption('--uuid ', 'Child collection UUID') .requiredOption( - '-c, --parent-collection-uuid ', + '-c, --parent-collection ', 'Parent collection UUID to which child NFTs will be minted to.', ) .requiredOption( - '-pid, --parent-nft-id ', - 'Parent NFT id to which child NFTs will be minted to', + '-p, --parent-nft ', + 'Parent NFT ID to which child NFTs will be minted to', ) .requiredOption( '-q, --quantity ', @@ -87,7 +98,7 @@ export function createNftsCommands(cli: Command) { .command('burn-nft') .description('Burn NFT token') .requiredOption('--uuid ', 'Collection UUID') - .requiredOption('-tid, --token-id ', 'NFT ID which will be burned') + .requiredOption('-t, --token-id ', 'NFT ID which will be burned') .action(async function () { await burnCollectionNft(this.optsWithGlobals()); }); @@ -111,15 +122,25 @@ export function createNftsCommands(cli: Command) { .requiredOption('--uuid ', 'Collection UUID') .addOption( new Option( - '--status ', - 'Transaction status (TransactionStatus enum)', - ), + '--status ', + 'Status of the transaction (optional) Choose from:\n' + + ` ${TransactionStatus.PENDING}: Pending\n` + + ` ${TransactionStatus.CONFIRMED}: Confirmed\n` + + ` ${TransactionStatus.FAILED}: Failed\n` + + ` ${TransactionStatus.ERROR}: Error`, + ).choices(Object.values(TransactionStatus).map((x) => `${x}`)), ) .addOption( new Option( - '-t, --type ', - 'Transaction type (TransactionType enum)', - ), + '-t, --type ', + 'Transaction type (optional) Choose from:\n' + + ` ${TransactionType.DEPLOY_CONTRACT}: Deploy Contract\n` + + ` ${TransactionType.TRANSFER_CONTRACT_OWNERSHIP}: Transfer Contract Ownership\n` + + ` ${TransactionType.MINT_NFT}: Mint NFT\n` + + ` ${TransactionType.SET_COLLECTION_BASE_URI}: Set Collection Base URI\n` + + ` ${TransactionType.BURN_NFT}: Burn NFT\n` + + ` ${TransactionType.NEST_MINT_NFT}: Nest Mint NFT`, + ).choices(Object.values(TransactionType).map((x) => `${x}`)), ) .action(async function () { await listCollectionTransactions(this.optsWithGlobals()); diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index bf2d9de..288fe17 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -29,8 +29,8 @@ export function createStorageCommands(cli: Command) { .command('list-objects') .description('List files and folders in directory') .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') - .option('-dir, --directory-uuid ', 'Directory UUID') - .option('-del, --deleted', 'Include deleted objects') + .option('-d, --directory-uuid ', 'Directory UUID') + .option('--deleted', 'Include deleted objects') .action(async function () { await listObjects(this.optsWithGlobals()); }); @@ -41,7 +41,7 @@ export function createStorageCommands(cli: Command) { .description('List all files from a bucket') .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') .option( - '-fs, --file-status ', + '-s, --file-status ', 'Filter by file status. Choose from:\n' + ` ${FileStatus.UPLOAD_REQUEST_GENERATED}: Upload request generated\n` + ` ${FileStatus.UPLOADED}: Uploaded\n` + From c09263996ef359aa738c0a8bf943d48be1f80faf Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 23 Nov 2023 10:00:01 +0100 Subject: [PATCH 60/68] Implement upload files as buffer methods --- EXAMPLE.md | 35 ++++++++++- .../src/modules/hosting/hosting-website.ts | 28 +++++++-- .../sdk/src/modules/storage/storage-bucket.ts | 26 ++++++-- packages/sdk/src/tests/hosting.test.ts | 41 +++++++++--- packages/sdk/src/tests/storage.test.ts | 38 +++++++++++- packages/sdk/src/types/storage.ts | 38 ++++++++++++ packages/sdk/src/util/file-utils.ts | 62 +++++++++++++------ 7 files changed, 230 insertions(+), 38 deletions(-) diff --git a/EXAMPLE.md b/EXAMPLE.md index 8e7bb3a..37e0cdf 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -24,7 +24,22 @@ await hosting.listWebsites({ orderBy: 'createdTime' }); const webpage1 = hosting.website('uuid'); await webpage1.get(); -await webpage1.uploadFromFolder('folder_path'); +// Upload files from local folder +await webpage1.uploadFromFolder('./my-foler/files/'); +// Or alternatively, send file buffers as upload parameters +await webpage1.uploadFiles( + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: htmlBuffer, + }, + ], + // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, +); + await webpage1.deploy(DeployToEnvironment.TO_STAGING); await webpage1.listDeployments(); const deployment = await webpage1.deployment(deployment_uuid).get(); @@ -45,11 +60,27 @@ Storage module encapsulates functionalities for Storage service available on Api ```ts import { Storage } from "@apillon/sdk"; +import * as fs from 'fs'; const storage = new Storage({ apillonConfig }); await storage.listBuckets({ limit: 5 }); const bucket = storage.bucket('uuid'); -await bucket.uploadFromFolder('folder_path'); + +// Upload files from local folder +await bucket.uploadFromFolder('./my-foler/files/'); +// Or alternatively, send file buffers as upload parameters +await bucket.uploadFiles( + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: htmlBuffer, + }, + ], + // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, +); await bucket.listObjects({ directoryUuid, markedForDeletion: false, diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index 96d5bc6..23b2064 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -7,10 +7,14 @@ import { LogLevel, } from '../../types/apillon'; import { Deployment } from './deployment'; -import { ApillonModel } from '../../docs-index'; +import { + ApillonModel, + FileMetadata, + IFileUploadRequest, +} from '../../docs-index'; import { ApillonApi } from '../../lib/apillon-api'; import { ApillonLogger } from '../../lib/apillon-logger'; -import { uploadFilesFromFolder } from '../../util/file-utils'; +import { uploadFiles } from '../../util/file-utils'; export class HostingWebsite extends ApillonModel { /** @@ -68,9 +72,25 @@ export class HostingWebsite extends ApillonModel { /** * Uploads website files inside a folder via path. * @param folderPath Path to the folder to upload. + * @param {IFileUploadRequest} params - Optional parameters to be used for uploading files + */ + public async uploadFromFolder( + folderPath: string, + params?: IFileUploadRequest, + ): Promise { + await uploadFiles(folderPath, this.API_PREFIX, params); + } + + /** + * Uploads files to the hosting bucket. + * @param {FileMetadata[]} files - The files to be uploaded + * @param {IFileUploadRequest} params - Optional parameters to be used for uploading files */ - public async uploadFromFolder(folderPath: string): Promise { - await uploadFilesFromFolder(folderPath, this.API_PREFIX); + public async uploadFiles( + files: FileMetadata[], + params?: IFileUploadRequest, + ): Promise { + await uploadFiles(null, this.API_PREFIX, params, files); } /** diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 18ab65d..75c1e17 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -1,6 +1,8 @@ import { Directory } from './directory'; import { + FileMetadata, IBucketFilesRequest, + IFileUploadRequest, IStorageBucketContentRequest, StorageContentType, } from '../../types/storage'; @@ -9,7 +11,7 @@ import { constructUrlWithQueryParams } from '../../lib/common'; import { IApillonList, IApillonListResponse } from '../../types/apillon'; import { ApillonApi } from '../../lib/apillon-api'; import { ApillonModel } from '../../docs-index'; -import { uploadFilesFromFolder } from '../../util/file-utils'; +import { uploadFiles } from '../../util/file-utils'; export class StorageBucket extends ApillonModel { /** @@ -93,11 +95,27 @@ export class StorageBucket extends ApillonModel { } /** - * Uploads files inside a folder via path. + * Uploads files inside a local folder via path. * @param folderPath Path to the folder to upload. + * @param {IFileUploadRequest} params - Optional parameters to be used for uploading files */ - public async uploadFromFolder(folderPath: string): Promise { - await uploadFilesFromFolder(folderPath, this.API_PREFIX); + public async uploadFromFolder( + folderPath: string, + params?: IFileUploadRequest, + ): Promise { + await uploadFiles(folderPath, this.API_PREFIX, params); + } + + /** + * Uploads files to the bucket. + * @param {FileMetadata[]} files - The files to be uploaded + * @param {IFileUploadRequest} params - Optional parameters to be used for uploading files + */ + public async uploadFiles( + files: FileMetadata[], + params?: IFileUploadRequest, + ): Promise { + await uploadFiles(null, this.API_PREFIX, params, files); } /** diff --git a/packages/sdk/src/tests/hosting.test.ts b/packages/sdk/src/tests/hosting.test.ts index c7051d2..72b95e7 100644 --- a/packages/sdk/src/tests/hosting.test.ts +++ b/packages/sdk/src/tests/hosting.test.ts @@ -4,6 +4,7 @@ import { Hosting } from '../modules/hosting/hosting'; import { DeployToEnvironment } from '../types/hosting'; import { getConfig, getWebsiteUUID } from './helpers/helper'; import { HostingWebsite } from '../modules/hosting/hosting-website'; +import * as fs from 'fs'; describe('Hosting tests', () => { let config: ApillonConfig; @@ -40,13 +41,39 @@ describe('Hosting tests', () => { expect(deployment.environment).toEqual(DeployToEnvironment.TO_STAGING); }); - // test('get deployment status', async () => { - // const hosting = new Hosting(config); - // const website = hosting.website(websiteUUID); - - // const deployStatus = await website.deploy(DeployToEnvironment.TO_STAGING); - // console.log(deployStatus); - // }); + test.skip('upload files from buffer', async () => { + const hosting = new Hosting(config); + const html = fs.readFileSync( + resolve(__dirname, './helpers/website/index.html'), + ); + const css = fs.readFileSync( + resolve(__dirname, './helpers/website/style.css'), + ); + try { + console.time('File upload complete'); + await hosting.website(websiteUUID).uploadFiles( + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: html, + }, + { + fileName: 'style.css', + contentType: 'text/css', + path: null, + content: css, + }, + ], + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, + ); + console.timeEnd('File upload complete'); + // console.log(content); + } catch (e) { + console.log(e); + } + }); test('list all deployments', async () => { const hosting = new Hosting(config); diff --git a/packages/sdk/src/tests/storage.test.ts b/packages/sdk/src/tests/storage.test.ts index 89ab075..dd62a00 100644 --- a/packages/sdk/src/tests/storage.test.ts +++ b/packages/sdk/src/tests/storage.test.ts @@ -3,6 +3,7 @@ import { ApillonConfig } from '../lib/apillon'; import { Storage } from '../modules/storage/storage'; import { StorageContentType } from '../types/storage'; import { getBucketUUID, getConfig } from './helpers/helper'; +import * as fs from 'fs'; describe('Storage tests', () => { let config: ApillonConfig; @@ -74,7 +75,7 @@ describe('Storage tests', () => { expect(file.name).toBeTruthy(); }); - test.skip('upload files', async () => { + test.skip('upload files from folder', async () => { const storage = new Storage(config); try { const uploadDir = resolve(__dirname, './helpers/website/'); @@ -88,6 +89,41 @@ describe('Storage tests', () => { } }); + test.skip('upload files from buffer', async () => { + const storage = new Storage(config); + const html = fs.readFileSync( + resolve(__dirname, './helpers/website/index.html'), + ); + const css = fs.readFileSync( + resolve(__dirname, './helpers/website/style.css'), + ); + try { + console.time('File upload complete'); + await storage.bucket(bucketUUID).uploadFiles( + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: html, + }, + { + fileName: 'style.css', + contentType: 'text/css', + path: null, + content: css, + }, + ], + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, + ); + console.timeEnd('File upload complete'); + + // console.log(content); + } catch (e) { + console.log(e); + } + }); + test.skip('delete a file', async () => { const storage = new Storage(config); await storage diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index ddecc4c..d28bc18 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -20,3 +20,41 @@ export interface IStorageBucketContentRequest extends IApillonPagination { export interface IBucketFilesRequest extends IApillonPagination { fileStatus?: FileStatus; } + +export interface FileMetadata { + fileName: string; + content: Buffer; + /** + * File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) + */ + contentType: string; + /** + * Virtual file path. Empty for root. Must not contain fileName. + * + * The path field can be used to place file in virtual directories inside a bucket. If directories do not yet exist, they will be automatically generated. + * + * For example, an images/icons path creates images directory in a bucket and icons directory inside it. File will then be created in the icons directory. + */ + path: string; +} + +export interface IFileUploadRequest { + /** + * Wrap uploaded files to IPFS directory. + * + * Files in session can be wrapped to CID on IPFS via wrapWithDirectory parameter. This means that the directory gets its own CID and its content cannot be modified afterwards. + * + * Read more on the [IPFS docs](https://dweb-primer.ipfs.io/files-on-ipfs/wrap-directories-around-content#explanation) + */ + wrapWithDirectory: boolean; + /** + * Path to wrapped directory inside bucket. + * + * Mandatory when `wrapWithDirectory` is true. + * + * **Example**: `main-dir` --> Files get uploaded to a folder named `main-dir` in the bucket. + * + * **Example 2**: `main-dir/sub-dir` --> Files get uploaded to a subfolder in the location `/main-dir/sub-dir`. + */ + directoryPath: string; +} diff --git a/packages/sdk/src/util/file-utils.ts b/packages/sdk/src/util/file-utils.ts index 2a5a41c..3187716 100644 --- a/packages/sdk/src/util/file-utils.ts +++ b/packages/sdk/src/util/file-utils.ts @@ -5,6 +5,7 @@ import axios from 'axios'; import { ApillonLogger } from '../lib/apillon-logger'; import { LogLevel } from '../types/apillon'; import { ApillonApi } from '../lib/apillon-api'; +import { FileMetadata, IFileUploadRequest } from '../docs-index'; export function listFilesRecursive( folderPath: string, @@ -36,18 +37,25 @@ export async function uploadFilesToS3(uploadLinks: any[], files: any[]) { throw new Error(`Cant find file ${link.path}${link.fileName}!`); } uploadWorkers.push( - new Promise((resolve, reject) => { - fs.readFile(file.index, async (err, data) => { - if (err) { - reject(err.message); - } - // const respS3 = - await s3Api.put(link.url, data); - // console.log(respS3); + new Promise(async (resolve, reject) => { + // If uploading from local folder read file, otherwise directly upload content + if (file.index) { + fs.readFile(file.index, async (err, data) => { + if (err) { + reject(err.message); + } + // const respS3 = + await s3Api.put(link.url, data); + // console.log(respS3); + console.log(`File uploaded: ${file.fileName} `); + resolve(); + }); + } else if (file.content) { + await s3Api.put(link.url, file.content); console.log(`File uploaded: ${file.fileName} `); resolve(); - }); + } }), ); } @@ -55,20 +63,33 @@ export async function uploadFilesToS3(uploadLinks: any[], files: any[]) { await Promise.all(uploadWorkers); } -export async function uploadFilesFromFolder( +export async function uploadFiles( folderPath: string, apiPrefix: string, + params?: IFileUploadRequest, + files?: FileMetadata[], ): Promise { - ApillonLogger.log( - `Preparing to upload files from ${folderPath}...`, - LogLevel.VERBOSE, - ); - let files; - try { - files = listFilesRecursive(folderPath); - } catch (err) { - console.error(err); - throw new Error(`Error reading files in ${folderPath}`); + if (folderPath) { + ApillonLogger.log( + `Preparing to upload files from ${folderPath}...`, + LogLevel.VERBOSE, + ); + } else if (files?.length) { + ApillonLogger.log( + `Preparing to upload ${files.length} files...`, + LogLevel.VERBOSE, + ); + } else { + throw new Error('Invalid upload parameters received'); + } + // If folderPath param passed, read files from local storage + if (folderPath && !files?.length) { + try { + files = listFilesRecursive(folderPath); + } catch (err) { + console.error(err); + throw new Error(`Error reading files in ${folderPath}`); + } } ApillonLogger.log(`Files to upload: ${files.length}`, LogLevel.VERBOSE); @@ -92,6 +113,7 @@ export async function uploadFilesFromFolder( ApillonLogger.log('Closing upload session...', LogLevel.VERBOSE); const { data: endSession } = await ApillonApi.post( `${apiPrefix}/upload/${data.sessionUuid}/end`, + params, ); ApillonLogger.logWithTime('Session ended.', LogLevel.VERBOSE); From 8f24140c13f93b576f071ac12efe3903c672ade9 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 23 Nov 2023 12:07:15 +0100 Subject: [PATCH 61/68] NFT command and response updates --- packages/cli/src/modules/nfts/nfts.commands.ts | 2 +- packages/sdk/src/modules/nft/nft-collection.ts | 9 ++++++++- packages/sdk/src/types/nfts.ts | 17 +++-------------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index f76af2e..7cc4709 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -68,7 +68,7 @@ export function createNftsCommands(cli: Command) { '-a, --address ', 'Address which will receive minted NFTs.', ) - .requiredOption('-q, --quantity ', 'Number of NFTs to mint.') + .requiredOption('-q, --quantity ', 'Number of NFTs to mint.', '1') .action(async function () { await mintCollectionNft(this.optsWithGlobals()); }); diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index ceda1e8..aaced73 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -1,3 +1,4 @@ +import { TransactionStatus } from './../../types/nfts'; import { ApillonModel } from '../../docs-index'; import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; @@ -14,6 +15,7 @@ import { CollectionType, CollectionStatus, EvmChain, + TransactionType, } from '../../types/nfts'; export class NftCollection extends ApillonModel { @@ -235,7 +237,9 @@ export class NftCollection extends ApillonModel { IApillonResponse> >(url); - return data.items; + return data.items.map((t) => + JSON.parse(JSON.stringify(t, this.serializeFilter)), + ); } protected override serializeFilter(key: string, value: any) { @@ -243,6 +247,9 @@ export class NftCollection extends ApillonModel { const enums = { collectionType: CollectionType[serialized], collectionStatus: CollectionStatus[serialized], + transactionType: TransactionType[serialized], + transactionStatus: TransactionStatus[serialized], + chain: EvmChain[serialized], }; return Object.keys(enums).includes(key) ? enums[key] : serialized; } diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index e4971de..7c90b72 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -57,7 +57,7 @@ export interface ICreateCollection { } //OUTPUTS -export interface ICollection { +export interface ICollection extends ICreateCollection { collectionUuid: string; contractAddress: string; deployerAddress: string; @@ -69,25 +69,14 @@ export interface ICollection { symbol: string; description: string; bucketUuid: string; - baseUri: string; - baseExtension: string; - maxSupply: number; - isRevokable: boolean; - isSoulbound: boolean; - royaltiesAddress: string; - royaltiesFees: number; - drop: boolean; - dropStart: number; - dropPrice: number; - dropReserve: number; updateTime: string; createTime: string; } export interface ITransaction { chainId: number; - transactionType: number; - transactionStatus: number; + transactionType: TransactionType; + transactionStatus: TransactionStatus; transactionHash: string; updateTime: string; createTime: string; From da7b95ec7bb36693424f5bd09bbdf059f4d0f75f Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 23 Nov 2023 12:07:40 +0100 Subject: [PATCH 62/68] Update SDK and CLI docs --- EXAMPLE.md | 137 ------- packages/cli/README.md | 334 ++++++++++++++---- .../src/modules/hosting/hosting.commands.ts | 8 +- .../src/modules/storage/storage.commands.ts | 4 +- packages/sdk/README.md | 167 ++++++++- 5 files changed, 429 insertions(+), 221 deletions(-) delete mode 100644 EXAMPLE.md diff --git a/EXAMPLE.md b/EXAMPLE.md deleted file mode 100644 index 37e0cdf..0000000 --- a/EXAMPLE.md +++ /dev/null @@ -1,137 +0,0 @@ -## Hosting - -Hosting module encapsulates functionalities for Hosting service available on Apillon dashboard. - -::: tip -You can only create a new webpage through the [dashboard hosting service](https://app.apillon.io/dashboard/service/hosting). -::: - -The flow of deploying a new website looks like this: - -1. upload new website files -2. trigger deploy to staging -3. trigger deploy from staging to production - -You can also directly deploy uploaded files to production. - -### Usage example - -```ts -import { Hosting } from "@apillon/sdk"; - -const hosting = new Hosting({ apillonConfig }); -await hosting.listWebsites({ orderBy: 'createdTime' }); -const webpage1 = hosting.website('uuid'); -await webpage1.get(); - -// Upload files from local folder -await webpage1.uploadFromFolder('./my-foler/files/'); -// Or alternatively, send file buffers as upload parameters -await webpage1.uploadFiles( - [ - { - fileName: 'index.html', - contentType: 'text/html', - path: null, - content: htmlBuffer, - }, - ], - // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket - { wrapWithDirectory: true, directoryPath: 'main/subdir' }, -); - -await webpage1.deploy(DeployToEnvironment.TO_STAGING); -await webpage1.listDeployments(); -const deployment = await webpage1.deployment(deployment_uuid).get(); -if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { - // done -} -``` - -### Detailed Hosting docs - -Detailed hosting SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Hosting.html). - -## Storage - -Storage module encapsulates functionalities for Storage service available on Apillon dashboard. - -### Usage example - -```ts -import { Storage } from "@apillon/sdk"; -import * as fs from 'fs'; - -const storage = new Storage({ apillonConfig }); -await storage.listBuckets({ limit: 5 }); -const bucket = storage.bucket('uuid'); - -// Upload files from local folder -await bucket.uploadFromFolder('./my-foler/files/'); -// Or alternatively, send file buffers as upload parameters -await bucket.uploadFiles( - [ - { - fileName: 'index.html', - contentType: 'text/html', - path: null, - content: htmlBuffer, - }, - ], - // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket - { wrapWithDirectory: true, directoryPath: 'main/subdir' }, -); -await bucket.listObjects({ - directoryUuid, - markedForDeletion: false, - limit: 5, -}); -await bucket.listFiles({ fileStatus: FileStatus.UPLOADED }); -const file = await bucket.file(file_uuid).get(); -await bucket.deleteFile(file_uuid); -``` - -### Detailed Storage docs - -Detailed Storage SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Storage.html). - -## NFTs - -NFT module encapsulates functionalities for NFT service available on Apillon dashboard. - -### Usage example - -```ts -import { Nft } from "@apillon/sdk"; - -const nft = new Nft({ apillonConfig }); - await nft.create({ - collectionType: CollectionType.GENERIC, - chain: EvmChain.MOONBEAM, - name: 'SpaceExplorers', - symbol: 'SE', - description: 'A collection of unique space exploration NFTs.', - baseUri: 'https://moonbeamnfts.com/collections/spaceexplorers/', - baseExtension: 'json', - maxSupply: 1000, - isRevokable: false, - isSoulbound: false, - royaltiesAddress: '0x1234567890abcdef', - royaltiesFees: 5, - drop: true, - dropStart: 1679875200, - dropPrice: 0.05, - dropReserve: 100, - }); - await nft.listCollections({ search: 'My NFT' }); - const collection = await nft.collection('uuid').get(); - await collection.mint(receiver, quantity); - await collection.nestMint(collection.uuid, 1, quantity); - await collection.burn(quantity); - await collection.listTransactions(); - await collection.transferOwnership(to_address); -``` - -### Detailed NFT docs - -Detailed NFT SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Nft.html). \ No newline at end of file diff --git a/packages/cli/README.md b/packages/cli/README.md index a4bcd30..77005f1 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -65,10 +65,10 @@ npx @apillon/cli hosting deploy-website --help For commands that return a list of results, for example `apillon storage list-files`, or `apillon hosting list-websites`, there are global list pagination options that are available to use: -- `-l, --limit `: Page limit -- `-o, --order-by `: Page order by (can be any property from the response data) -- `-p, --page `: Page number -- `-s, --search `: Search by name or other object identifier +- `--limit `: Page limit +- `--order-by `: Page order by (can be any property from the response data) +- `--page `: Page number +- `--search `: Search by name or other object identifier > For example responses and for an overview of all properties, refer to [the Apillon API wiki](https://wiki.apillon.io/build/1-apillon-api.html). Note: CLI responses may be dfferent from API responses. @@ -76,26 +76,48 @@ For commands that return a list of results, for example `apillon storage list-fi The Apillon CLI currently supports the following commands: -## `Hosting` - -To be able to deploy a website with Apillon CLI, you have to create a website deployment inside your project on [Apillon Developer dashboard](https://app.apillon.io/dashboard/service/hosting). Upon creating a website deployment, you will get the website UUID number, that you will need to run CLI hosting commands. +## Hosting #### `hosting list-websites` +Lists all websites associated with your project. -This command lists all websites associated with your project. - +**Example** ```sh apillon hosting list-websites --search "My-Website" --limit 1 ``` +**Example response** +```json +[ + { + "createTime": "2023-10-25T10:41:06.000Z", + "updateTime": "2023-10-26T12:41:41.000Z", + "uuid": "5b908779-3687-4592-a073-9bebbf86afe2", + "name": "My Website", + "description": "My own website", + "domain": "https://my-website.com", + "bucketUuid": "47251013-37c6-4b30-be2b-8583dea25c4c", + "ipnsStaging": "k2k4r8ob2rf35wbmhhtzbq6nd4lhwv4qphwv9zl5smbzkuakwd50m6fd", + "ipnsProduction": "k2k4r8pple7phwm9azqgxshxdzyb1fs4n1hy8k5kcq5bkm5jnpznthrb" + } + ... +] + +``` + #### `hosting get-website` -This command retrieves information about a specific website. +Retrieves information about a specific website. **Options** - `--uuid `: UUID of the website to get details for. +**Example** +```sh +apillon hosting get-website --uuid "123e4567-e89b-12d3-a456-426655440000" +``` + #### `hosting deploy-website` -This command deployes website from a local folder directly to Apillon hosting production environment. +Deploys a website from a local folder directly to Apillon hosting production environment. **Options** - ``: Path to the folder containing your website files. @@ -104,78 +126,161 @@ This command deployes website from a local folder directly to Apillon hosting pr **Example** ```sh -apillon hosting deploy-website ./public_html --uuid your-website-uuid -p +apillon hosting deploy-website ./public_html --uuid "123e4567-e89b-12d3-a456-426655440000" -p ``` #### `hosting upload` -Upload a file folder to a website deployment bucket. +Uploads a local folder's contents to a website deployment bucket. **Options** -- ``: Path to the folder containing your website files. +- ``: Path to the folder containing your website files. - `--uuid `: UUID of the website to upload files to. **Example** ```sh -apillon hosting upload ./public_html --uuid your-website-uuid +apillon hosting upload ./public_html --uuid "123e4567-e89b-12d3-a456-426655440000" ``` #### `hosting start-deployment` -This command deploys a website to the specified environment, from files already uploaded to the hosting bucket. +Deploys a website to the specified environment, from files already uploaded to the hosting bucket. **Options** - `--uuid `: UUID of the website to deploy. -- `--env `: The environment to deploy to. Can be 1 - staging, 2 - staging to production, or 3 - direct to productiion. +- `--env `: The environment to deploy to. + +Available choices: +``` +TO_STAGING = 1 +STAGING_TO_PRODUCTION = 2 +DIRECTLY_TO_PRODUCTION = 3 +``` **Example** ```sh -apillon hosting start-deployment --uuid your-website-uuid --env 3 +apillon hosting start-deployment --uuid "123e4567-e89b-12d3-a456-426655440000" --env 1 ``` #### `hosting list-deployments` -This command lists all deployments for a specific website. +Lists all deployments for a specific website. **Options** +- `--uuid `: UUID of the website to list deployments for. - `--status `: The status of the deployments (DeploymentStatus enum, optional). Available choices: ``` -TO_STAGING = 1 -STAGING_TO_PRODUCTION = 2 -DIRECTLY_TO_PRODUCTION = 3 +INITIATED = 0 +IN_PROCESS = 1 +SUCCESSFUL = 10 +FAILED = 100 ``` + - `--env `: The environment of the deployments (DeploymentStatus enum, optional). Available choices: ``` -INITIATED = 0 -IN_PROCESS = 1 -SUCCESSFUL = 10 -FAILED = 100 +STAGING = 2 +PRODUCTION = 3 +``` + +**Example** +```sh +apillon hosting list-deployments --uuid "58a16026-1356-405b-97f9-efcc9dfac1dd" --order-by createTime --desc true +``` + +**Example response** +```json +[ + { + "createTime": "2023-11-14T12:09:20.000Z", + "updateTime": "2023-11-14T12:09:42.000Z", + "uuid": "9b677fe2-1bb1-44d9-8956-e7749452f02d", + "websiteUuid": "58a16026-1356-405b-97f9-efcc9dfac1dd", + "cid": "QmPPBMsFccJVaLwvdhSh3zMbfEvonxoNSBLVd1kWK34Nps", + "cidv1": "bafybeizpqaa5xb5r46d2voj35qtokhb3c3bekofe5fnistbs7s3g7nnvmq", + "environment": "DIRECTLY_TO_PRODUCTION", + "deploymentStatus": "SUCCESSFUL", + "size": 7162, + "number": 1 + } + ... +] ``` #### `hosting get-deployment` -This command retrieves information about a specific deployment. +Retrieves information about a specific deployment. **Options** - `-w, --website-uuid `: UUID of the website. - `-d, --deployment-uuid `: UUID of the deployment -## `Storage` +**Example** +```sh +apillon hosting get-deployment --website-uuid "123e4567-e89b-12d3-a456-426655440000" --deployment-uuid "987e6543-e21c-32f1-b123-426655441111" +``` + +## Storage Commands + #### `storage list-buckets` +Lists all storage buckets associated with your project. -This command lists all storage buckets associated with your project. +**Example** +```sh +apillon storage list-buckets +``` -#### `storage list-objects` +**Example response** +```json +[ + { + "createTime": "2023-11-15T09:56:53.000Z", + "updateTime": "2023-11-23T08:55:46.000Z", + "uuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3", + "name": "My Storage Bucket", + "description": "For storing my images and videos", + "size": 23576 + } + ... +] +``` -This command retrieves objects (files and directories) recursively from a specific bucket. +#### `storage list-objects` +Retrieves objects (files and folders) from a specific bucket or bucket directory. **Options** - `-b, --bucket-uuid `: UUID of the bucket to retrieve objects from. -- `-d, --directory-uuid `: UUID of the directory to retreive objects from (optional, default root folder) -- `--deleted`: Include objects deleted from the bucket +- `-d, --directory-uuid `: UUID of the directory to retrieve objects from (optional, default root folder). +- `--deleted`: Include objects deleted from the bucket. + +**Example** +```sh +apillon storage list-objects --bucket-uuid "123e4567-e89b-12d3-a456-426655440000" --directory-uuid "987e6543-e21c-32f1-b123-426655441111" +``` + +**Example response** + +```json +[ + { + "createTime": "2023-11-23T08:55:45.000Z", + "updateTime": "2023-11-23T08:55:46.000Z", + "uuid": "14a7a891-877c-41ac-900c-7382347e1e77", + "name": "index.html", + "CID": "QmWX5CcNvnaVmgGBn4o82XW9uW1uLvsHQDdNrANrQeSdXm", + "CIDv1": "bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima", + "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", + "directoryUuid": null, + "type": "FILE", + "link": "https://ipfs-eu1.apillon.io/ipfs/bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJiYWZ5YmVpZHpyZDdwNWRkajY3ajJtdWQzMmNibnplMmM3YjJwdmJobjdmbGZkMjJzaG56dXZnbmltYSIsInByb2plY3RfdXVpZCI6IjgwOWQzYjljLTMxNjMtNDgzMC1hZjg2LTJiNTMxYmZmNTUyZCIsImlhdCI6MTcwMDczNjM5Mywic3ViIjoiSVBGUy10b2tlbiJ9.nmq7BYdEYGXW6kHO9_ExOr3i5OBesWkN4TDI4QG6Fok", + "path": null, + "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" + } + ... +] +``` #### `storage list-files` -This command retrieves files from a specific bucket. +Retrieves files from a specific bucket. **Options** - `-b, --bucket-uuid `: UUID of the bucket to retrieve files from. @@ -189,6 +294,11 @@ AVAILABLE_ON_IPFS = 3 AVAILABLE_ON_IPFS_AND_REPLICATED = 4 ``` +**Example** +```sh +apillon storage list-files --bucket-uuid "123e4567-e89b-12d3-a456-426655440000" -s 2 +``` + **Example response** ```json [ @@ -196,54 +306,59 @@ AVAILABLE_ON_IPFS_AND_REPLICATED = 4 "createTime": "2023-11-15T09:58:04.000Z", "updateTime": "2023-11-15T09:58:10.000Z", "name": "style.css", - "CID": "QmR6nTwU4V1rRFAd7rqANmVTEYe6rPV3nwRWxVyq2K24ud", + "CID": "QmWX5CcNvnaVmgGBn4o82XW9uW1uLvsHQDdNrANrQeSdXm", + "CIDv1": "bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima", "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", + "directoryUuid": null, "type": "FILE", - "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" - }, - { - "createTime": "2023-11-15T09:58:04.000Z", - "updateTime": "2023-11-15T09:58:09.000Z", - "name": "index.html", - "CID": "QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH", - "status": "AVAILABLE_ON_IPFS", - "type": "FILE", + "link": "https://ipfs-eu1.apillon.io/ipfs/bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJiYWZ5YmVpZHpyZDdwNWRkajY3ajJtdWQzMmNibnplMmM3YjJwdmJobjdmbGZkMjJzaG56dXZnbmltYSIsInByb2plY3RfdXVpZCI6IjgwOWQzYjljLTMxNjMtNDgzMC1hZjg2LTJiNTMxYmZmNTUyZCIsImlhdCI6MTcwMDczNjM5Mywic3ViIjoiSVBGUy10b2tlbiJ9.nmq7BYdEYGXW6kHO9_ExOr3i5OBesWkN4TDI4QG6Fok", + "path": null, "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" } + ... ] ``` #### `storage upload` -This command uploads files to a specified bucket. +Upload contents of a local folder to specified bucket. **Options** -- ``: Path to the folder containing your files. +- ``: Path to the folder containing your files. - `-b, --bucket-uuid `: UUID of the bucket to upload files to. **Example** ```sh -apillon storage upload ./my_folder --bucket-uuid your-bucket-uuid +apillon storage upload ./my_folder --bucket-uuid "123e4567-e89b-12d3-a456-426655440000" ``` -#### `storage get-file` -This command retrieves information about a specific file in a bucket. +#### `storage get-file` +Retrieves information about a specific file in a bucket. **Options** - `-b, --bucket-uuid `: UUID of the bucket. - `-f, --file-uuid `: UUID or CID of the file to retrieve. -#### `storage delete-file` +**Example** +```sh +apillon storage get-file --bucket-uuid "123e4567-e89b-12d3-a456-426655440000" --file-uuid "file_uuid_or_cid" +``` -This command deletes a specific file from a bucket. +#### `storage delete-file` +Deletes a specific file from a bucket. **Options** - `-b, --bucket-uuid `: UUID of the bucket. - `-f, --file-uuid `: UUID or CID of the file to delete. -## `NFTs` +**Example** +```sh +apillon storage delete-file --bucket-uuid "123e4567-e89b-12d3-a456-426655440000" --file-uuid "file_uuid_or_cid" +``` + +## NFT Commands #### `nfts list-collections` -This command lists all NFT collections owned by the project related to the API key. +Lists all NFT collections owned by the project related to the API key. **Options** - `--status `: UUID of the collection to retrieve (CollectionStatus enum, optional). @@ -258,14 +373,57 @@ TRANSFERRED = 4 FAILED = 5 ``` +**Example** +```sh +apillon nfts list-collections --status 3 +``` + +**Example response** + +```json +[ + { + "createTime": "2023-11-20T10:21:12.000Z", + "updateTime": "2023-11-20T14:12:33.000Z", + "uuid": "2cda3a9b-01b1-4b5e-9709-7087129d55d0", + "symbol": "SE", + "name": "SpaceExplorers", + "description": "A collection of unique space exploration NFTs.", + "collectionType": "GENERIC", + "maxSupply": 1000, + "baseUri": "https://moonbeamnfts.com/collections/spaceexplorers/", + "baseExtension": ".json", + "isSoulbound": false, + "isRevokable": false, + "drop": false, + "dropPrice": 0.05, + "dropStart": 1679875200, + "dropReserve": 100, + "royaltiesFees": 5, + "royaltiesAddress": "0xaz5Bh6E56c5d3B58c944542de2bF18E7F65eED82", + "collectionStatus": "TRANSFERRED", + "contractAddress": "0x4e22162A6d0c91a088Cb57A72aB976ccA2A96B25", + "transactionHash": null, + "deployerAddress": "0xba015fgc6d80378a9a95f1687e9960857593983b", + "chain": "MOONBASE" + } + ... +] +``` + #### `nfts get-collection` -This command retrieves information about a specific NFT collection. +Retrieves information about a specific NFT collection. **Options** - `--uuid `: UUID of the collection to retrieve. +**Example** +```sh +apillon nfts get-collection --uuid "123e4567-e89b-12d3-a456-426655440000" +``` + #### `nfts create-collection` -This command creates a new NFT collection. The JSON file needs to have the property structure as type `ICreateCollection`, which can be found in the SDK docs. +Creates a new NFT collection. The JSON file needs to have the property structure as type `ICreateCollection`, which can be found in the [SDK docs](https://sdk-docs.apillon.io/interfaces/ICreateCollection.html). An example object can be also seen on the [NFT SDK docs](https://wiki.apillon.io/build/5-apillon-sdk.html#nfts). **Options** - ``: Path to the JSON data file for the new collection. @@ -276,37 +434,57 @@ apillon nfts create-collection ./nft-data.json ``` #### `nfts mint-nft` -This command mints NFTs for a collection with a specific UUID. +Mints NFTs for a collection with a specific UUID. **Options** - `--uuid `: UUID of the collection to mint NFTs to. - `-a, --address `: Address which will receive minted NFTs. -- `-q --quantity `: Number of NFTs to mint. +- `-q --quantity `: Number of NFTs to mint. (default 1). + +**Example** +```sh +apillon nfts mint-nft --uuid "123e4567-e89b-12d3-a456-426655440000" --address "0xdAC17F958D2ee523a2206206994597C13D831ec7" --quantity 2 +``` #### `nfts nest-mint-nft` -This command nest mints NFT child collection to a parent collection with a specific UUID and parent NFT with id. +Nest mints NFT child collection to a parent collection with a specific UUID and parent NFT with id. **Options** -- `-c, --parent-colleciton-uuid `: Parent collection UUID to which child NFTs will be minted to. +- `-c, --parent-collection-uuid `: Parent collection UUID to which child NFTs will be minted to. - `-p, --parent-nft-id `: Parent collection NFT id to which child NFTs will be minted to. -- `-q, --quantity `: Number of child NFTs to mint. +- `-q, --quantity `: Number of child NFTs to mint (default 1). + +**Example** +```sh +apillon nfts nest-mint-nft --parent-collection-uuid "123e4567-e89b-12d3-a456-426655440000" --parent-nft-id 5 --quantity 2 +``` #### `nfts burn-nft` -This command burns NFT for a collection with a specific UUID. +Burns an NFT for a collection with a specific UUID. **Options** - `--uuid `: Collection UUID. - `-t, --token-id `: NFT id which will be burned. +**Example** +```sh +apillon nfts burn-nft --uuid "123e4567-e89b-12d3-a456-426655440000" --token-id 123 +``` + #### `nfts transfer-collection` -This command transfers NFT collection ownership to a new wallet address. +Transfers NFT collection ownership to a new wallet address. **Options** - `--uuid `: Collection UUID. - `-a, --address `: Address which you want to transfer collection ownership to. +**Example** +```sh +apillon nfts transfer-collection --uuid "123e4567-e89b-12d3-a456-426655440000" --address "0xdAC17F958D2ee523a2206206994597C13D831ec7" +``` + #### `nfts list-transactions` -This command lists NFT transactions for a specific collection UUID. +Lists NFT transactions for a specific collection UUID. **Options** - `--uuid `: Collection UUID. @@ -319,6 +497,7 @@ CONFIRMED = 2 FAILED = 3 ERROR = 4 ``` + - `--type `: Transaction type (TransactionType enum, optional). Available choices: @@ -331,6 +510,35 @@ BURN_NFT = 5 NEST_MINT_NFT = 6 ``` +**Example** +```sh +apillon nfts list-transactions --uuid "123e4567-e89b-12d3-a456-426655440000" +``` + +**Example response** + +```json +[ + { + "createTime": "2023-11-20T10:21:22.000Z", + "updateTime": "2023-11-20T10:23:31.000Z", + "chainId": 1287, + "transactionType": "DEPLOY_CONTRACT", + "transactionStatus": "CONFIRMED", + "transactionHash": "0xab99e630f9475df92768b1e5d73f43e291252d889dba81e8fcc0f0fbe690bc0b" + }, + { + "createTime": "2023-11-20T11:55:13.000Z", + "updateTime": "2023-11-20T11:57:31.000Z", + "chainId": 1287, + "transactionType": "MINT_NFT", + "transactionStatus": "CONFIRMED", + "transactionHash": "0x1ecfeeaeddfa0a39fc2ae1ec755d2736b2577866089fe1d619c84690fbdac05a" + } + ... +] +``` + ## Using in CI/CD tools CLI is particularly useful for CI/CD builds and pipelines. diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index d398de2..ff7c7b7 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -45,8 +45,10 @@ export function createHostingCommands(cli: Command) { }); hosting - .command('upload-files') - .description('Uploads files from local folder to deployment bucket') + .command('upload') + .description( + `Uploads a local folder's contents to a website deployment bucket.`, + ) .argument('', 'path to folder with website files') .requiredOption( '--uuid ', @@ -70,7 +72,7 @@ export function createHostingCommands(cli: Command) { ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production\n` + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production`, ) - .choices(['1', '2', '3']) + .choices(Object.values(DeployToEnvironment).map((x) => `${x}`)) .makeOptionMandatory(true), ) .action(async function () { diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index 288fe17..95e7677 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -55,8 +55,8 @@ export function createStorageCommands(cli: Command) { storage .command('upload') - .description('Upload files and folders to bucket') - .argument('', 'path to source') + .description('Upload contents of a local folder to bucket') + .argument('', 'path to local folder') .requiredOption('-b, --bucket-uuid ', 'UUID of destination bucket') .action(async function (path: string) { await uploadFromFolder(path, this.optsWithGlobals()); diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 0855f14..91542dc 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -1,39 +1,174 @@ -# Apillon SDK for NodeJS +# Apillon SDK [![npm version](https://badge.fury.io/js/@apillon%2Fsdk.svg)](https://badge.fury.io/js/@apillon%2Fsdk) [![Twitter Follow](https://img.shields.io/twitter/follow/Apillon?style=social)](https://twitter.com/intent/follow?screen_name=Apillon) -Apillon SDK is a NodeJS library written in Typescript for using Apillon Web3 services. +Libraries and tools for interacting with your Apillon integration. +Apillon SDK reduces the amount of work required to use Apillons REST API. It reduces the boilerplate code you need to write +as well as compresses multi step flows into single operations. ## Requirements -To be able to use Apillon CLI, you must register an account at [Apillon.io](https://app.apillon.io), create a project and generate an API key with appropriate permissions. +- npm 8.4.0 or higher +- node.js 16.17.0 or higher +- Apillon API key and secret -## Installation +## Getting started -To install the SDK, run the following command: +SDK is available on [NPM](https://www.npmjs.com/package/@apillon/sdk) and you can also check it out directly on [GitHub](https://github.com/Apillon/sdk). + +### Installation ```sh npm install @apillon/sdk ``` -## Usage +### Initialization -To use the SDK in your project, first import appropriate module: +```ts +import { Hosting } from "@apillon/sdk"; -```typescript -import { Hosting } from '@apillon/sdk'; +const hosting = new Hosting({ + apiKey: "", + apiSecret: "", +}); ``` -Then, create a new instance of the module class: +Apillon SDK consists of different modules depending on which service you want to use. But all modules require the same initial config of `apiKey` and `apiSecret` shown above in `Hosting` module example. -```typescript -const hosting = new Hosting({ - key: 'yourApiKey', - secret:'yourApiSecret' +## Hosting + +Hosting module encapsulates functionalities for Hosting service available on Apillon dashboard. + +::: tip +You can only create a new webpage through the [dashboard hosting service](https://app.apillon.io/dashboard/service/hosting). +::: + +The flow of deploying a new website looks like this: + +1. upload new website files +2. trigger deploy to staging +3. trigger deploy from staging to production + +You can also directly deploy uploaded files to production. + +### Usage example + +```ts +import { Hosting } from "@apillon/sdk"; + +const hosting = new Hosting({ apillonConfig }); +await hosting.listWebsites({ orderBy: 'createdTime' }); +const webpage1 = hosting.website('uuid'); +await webpage1.get(); + +// Upload files from local folder +await webpage1.uploadFromFolder('./my-foler/files/'); +// Or alternatively, send file buffers as upload parameters +await webpage1.uploadFiles( + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: htmlBuffer, + }, + ], + // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, +); + +await webpage1.deploy(DeployToEnvironment.TO_STAGING); +await webpage1.listDeployments(); +const deployment = await webpage1.deployment(deployment_uuid).get(); +if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { + // done +} +``` + +### Detailed Hosting docs + +Detailed hosting SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Hosting.html). + +## Storage + +Storage module encapsulates functionalities for Storage service available on Apillon dashboard. + +### Usage example + +```ts +import { Storage } from "@apillon/sdk"; + +const storage = new Storage({ apillonConfig }); +await storage.listBuckets({ limit: 5 }); +const bucket = storage.bucket('uuid'); + +// Upload files from local folder +await bucket.uploadFromFolder('./my-foler/files/'); +// Or alternatively, send file buffers as upload parameters +await bucket.uploadFiles( + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: htmlBuffer, + }, + ], + // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, +); +await bucket.listObjects({ + directoryUuid, + markedForDeletion: false, + limit: 5, +}); +await bucket.listFiles({ fileStatus: FileStatus.UPLOADED }); +const file = await bucket.file(file_uuid).get(); +await bucket.deleteFile(file_uuid); +``` + +### Detailed Storage docs + +Detailed Storage SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Storage.html). + +## NFTs + +NFT module encapsulates functionalities for NFT service available on Apillon dashboard. + +### Usage example + +```ts +import { Nft } from "@apillon/sdk"; + +const nft = new Nft({ apillonConfig }); + await nft.create({ + collectionType: CollectionType.GENERIC, + chain: EvmChain.MOONBEAM, + name: 'SpaceExplorers', + symbol: 'SE', + description: 'A collection of unique space exploration NFTs.', + baseUri: 'https://moonbeamnfts.com/collections/spaceexplorers/', + baseExtension: 'json', + maxSupply: 1000, + isRevokable: false, + isSoulbound: false, + royaltiesAddress: '0x1234567890abcdef', + royaltiesFees: 5, + drop: true, + dropStart: 1679875200, + dropPrice: 0.05, + dropReserve: 100, }); + await nft.listCollections({ search: 'My NFT' }); + const collection = await nft.collection('uuid').get(); + await collection.mint(receiver, quantity); + await collection.nestMint(collection.uuid, 1, quantity); + await collection.burn(quantity); + await collection.listTransactions(); + await collection.transferOwnership(to_address); ``` -You can then use the methods on the module instance to interact with the Apillon APIs. +### Detailed NFT docs -For more information on using the SDK, see the [Apillon documentation](https://wiki.apillon.io). +Detailed NFT SDK method, class and property documentation is available [here](https://sdk-docs.apillon.io/classes/Nft.html). \ No newline at end of file From 69cc8526a5f6e326ea5c9dbcaa14c53850ab5e04 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 23 Nov 2023 12:28:49 +0100 Subject: [PATCH 63/68] Include pagination data in all listing responses --- packages/cli/README.md | 261 ++++++++++-------- .../src/modules/hosting/hosting.service.ts | 12 +- .../src/modules/storage/storage.service.ts | 27 +- .../src/modules/hosting/hosting-website.ts | 2 +- packages/sdk/src/modules/hosting/hosting.ts | 2 +- .../sdk/src/modules/nft/nft-collection.ts | 12 +- packages/sdk/src/modules/nft/nft.ts | 15 +- .../sdk/src/modules/storage/storage-bucket.ts | 2 +- packages/sdk/src/modules/storage/storage.ts | 2 +- packages/sdk/src/tests/nft.test.ts | 4 +- 10 files changed, 185 insertions(+), 154 deletions(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index 77005f1..d4f6f31 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -88,21 +88,23 @@ apillon hosting list-websites --search "My-Website" --limit 1 **Example response** ```json -[ - { - "createTime": "2023-10-25T10:41:06.000Z", - "updateTime": "2023-10-26T12:41:41.000Z", - "uuid": "5b908779-3687-4592-a073-9bebbf86afe2", - "name": "My Website", - "description": "My own website", - "domain": "https://my-website.com", - "bucketUuid": "47251013-37c6-4b30-be2b-8583dea25c4c", - "ipnsStaging": "k2k4r8ob2rf35wbmhhtzbq6nd4lhwv4qphwv9zl5smbzkuakwd50m6fd", - "ipnsProduction": "k2k4r8pple7phwm9azqgxshxdzyb1fs4n1hy8k5kcq5bkm5jnpznthrb" - } - ... -] - +{ + "items": [ + { + "createTime": "2023-10-25T10:41:06.000Z", + "updateTime": "2023-10-26T12:41:41.000Z", + "uuid": "5b908779-3687-4592-a073-9bebbf86afe2", + "name": "My Website", + "description": "My own website", + "domain": "https://my-website.com", + "bucketUuid": "47251013-37c6-4b30-be2b-8583dea25c4c", + "ipnsStaging": "k2k4r8ob2rf35wbmhhtzbq6nd4lhwv4qphwv9zl5smbzkuakwd50m6fd", + "ipnsProduction": "k2k4r8pple7phwm9azqgxshxdzyb1fs4n1hy8k5kcq5bkm5jnpznthrb" + }, + ... + ], + "total": 3 +} ``` #### `hosting get-website` @@ -190,21 +192,24 @@ apillon hosting list-deployments --uuid "58a16026-1356-405b-97f9-efcc9dfac1dd" - **Example response** ```json -[ - { - "createTime": "2023-11-14T12:09:20.000Z", - "updateTime": "2023-11-14T12:09:42.000Z", - "uuid": "9b677fe2-1bb1-44d9-8956-e7749452f02d", - "websiteUuid": "58a16026-1356-405b-97f9-efcc9dfac1dd", - "cid": "QmPPBMsFccJVaLwvdhSh3zMbfEvonxoNSBLVd1kWK34Nps", - "cidv1": "bafybeizpqaa5xb5r46d2voj35qtokhb3c3bekofe5fnistbs7s3g7nnvmq", - "environment": "DIRECTLY_TO_PRODUCTION", - "deploymentStatus": "SUCCESSFUL", - "size": 7162, - "number": 1 - } - ... -] +{ + "items": [ + { + "createTime": "2023-11-14T12:09:20.000Z", + "updateTime": "2023-11-14T12:09:42.000Z", + "uuid": "9b677fe2-1bb1-44d9-8956-e7749452f02d", + "websiteUuid": "58a16026-1356-405b-97f9-efcc9dfac1dd", + "cid": "QmPPBMsFccJVaLwvdhSh3zMbfEvonxoNSBLVd1kWK34Nps", + "cidv1": "bafybeizpqaa5xb5r46d2voj35qtokhb3c3bekofe5fnistbs7s3g7nnvmq", + "environment": "DIRECTLY_TO_PRODUCTION", + "deploymentStatus": "SUCCESSFUL", + "size": 7162, + "number": 1 + }, + ... + ], + "total": 7 +} ``` #### `hosting get-deployment` @@ -231,17 +236,20 @@ apillon storage list-buckets **Example response** ```json -[ - { - "createTime": "2023-11-15T09:56:53.000Z", - "updateTime": "2023-11-23T08:55:46.000Z", - "uuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3", - "name": "My Storage Bucket", - "description": "For storing my images and videos", - "size": 23576 - } - ... -] +{ + "items": [ + { + "createTime": "2023-11-15T09:56:53.000Z", + "updateTime": "2023-11-23T08:55:46.000Z", + "uuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3", + "name": "My Storage Bucket", + "description": "For storing my images and videos", + "size": 23576 + }, + ... + ], + "total": 2 +} ``` #### `storage list-objects` @@ -260,23 +268,26 @@ apillon storage list-objects --bucket-uuid "123e4567-e89b-12d3-a456-426655440000 **Example response** ```json -[ - { - "createTime": "2023-11-23T08:55:45.000Z", - "updateTime": "2023-11-23T08:55:46.000Z", - "uuid": "14a7a891-877c-41ac-900c-7382347e1e77", - "name": "index.html", - "CID": "QmWX5CcNvnaVmgGBn4o82XW9uW1uLvsHQDdNrANrQeSdXm", - "CIDv1": "bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima", - "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", - "directoryUuid": null, - "type": "FILE", - "link": "https://ipfs-eu1.apillon.io/ipfs/bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJiYWZ5YmVpZHpyZDdwNWRkajY3ajJtdWQzMmNibnplMmM3YjJwdmJobjdmbGZkMjJzaG56dXZnbmltYSIsInByb2plY3RfdXVpZCI6IjgwOWQzYjljLTMxNjMtNDgzMC1hZjg2LTJiNTMxYmZmNTUyZCIsImlhdCI6MTcwMDczNjM5Mywic3ViIjoiSVBGUy10b2tlbiJ9.nmq7BYdEYGXW6kHO9_ExOr3i5OBesWkN4TDI4QG6Fok", - "path": null, - "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" - } - ... -] +{ + "items": [ + { + "createTime": "2023-11-23T08:55:45.000Z", + "updateTime": "2023-11-23T08:55:46.000Z", + "uuid": "14a7a891-877c-41ac-900c-7382347e1e77", + "name": "index.html", + "CID": "QmWX5CcNvnaVmgGBn4o82XW9uW1uLvsHQDdNrANrQeSdXm", + "CIDv1": "bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima", + "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", + "directoryUuid": null, + "type": "FILE", + "link": "https://ipfs-eu1.apillon.io/ipfs/bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJiYWZ5YmVpZHpyZDdwNWRkajY3ajJtdWQzMmNibnplMmM3YjJwdmJobjdmbGZkMjJzaG56dXZnbmltYSIsInByb2plY3RfdXVpZCI6IjgwOWQzYjljLTMxNjMtNDgzMC1hZjg2LTJiNTMxYmZmNTUyZCIsImlhdCI6MTcwMDczNjM5Mywic3ViIjoiSVBGUy10b2tlbiJ9.nmq7BYdEYGXW6kHO9_ExOr3i5OBesWkN4TDI4QG6Fok", + "path": null, + "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" + }, + ... + ], + "total": 16 +} ``` #### `storage list-files` @@ -301,22 +312,25 @@ apillon storage list-files --bucket-uuid "123e4567-e89b-12d3-a456-426655440000" **Example response** ```json -[ - { - "createTime": "2023-11-15T09:58:04.000Z", - "updateTime": "2023-11-15T09:58:10.000Z", - "name": "style.css", - "CID": "QmWX5CcNvnaVmgGBn4o82XW9uW1uLvsHQDdNrANrQeSdXm", - "CIDv1": "bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima", - "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", - "directoryUuid": null, - "type": "FILE", - "link": "https://ipfs-eu1.apillon.io/ipfs/bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJiYWZ5YmVpZHpyZDdwNWRkajY3ajJtdWQzMmNibnplMmM3YjJwdmJobjdmbGZkMjJzaG56dXZnbmltYSIsInByb2plY3RfdXVpZCI6IjgwOWQzYjljLTMxNjMtNDgzMC1hZjg2LTJiNTMxYmZmNTUyZCIsImlhdCI6MTcwMDczNjM5Mywic3ViIjoiSVBGUy10b2tlbiJ9.nmq7BYdEYGXW6kHO9_ExOr3i5OBesWkN4TDI4QG6Fok", - "path": null, - "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" - } - ... -] +{ + "items": [ + { + "createTime": "2023-11-15T09:58:04.000Z", + "updateTime": "2023-11-15T09:58:10.000Z", + "name": "style.css", + "CID": "QmWX5CcNvnaVmgGBn4o82XW9uW1uLvsHQDdNrANrQeSdXm", + "CIDv1": "bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima", + "status": "AVAILABLE_ON_IPFS_AND_REPLICATED", + "directoryUuid": null, + "type": "FILE", + "link": "https://ipfs-eu1.apillon.io/ipfs/bafybeidzrd7p5ddj67j2mud32cbnze2c7b2pvbhn7flfd22shnzuvgnima/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjaWQiOiJiYWZ5YmVpZHpyZDdwNWRkajY3ajJtdWQzMmNibnplMmM3YjJwdmJobjdmbGZkMjJzaG56dXZnbmltYSIsInByb2plY3RfdXVpZCI6IjgwOWQzYjljLTMxNjMtNDgzMC1hZjg2LTJiNTMxYmZmNTUyZCIsImlhdCI6MTcwMDczNjM5Mywic3ViIjoiSVBGUy10b2tlbiJ9.nmq7BYdEYGXW6kHO9_ExOr3i5OBesWkN4TDI4QG6Fok", + "path": null, + "bucketUuid": "91c57d55-e8e4-40b7-ad6a-81a82831bfb3" + }, + ... + ], + "total": 10 +} ``` #### `storage upload` @@ -381,34 +395,36 @@ apillon nfts list-collections --status 3 **Example response** ```json -[ - { - "createTime": "2023-11-20T10:21:12.000Z", - "updateTime": "2023-11-20T14:12:33.000Z", - "uuid": "2cda3a9b-01b1-4b5e-9709-7087129d55d0", - "symbol": "SE", - "name": "SpaceExplorers", - "description": "A collection of unique space exploration NFTs.", - "collectionType": "GENERIC", - "maxSupply": 1000, - "baseUri": "https://moonbeamnfts.com/collections/spaceexplorers/", - "baseExtension": ".json", - "isSoulbound": false, - "isRevokable": false, - "drop": false, - "dropPrice": 0.05, - "dropStart": 1679875200, - "dropReserve": 100, - "royaltiesFees": 5, - "royaltiesAddress": "0xaz5Bh6E56c5d3B58c944542de2bF18E7F65eED82", - "collectionStatus": "TRANSFERRED", - "contractAddress": "0x4e22162A6d0c91a088Cb57A72aB976ccA2A96B25", - "transactionHash": null, - "deployerAddress": "0xba015fgc6d80378a9a95f1687e9960857593983b", - "chain": "MOONBASE" - } - ... -] +{ + "items": [ + { + "createTime": "2023-11-20T10:21:12.000Z", + "updateTime": "2023-11-20T14:12:33.000Z", + "uuid": "2cda3a9b-01b1-4b5e-9709-7087129d55d0", + "symbol": "SE", + "name": "SpaceExplorers", + "description": "A collection of unique space exploration NFTs.", + "collectionType": "GENERIC", + "maxSupply": 1000, + "baseUri": "https://moonbeamnfts.com/collections/spaceexplorers/", + "baseExtension": ".json", + "isSoulbound": false, + "isRevokable": false, + "drop": false, + "dropPrice": 0.05, + "dropStart": 1679875200, + "dropReserve": 100, + "royaltiesFees": 5, + "royaltiesAddress": "0xaz5Bh6E56c5d3B58c944542de2bF18E7F65eED82", + "collectionStatus": "TRANSFERRED", + "contractAddress": "0x4e22162A6d0c91a088Cb57A72aB976ccA2A96B25", + "transactionHash": null, + "deployerAddress": "0xba015fgc6d80378a9a95f1687e9960857593983b", + "chain": "MOONBASE" + } + ], + "total": 1 +} ``` #### `nfts get-collection` @@ -518,25 +534,28 @@ apillon nfts list-transactions --uuid "123e4567-e89b-12d3-a456-426655440000" **Example response** ```json -[ - { - "createTime": "2023-11-20T10:21:22.000Z", - "updateTime": "2023-11-20T10:23:31.000Z", - "chainId": 1287, - "transactionType": "DEPLOY_CONTRACT", - "transactionStatus": "CONFIRMED", - "transactionHash": "0xab99e630f9475df92768b1e5d73f43e291252d889dba81e8fcc0f0fbe690bc0b" - }, - { - "createTime": "2023-11-20T11:55:13.000Z", - "updateTime": "2023-11-20T11:57:31.000Z", - "chainId": 1287, - "transactionType": "MINT_NFT", - "transactionStatus": "CONFIRMED", - "transactionHash": "0x1ecfeeaeddfa0a39fc2ae1ec755d2736b2577866089fe1d619c84690fbdac05a" - } - ... -] +{ + "items": [ + { + "createTime": "2023-11-20T10:21:22.000Z", + "updateTime": "2023-11-20T10:23:31.000Z", + "chainId": "MOONBEAM", + "transactionType": "DEPLOY_CONTRACT", + "transactionStatus": "CONFIRMED", + "transactionHash": "0xab99e630f9475df92768b1e5d73f43e291252d889dba81e8fcc0f0fbe690bc0b" + }, + { + "createTime": "2023-11-20T11:55:13.000Z", + "updateTime": "2023-11-20T11:57:31.000Z", + "chainId": "MOONBEAM", + "transactionType": "MINT_NFT", + "transactionStatus": "CONFIRMED", + "transactionHash": "0x1ecfeeaeddfa0a39fc2ae1ec755d2736b2577866089fe1d619c84690fbdac05a" + }, + ... + ], + "total": 4 +} ``` ## Using in CI/CD tools diff --git a/packages/cli/src/modules/hosting/hosting.service.ts b/packages/cli/src/modules/hosting/hosting.service.ts index 9ef3a10..30cd940 100644 --- a/packages/cli/src/modules/hosting/hosting.service.ts +++ b/packages/cli/src/modules/hosting/hosting.service.ts @@ -10,10 +10,9 @@ import { paginate } from '../../lib/options'; export async function listWebsites(optsWithGlobals: GlobalOptions) { const hosting = new Hosting(optsWithGlobals); try { - const { items: websites } = await hosting.listWebsites( - paginate(optsWithGlobals), - ); - console.log(websites.map((w) => w.serialize())); + const data = await hosting.listWebsites(paginate(optsWithGlobals)); + data.items = data.items.map((w) => w.serialize()); + console.log(data); } catch (err) { exceptionHandler(err); } @@ -84,10 +83,11 @@ export async function listDeployments(optsWithGlobals: GlobalOptions) { deploymentStatus: toInteger(optsWithGlobals.status), }; try { - const { items: deployments } = await hosting + const data = await hosting .website(optsWithGlobals.uuid) .listDeployments(params); - console.log(deployments.map((d) => d.serialize())); + data.items = data.items.map((w) => w.serialize()); + console.log(data); } catch (err) { exceptionHandler(err); } diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index ff36fc4..e30457f 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -5,10 +5,9 @@ import { paginate } from '../../lib/options'; export async function listBuckets(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { - const { items: buckets } = await storage.listBuckets( - paginate(optsWithGlobals), - ); - console.log(buckets.map((x) => x.serialize())); + const data = await storage.listBuckets(paginate(optsWithGlobals)); + data.items = data.items.map((w) => w.serialize()); + console.log(data); } catch (err) { exceptionHandler(err); } @@ -17,14 +16,13 @@ export async function listBuckets(optsWithGlobals: GlobalOptions) { export async function listObjects(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { - const { items: objects } = await storage - .bucket(optsWithGlobals.bucketUuid) - .listObjects({ - ...paginate(optsWithGlobals), - directoryUuid: optsWithGlobals.directoryUuid, - markedForDeletion: !!optsWithGlobals.deleted, - }); - console.log(objects.map((x) => x.serialize())); + const data = await storage.bucket(optsWithGlobals.bucketUuid).listObjects({ + ...paginate(optsWithGlobals), + directoryUuid: optsWithGlobals.directoryUuid, + markedForDeletion: !!optsWithGlobals.deleted, + }); + data.items = data.items.map((w) => w.serialize()); + console.log(data); } catch (err) { exceptionHandler(err); } @@ -33,10 +31,11 @@ export async function listObjects(optsWithGlobals: GlobalOptions) { export async function listFiles(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { - const { items: files } = await storage + const data = await storage .bucket(optsWithGlobals.bucketUuid) .listFiles(paginate(optsWithGlobals)); - console.log(files.map((x) => x.serialize())); + data.items = data.items.map((w) => w.serialize()); + console.log(data); } catch (err) { exceptionHandler(err); } diff --git a/packages/sdk/src/modules/hosting/hosting-website.ts b/packages/sdk/src/modules/hosting/hosting-website.ts index 23b2064..1d1c73f 100644 --- a/packages/sdk/src/modules/hosting/hosting-website.ts +++ b/packages/sdk/src/modules/hosting/hosting-website.ts @@ -135,10 +135,10 @@ export class HostingWebsite extends ApillonModel { >(url); return { + ...data, items: data.items.map( (item) => new Deployment(item.websiteUuid, item.deploymentUuid, item), ), - total: data.total, }; } diff --git a/packages/sdk/src/modules/hosting/hosting.ts b/packages/sdk/src/modules/hosting/hosting.ts index f031e5c..7c7d29e 100644 --- a/packages/sdk/src/modules/hosting/hosting.ts +++ b/packages/sdk/src/modules/hosting/hosting.ts @@ -25,10 +25,10 @@ export class Hosting extends ApillonModule { ); return { + ...data, items: data.items.map( (website) => new HostingWebsite(website['websiteUuid'], website), ), - total: data.total, }; } diff --git a/packages/sdk/src/modules/nft/nft-collection.ts b/packages/sdk/src/modules/nft/nft-collection.ts index aaced73..fd0a99b 100644 --- a/packages/sdk/src/modules/nft/nft-collection.ts +++ b/packages/sdk/src/modules/nft/nft-collection.ts @@ -227,7 +227,7 @@ export class NftCollection extends ApillonModel { */ public async listTransactions( params?: ITransactionFilters, - ): Promise { + ): Promise> { const url = constructUrlWithQueryParams( `${this.API_PREFIX}/transactions`, params, @@ -237,9 +237,12 @@ export class NftCollection extends ApillonModel { IApillonResponse> >(url); - return data.items.map((t) => - JSON.parse(JSON.stringify(t, this.serializeFilter)), - ); + return { + ...data, + items: data.items.map((t) => + JSON.parse(JSON.stringify(t, this.serializeFilter)), + ), + }; } protected override serializeFilter(key: string, value: any) { @@ -250,6 +253,7 @@ export class NftCollection extends ApillonModel { transactionType: TransactionType[serialized], transactionStatus: TransactionStatus[serialized], chain: EvmChain[serialized], + chainId: EvmChain[serialized], }; return Object.keys(enums).includes(key) ? enums[key] : serialized; } diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 79842fb..0110d44 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -1,7 +1,11 @@ import { ApillonModule } from '../../lib/apillon'; import { ApillonApi } from '../../lib/apillon-api'; import { constructUrlWithQueryParams } from '../../lib/common'; -import { IApillonResponse, IApillonListResponse } from '../../types/apillon'; +import { + IApillonResponse, + IApillonListResponse, + IApillonList, +} from '../../types/apillon'; import { ICollectionFilters, ICollection, @@ -30,14 +34,19 @@ export class Nft extends ApillonModule { */ public async listCollections( params?: ICollectionFilters, - ): Promise { + ): Promise> { const url = constructUrlWithQueryParams(this.API_PREFIX, params); const { data } = await ApillonApi.get>( url, ); - return data.items.map((nft) => new NftCollection(nft.collectionUuid, nft)); + return { + ...data, + items: data.items.map( + (nft) => new NftCollection(nft.collectionUuid, nft), + ), + }; } /** diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index 75c1e17..30dd0bc 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -87,7 +87,7 @@ export class StorageBucket extends ApillonModel { const { data } = await ApillonApi.get>(url); return { - total: data.total, + ...data, items: data.items.map( (file) => new File(this.uuid, file.directoryUuid, file.uuid, file), ), diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index 043e380..e1359ac 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -24,10 +24,10 @@ export class Storage extends ApillonModule { const { data } = await ApillonApi.get>(url); return { + ...data, items: data.items.map( (bucket) => new StorageBucket(bucket.bucketUuid, bucket), ), - total: data.total, }; } diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index c9f3d07..4ffbca4 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -16,7 +16,7 @@ describe('Nft tests', () => { test('list nft collections', async () => { const nft = new Nft(config); - const collections = await nft.listCollections(); + const { items: collections } = await nft.listCollections(); expect(collections.length).toBeGreaterThan(0); expect(collections[0]).toBeInstanceOf(NftCollection); }); @@ -52,7 +52,7 @@ describe('Nft tests', () => { test('get nft collection transactions', async () => { const nft = new Nft(config); - const transactions = await nft + const { items: transactions } = await nft .collection(collectionUUID) .listTransactions(); expect(transactions.length).toBeGreaterThan(0); From 4006cbf847f4e8a97c3fa9063b05c2058fec2354 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 23 Nov 2023 12:39:36 +0100 Subject: [PATCH 64/68] Update CLI choice commands --- packages/cli/src/lib/options.ts | 2 +- packages/cli/src/lib/utils.ts | 5 +++++ .../src/modules/hosting/hosting.commands.ts | 13 +++++++------ packages/cli/src/modules/nfts/nft.service.ts | 2 +- .../cli/src/modules/nfts/nfts.commands.ts | 13 +++++++------ .../src/modules/storage/storage.commands.ts | 19 +++++++++++-------- .../src/modules/storage/storage.service.ts | 9 +++++---- 7 files changed, 37 insertions(+), 26 deletions(-) create mode 100644 packages/cli/src/lib/utils.ts diff --git a/packages/cli/src/lib/options.ts b/packages/cli/src/lib/options.ts index d84d308..e128b00 100644 --- a/packages/cli/src/lib/options.ts +++ b/packages/cli/src/lib/options.ts @@ -6,7 +6,7 @@ export function addPaginationOptions(command: Command) { return command .addOption( new Option( - '-s, --search ', + '--search ', 'Search by name or other object identifier', ), ) diff --git a/packages/cli/src/lib/utils.ts b/packages/cli/src/lib/utils.ts new file mode 100644 index 0000000..17cb132 --- /dev/null +++ b/packages/cli/src/lib/utils.ts @@ -0,0 +1,5 @@ +export function enumValues(enumType: any): string[] { + return Object.values(enumType) + .filter((value) => typeof value === 'number') + .map((value) => value.toString()); +} diff --git a/packages/cli/src/modules/hosting/hosting.commands.ts b/packages/cli/src/modules/hosting/hosting.commands.ts index ff7c7b7..cc83f7c 100644 --- a/packages/cli/src/modules/hosting/hosting.commands.ts +++ b/packages/cli/src/modules/hosting/hosting.commands.ts @@ -10,6 +10,7 @@ import { deployWebsite, } from './hosting.service'; import { DeployToEnvironment, DeploymentStatus } from '@apillon/sdk'; +import { enumValues } from '../../lib/utils'; export function createHostingCommands(cli: Command) { const hosting = cli @@ -70,9 +71,9 @@ export function createHostingCommands(cli: Command) { 'Sets the environment to deploy the files to. Choose from:\n' + ` ${DeployToEnvironment.TO_STAGING}: To Staging\n` + ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production\n` + - ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production`, + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production\n`, ) - .choices(Object.values(DeployToEnvironment).map((x) => `${x}`)) + .choices(enumValues(DeployToEnvironment)) .makeOptionMandatory(true), ) .action(async function () { @@ -92,8 +93,8 @@ export function createHostingCommands(cli: Command) { 'Sets the environment to deploy the files to. Choose from:\n' + ` ${DeployToEnvironment.TO_STAGING}: To Staging\n` + ` ${DeployToEnvironment.STAGING_TO_PRODUCTION}: Staging to Production\n` + - ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production`, - ).choices(Object.values(DeployToEnvironment).map((x) => `${x}`)), + ` ${DeployToEnvironment.DIRECTLY_TO_PRODUCTION}: Directly to Production\n`, + ).choices(enumValues(DeployToEnvironment)), ) .addOption( new Option( @@ -102,8 +103,8 @@ export function createHostingCommands(cli: Command) { ` ${DeploymentStatus.INITIATED}: Initiated\n` + ` ${DeploymentStatus.IN_PROCESS}: In process\n` + ` ${DeploymentStatus.SUCCESSFUL}: Successful\n` + - ` ${DeploymentStatus.FAILED}: Failed`, - ).choices(Object.values(DeploymentStatus).map((x) => `${x}`)), + ` ${DeploymentStatus.FAILED}: Failed\n`, + ).choices(enumValues(DeploymentStatus)), ) .action(async function () { await listDeployments(this.optsWithGlobals()); diff --git a/packages/cli/src/modules/nfts/nft.service.ts b/packages/cli/src/modules/nfts/nft.service.ts index b6a66a9..e1eb36e 100644 --- a/packages/cli/src/modules/nfts/nft.service.ts +++ b/packages/cli/src/modules/nfts/nft.service.ts @@ -17,7 +17,7 @@ export async function listCollections(optsWithGlobals: GlobalOptions) { ...paginate(optsWithGlobals), collectionStatus: toInteger(optsWithGlobals.status), }); - console.log(data.map((d) => d.serialize())); + console.log(data.items.map((d) => d.serialize())); } catch (e: any) { exceptionHandler(e); } diff --git a/packages/cli/src/modules/nfts/nfts.commands.ts b/packages/cli/src/modules/nfts/nfts.commands.ts index 7cc4709..2be04b3 100644 --- a/packages/cli/src/modules/nfts/nfts.commands.ts +++ b/packages/cli/src/modules/nfts/nfts.commands.ts @@ -15,6 +15,7 @@ import { TransactionStatus, TransactionType, } from '@apillon/sdk'; +import { enumValues } from '../../lib/utils'; export function createNftsCommands(cli: Command) { const nfts = cli @@ -36,8 +37,8 @@ export function createNftsCommands(cli: Command) { ` ${CollectionStatus.DEPLOYING}: Deploying\n` + ` ${CollectionStatus.DEPLOYED}: Deployed\n` + ` ${CollectionStatus.TRANSFERRED}: Transferred\n` + - ` ${CollectionStatus.FAILED}: Failed`, - ).choices(Object.values(CollectionStatus).map((x) => `${x}`)), + ` ${CollectionStatus.FAILED}: Failed\n`, + ).choices(enumValues(CollectionStatus)), ) .action(async function () { await listCollections(this.optsWithGlobals()); @@ -127,8 +128,8 @@ export function createNftsCommands(cli: Command) { ` ${TransactionStatus.PENDING}: Pending\n` + ` ${TransactionStatus.CONFIRMED}: Confirmed\n` + ` ${TransactionStatus.FAILED}: Failed\n` + - ` ${TransactionStatus.ERROR}: Error`, - ).choices(Object.values(TransactionStatus).map((x) => `${x}`)), + ` ${TransactionStatus.ERROR}: Error\n`, + ).choices(enumValues(TransactionStatus)), ) .addOption( new Option( @@ -139,8 +140,8 @@ export function createNftsCommands(cli: Command) { ` ${TransactionType.MINT_NFT}: Mint NFT\n` + ` ${TransactionType.SET_COLLECTION_BASE_URI}: Set Collection Base URI\n` + ` ${TransactionType.BURN_NFT}: Burn NFT\n` + - ` ${TransactionType.NEST_MINT_NFT}: Nest Mint NFT`, - ).choices(Object.values(TransactionType).map((x) => `${x}`)), + ` ${TransactionType.NEST_MINT_NFT}: Nest Mint NFT\n`, + ).choices(enumValues(TransactionType)), ) .action(async function () { await listCollectionTransactions(this.optsWithGlobals()); diff --git a/packages/cli/src/modules/storage/storage.commands.ts b/packages/cli/src/modules/storage/storage.commands.ts index 95e7677..59cac01 100644 --- a/packages/cli/src/modules/storage/storage.commands.ts +++ b/packages/cli/src/modules/storage/storage.commands.ts @@ -1,4 +1,4 @@ -import { Command } from 'commander'; +import { Command, Option } from 'commander'; import { addPaginationOptions } from '../../lib/options'; import { listBuckets, @@ -9,6 +9,7 @@ import { deleteFile, } from './storage.service'; import { FileStatus } from '@apillon/sdk'; +import { enumValues } from '../../lib/utils'; export function createStorageCommands(cli: Command) { const storage = cli @@ -40,13 +41,15 @@ export function createStorageCommands(cli: Command) { .command('list-files') .description('List all files from a bucket') .requiredOption('-b, --bucket-uuid ', 'UUID of bucket') - .option( - '-s, --file-status ', - 'Filter by file status. Choose from:\n' + - ` ${FileStatus.UPLOAD_REQUEST_GENERATED}: Upload request generated\n` + - ` ${FileStatus.UPLOADED}: Uploaded\n` + - ` ${FileStatus.AVAILABLE_ON_IPFS}: Available on IPFS\n` + - ` ${FileStatus.AVAILABLE_ON_IPFS_AND_REPLICATED}: Available on IPFS and replicated\n`, + .addOption( + new Option( + '-s, --file-status ', + 'Filter by file status. Choose from:\n' + + ` ${FileStatus.UPLOAD_REQUEST_GENERATED}: Upload request generated\n` + + ` ${FileStatus.UPLOADED}: Uploaded\n` + + ` ${FileStatus.AVAILABLE_ON_IPFS}: Available on IPFS\n` + + ` ${FileStatus.AVAILABLE_ON_IPFS_AND_REPLICATED}: Available on IPFS and replicated\n`, + ).choices(enumValues(FileStatus)), ) .action(async function () { await listFiles(this.optsWithGlobals()); diff --git a/packages/cli/src/modules/storage/storage.service.ts b/packages/cli/src/modules/storage/storage.service.ts index e30457f..875f108 100644 --- a/packages/cli/src/modules/storage/storage.service.ts +++ b/packages/cli/src/modules/storage/storage.service.ts @@ -1,4 +1,4 @@ -import { Storage, exceptionHandler } from '@apillon/sdk'; +import { Storage, exceptionHandler, toInteger } from '@apillon/sdk'; import { GlobalOptions } from '../../lib/types'; import { paginate } from '../../lib/options'; @@ -31,9 +31,10 @@ export async function listObjects(optsWithGlobals: GlobalOptions) { export async function listFiles(optsWithGlobals: GlobalOptions) { const storage = new Storage(optsWithGlobals); try { - const data = await storage - .bucket(optsWithGlobals.bucketUuid) - .listFiles(paginate(optsWithGlobals)); + const data = await storage.bucket(optsWithGlobals.bucketUuid).listFiles({ + ...paginate(optsWithGlobals), + fileStatus: toInteger(optsWithGlobals.fileStatus), + }); data.items = data.items.map((w) => w.serialize()); console.log(data); } catch (err) { From 556648c213d67e56baa55dfea5f78afc3eb2591d Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Thu, 23 Nov 2023 14:11:33 +0100 Subject: [PATCH 65/68] Update SDK README examples --- packages/cli/package.json | 4 +- packages/sdk/README.md | 166 ++++++++++++++++++++------------- packages/sdk/package.json | 4 +- packages/sdk/src/types/nfts.ts | 6 +- 4 files changed, 109 insertions(+), 71 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index a7ef38e..a2be8f0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -6,11 +6,11 @@ "license": "MIT", "main": "./dist/index.js", "bugs": { - "url": "https://github.com/Apillon-web3/sdk/issues" + "url": "https://github.com/Apillon/sdk/issues" }, "repository": { "type": "git", - "url": "https://github.com/Apillon-web3/sdk" + "url": "https://github.com/Apillon/sdk" }, "homepage": "https://wiki.apillon.io", "declaration": true, diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 91542dc..1664ff8 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -15,7 +15,11 @@ as well as compresses multi step flows into single operations. ## Getting started -SDK is available on [NPM](https://www.npmjs.com/package/@apillon/sdk) and you can also check it out directly on [GitHub](https://github.com/Apillon/sdk). +To be able to use Apillon SDK, you must register an account at [Apillon.io](https://app.apillon.io), create a project and generate an API key with appropriate permissions. + +SDK package is available on [NPM](https://www.npmjs.com/package/@apillon/sdk) and you can also check it out directly on [GitHub](https://github.com/Apillon/sdk). + +For additional information on using the SDK, see the [Apillon documentation](https://wiki.apillon.io). ### Installation @@ -40,24 +44,33 @@ Apillon SDK consists of different modules depending on which service you want to Hosting module encapsulates functionalities for Hosting service available on Apillon dashboard. -::: tip -You can only create a new webpage through the [dashboard hosting service](https://app.apillon.io/dashboard/service/hosting). -::: +> Note: You can only create a new webpage through the [dashboard hosting service](https://app.apillon.io/dashboard/service/hosting). The flow of deploying a new website looks like this: -1. upload new website files -2. trigger deploy to staging -3. trigger deploy from staging to production +1. Upload new website files +2. Trigger deploy to staging +3. Trigger deploy from staging to production You can also directly deploy uploaded files to production. ### Usage example ```ts -import { Hosting } from "@apillon/sdk"; +import { + DeployToEnvironment, + DeploymentStatus, + Hosting, + LogLevel, +} from '@apillon/sdk'; +import * as fs from 'fs'; -const hosting = new Hosting({ apillonConfig }); +const hosting = new Hosting({ + key: 'yourApiKey', + secret: 'yourApiSecret', + apiUrl: 'https://api.apillon.io', + logLevel: LogLevel.VERBOSE, +}); await hosting.listWebsites({ orderBy: 'createdTime' }); const webpage1 = hosting.website('uuid'); await webpage1.get(); @@ -65,22 +78,25 @@ await webpage1.get(); // Upload files from local folder await webpage1.uploadFromFolder('./my-foler/files/'); // Or alternatively, send file buffers as upload parameters +const htmlBuffer = fs.readFileSync('./public/index.html'); await webpage1.uploadFiles( - [ - { - fileName: 'index.html', - contentType: 'text/html', - path: null, - content: htmlBuffer, - }, - ], - // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket - { wrapWithDirectory: true, directoryPath: 'main/subdir' }, + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: htmlBuffer, + }, + ], + // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, ); await webpage1.deploy(DeployToEnvironment.TO_STAGING); await webpage1.listDeployments(); -const deployment = await webpage1.deployment(deployment_uuid).get(); +const deployment = await webpage1 + .deployment('3e0c66ea-317d-4e1f-bcd9-38026c3ea1ee') + .get(); if (deployment.deploymentStatus === DeploymentStatus.SUCCESSFUL) { // done } @@ -97,35 +113,42 @@ Storage module encapsulates functionalities for Storage service available on Api ### Usage example ```ts -import { Storage } from "@apillon/sdk"; - -const storage = new Storage({ apillonConfig }); +import { Storage, LogLevel, FileStatus } from '@apillon/sdk'; +import * as fs from 'fs'; + +const storage = new Storage({ + key: 'yourApiKey', + secret: 'yourApiSecret', + apiUrl: 'https://api.apillon.io', + logLevel: LogLevel.VERBOSE, +}); await storage.listBuckets({ limit: 5 }); const bucket = storage.bucket('uuid'); // Upload files from local folder await bucket.uploadFromFolder('./my-foler/files/'); // Or alternatively, send file buffers as upload parameters +const htmlBuffer = fs.readFileSync('./public/index.html'); await bucket.uploadFiles( - [ - { - fileName: 'index.html', - contentType: 'text/html', - path: null, - content: htmlBuffer, - }, - ], - // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket - { wrapWithDirectory: true, directoryPath: 'main/subdir' }, + [ + { + fileName: 'index.html', + contentType: 'text/html', + path: null, + content: htmlBuffer, + }, + ], + // Upload the files in a new subdirectory in the bucket instead of in the root of the bucket + { wrapWithDirectory: true, directoryPath: 'main/subdir' }, ); await bucket.listObjects({ - directoryUuid, + directoryUuid: 'eaff2672-3012-46fb-9278-5efacc6cb616', markedForDeletion: false, limit: 5, }); await bucket.listFiles({ fileStatus: FileStatus.UPLOADED }); -const file = await bucket.file(file_uuid).get(); -await bucket.deleteFile(file_uuid); +const file = await bucket.file('2195521d-15cc-4f6e-abf2-13866f9c6e03').get(); +await bucket.deleteFile('2195521d-15cc-4f6e-abf2-13866f9c6e03'); ``` ### Detailed Storage docs @@ -139,34 +162,49 @@ NFT module encapsulates functionalities for NFT service available on Apillon das ### Usage example ```ts -import { Nft } from "@apillon/sdk"; - -const nft = new Nft({ apillonConfig }); - await nft.create({ - collectionType: CollectionType.GENERIC, - chain: EvmChain.MOONBEAM, - name: 'SpaceExplorers', - symbol: 'SE', - description: 'A collection of unique space exploration NFTs.', - baseUri: 'https://moonbeamnfts.com/collections/spaceexplorers/', - baseExtension: 'json', - maxSupply: 1000, - isRevokable: false, - isSoulbound: false, - royaltiesAddress: '0x1234567890abcdef', - royaltiesFees: 5, - drop: true, - dropStart: 1679875200, - dropPrice: 0.05, - dropReserve: 100, - }); - await nft.listCollections({ search: 'My NFT' }); - const collection = await nft.collection('uuid').get(); - await collection.mint(receiver, quantity); - await collection.nestMint(collection.uuid, 1, quantity); - await collection.burn(quantity); - await collection.listTransactions(); - await collection.transferOwnership(to_address); +import { + CollectionType, + EvmChain, + LogLevel, + Nft, + TransactionStatus, +} from '@apillon/sdk'; + +const nft = new Nft({ + key: 'yourApiKey', + secret: 'yourApiSecret', + apiUrl: 'https://api.apillon.io', + logLevel: LogLevel.VERBOSE, +}); +await nft.create({ + collectionType: CollectionType.GENERIC, + chain: EvmChain.MOONBEAM, + name: 'SpaceExplorers', + symbol: 'SE', + description: 'A collection of unique space exploration NFTs.', + baseUri: 'https://moonbeamnfts.com/collections/spaceexplorers/', + baseExtension: 'json', + maxSupply: 1000, + isRevokable: false, + isSoulbound: false, + royaltiesAddress: '0x1234567890abcdef', + royaltiesFees: 5, + drop: true, + dropStart: 1679875200, + dropPrice: 0.05, + dropReserve: 100, +}); +await nft.listCollections({ search: 'My NFT' }); +const collection = await nft.collection('uuid').get(); +await collection.mint('0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD', 1); +await collection.nestMint(collection.uuid, 1, 1); +await collection.burn('1'); +await collection.listTransactions({ + transactionStatus: TransactionStatus.CONFIRMED, +}); +await collection.transferOwnership( + '0x5BA8B0c24bA5307b67E619ad500a635204F73bF1', +); ``` ### Detailed NFT docs diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 869873a..8e9c042 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -8,11 +8,11 @@ "source": "./src/index.ts", "types": "./dist/index.d.ts", "bugs": { - "url": "https://github.com/Apillon-web3/sdk/issues" + "url": "https://github.com/Apillon/sdk/issues" }, "repository": { "type": "git", - "url": "https://github.com/Apillon-web3/sdk" + "url": "https://github.com/Apillon/sdk" }, "homepage": "https://wiki.apillon.io", "declaration": true, diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index 7c90b72..fa730ef 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -83,10 +83,10 @@ export interface ITransaction { } export interface ICollectionFilters extends IApillonPagination { - collectionStatus: CollectionStatus; + collectionStatus?: CollectionStatus; } export interface ITransactionFilters extends IApillonPagination { - transactionStatus: TransactionStatus; - transactionType: TransactionType; + transactionStatus?: TransactionStatus; + transactionType?: TransactionType; } From 9268c879a333fa63c10bd35cc42a24424b93f9a9 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Mon, 27 Nov 2023 11:31:32 +0100 Subject: [PATCH 66/68] Add missing JSdoc on properties and methods --- packages/cli/src/modules/nfts/nft.service.ts | 4 +-- packages/sdk/README.md | 11 +++++--- packages/sdk/src/lib/apillon.ts | 26 +++++++++++++++++++ .../sdk/src/modules/storage/storage-bucket.ts | 1 + packages/sdk/src/modules/storage/storage.ts | 2 +- packages/sdk/src/types/apillon.ts | 1 + 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/modules/nfts/nft.service.ts b/packages/cli/src/modules/nfts/nft.service.ts index e1eb36e..77aac2e 100644 --- a/packages/cli/src/modules/nfts/nft.service.ts +++ b/packages/cli/src/modules/nfts/nft.service.ts @@ -94,7 +94,7 @@ export async function nestMintCollectionNft(optsWithGlobals: GlobalOptions) { toInteger(optsWithGlobals.parentNft), toInteger(optsWithGlobals.quantity), ); - if (data.status === 5) { + if (data.success) { console.log('NFT nest minted successfully'); } } catch (e: any) { @@ -109,7 +109,7 @@ export async function burnCollectionNft(optsWithGlobals: GlobalOptions) { const data = await nftService .collection(optsWithGlobals.uuid) .burn(optsWithGlobals.tokenId); - if (data.status === 5) { + if (data.success) { console.log('NFT burned successfully'); } } catch (e: any) { diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 1664ff8..50151b6 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -33,12 +33,17 @@ npm install @apillon/sdk import { Hosting } from "@apillon/sdk"; const hosting = new Hosting({ - apiKey: "", - apiSecret: "", + key: "", + secret: "", }); ``` -Apillon SDK consists of different modules depending on which service you want to use. But all modules require the same initial config of `apiKey` and `apiSecret` shown above in `Hosting` module example. +Apillon SDK consists of different modules depending on which service you want to use. All modules require the same initial config of `key` and `secret` shown above in `Hosting` module example. + +Alternatively, you can populate the `APILLON_API_KEY` and `APILLON_API_SECRET` environment variables. + +View each individual module examples in the sections below. + ## Hosting diff --git a/packages/sdk/src/lib/apillon.ts b/packages/sdk/src/lib/apillon.ts index 5752f8a..827db5c 100644 --- a/packages/sdk/src/lib/apillon.ts +++ b/packages/sdk/src/lib/apillon.ts @@ -3,10 +3,30 @@ import { ApillonApi } from './apillon-api'; import { ApillonLogger } from './apillon-logger'; export interface ApillonConfig { + /** + * Your API key, generated through the Apillon dashboard + * @default env.APILLON_API_KEY + */ key?: string; + /** + * Your API secret, generated through the Apillon dashboard + * @default env.APILLON_API_SECRET + */ secret?: string; + /** + * The API URL to use for executing the queries and actions. + * @default https://api.apillon.io + */ apiUrl?: string; + /** + * The level of logger output to use for the Apillon logger. + * @default ERROR + */ logLevel?: LogLevel; + /** + * Used for CLI - indicates whether to output verbose logs + * @default false + */ debug?: boolean; } @@ -70,10 +90,16 @@ export class ApillonModel { return this; } + /** + * Convert object to JSON output, with unnecessary properties excluded + */ public serialize() { return JSON.parse(JSON.stringify(this, this.serializeFilter)); } + /** + * Define and exclude custom keys from serialized object + */ protected serializeFilter(key: string, value: any) { const excludedKeys = ['API_PREFIX']; return excludedKeys.includes(key) ? undefined : value; diff --git a/packages/sdk/src/modules/storage/storage-bucket.ts b/packages/sdk/src/modules/storage/storage-bucket.ts index eaf2405..ec5f9bb 100644 --- a/packages/sdk/src/modules/storage/storage-bucket.ts +++ b/packages/sdk/src/modules/storage/storage-bucket.ts @@ -47,6 +47,7 @@ export class StorageBucket extends ApillonModel { /** * Gets contents of a bucket. + * @returns A a list of File and Directory objects. */ async listObjects( params?: IStorageBucketContentRequest, diff --git a/packages/sdk/src/modules/storage/storage.ts b/packages/sdk/src/modules/storage/storage.ts index 8d84f7d..ac1e94e 100644 --- a/packages/sdk/src/modules/storage/storage.ts +++ b/packages/sdk/src/modules/storage/storage.ts @@ -17,7 +17,7 @@ export class Storage extends ApillonModule { /** * Lists all buckets. * @param {ICollectionFilters} params Filter for listing collections. - * @returns Array of NftCollection. + * @returns Array of StorageBucket objects. */ public async listBuckets( params?: IApillonPagination, diff --git a/packages/sdk/src/types/apillon.ts b/packages/sdk/src/types/apillon.ts index a26e258..fa0c3aa 100644 --- a/packages/sdk/src/types/apillon.ts +++ b/packages/sdk/src/types/apillon.ts @@ -11,6 +11,7 @@ export interface IApillonResponse { export interface IApillonStatus { status: number; + success: boolean; } export interface IApillonPagination { From 2a4dca1a0f32567d80bc386c77a6d7069b732e80 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 28 Nov 2023 11:54:04 +0100 Subject: [PATCH 67/68] Small SDK fixes --- packages/sdk/README.md | 2 +- packages/sdk/src/modules/storage/file.ts | 2 +- packages/sdk/src/types/storage.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 50151b6..695eb9a 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -76,7 +76,7 @@ const hosting = new Hosting({ apiUrl: 'https://api.apillon.io', logLevel: LogLevel.VERBOSE, }); -await hosting.listWebsites({ orderBy: 'createdTime' }); +await hosting.listWebsites({ orderBy: 'createTime' }); const webpage1 = hosting.website('uuid'); await webpage1.get(); diff --git a/packages/sdk/src/modules/storage/file.ts b/packages/sdk/src/modules/storage/file.ts index f46a070..5ca1d82 100644 --- a/packages/sdk/src/modules/storage/file.ts +++ b/packages/sdk/src/modules/storage/file.ts @@ -30,7 +30,7 @@ export class File extends ApillonModel { public CIDv1: string = null; /** - * File status. + * File upload status. */ public status: FileStatus = null; diff --git a/packages/sdk/src/types/storage.ts b/packages/sdk/src/types/storage.ts index d28bc18..55153d0 100644 --- a/packages/sdk/src/types/storage.ts +++ b/packages/sdk/src/types/storage.ts @@ -27,7 +27,7 @@ export interface FileMetadata { /** * File [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) */ - contentType: string; + contentType?: string; /** * Virtual file path. Empty for root. Must not contain fileName. * @@ -35,7 +35,7 @@ export interface FileMetadata { * * For example, an images/icons path creates images directory in a bucket and icons directory inside it. File will then be created in the icons directory. */ - path: string; + path?: string; } export interface IFileUploadRequest { From 602b85adefb2921366a9d5705ce470ed1a6b02d2 Mon Sep 17 00:00:00 2001 From: Damjan Dimitrov Date: Tue, 28 Nov 2023 12:59:43 +0100 Subject: [PATCH 68/68] NFT collection: Set drop properties to nullable --- packages/sdk/src/modules/nft/nft.ts | 4 ++++ packages/sdk/src/tests/nft.test.ts | 3 --- packages/sdk/src/types/nfts.ts | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/sdk/src/modules/nft/nft.ts b/packages/sdk/src/modules/nft/nft.ts index 0110d44..5b01e3b 100644 --- a/packages/sdk/src/modules/nft/nft.ts +++ b/packages/sdk/src/modules/nft/nft.ts @@ -55,6 +55,10 @@ export class Nft extends ApillonModule { * @returns A NftCollection instance. */ public async create(data: ICreateCollection) { + // If not drop, set drop properties to default 0 + if (!data.drop) { + data.dropStart = data.dropPrice = data.dropReserve = 0; + } const { data: response } = await ApillonApi.post< IApillonResponse >(this.API_PREFIX, data); diff --git a/packages/sdk/src/tests/nft.test.ts b/packages/sdk/src/tests/nft.test.ts index 48aa741..5c13bb4 100644 --- a/packages/sdk/src/tests/nft.test.ts +++ b/packages/sdk/src/tests/nft.test.ts @@ -37,9 +37,6 @@ describe('Nft tests', () => { isRevokable: true, isSoulbound: false, drop: false, - dropStart: 0, - dropPrice: 0, - dropReserve: 0, }); expect(collection.uuid).toBeDefined(); }); diff --git a/packages/sdk/src/types/nfts.ts b/packages/sdk/src/types/nfts.ts index fa730ef..9b1ee2a 100644 --- a/packages/sdk/src/types/nfts.ts +++ b/packages/sdk/src/types/nfts.ts @@ -51,9 +51,9 @@ export interface ICreateCollection { royaltiesAddress: string; royaltiesFees: number; drop: boolean; - dropStart: number; - dropPrice: number; - dropReserve: number; + dropStart?: number; + dropPrice?: number; + dropReserve?: number; } //OUTPUTS