diff --git a/.eslintrc.js b/.eslintrc.js index ae1a3cd..484381d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,10 @@ module.exports = { - extends: ['@exodus/eslint-config/javascript'], + extends: ['@exodus/eslint-config/typescript'], globals: { WebSocket: 'readonly', }, + rules: { + '@typescript-eslint/no-unnecessary-condition': 'off', + '@typescript-eslint/no-var-requires': 'off', + }, } diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c9b6c7c..a3b1450 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: - node-version: 16 + node-version: 24.14.0 cache: 'npm' - name: Install dependencies run: npm ci --ignore-scripts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 24b9b11..a677f44 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: persist-credentials: false - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: 20 + node-version: 24.14.0 cache: 'npm' - name: Install dependencies run: npm ci --ignore-scripts diff --git a/.gitignore b/.gitignore index 042ccf2..392b2f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ node_modules +lib +.cache *~ diff --git a/core.js b/core.js deleted file mode 100644 index 58bc61a..0000000 --- a/core.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict' - -// NOTE: use targeted imports in new code - -const fetch = require('./fetch') -const WebSocket = require('./websocket') - -module.exports = { fetch, WebSocket } diff --git a/experimental/fetchival.js b/experimental/fetchival.js deleted file mode 100644 index 060560b..0000000 --- a/experimental/fetchival.js +++ /dev/null @@ -1,3 +0,0 @@ -const createFetchival = require('./create-fetchival') - -module.exports = createFetchival() diff --git a/fetch.browser.js b/fetch.browser.js deleted file mode 100644 index 2357f10..0000000 --- a/fetch.browser.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = (i, ...r) => globalThis.fetch(i, ...r) diff --git a/fetch.native.js b/fetch.native.js deleted file mode 100644 index 9afa8b1..0000000 --- a/fetch.native.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' - -if (typeof fetch === 'undefined') { - // Fall back to node-fetch - module.exports = require('node-fetch') -} else { - // Prefer native / Node.js fetch if exists - module.exports = (i, ...r) => globalThis.fetch(i, ...r) -} diff --git a/fetchival.js b/fetchival.js deleted file mode 100644 index 6171c5c..0000000 --- a/fetchival.js +++ /dev/null @@ -1,6 +0,0 @@ -const fetchival = require('./fetchival.browser') -const fetch = require('./fetch') - -if (!fetchival.fetch) fetchival.fetch = fetch - -module.exports = fetchival diff --git a/index.browser.js b/index.browser.js deleted file mode 100644 index eaf5de6..0000000 --- a/index.browser.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' - -// Don't need to require node-fetch here, global fetch is defined -// Same for global WebSocket - -const fetchival = require('./fetchival.browser.js') -const fetch = require('./fetch.browser.js') - -module.exports = { fetch, WebSocket, fetchival } diff --git a/index.js b/index.js deleted file mode 100644 index 10de143..0000000 --- a/index.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict' - -// NOTE: use targeted imports in new code - -const fetch = require('./fetch') -const WebSocket = require('./websocket') -const fetchival = require('./fetchival') - -module.exports = { fetch, WebSocket, fetchival } diff --git a/package-lock.json b/package-lock.json index f19f5d4..ddfe640 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@exodus/fetch", - "version": "1.3.1", + "version": "1.7.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@exodus/fetch", - "version": "1.3.1", + "version": "1.7.1", "license": "MIT", "dependencies": { "node-fetch": "^2.6.0", @@ -18,14 +18,19 @@ "@exodus/prettier": "^1.0.0", "@semantic-release/changelog": "^6.0.3", "@semantic-release/github": "^9.2.3", + "@types/node": "^24.12.2", "@types/tape": "^5.6.0", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "conventional-changelog-conventionalcommits": "^6.0.0", "eslint": "^8.49.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-prettier": "^5.0.0", "prettier": "^3.0.3", "semantic-release": "^21.1.1", "tap-spec": "^5.0.0", - "tape": "^5.3.1" + "tape": "^5.3.1", + "typescript": "^6.0.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -175,19 +180,21 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", - "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -207,10 +214,11 @@ } }, "node_modules/@eslint/js": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", - "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -284,13 +292,15 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -311,10 +321,12 @@ } }, "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==", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@ljharb/resumer": { "version": "0.0.1", @@ -1383,10 +1395,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", - "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==", - "dev": true + "version": "24.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", + "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -1419,6 +1435,333 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/parser/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", @@ -1436,6 +1779,178 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", @@ -1571,11 +2086,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1588,6 +2111,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -1618,10 +2142,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2345,12 +2870,13 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2580,6 +3106,20 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/enhanced-resolve": { + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz", + "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/env-ci": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-9.1.1.tgz", @@ -2729,18 +3269,21 @@ } }, "node_modules/eslint": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", - "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.49.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2831,6 +3374,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "license": "ISC", + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, "node_modules/eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -3281,6 +3850,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -3375,7 +3945,8 @@ "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { "version": "1.3.0", @@ -3415,7 +3986,8 @@ "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -3644,6 +4216,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -3699,10 +4284,11 @@ } }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -4576,7 +5162,8 @@ "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -5026,10 +5613,11 @@ } }, "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==", - "dev": true + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -8779,10 +9367,11 @@ "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==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -9100,6 +9689,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10110,6 +10709,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -10225,6 +10825,20 @@ "tspec": "bin/cmd.js" } }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/tape": { "version": "5.6.6", "dev": true, @@ -10412,6 +11026,19 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -10462,6 +11089,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -10531,11 +11159,11 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "dev": true, - "peer": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10571,6 +11199,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, "node_modules/unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", @@ -10627,6 +11262,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -11007,15 +11643,15 @@ } }, "@eslint-community/regexpp": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", - "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true }, "@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -11030,9 +11666,9 @@ } }, "@eslint/js": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", - "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true }, "@exodus/eslint-config": { @@ -11087,13 +11723,13 @@ "requires": {} }, "@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" } }, @@ -11104,9 +11740,9 @@ "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==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "dev": true }, "@ljharb/resumer": { @@ -11860,10 +12496,13 @@ "dev": true }, "@types/node": { - "version": "20.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", - "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==", - "dev": true + "version": "24.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", + "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", + "dev": true, + "requires": { + "undici-types": "~7.16.0" + } }, "@types/normalize-package-data": { "version": "2.4.1", @@ -11896,6 +12535,189 @@ "@types/node": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + } + }, + "@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "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" + } + }, + "semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true + } + } + }, + "@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + } + }, + "@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "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" + } + }, + "semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true + } + } + }, "@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", @@ -11906,6 +12728,101 @@ "@typescript-eslint/visitor-keys": "5.62.0" } }, + "@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + } + }, + "@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "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" + } + }, + "semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true + } + } + }, "@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", @@ -11991,10 +12908,16 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true + }, "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true }, "acorn-jsx": { @@ -12024,9 +12947,9 @@ } }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -12535,12 +13458,12 @@ "dev": true }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "decamelize": { @@ -12702,6 +13625,16 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "enhanced-resolve": { + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz", + "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + } + }, "env-ci": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-9.1.1.tgz", @@ -12819,18 +13752,19 @@ "dev": true }, "eslint": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", - "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.49.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -12975,6 +13909,21 @@ } } }, + "eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + } + }, "eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -13458,6 +14407,15 @@ "get-intrinsic": "^1.1.1" } }, + "get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, "git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -13505,9 +14463,9 @@ } }, "globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -14388,9 +15346,9 @@ "dev": true }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "natural-compare": { @@ -16894,9 +17852,9 @@ "dev": true }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "queue-microtask": { @@ -17121,6 +18079,12 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -17896,6 +18860,12 @@ "through2": "^2.0.0" } }, + "tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true + }, "tape": { "version": "5.6.6", "dev": true, @@ -18037,6 +19007,13 @@ "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, + "ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "requires": {} + }, "tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -18119,11 +19096,10 @@ } }, "typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "dev": true, - "peer": true + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true }, "uglify-js": { "version": "3.17.4", @@ -18142,6 +19118,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true + }, "unicorn-magic": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", diff --git a/package.json b/package.json index c0fc607..11ae2f0 100644 --- a/package.json +++ b/package.json @@ -9,99 +9,97 @@ "bugs": { "url": "https://github.com/ExodusMovement/fetch/issues" }, - "main": "index.js", + "main": "lib/index.js", + "types": "lib/index.d.ts", "exports": { ".": { - "browser": "./index.browser.js", - "react-native": "./index.js", - "node": "./index.js", - "default": "./index.js" + "types": "./lib/index.d.ts", + "browser": "./lib/index.browser.js", + "react-native": "./lib/index.js", + "node": "./lib/index.js", + "default": "./lib/index.js" }, "./fetch": { - "browser": "./fetch.browser.js", - "react-native": "./fetch.native.js", - "node": "./fetch.js", - "default": "./fetch.js" + "types": "./lib/fetch.d.ts", + "browser": "./lib/fetch.browser.js", + "react-native": "./lib/fetch.native.js", + "node": "./lib/fetch.js", + "default": "./lib/fetch.js" }, "./websocket": { - "browser": "./websocket.browser.js", - "react-native": "./websocket.native.js", - "node": "./websocket.js", - "default": "./websocket.js" + "types": "./lib/websocket.d.ts", + "browser": "./lib/websocket.browser.js", + "react-native": "./lib/websocket.native.js", + "node": "./lib/websocket.js", + "default": "./lib/websocket.js" }, "./core": { - "browser": "./core.js", - "react-native": "./core.js", - "node": "./core.js", - "default": "./core.js" + "types": "./lib/core.d.ts", + "browser": "./lib/core.js", + "react-native": "./lib/core.js", + "node": "./lib/core.js", + "default": "./lib/core.js" }, "./experimental/fetchival": { - "browser": "./experimental/fetchival.js", - "react-native": "./experimental/fetchival.js", - "node": "./experimental/fetchival.js", - "default": "./experimental/fetchival.js" + "types": "./lib/experimental/fetchival.d.ts", + "browser": "./lib/experimental/fetchival.js", + "react-native": "./lib/experimental/fetchival.js", + "node": "./lib/experimental/fetchival.js", + "default": "./lib/experimental/fetchival.js" }, "./experimental/create-fetchival": { - "default": "./experimental/create-fetchival.js" + "types": "./lib/experimental/create-fetchival.d.ts", + "default": "./lib/experimental/create-fetchival.js" }, "./fetchival": { - "browser": "./fetchival.browser.js", - "react-native": "./fetchival.js", - "node": "./fetchival.js", - "default": "./fetchival.js" + "types": "./lib/fetchival.d.ts", + "browser": "./lib/fetchival.browser.js", + "react-native": "./lib/fetchival.js", + "node": "./lib/fetchival.js", + "default": "./lib/fetchival.js" }, "./create-fetchival": { - "default": "./create-fetchival.js" + "types": "./lib/create-fetchival.d.ts", + "default": "./lib/create-fetchival.js" }, "./wretch": { - "browser": "./wretch.browser.js", - "react-native": "./wretch.js", - "node": "./wretch.js", - "default": "./wretch.js" + "types": "./lib/wretch.d.ts", + "browser": "./lib/wretch.browser.js", + "react-native": "./lib/wretch.js", + "node": "./lib/wretch.js", + "default": "./lib/wretch.js" }, "./url": { - "browser": "./url.js", - "react-native": "./url.js", - "node": "./url.js", - "default": "./url.js" + "types": "./lib/url.d.ts", + "browser": "./lib/url.js", + "react-native": "./lib/url.js", + "node": "./lib/url.js", + "default": "./lib/url.js" } }, "browser": { - "./fetch.js": "./fetch.browser.js", - "./fetchival.js": "./fetchival.browser.js", - "./index.js": "./index.browser.js", - "./websocket.js": "./websocket.browser.js", - "./wretch.js": "./wretch.browser.js" + "./lib/fetch.js": "./lib/fetch.browser.js", + "./lib/fetchival.js": "./lib/fetchival.browser.js", + "./lib/index.js": "./lib/index.browser.js", + "./lib/websocket.js": "./lib/websocket.browser.js", + "./lib/wretch.js": "./lib/wretch.browser.js" }, "react-native": { - "./fetch.js": "./fetch.native.js", - "./websocket.js": "./websocket.native.js" + "./lib/fetch.js": "./lib/fetch.native.js", + "./lib/websocket.js": "./lib/websocket.native.js" }, "files": [ - "experimental/fetchival.js", - "experimental/create-fetchival.js", - "core.js", - "fetch.browser.js", - "fetch.native.js", - "fetch.js", - "websocket.browser.js", - "websocket.native.js", - "websocket.js", - "create-fetchival.js", - "fetchival.browser.js", - "fetchival.js", - "wretch.browser.js", - "wretch.js", - "url.js", - "index.browser.js", - "index.js", + "lib", "CHANGELOG.md" ], "scripts": { - "lint": "eslint . --ignore-path .gitignore", + "build": "tsc -p tsconfig.build.json", + "typecheck": "tsc -p tsconfig.json --noEmit", + "lint": "eslint src test --ext .ts --ignore-path .gitignore", "lint:fix": "npm run lint -- --fix", - "format": "prettier --write '**/*.{md,yml}'", - "test": "tape test/*.js | tap-spec", + "format": "prettier --write '**/*.{md,yml,ts,json}'", + "test": "npm run build && tsc -p tsconfig.test.json && tape '.cache/test/test/*.js' | tap-spec", + "prepack": "npm run build", "release": "semantic-release" }, "author": "Exodus Movement Inc.", @@ -116,14 +114,19 @@ "@exodus/prettier": "^1.0.0", "@semantic-release/changelog": "^6.0.3", "@semantic-release/github": "^9.2.3", + "@types/node": "^24.12.2", "@types/tape": "^5.6.0", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "conventional-changelog-conventionalcommits": "^6.0.0", "eslint": "^8.49.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-prettier": "^5.0.0", "prettier": "^3.0.3", "semantic-release": "^21.1.1", "tap-spec": "^5.0.0", - "tape": "^5.3.1" + "tape": "^5.3.1", + "typescript": "^6.0.3" }, "prettier": "@exodus/prettier" } diff --git a/src/core.ts b/src/core.ts new file mode 100644 index 0000000..474525c --- /dev/null +++ b/src/core.ts @@ -0,0 +1,8 @@ +'use strict' + +// NOTE: use targeted imports in new code + +import fetch = require('./fetch') +import WebSocket = require('./websocket') + +export = { fetch, WebSocket } diff --git a/create-fetchival.js b/src/create-fetchival.ts similarity index 56% rename from create-fetchival.js rename to src/create-fetchival.ts index 6b3041f..63ebfed 100644 --- a/create-fetchival.js +++ b/src/create-fetchival.ts @@ -1,20 +1,35 @@ // Based on https://github.com/typicode/fetchival and aims to keep most of the same API -// Unlike fetchival, we also encode the keys -function query(params) { +import type { + CreateFetchivalOptions, + Fetchival, + FetchivalError, + FetchivalOptions, + HttpMethod, + JsonValue, + LegacyQueryParams, + UrlInput, +} from './types' + +function query(params?: LegacyQueryParams) { if (!params) return '' return `?${Object.entries(params) - .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`) + .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`) .join('&')}` } -function createFetchival({ fetch }) { - async function _fetch(method, url, opts, data) { +function createFetchival({ fetch }: CreateFetchivalOptions): Fetchival { + async function _fetch( + method: HttpMethod, + url: UrlInput, + opts: FetchivalOptions, + data?: JsonValue + ) { // Unlike fetchival, don't silently ignore and override if (opts.body) throw new Error('unexpected pre-set body option') // Unlike fetchival, don't pollute the opts object we were given - const res = await fetchival.fetch(url, { + const res = await fetchival.fetch!(url, { ...opts, method, headers: { @@ -32,23 +47,23 @@ function createFetchival({ fetch }) { return res.json() } - const err = new Error(res.statusText) + const err = new Error(res.statusText) as FetchivalError err.response = res throw err } - function fetchival(url, opts = {}) { - const _ = (sub, o = {}) => { + function fetchival(url: UrlInput, opts: FetchivalOptions = {}) { + const _ = (sub: string, o: FetchivalOptions = {}) => { // TODO: validate subpath here const str = `${url}` const joined = str.endsWith('/') ? `${url}${sub}` : `${url}/${sub}` return fetchival(joined, { ...opts, ...o }) } - _.get = (params) => _fetch('GET', url + query(params), opts) - _.post = (data) => _fetch('POST', url, opts, data) - _.put = (data) => _fetch('PUT', url, opts, data) - _.patch = (data) => _fetch('PATCH', url, opts, data) + _.get = (params?: LegacyQueryParams) => _fetch('GET', `${url}${query(params)}`, opts) + _.post = (data?: JsonValue) => _fetch('POST', url, opts, data) + _.put = (data?: JsonValue) => _fetch('PUT', url, opts, data) + _.patch = (data?: JsonValue) => _fetch('PATCH', url, opts, data) _.delete = () => _fetch('DELETE', url, opts) return _ @@ -59,4 +74,4 @@ function createFetchival({ fetch }) { return fetchival } -module.exports = createFetchival +export = createFetchival diff --git a/experimental/create-fetchival.js b/src/experimental/create-fetchival.ts similarity index 53% rename from experimental/create-fetchival.js rename to src/experimental/create-fetchival.ts index 235b04d..fd62107 100644 --- a/experimental/create-fetchival.js +++ b/src/experimental/create-fetchival.ts @@ -1,9 +1,29 @@ -const { url } = require('../url') +import urlModule = require('../url') +import type { + ClientMethod, + ExperimentalCreateFetchivalOptions, + ExperimentalFetchival, + ExperimentalFetchivalOptions, + ExperimentalFetchLike, + FetchivalError, + HttpMethod, + JsonValue, + QueryParams, +} from '../types' -function createFetchival({ fetch = require('../fetch') } = {}) { +const { url } = urlModule + +function createFetchival({ + fetch = require('../fetch') as ExperimentalFetchLike, +}: ExperimentalCreateFetchivalOptions = {}): ExperimentalFetchival { // API somewhat based on https://github.com/typicode/fetchival, but with significant changes - async function _fetch(method, link, opts, data) { + async function _fetch( + method: HttpMethod, + link: URL, + opts: ExperimentalFetchivalOptions, + data?: JsonValue + ) { // Unlike fetchival, don't silently ignore and override if (opts.body) throw new Error('unexpected pre-set body option') @@ -27,45 +47,45 @@ function createFetchival({ fetch = require('../fetch') } = {}) { return res.json() } - const err = new Error(res.statusText) + const err = new Error(res.statusText) as FetchivalError err.response = res throw err } - function fetchival(link, opts = {}) { + function fetchival(link: URL, opts: ExperimentalFetchivalOptions = {}) { if (!(link instanceof URL)) throw new TypeError('Url should be an instance of URL') const str = `${link}` if (str.includes('?') || str.includes('&')) throw new Error('Invalid url with params!') if (str.includes('#')) throw new Error('Invalid url with hash!') - const _ = (sub, o = {}) => { + const _ = (sub: string, o: ExperimentalFetchivalOptions = {}) => { // Unlike fetchival, this performs additional validation if (sub.includes('/')) throw new Error('Only simple subpaths are allowed!') const joined = str.endsWith('/') ? url`${link}${sub}` : url`${link}/${sub}` return fetchival(joined, { ...opts, ...o }) } - _.head = (params) => _fetch('HEAD', params ? url`${link}?${params}` : link, opts) - _.get = (params) => _fetch('GET', params ? url`${link}?${params}` : link, opts) - _.post = (data) => _fetch('POST', link, opts, data) - _.put = (data) => _fetch('PUT', link, opts, data) - _.patch = (data) => _fetch('PATCH', link, opts, data) + _.head = (params?: QueryParams) => _fetch('HEAD', params ? url`${link}?${params}` : link, opts) + _.get = (params?: QueryParams) => _fetch('GET', params ? url`${link}?${params}` : link, opts) + _.post = (data?: JsonValue) => _fetch('POST', link, opts, data) + _.put = (data?: JsonValue) => _fetch('PUT', link, opts, data) + _.patch = (data?: JsonValue) => _fetch('PATCH', link, opts, data) _.delete = () => _fetch('DELETE', link, opts) - _.method = (method, ...args) => { + _.method = (method: ClientMethod, arg?: JsonValue | QueryParams) => { switch (method) { case 'head': - return _.head(...args) + return _.head(arg as QueryParams | undefined) case 'get': - return _.get(...args) + return _.get(arg as QueryParams | undefined) case 'post': - return _.post(...args) + return _.post(arg as JsonValue | undefined) case 'put': - return _.put(...args) + return _.put(arg as JsonValue | undefined) case 'patch': - return _.patch(...args) + return _.patch(arg as JsonValue | undefined) case 'delete': - return _.delete(...args) + return _.delete() default: throw new Error('Unexpected method') } @@ -79,4 +99,4 @@ function createFetchival({ fetch = require('../fetch') } = {}) { return fetchival } -module.exports = createFetchival +export = createFetchival diff --git a/src/experimental/fetchival.ts b/src/experimental/fetchival.ts new file mode 100644 index 0000000..7d93a8c --- /dev/null +++ b/src/experimental/fetchival.ts @@ -0,0 +1,3 @@ +import createFetchival = require('./create-fetchival') + +export = createFetchival() diff --git a/src/fetch.browser.ts b/src/fetch.browser.ts new file mode 100644 index 0000000..7e15b5c --- /dev/null +++ b/src/fetch.browser.ts @@ -0,0 +1,3 @@ +const fetchImplementation: typeof globalThis.fetch = (i, ...r) => globalThis.fetch(i, ...r) + +export = fetchImplementation diff --git a/src/fetch.native.ts b/src/fetch.native.ts new file mode 100644 index 0000000..b8b8b59 --- /dev/null +++ b/src/fetch.native.ts @@ -0,0 +1,13 @@ +'use strict' + +let fetchImplementation: typeof globalThis.fetch + +if (typeof fetch === 'undefined') { + // Fall back to node-fetch + fetchImplementation = require('node-fetch') as typeof globalThis.fetch +} else { + // Prefer native / Node.js fetch if exists + fetchImplementation = (i, ...r) => globalThis.fetch(i, ...r) +} + +export = fetchImplementation diff --git a/fetch.js b/src/fetch.ts similarity index 55% rename from fetch.js rename to src/fetch.ts index 3ec97ff..856ce36 100644 --- a/fetch.js +++ b/src/fetch.ts @@ -4,23 +4,31 @@ // the require calls based on hardcoded process.type per bundle. // Do not refactor or deduplicate. +let fetchImplementation: FetchFunction + // Try to use global browser APIs (e.g. if in Electron), otherwise require impls if (typeof process !== 'undefined' && process) { + const processWithType = process as NodeJS.Process & { type?: string } + // Node.js or Electron with Node.js integration - if (process.type === 'renderer' || process.type === 'worker') { + if (processWithType.type === 'renderer' || processWithType.type === 'worker') { // Electron renderer with Node.js integration - module.exports = (i, ...r) => globalThis.fetch(i, ...r) + fetchImplementation = (i, ...r) => globalThis.fetch(i, ...r) } else { // Node.js or Electron browser process if (typeof fetch === 'undefined') { // Fall back to node-fetch - module.exports = require('node-fetch') + fetchImplementation = require('node-fetch') as FetchFunction } else { // Prefer Node.js fetch if exists - module.exports = (i, ...r) => globalThis.fetch(i, ...r) + fetchImplementation = (i, ...r) => globalThis.fetch(i, ...r) } } } else { // Browser or Electron without Node.js integration - module.exports = (i, ...r) => globalThis.fetch(i, ...r) + fetchImplementation = (i, ...r) => globalThis.fetch(i, ...r) } + +export = fetchImplementation + +type FetchFunction = typeof globalThis.fetch diff --git a/fetchival.browser.js b/src/fetchival.browser.ts similarity index 50% rename from fetchival.browser.js rename to src/fetchival.browser.ts index 326ee22..fca08fd 100644 --- a/fetchival.browser.js +++ b/src/fetchival.browser.ts @@ -1,5 +1,5 @@ -const createFetchival = require('./create-fetchival') +import createFetchival = require('./create-fetchival') -module.exports = createFetchival({ +export = createFetchival({ fetch: typeof fetch === 'undefined' ? null : (i, ...r) => globalThis.fetch(i, ...r), }) diff --git a/src/fetchival.ts b/src/fetchival.ts new file mode 100644 index 0000000..02cd4a9 --- /dev/null +++ b/src/fetchival.ts @@ -0,0 +1,6 @@ +import fetchival = require('./fetchival.browser') +import fetch = require('./fetch') + +if (!fetchival.fetch) fetchival.fetch = fetch + +export = fetchival diff --git a/src/index.browser.ts b/src/index.browser.ts new file mode 100644 index 0000000..ad5ad76 --- /dev/null +++ b/src/index.browser.ts @@ -0,0 +1,9 @@ +'use strict' + +// Don't need to require node-fetch here, global fetch is defined +// Same for global WebSocket + +import fetchival = require('./fetchival.browser') +import fetch = require('./fetch.browser') + +export = { fetch, WebSocket: globalThis.WebSocket, fetchival } diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a6ac966 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,9 @@ +'use strict' + +// NOTE: use targeted imports in new code + +import fetch = require('./fetch') +import WebSocket = require('./websocket') +import fetchival = require('./fetchival') + +export = { fetch, WebSocket, fetchival } diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..53c3533 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,73 @@ +export interface CreateFetchivalOptions { + fetch: FetchLike | null +} + +export interface ExperimentalCreateFetchivalOptions { + fetch?: ExperimentalFetchLike +} + +export interface FetchivalOptions extends Omit { + body?: string + headers?: Record + responseAs?: 'json' | 'response' | 'text' +} + +export interface ExperimentalFetchivalOptions extends FetchivalOptions { + timeout?: number +} + +export interface FetchivalError extends Error { + response: ResponseLike +} + +export interface ResponseLike { + status: number + statusText: string + json(): Promise + text(): Promise +} + +export interface Fetchival { + (url: UrlInput, opts?: FetchivalOptions): FetchivalClient + fetch: FetchLike | null +} + +export interface ExperimentalFetchival { + (link: URL, opts?: ExperimentalFetchivalOptions): ExperimentalFetchivalClient + fetch: ExperimentalFetchLike +} + +export interface FetchivalClient { + (sub: string, opts?: FetchivalOptions): FetchivalClient + get(params?: LegacyQueryParams): Promise + post(data?: JsonValue): Promise + put(data?: JsonValue): Promise + patch(data?: JsonValue): Promise + delete(): Promise +} + +export interface ExperimentalFetchivalClient { + (sub: string, opts?: ExperimentalFetchivalOptions): ExperimentalFetchivalClient + head(params?: QueryParams): Promise + get(params?: QueryParams): Promise + post(data?: JsonValue): Promise + put(data?: JsonValue): Promise + patch(data?: JsonValue): Promise + delete(): Promise + method(method: ClientMethod, arg?: JsonValue | QueryParams): Promise +} + +export type ClientMethod = 'delete' | 'get' | 'head' | 'patch' | 'post' | 'put' +export type ExperimentalFetchLike = ( + input: URL, + init?: RequestInit & { timeout?: number } +) => Promise +export type FetchivalResult = JsonValue | ResponseLike | null | string +export type FetchLike = (input: UrlInput, init?: RequestInit) => Promise +export type HttpMethod = 'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' +export type JsonValue = JsonPrimitive | JsonValue[] | { [key: string]: JsonValue } +export type JsonPrimitive = boolean | null | number | string +export type LegacyQueryParams = Record +export type QueryParams = Map | Record +export type QueryValue = boolean | null | number | string +export type UrlInput = RequestInfo | URL | string diff --git a/url.js b/src/url.ts similarity index 61% rename from url.js rename to src/url.ts index 4f795f8..dbe6e79 100644 --- a/url.js +++ b/src/url.ts @@ -1,26 +1,30 @@ const urlSymbol = Symbol('url') class WrappedUrl { - constructor(raw, symbol) { + constructor(raw: string, symbol: typeof urlSymbol) { if (typeof raw !== 'string') throw new TypeError('first argument of WrappedUrl constructor should be of type "string"') if (symbol !== urlSymbol) throw new TypeError('Use url`` to construct urls') // Just a double-check against misuse this[urlSymbol] = raw } + toString() { return this[urlSymbol] } + valueOf() { return this[urlSymbol] } + + private readonly [urlSymbol]: string } -const urlUnwrap = (url) => { +const urlUnwrap = (url: WrappedUrl) => { if (url instanceof WrappedUrl) return url[urlSymbol] throw new TypeError('Input is not a safe wrapped URL string') } -const encodeComponent = (raw) => { +const encodeComponent = (raw: UrlComponentInput) => { if (raw instanceof WrappedUrl) return urlUnwrap(raw) if (typeof raw === 'string' || typeof raw === 'number') { const arg = String(raw) @@ -32,24 +36,26 @@ const encodeComponent = (raw) => { } // URI-escape all components of the string -function urlComponent(strings, ...args) { +function urlComponent(strings: TemplateStringsArray, ...args: UrlComponentInput[]) { if (!strings.raw) throw new TypeError('urlComponent`` should be only used as a template literal') const escaped = args.map((arg) => encodeComponent(arg)) - const raw = [strings[0], ...escaped.flatMap((arg, i) => [arg, strings[i + 1]])].join('') + const raw = [strings[0] ?? '', ...escaped.flatMap((arg, i) => [arg, strings[i + 1] ?? ''])].join( + '' + ) return new WrappedUrl(raw, urlSymbol) } // Returns a template constructor -function urlBase(base) { +function urlBase(base: string) { if (typeof base !== 'string') throw new TypeError('Expected a string as base URL') - return (...args) => { + return (...args: Parameters) => { const res = urlUnwrap(urlComponent(...args)) if (!base.endsWith('/') && !res.startsWith('/')) throw new Error('Missing / after base URL') return new WrappedUrl(base + res, urlSymbol) } } -function validateBase(url, res) { +function validateBase(url: string, res: string) { if (typeof url !== 'string' || typeof res !== 'string') throw new TypeError('Unexpected types') if (res === url) return if (res.startsWith(url) && (url.endsWith('/') || url.endsWith('?') || url.endsWith('&'))) return @@ -57,20 +63,22 @@ function validateBase(url, res) { throw new Error('Result url does not start with the base url!') } -function subquery(params) { - let entries +function subquery(params: QueryParams) { + let entries: QueryEntries if (Object.getPrototypeOf(params) === Map.prototype) { - entries = [...params] + entries = [...(params as Map)] } else if (typeof params === 'object' && Object.getPrototypeOf(params) === Object.prototype) { - entries = Object.entries(params) + entries = Object.entries(params as Record) } else throw new TypeError('query can be only a Map or a plain object') - return entries.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&') + return entries + .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`) + .join('&') } // Returns an URL() object based on the logic above -function url(strings, ...args) { +function url(strings: TemplateStringsArray, ...args: UrlInput[]) { if (!strings.raw) throw new TypeError('url`` should be only used as a template literal') - let base + let base: string | undefined const escaped = args.map((raw, i) => { if (raw instanceof URL) { if (i === 0 && strings[0] === '') { @@ -79,28 +87,40 @@ function url(strings, ...args) { } throw new Error('URL typed argument should always be first') - } else if ( - Object.getPrototypeOf(raw) === Map.prototype || - (typeof raw === 'object' && Object.getPrototypeOf(raw) === Object.prototype) - ) { + } else if (isQueryParams(raw)) { if (i === args.length - 1 && strings[i + 1] === '') { - if (!/^[&?]$/.test(strings[i].slice(-1))) { + if (!/^[&?]$/.test((strings[i] ?? '').slice(-1))) { throw new Error('Missing & or ? before object params!') } - return subquery(raw) + return subquery(raw as QueryParams) } throw new Error('Object/map params could come only at the end of the URL') } - return encodeComponent(raw) + return encodeComponent(raw as UrlComponentInput) }) - const res = [strings[0], ...escaped.flatMap((arg, i) => [arg, strings[i + 1]])].join('') + const res = [strings[0] ?? '', ...escaped.flatMap((arg, i) => [arg, strings[i + 1] ?? ''])].join( + '' + ) if (base) validateBase(base, res) const url = new URL(res) if (String(url) !== res) throw new Error('Unexpected URL produced!') // e.g. .. which get resolved return url } -module.exports = { url, urlComponent, urlBase, urlUnwrap } +export = { url, urlComponent, urlBase, urlUnwrap } + +type QueryEntries = [string, QueryValue][] +type QueryParams = Map | Record +type QueryValue = boolean | null | number | string +type UrlComponentInput = WrappedUrl | number | string +type UrlInput = QueryParams | URL | UrlComponentInput + +function isQueryParams(value: UrlInput): value is QueryParams { + if (value instanceof Map) return true + return ( + typeof value === 'object' && value !== null && Object.getPrototypeOf(value) === Object.prototype + ) +} diff --git a/src/websocket.browser.ts b/src/websocket.browser.ts new file mode 100644 index 0000000..9435fdf --- /dev/null +++ b/src/websocket.browser.ts @@ -0,0 +1 @@ +export = globalThis.WebSocket diff --git a/src/websocket.native.ts b/src/websocket.native.ts new file mode 100644 index 0000000..9435fdf --- /dev/null +++ b/src/websocket.native.ts @@ -0,0 +1 @@ +export = globalThis.WebSocket diff --git a/websocket.js b/src/websocket.ts similarity index 58% rename from websocket.js rename to src/websocket.ts index 3fb86eb..e467c0f 100644 --- a/websocket.js +++ b/src/websocket.ts @@ -4,24 +4,32 @@ // the require calls based on hardcoded process.type per bundle. // Do not refactor or deduplicate. +let webSocketImplementation: WebSocketConstructor + // Try to use global browser APIs (e.g. if in Electron), otherwise require impls if (typeof process !== 'undefined' && process) { + const processWithType = process as NodeJS.Process & { type?: string } + // Node.js or Electron with Node.js integration - if (process.type === 'renderer' || process.type === 'worker') { + if (processWithType.type === 'renderer' || processWithType.type === 'worker') { // Electron renderer with Node.js integration - module.exports = globalThis.WebSocket + webSocketImplementation = globalThis.WebSocket } else { // Node.js or Electron browser process // eslint-disable-next-line unicorn/no-typeof-undefined if (typeof globalThis.WebSocket === 'undefined') { // Fall back to ws - module.exports = require('ws') + webSocketImplementation = require('ws') as WebSocketConstructor } else { // Prefer Node.js WebSocket if exists - module.exports = globalThis.WebSocket + webSocketImplementation = globalThis.WebSocket } } } else { // Browser or Electron without Node.js integration - module.exports = globalThis.WebSocket + webSocketImplementation = globalThis.WebSocket } + +export = webSocketImplementation + +type WebSocketConstructor = typeof globalThis.WebSocket diff --git a/src/wretch.browser.ts b/src/wretch.browser.ts new file mode 100644 index 0000000..0f3b1e6 --- /dev/null +++ b/src/wretch.browser.ts @@ -0,0 +1,8 @@ +import wretchModule = require('wretch') + +const wretch = wretchModule.default + +// Removes the .default property from the exported function to deconfuse bundlers +export = (url?: string, options?: WretchOptions) => wretch(url, options) + +type WretchOptions = Parameters[1] diff --git a/src/wretch.ts b/src/wretch.ts new file mode 100644 index 0000000..0857aa8 --- /dev/null +++ b/src/wretch.ts @@ -0,0 +1,7 @@ +// NOTE: does not export Wretcher +import wretch = require('./wretch.browser') +import fetch = require('./fetch') + +wretch().polyfills({ fetch }) + +export = wretch diff --git a/test/create-fetchival.js b/test/create-fetchival.ts similarity index 73% rename from test/create-fetchival.js rename to test/create-fetchival.ts index c83d690..2c4c145 100644 --- a/test/create-fetchival.js +++ b/test/create-fetchival.ts @@ -1,13 +1,13 @@ 'use strict' -const tape = require('tape') -const createFetchival = require('../create-fetchival') +import tape = require('tape') +import createFetchival = require('../src/create-fetchival') tape('createFetchival', (t) => { t.test('uses injected fetch to fetch json', async (t) => { const data = { identity: 'Bruce Wayne' } const fetch = async () => { - return { status: 200, json: async () => data } + return { status: 200, statusText: 'OK', json: async () => data, text: async () => '' } } const fetchival = createFetchival({ fetch }) @@ -28,7 +28,7 @@ tape('createFetchival', (t) => { await fetchival('https://jsonplaceholder.typicode.com')('posts').get() t.fail('request should have failed') } catch (err) { - t.equals(err.message, 'Couldnt establish connection') + t.equals((err as Error).message, 'Couldnt establish connection') } }) }) diff --git a/test/fetchival.experimental.js b/test/fetchival.experimental.ts similarity index 51% rename from test/fetchival.experimental.js rename to test/fetchival.experimental.ts index 257a1eb..897b643 100644 --- a/test/fetchival.experimental.js +++ b/test/fetchival.experimental.ts @@ -1,15 +1,15 @@ -const tape = require('tape') -const fetchival = require('../experimental/fetchival') +import tape = require('tape') +import fetchival = require('../src/experimental/fetchival') function Captor() { - const captor = { + const captor: CaptorState = { calls: [], async capture(...args) { this.calls.push(args) - return { status: 204 } + return { status: 204, statusText: 'No Content', json: async () => null, text: async () => '' } }, } - const capture = captor.capture.bind(captor) + const capture = captor.capture.bind(captor) as CaptureFunction capture.calls = captor.calls return capture @@ -17,7 +17,9 @@ function Captor() { tape('fetchival', (t) => { t.test('fetches json', async () => { - const res = await fetchival(new URL('https://jsonplaceholder.typicode.com'))('posts').get() + const res = (await fetchival(new URL('https://jsonplaceholder.typicode.com'))( + 'posts' + ).get()) as unknown[] t.equals(res.length, 100) }) @@ -30,7 +32,7 @@ tape('fetchival', (t) => { await client.post({ some: 'data' }) - const [url] = captor.calls[0] + const [url] = captor.calls[0]! t.deepEqual(url, new URL('https://wayne-foundation.com/register')) }) @@ -43,8 +45,27 @@ tape('fetchival', (t) => { await client.post({ some: 'data' }) - const [url] = captor.calls[0] + const [url] = captor.calls[0]! t.deepEqual(url, new URL('https://wayne-foundation.com/register')) }) }) + +interface CaptorState { + calls: CaptureArgs[] + capture(...args: CaptureArgs): Promise +} + +interface CaptureFunction { + (...args: CaptureArgs): Promise + calls: CaptureArgs[] +} + +interface CaptureResponse { + status: number + statusText: string + json(): Promise + text(): Promise +} + +type CaptureArgs = [URL, (RequestInit & { timeout?: number })?] diff --git a/test/fetchival.js b/test/fetchival.ts similarity index 50% rename from test/fetchival.js rename to test/fetchival.ts index 47942d7..c9f69c3 100644 --- a/test/fetchival.js +++ b/test/fetchival.ts @@ -1,15 +1,17 @@ -const tape = require('tape') -const { fetchival } = require('../index') +import tape = require('tape') +import index = require('../src/index') + +const { fetchival } = index function Captor() { - const captor = { + const captor: CaptorState = { calls: [], async capture(...args) { this.calls.push(args) - return { status: 204 } + return { status: 204, statusText: 'No Content', json: async () => null, text: async () => '' } }, } - const capture = captor.capture.bind(captor) + const capture = captor.capture.bind(captor) as CaptureFunction capture.calls = captor.calls return capture @@ -17,7 +19,9 @@ function Captor() { tape('fetchival', (t) => { t.test('fetches json', async () => { - const res = await fetchival('https://jsonplaceholder.typicode.com')('posts').get() + const res = (await fetchival('https://jsonplaceholder.typicode.com')( + 'posts' + ).get()) as unknown[] t.equals(res.length, 100) }) @@ -30,7 +34,7 @@ tape('fetchival', (t) => { await client.post({ some: 'data' }) - const [url] = captor.calls[0] + const [url] = captor.calls[0]! t.equals(url, 'https://wayne-foundation.com/register') }) @@ -43,8 +47,27 @@ tape('fetchival', (t) => { await client.post({ some: 'data' }) - const [url] = captor.calls[0] + const [url] = captor.calls[0]! t.equals(url, 'https://wayne-foundation.com/register') }) }) + +interface CaptorState { + calls: CaptureArgs[] + capture(...args: CaptureArgs): Promise +} + +interface CaptureFunction { + (...args: CaptureArgs): Promise + calls: CaptureArgs[] +} + +interface CaptureResponse { + status: number + statusText: string + json(): Promise + text(): Promise +} + +type CaptureArgs = [RequestInfo | URL | string, RequestInit?] diff --git a/test/url.js b/test/url.ts similarity index 89% rename from test/url.js rename to test/url.ts index 11c0b9a..9bb9e5e 100644 --- a/test/url.js +++ b/test/url.ts @@ -1,10 +1,12 @@ 'use strict' -const tape = require('tape') -const { url, urlBase } = require('../url') +import tape = require('tape') +import urlModule = require('../src/url') + +const { url, urlBase } = urlModule tape('url', (t) => { - const check = (val, expected) => { + const check = (val: URL, expected: string) => { t.strictEqual(Object.getPrototypeOf(val), URL.prototype, 'is an URL object') t.strictEqual(`${val}`, expected, `value is correct: ${expected}`) } diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..b1b3066 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "outDir": "lib", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..db6d087 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "Node16", + "moduleResolution": "Node16", + "lib": ["ES2022", "DOM"], + "strict": true, + "noUncheckedIndexedAccess": true, + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "types": ["node"] + }, + "include": ["src/**/*.ts", "test/**/*.ts"] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..5f0f695 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": false, + "noEmit": false, + "outDir": ".cache/test", + "rootDir": "." + }, + "include": ["src/**/*.ts", "test/**/*.ts"] +} diff --git a/websocket.browser.js b/websocket.browser.js deleted file mode 100644 index dc9e3ef..0000000 --- a/websocket.browser.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = globalThis.WebSocket diff --git a/websocket.native.js b/websocket.native.js deleted file mode 100644 index dc9e3ef..0000000 --- a/websocket.native.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = globalThis.WebSocket diff --git a/wretch.browser.js b/wretch.browser.js deleted file mode 100644 index 04fc5d9..0000000 --- a/wretch.browser.js +++ /dev/null @@ -1,4 +0,0 @@ -const { default: wretch } = require('wretch') - -// Removes the .default property from the exported function to deconfuse bundlers -module.exports = (url, options) => wretch(url, options) diff --git a/wretch.js b/wretch.js deleted file mode 100644 index 91e1808..0000000 --- a/wretch.js +++ /dev/null @@ -1,7 +0,0 @@ -// NOTE: does not export Wretcher -const wretch = require('./wretch.browser') -const fetch = require('./fetch') - -wretch().polyfills({ fetch }) - -module.exports = wretch