From 3b0562f21a38f46c657fe830a97693cc6d8534ff Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Mon, 8 Sep 2025 17:45:01 -0400 Subject: [PATCH 1/6] [chore] Update MCP DevKit server to use ESM/vitest --- .editorconfig | 8 + .gitignore | 7 + eslint.config.mjs | 102 +- jest.config.js | 24 - manifest.json | 2 +- package-lock.json | 5863 +++++++---------- package.json | 69 +- scripts/add-shebang.cjs | 31 +- scripts/build-helpers.cjs | 41 +- src/index.test.ts | 7 - src/index.ts | 15 +- src/tools/BaseTool.ts | 2 +- .../bounding-box-tool/BoundariesData-cjs.cts | 3 + src/tools/bounding-box-tool/BoundariesData.ts | 5 + .../CountryBoundingBoxTool.ts | 2 +- .../create-style-tool/CreateStyleTool.ts | 5 +- .../create-token-tool/CreateTokenTool.ts | 5 +- .../GetMapboxDocSourceTool.ts | 6 +- src/tools/list-styles-tool/ListStylesTool.ts | 5 +- src/tools/list-tokens-tool/ListTokensTool.ts | 5 +- src/utils/fetchRequest.ts | 125 + src/utils/requestUtils.test-helpers.ts | 36 - src/utils/requestUtils.test.ts | 136 - src/utils/requestUtils.ts | 75 - src/utils/versionUtils-cjs.cts | 29 + src/utils/versionUtils.ts | 10 +- {src => test}/config/toolConfig.test.ts | 17 +- .../tools/MapboxApiBasedTool.test.ts | 259 +- .../tool-naming-convention.test.ts.snap | 86 + .../bounding-box-tool/BoundingBoxTool.test.ts | 11 +- .../CountryBoundingBoxTool.test.ts | 13 +- .../CoordinateConversionTool.test.ts | 13 +- .../create-style-tool/CreateStyleTool.test.ts | 22 +- .../create-token-tool/CreateTokenTool.test.ts | 94 +- .../GeojsonPreviewTool.test.ts | 13 +- .../GetMapboxDocSourceTool.test.ts | 52 +- .../list-styles-tool/ListStylesTool.test.ts | 41 +- .../list-tokens-tool/ListTokensTool.test.ts | 128 +- .../PreviewStyleTool.test.ts | 10 +- .../StyleComparisonTool.test.ts | 23 +- .../tilequery-tool/TilequeryTool.test.ts | 5 +- .../tools/tool-naming-convention.test.ts | 22 +- test/utils/fetchRequest.test.ts | 164 + test/utils/fetchRequestUtils.ts | 34 + tsconfig.base.json | 21 + tsconfig.json | 35 +- tsconfig.src.json | 7 + tsconfig.test.json | 9 + tsconfig.types.json | 9 - vitest.config.ts | 21 + 50 files changed, 3268 insertions(+), 4459 deletions(-) create mode 100644 .editorconfig delete mode 100644 jest.config.js delete mode 100644 src/index.test.ts create mode 100644 src/tools/bounding-box-tool/BoundariesData-cjs.cts create mode 100644 src/tools/bounding-box-tool/BoundariesData.ts create mode 100644 src/utils/fetchRequest.ts delete mode 100644 src/utils/requestUtils.test-helpers.ts delete mode 100644 src/utils/requestUtils.test.ts delete mode 100644 src/utils/requestUtils.ts create mode 100644 src/utils/versionUtils-cjs.cts rename {src => test}/config/toolConfig.test.ts (96%) rename {src => test}/tools/MapboxApiBasedTool.test.ts (51%) create mode 100644 test/tools/__snapshots__/tool-naming-convention.test.ts.snap rename {src => test}/tools/bounding-box-tool/BoundingBoxTool.test.ts (95%) rename {src => test}/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts (94%) rename {src => test}/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts (94%) rename {src => test}/tools/create-style-tool/CreateStyleTool.test.ts (67%) rename {src => test}/tools/create-token-tool/CreateTokenTool.test.ts (81%) rename {src => test}/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts (92%) rename {src => test}/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts (73%) rename {src => test}/tools/list-styles-tool/ListStylesTool.test.ts (74%) rename {src => test}/tools/list-tokens-tool/ListTokensTool.test.ts (82%) rename {src => test}/tools/preview-style-tool/PreviewStyleTool.test.ts (92%) rename {src => test}/tools/style-comparison-tool/StyleComparisonTool.test.ts (92%) rename {src => test}/tools/tilequery-tool/TilequeryTool.test.ts (91%) rename {src => test}/tools/tool-naming-convention.test.ts (90%) create mode 100644 test/utils/fetchRequest.test.ts create mode 100644 test/utils/fetchRequestUtils.ts create mode 100644 tsconfig.base.json create mode 100644 tsconfig.src.json create mode 100644 tsconfig.test.json delete mode 100644 tsconfig.types.json create mode 100644 vitest.config.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..035388c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +indent_size = 2 +indent_style = space +end_of_line = lf +insert_final_newline = true +charset = utf-8 \ No newline at end of file diff --git a/.gitignore b/.gitignore index f95fe48..d23b8bd 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,10 @@ dist/ .env .env.local .env.*.local + +# tshy +.tshy/ +.tshy-build/ + +# Test results +test-results.xml diff --git a/eslint.config.mjs b/eslint.config.mjs index 544bcd7..ca7ac5e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,97 +1,25 @@ -import js from '@eslint/js'; -import typescript from '@typescript-eslint/eslint-plugin'; -import typescriptParser from '@typescript-eslint/parser'; -import prettier from 'eslint-config-prettier'; -import importPlugin from 'eslint-plugin-import'; -import unusedImports from 'eslint-plugin-unused-imports'; +import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; +import tseslint from 'typescript-eslint'; +import globals from 'globals'; -export default [ +export default defineConfig( + eslint.configs.recommended, + tseslint.configs.recommended, { - ignores: ['dist/**', 'node_modules/**', '*.js', '*.cjs', '*.mjs'] - }, - { - files: ['**/*.test.ts', '**/*.spec.ts', '**/*.test-helpers.ts'], languageOptions: { globals: { - describe: 'readonly', - test: 'readonly', - it: 'readonly', - expect: 'readonly', - beforeEach: 'readonly', - afterEach: 'readonly', - jest: 'readonly', - fetch: 'readonly', - global: 'readonly' - }, + ...globals.node, + } }, rules: { - 'no-undef': 'off', - '@typescript-eslint/no-unused-vars': 'off', - 'unused-imports/no-unused-imports': 'off', - 'import/order': 'off', - }, + "@typescript-eslint/no-explicit-any": "warn", + } }, - js.configs.recommended, { - files: ['src/**/*.ts', 'src/**/*.tsx'], - languageOptions: { - parser: typescriptParser, - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - project: './tsconfig.json' - }, - globals: { - fetch: 'readonly', - process: 'readonly', - global: 'readonly', - globalThis: 'readonly', - URL: 'readonly', - Request: 'readonly', - RequestInit: 'readonly', - Response: 'readonly', - Buffer: 'readonly', - console: 'readonly', - require: 'readonly', - __dirname: 'readonly', - __filename: 'readonly', - }, - }, - plugins: { - '@typescript-eslint': typescript, - 'import': importPlugin, - 'unused-imports': unusedImports - }, + files: ["test/**/*.ts"], rules: { - ...typescript.configs.recommended.rules, - '@typescript-eslint/no-unused-vars': 'off', - 'unused-imports/no-unused-imports': 'error', - 'unused-imports/no-unused-vars': [ - 'warn', - { - vars: 'all', - varsIgnorePattern: '^_', - args: 'after-used', - argsIgnorePattern: '^_' - } - ], - 'import/order': [ - 'error', - { - groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], - 'newlines-between': 'never', - alphabetize: { - order: 'asc' - } - } - ], - 'no-console': 'warn', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/no-explicit-any': 'warn', - '@typescript-eslint/no-non-null-assertion': 'warn', - '@typescript-eslint/no-require-imports': 'off', - 'no-undef': 'off' // TypeScript handles this + "@typescript-eslint/no-unused-vars": "off", } - }, - prettier -]; \ No newline at end of file + } +); diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index f313f85..0000000 --- a/jest.config.js +++ /dev/null @@ -1,24 +0,0 @@ -export default { - preset: 'ts-jest', - testEnvironment: 'node', - roots: ['/src'], - testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], - transform: { - '^.+\\.ts$': [ - 'ts-jest', - { - useESM: true - } - ] - }, - extensionsToTreatAsEsm: ['.ts'], - moduleNameMapper: { - '^(\\.{1,2}/.*)\\.js$': '$1' - }, - collectCoverageFrom: [ - 'src/**/*.ts', - '!src/**/*.d.ts', - '!src/**/*.test.ts', - '!src/**/*.spec.ts' - ] -}; diff --git a/manifest.json b/manifest.json index 4187694..e23fbdd 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "dxt_version": "0.1", "name": "@mapbox/mcp-devkit-server", "display_name": "Mapbox MCP DevKit Server", - "version": "0.3.1", + "version": "0.3.2", "description": "Mapbox MCP devkit server", "author": { "name": "Mapbox, Inc." diff --git a/package-lock.json b/package-lock.json index 191f4cd..807f143 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,30 +9,28 @@ "version": "0.3.2", "license": "BSD-3-Clause", "dependencies": { - "@modelcontextprotocol/sdk": "^1.12.1", + "@modelcontextprotocol/sdk": "^1.17.5", "zod": "^3.25.42" }, "bin": { - "mapbox-mcp-devkit": "dist/index.js" + "mapbox-mcp-devkit": "dist/esm/index.js" }, "devDependencies": { "@eslint/js": "^9.27.0", "@types/geojson": "^7946.0.16", - "@types/jest": "^29.0.1", "@types/node": "^22.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", + "@vitest/coverage-istanbul": "^3.2.4", "eslint": "^9.0.0", - "eslint-config-prettier": "^10.1.5", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-unused-imports": "^4.0.0", "husky": "^9.0.0", - "jest": "^29.1.0", "lint-staged": "^16.1.0", "plop": "^4.0.1", "prettier": "^3.0.0", - "ts-jest": "^29.3.4", - "typescript": "^5.8.3" + "tshy": "^3.0.2", + "typescript": "^5.8.3", + "typescript-eslint": "^8.42.0", + "vitest": "^3.2.4" }, "engines": { "node": ">=22" @@ -182,14 +180,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "dev": true, @@ -240,294 +230,526 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", + "node_modules/@babel/template": { + "version": "7.27.2", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", + "node_modules/@babel/traverse": { + "version": "7.28.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", + "node_modules/@babel/types": { + "version": "7.28.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/template": { - "version": "7.27.2", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/traverse": { - "version": "7.28.0", + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", - "debug": "^4.3.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/types": { - "version": "7.28.0", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { @@ -725,95 +947,130 @@ "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": "20 || >=22" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", "dev": true, "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "engines": { + "node": ">=12" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/@istanbuljs/schema": { @@ -824,417 +1081,416 @@ "node": ">=8" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", "dev": true, "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.0.0" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "MIT" }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "dev": true, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.5.tgz", + "integrity": "sha512-QakrKIGniGuRVfWBdMsDea/dx1PNE739QJ7gCM41s9q+qaCYTHCdsIBXQVVXry3mfWAiaM9kT22Hyz53Uw8mfg==", "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", "dev": true, "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, + "optional": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz", + "integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz", + "integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz", + "integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz", + "integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz", + "integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz", + "integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz", + "integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==", + "cpu": [ + "arm" + ], "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz", + "integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.13.3", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz", + "integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.12.6", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz", + "integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz", + "integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz", + "integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz", + "integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz", + "integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz", + "integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz", + "integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz", + "integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz", + "integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz", + "integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz", + "integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", + "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.20.7" + "@types/deep-eql": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "dev": true, @@ -1250,14 +1506,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/inquirer": { "version": "9.0.8", "dev": true, @@ -1267,46 +1515,11 @@ "rxjs": "^7.2.0" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "29.5.14", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "dev": true, "license": "MIT" }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, "node_modules/@types/liftoff": { "version": "4.0.3", "dev": true, @@ -1324,11 +1537,6 @@ "undici-types": "~6.21.0" } }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, "node_modules/@types/through": { "version": "0.0.33", "dev": true, @@ -1337,29 +1545,18 @@ "@types/node": "*" } }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "dev": true, - "license": "MIT" - }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.42.0.tgz", + "integrity": "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.35.1", - "@typescript-eslint/type-utils": "8.35.1", - "@typescript-eslint/utils": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1", + "@typescript-eslint/scope-manager": "8.42.0", + "@typescript-eslint/type-utils": "8.42.0", + "@typescript-eslint/utils": "8.42.0", + "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -1373,20 +1570,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.35.1", + "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.42.0.tgz", + "integrity": "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.35.1", - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/typescript-estree": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1", + "@typescript-eslint/scope-manager": "8.42.0", + "@typescript-eslint/types": "8.42.0", + "@typescript-eslint/typescript-estree": "8.42.0", + "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "engines": { @@ -1398,16 +1597,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.42.0.tgz", + "integrity": "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.35.1", - "@typescript-eslint/types": "^8.35.1", + "@typescript-eslint/tsconfig-utils": "^8.42.0", + "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "engines": { @@ -1418,16 +1619,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.42.0.tgz", + "integrity": "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1" + "@typescript-eslint/types": "8.42.0", + "@typescript-eslint/visitor-keys": "8.42.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1438,7 +1641,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.42.0.tgz", + "integrity": "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==", "dev": true, "license": "MIT", "engines": { @@ -1449,16 +1654,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.42.0.tgz", + "integrity": "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.35.1", - "@typescript-eslint/utils": "8.35.1", + "@typescript-eslint/types": "8.42.0", + "@typescript-eslint/typescript-estree": "8.42.0", + "@typescript-eslint/utils": "8.42.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1471,11 +1679,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.42.0.tgz", + "integrity": "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==", "dev": true, "license": "MIT", "engines": { @@ -1487,14 +1697,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.42.0.tgz", + "integrity": "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.35.1", - "@typescript-eslint/tsconfig-utils": "8.35.1", - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/visitor-keys": "8.35.1", + "@typescript-eslint/project-service": "8.42.0", + "@typescript-eslint/tsconfig-utils": "8.42.0", + "@typescript-eslint/types": "8.42.0", + "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1510,18 +1722,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.42.0.tgz", + "integrity": "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.35.1", - "@typescript-eslint/types": "8.35.1", - "@typescript-eslint/typescript-estree": "8.35.1" + "@typescript-eslint/scope-manager": "8.42.0", + "@typescript-eslint/types": "8.42.0", + "@typescript-eslint/typescript-estree": "8.42.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1532,15 +1746,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.35.1", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.42.0.tgz", + "integrity": "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.35.1", + "@typescript-eslint/types": "8.42.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -1553,6 +1769,8 @@ }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1562,381 +1780,357 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/accepts": { - "version": "2.0.0", + "node_modules/@vitest/coverage-istanbul": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-istanbul/-/coverage-istanbul-3.2.4.tgz", + "integrity": "sha512-IDlpuFJiWU9rhcKLkpzj8mFu/lpe64gVgnV15ZOrYx1iFzxxrxCzbExiUEKtwwXRvEiEMUS6iZeYgnMxgbqbxQ==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "@istanbuljs/schema": "^0.1.3", + "debug": "^4.4.1", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-instrument": "^6.0.3", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.6", + "istanbul-reports": "^3.1.7", + "magicast": "^0.3.5", + "test-exclude": "^7.0.1", + "tinyrainbow": "^2.0.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "funding": { + "url": "https://opencollective.com/vitest" }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "vitest": "3.2.4" } }, - "node_modules/aggregate-error": { - "version": "4.0.1", + "node_modules/@vitest/coverage-istanbul/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ajv": { - "version": "6.12.6", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", + "node_modules/@vitest/coverage-istanbul/node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "type-fest": "^0.21.3" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", + "node_modules/@vitest/coverage-istanbul/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "ISC" }, - "node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/@vitest/coverage-istanbul/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "color-convert": "^2.0.1" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/anymatch": { - "version": "3.1.3", + "node_modules/@vitest/coverage-istanbul/node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, "license": "ISC", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, "engines": { - "node": ">= 8" + "node": ">=18" } }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/array-each": { - "version": "1.0.1", + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/array-includes": { - "version": "3.1.9", + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" + "tinyrainbow": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/array-slice": { - "version": "1.1.0", + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "tinyspy": "^4.0.3" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "dev": true, + "node_modules/accepts": { + "version": "2.0.0", "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, - "node_modules/async": { - "version": "3.2.6", + "node_modules/acorn": { + "version": "8.15.0", "dev": true, - "license": "MIT" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/async-function": { - "version": "1.0.0", + "node_modules/acorn-jsx": { + "version": "5.3.2", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", + "node_modules/aggregate-error": { + "version": "4.0.1", "dev": true, "license": "MIT", "dependencies": { - "possible-typed-array-names": "^1.0.0" + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/babel-jest": { - "version": "29.7.0", + "node_modules/ansi-escapes": { + "version": "4.3.2", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "type-fest": "^0.21.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", + "node_modules/ansi-regex": { + "version": "5.0.1", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", + "node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", + "node_modules/anymatch": { + "version": "3.1.3", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-each": { + "version": "1.0.1", "dev": true, "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/babel-preset-current-node-syntax": { + "node_modules/array-slice": { "version": "1.1.0", "dev": true, "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, "node_modules/balanced-match": { @@ -1963,6 +2157,19 @@ ], "license": "MIT" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bl": { "version": "4.1.0", "dev": true, @@ -2041,25 +2248,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, "node_modules/buffer": { "version": "5.7.1", "dev": true, @@ -2083,11 +2271,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/bytes": { "version": "3.1.2", "license": "MIT", @@ -2095,21 +2278,14 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.8", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, "node_modules/call-bind-apply-helpers": { @@ -2154,14 +2330,6 @@ "tslib": "^2.0.3" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001726", "dev": true, @@ -2191,8 +2359,25 @@ "upper-case-first": "^2.0.2" } }, - "node_modules/chalk": { - "version": "4.1.2", + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { @@ -2225,37 +2410,58 @@ "tslib": "^2.0.3" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/chardet": { "version": "0.7.0", "dev": true, "license": "MIT" }, - "node_modules/ci-info": { - "version": "3.9.0", + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 16" } }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/clean-stack": { "version": "4.2.0", @@ -2376,19 +2582,6 @@ "node": ">= 12" } }, - "node_modules/cliui": { - "version": "8.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/clone": { "version": "1.0.4", "dev": true, @@ -2397,20 +2590,6 @@ "node": ">=0.8" } }, - "node_modules/co": { - "version": "4.6.0", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, "node_modules/color-convert": { "version": "2.0.1", "dev": true, @@ -2502,26 +2681,6 @@ "node": ">= 0.10" } }, - "node_modules/create-jest": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "license": "MIT", @@ -2534,54 +2693,6 @@ "node": ">= 8" } }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/debug": { "version": "4.4.1", "license": "MIT", @@ -2597,17 +2708,14 @@ } } }, - "node_modules/dedent": { - "version": "1.6.0", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "engines": { + "node": ">=6" } }, "node_modules/deep-is": { @@ -2615,14 +2723,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/defaults": { "version": "1.0.4", "dev": true, @@ -2634,38 +2734,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/del": { "version": "7.1.0", "dev": true, @@ -2713,22 +2781,6 @@ "node": ">=0.10.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "dev": true, @@ -2740,17 +2792,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/dot-case": { "version": "3.0.4", "dev": true, @@ -2772,40 +2813,22 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/ee-first": { "version": "1.1.1", "license": "MIT" }, - "node_modules/ejs": { - "version": "3.1.10", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.179", "dev": true, "license": "ISC" }, - "node_modules/emittery": { - "version": "0.13.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "dev": true, @@ -2829,81 +2852,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.24.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-define-property": { "version": "1.0.1", "license": "MIT", @@ -2918,6 +2866,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "license": "MIT", @@ -2928,45 +2883,46 @@ "node": ">= 0.4" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" } }, "node_modules/escalade": { @@ -3051,146 +3007,8 @@ } } }, - "node_modules/eslint-config-prettier": { - "version": "10.1.5", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.12", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-unused-imports": { - "version": "4.1.4", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", - "eslint": "^9.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", + "node_modules/eslint-scope": { + "version": "8.4.0", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3281,18 +3099,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.6.0", "dev": true, @@ -3323,6 +3129,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "dev": true, @@ -3360,35 +3176,6 @@ "node": ">=20.0.0" } }, - "node_modules/execa": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/expand-tilde": { "version": "2.0.2", "dev": true, @@ -3400,19 +3187,14 @@ "node": ">=0.10.0" } }, - "node_modules/expect": { - "version": "29.7.0", + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, + "license": "Apache-2.0", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.0.0" } }, "node_modules/express": { @@ -3544,14 +3326,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "dev": true, @@ -3563,25 +3337,6 @@ "node": ">=16.0.0" } }, - "node_modules/filelist": { - "version": "1.0.4", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fill-range": { "version": "7.1.1", "dev": true, @@ -3677,20 +3432,6 @@ "dev": true, "license": "ISC" }, - "node_modules/for-each": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/for-in": { "version": "1.0.2", "dev": true, @@ -3710,6 +3451,36 @@ "node": ">=0.10.0" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forwarded": { "version": "0.2.0", "license": "MIT", @@ -3748,33 +3519,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "dev": true, @@ -3783,14 +3527,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, "node_modules/get-east-asian-width": { "version": "1.3.0", "dev": true, @@ -3824,14 +3560,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/get-proto": { "version": "1.0.1", "license": "MIT", @@ -3843,33 +3571,6 @@ "node": ">= 0.4" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/glob": { "version": "7.2.3", "dev": true, @@ -3970,21 +3671,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/globby": { "version": "13.2.2", "dev": true, @@ -4062,68 +3748,18 @@ "uglify-js": "^3.1.4" } }, - "node_modules/has-bigints": { - "version": "1.1.0", + "node_modules/has-flag": { + "version": "4.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { "node": ">= 0.4" }, "funding": { @@ -4186,14 +3822,6 @@ "node": ">= 0.8" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/husky": { "version": "9.1.7", "dev": true, @@ -4260,24 +3888,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "dev": true, @@ -4399,1186 +4009,296 @@ }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inquirer/node_modules/restore-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/wrap-ansi": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-path-inside": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "license": "MIT" - }, - "node_modules/is-regex": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/isbinaryfile": { - "version": "5.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "license": "ISC" - }, - "node_modules/isobject": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jake": { - "version": "10.9.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jake/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/inquirer/node_modules/restore-cursor": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" } }, - "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/jest": { - "version": "29.7.0", + "node_modules/interpret": { + "version": "3.1.1", "dev": true, "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=10.13.0" } }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "dev": true, + "node_modules/ipaddr.js": { + "version": "1.9.1", "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.10" } }, - "node_modules/jest-circus": { - "version": "29.7.0", + "node_modules/is-absolute": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-cli": { - "version": "29.7.0", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "binary-extensions": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=8" } }, - "node_modules/jest-config": { - "version": "29.7.0", + "node_modules/is-core-module": { + "version": "2.16.1", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "hasown": "^2.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-diff": { - "version": "29.7.0", + "node_modules/is-extglob": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-each": { - "version": "29.7.0", + "node_modules/is-glob": { + "version": "4.0.3", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", + "node_modules/is-interactive": { + "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", + "node_modules/is-number": { + "version": "7.0.0", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.12.0" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", + "node_modules/is-path-cwd": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", + "node_modules/is-path-inside": { + "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", + "node_modules/is-plain-object": { + "version": "5.0.0", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", + "node_modules/is-promise": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/is-relative": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "is-unc-path": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-mock": { - "version": "29.7.0", + "node_modules/is-unc-path": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" + "unc-path-regex": "^0.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", + "node_modules/is-unicode-supported": { + "version": "2.1.0", "dev": true, "license": "MIT", "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" + "node": ">=18" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", + "node_modules/is-windows": { + "version": "1.0.2", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-resolve": { - "version": "29.7.0", + "node_modules/isbinaryfile": { + "version": "5.0.4", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" + "node": ">= 18.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" } }, - "node_modules/jest-runner": { - "version": "29.7.0", + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-util": { - "version": "29.7.0", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, + "license": "BSD-3-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-validate": { - "version": "29.7.0", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "dev": true, - "license": "MIT", "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-watcher": { - "version": "29.7.0", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/jest-worker": { - "version": "29.7.0", + "node_modules/istanbul-reports": { + "version": "3.1.7", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@isaacs/cliui": "^8.0.2" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-tokens": { @@ -5613,11 +4333,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "license": "MIT" @@ -5654,22 +4369,6 @@ "node": ">=0.10.0" } }, - "node_modules/kleur": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "dev": true, @@ -5711,11 +4410,6 @@ "url": "https://github.com/sponsors/antonk52" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, "node_modules/lint-staged": { "version": "16.1.2", "dev": true, @@ -5861,11 +4555,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "dev": true, @@ -6042,6 +4731,13 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lower-case": { "version": "2.0.2", "dev": true, @@ -6058,6 +4754,28 @@ "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.18", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", + "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, "node_modules/make-dir": { "version": "4.0.0", "dev": true, @@ -6072,11 +4790,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-error": { - "version": "1.3.6", - "dev": true, - "license": "ISC" - }, "node_modules/make-iterator": { "version": "1.0.1", "dev": true, @@ -6088,14 +4801,6 @@ "node": ">=0.10.0" } }, - "node_modules/makeerror": { - "version": "1.0.12", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/map-cache": { "version": "0.2.2", "dev": true, @@ -6128,11 +4833,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "dev": true, @@ -6211,6 +4911,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "3.0.1", "dev": true, @@ -6248,6 +4958,25 @@ "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "dev": true, @@ -6274,11 +5003,6 @@ "tslib": "^2.0.3" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, "node_modules/node-plop": { "version": "0.32.0", "dev": true, @@ -6315,17 +5039,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/object-assign": { "version": "4.1.1", "license": "MIT", @@ -6343,33 +5056,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.defaults": { "version": "1.1.0", "dev": true, @@ -6384,36 +5070,6 @@ "node": ">=0.10.0" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/object.map": { "version": "1.0.1", "dev": true, @@ -6437,23 +5093,6 @@ "node": ">=0.10.0" } }, - "node_modules/object.values": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/on-finished": { "version": "2.4.1", "license": "MIT", @@ -6588,22 +5227,6 @@ "node": ">=0.10.0" } }, - "node_modules/own-keys": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/p-limit": { "version": "3.1.0", "dev": true, @@ -6646,13 +5269,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "BlueOak-1.0.0" }, "node_modules/param-case": { "version": "3.0.4", @@ -6687,23 +5309,6 @@ "node": ">=0.8" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse-passwd": { "version": "1.0.0", "dev": true, @@ -6784,6 +5389,33 @@ "node": ">=0.10.0" } }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz", + "integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/path-to-regexp": { "version": "8.2.0", "license": "MIT", @@ -6799,6 +5431,23 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/picocolors": { "version": "1.1.1", "dev": true, @@ -6826,14 +5475,6 @@ "node": ">=0.10" } }, - "node_modules/pirates": { - "version": "4.0.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/pkce-challenge": { "version": "5.0.0", "license": "MIT", @@ -6841,65 +5482,6 @@ "node": ">=16.20.0" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/plop": { "version": "4.0.1", "dev": true, @@ -6925,19 +5507,53 @@ "version": "5.4.1", "dev": true, "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/polite-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/polite-json/-/polite-json-5.0.0.tgz", + "integrity": "sha512-OLS/0XeUAcE8a2fdwemNja+udKgXNnY6yKVIXqAD2zVRx1KvY6Ato/rZ2vdzbxqYwPW0u6SCNC/bAMPNzpzxbw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >=14" } }, "node_modules/prelude-ls": { @@ -6962,42 +5578,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "license": "MIT", @@ -7016,21 +5596,6 @@ "node": ">=6" } }, - "node_modules/pure-rand": { - "version": "6.1.0", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, "node_modules/qs": { "version": "6.14.0", "license": "BSD-3-Clause", @@ -7083,11 +5648,6 @@ "node": ">= 0.8" } }, - "node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, "node_modules/readable-stream": { "version": "3.6.2", "dev": true, @@ -7101,63 +5661,28 @@ "node": ">= 6" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" + "picomatch": "^2.2.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.10.0" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", + "node_modules/rechoir": { + "version": "0.8.0", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "resolve": "^1.20.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, "node_modules/resolve": { @@ -7179,51 +5704,97 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", + "node_modules/resolve-dir": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/resolve-from": { + "version": "4.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", + "node_modules/resolve-import": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-import/-/resolve-import-2.0.0.tgz", + "integrity": "sha512-jpKjLibLuc8D1XEV2+7zb0aqN7I8d12u89g/v6IsgCzdVlccMQJq4TKkPw5fbhHdxhm7nbVtN+KvOTnjFf+nEA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "glob": "^11.0.0", + "walk-up-path": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/resolve-from": { - "version": "4.0.0", + "node_modules/resolve-import/node_modules/glob": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { - "node": ">=4" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/resolve.exports": { - "version": "2.0.3", + "node_modules/resolve-import/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, "engines": { - "node": ">=10" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/resolve-import/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/restore-cursor": { @@ -7294,6 +5865,47 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.50.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz", + "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.50.0", + "@rollup/rollup-android-arm64": "4.50.0", + "@rollup/rollup-darwin-arm64": "4.50.0", + "@rollup/rollup-darwin-x64": "4.50.0", + "@rollup/rollup-freebsd-arm64": "4.50.0", + "@rollup/rollup-freebsd-x64": "4.50.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", + "@rollup/rollup-linux-arm-musleabihf": "4.50.0", + "@rollup/rollup-linux-arm64-gnu": "4.50.0", + "@rollup/rollup-linux-arm64-musl": "4.50.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", + "@rollup/rollup-linux-ppc64-gnu": "4.50.0", + "@rollup/rollup-linux-riscv64-gnu": "4.50.0", + "@rollup/rollup-linux-riscv64-musl": "4.50.0", + "@rollup/rollup-linux-s390x-gnu": "4.50.0", + "@rollup/rollup-linux-x64-gnu": "4.50.0", + "@rollup/rollup-linux-x64-musl": "4.50.0", + "@rollup/rollup-openharmony-arm64": "4.50.0", + "@rollup/rollup-win32-arm64-msvc": "4.50.0", + "@rollup/rollup-win32-ia32-msvc": "4.50.0", + "@rollup/rollup-win32-x64-msvc": "4.50.0", + "fsevents": "~2.3.2" + } + }, "node_modules/router": { "version": "2.2.0", "license": "MIT", @@ -7346,24 +5958,6 @@ "tslib": "^2.1.0" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "funding": [ @@ -7382,37 +5976,6 @@ ], "license": "MIT" }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "license": "MIT" @@ -7471,49 +6034,6 @@ "node": ">= 18" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "license": "ISC" @@ -7599,23 +6119,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, - "node_modules/sisteransi": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", + "node_modules/signal-exit": { + "version": "3.0.7", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "ISC" }, "node_modules/slice-ansi": { "version": "5.0.0", @@ -7665,45 +6179,29 @@ }, "node_modules/source-map": { "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/statuses": { "version": "2.0.2", "license": "MIT", @@ -7711,6 +6209,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true, + "license": "MIT" + }, "node_modules/stdin-discarder": { "version": "0.2.2", "dev": true, @@ -7722,18 +6227,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "dev": true, @@ -7750,20 +6243,24 @@ "node": ">=0.6.19" } }, - "node_modules/string-length": { - "version": "4.0.2", + "node_modules/string-width": { + "version": "4.2.3", "dev": true, "license": "MIT", "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/string-width": { + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -7775,150 +6272,273 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", + "node_modules/strip-ansi": { + "version": "6.0.1", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "js-tokens": "^9.0.1" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", + "node_modules/sync-content": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/sync-content/-/sync-content-2.0.1.tgz", + "integrity": "sha512-NI1mo514yFhr8pV/5Etvgh+pSBUIpoAKoiBIUwALVlQQNAwb40bTw8hhPFaip/dvv0GhpHVOq0vq8iY02ppLTg==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^11.0.0", + "mkdirp": "^3.0.1", + "path-scurry": "^2.0.0", + "rimraf": "^6.0.0", + "tshy": "^3.0.0" + }, + "bin": { + "sync-content": "dist/esm/bin.mjs" + }, "engines": { - "node": ">=6" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", + "node_modules/sync-content/node_modules/glob": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { - "node": ">=8" + "node": "20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/supports-color": { - "version": "7.2.0", + "node_modules/sync-content/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "has-flag": "^4.0.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", + "node_modules/sync-content/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, "engines": { - "node": ">= 0.4" + "node": "20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/test-exclude": { - "version": "6.0.0", + "node_modules/sync-content/node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, "license": "ISC", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=8" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.12", + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", "engines": { - "node": "*" + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz", + "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" } }, "node_modules/title-case": { @@ -7940,11 +6560,6 @@ "node": ">=0.6.0" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/to-regex-range": { "version": "5.0.1", "dev": true, @@ -7974,96 +6589,119 @@ "typescript": ">=4.8.4" } }, - "node_modules/ts-jest": { - "version": "29.4.0", + "node_modules/tshy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tshy/-/tshy-3.0.2.tgz", + "integrity": "sha512-8GkWnAfmNXxl8iDTZ1o2H4jdaj9H7HeDKkr5qd0ZhQBCNA41D3xqTyg2Ycs51VCfmjJ5e+0v9AUmD6ylAI9Bgw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "bs-logger": "^0.2.6", - "ejs": "^3.1.10", - "fast-json-stable-stringify": "^2.1.0", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.7.2", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" + "chalk": "^5.3.0", + "chokidar": "^3.6.0", + "foreground-child": "^3.1.1", + "minimatch": "^10.0.0", + "mkdirp": "^3.0.1", + "polite-json": "^5.0.0", + "resolve-import": "^2.0.0", + "rimraf": "^6.0.0", + "sync-content": "^2.0.1", + "typescript": "^5.5.3", + "walk-up-path": "^4.0.0" }, "bin": { - "ts-jest": "cli.js" + "tshy": "dist/esm/index.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0 || ^30.0.0", - "@jest/types": "^29.0.0 || ^30.0.0", - "babel-jest": "^29.0.0 || ^30.0.0", - "jest": "^29.0.0 || ^30.0.0", - "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <6" + "node": "20 || >=22" + } + }, + "node_modules/tshy/node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jest-util": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.41.0", + "node_modules/tshy/node_modules/glob": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { - "node": ">=16" + "node": "20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", + "node_modules/tshy/node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", + "node_modules/tshy/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "minimist": "^1.2.0" + "@isaacs/brace-expansion": "^5.0.0" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", + "node_modules/tshy/node_modules/rimraf": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, "engines": { - "node": ">=4" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/tslib": { @@ -8082,14 +6720,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.21.3", "dev": true, @@ -8113,86 +6743,40 @@ "node": ">= 0.6" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", + "node_modules/typescript": { + "version": "5.8.3", "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.17" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", + "node_modules/typescript-eslint": { + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.42.0.tgz", + "integrity": "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "@typescript-eslint/eslint-plugin": "8.42.0", + "@typescript-eslint/parser": "8.42.0", + "@typescript-eslint/typescript-estree": "8.42.0", + "@typescript-eslint/utils": "8.42.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "engines": { - "node": ">=14.17" + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/uglify-js": { @@ -8207,23 +6791,6 @@ "node": ">=0.8.0" } }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/unc-path-regex": { "version": "0.1.2", "dev": true, @@ -8301,19 +6868,6 @@ "dev": true, "license": "MIT" }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/v8flags": { "version": "4.0.1", "dev": true, @@ -8329,114 +6883,267 @@ "node": ">= 0.8" } }, - "node_modules/walker": { - "version": "1.0.8", + "node_modules/vite": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.4.tgz", + "integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "makeerror": "1.0.12" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.14" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/wcwidth": { - "version": "1.0.1", + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, "license": "MIT", "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/which": { - "version": "2.0.2", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { - "node-which": "bin/node-which" + "vite-node": "vite-node.mjs" }, "engines": { - "node": ">= 8" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/which-builtin-type": { - "version": "1.2.1", + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" }, "engines": { - "node": ">= 0.4" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } } }, - "node_modules/which-collection": { - "version": "1.0.2", + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==", + "dev": true, + "license": "ISC", + "engines": { + "node": "20 || >=22" } }, - "node_modules/which-typed-array": { - "version": "1.1.19", + "node_modules/wcwidth": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">= 0.4" + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" } }, "node_modules/word-wrap": { @@ -8452,8 +7159,11 @@ "dev": true, "license": "MIT" }, - "node_modules/wrap-ansi": { + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -8472,26 +7182,6 @@ "version": "1.0.2", "license": "ISC" }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "3.1.1", "dev": true, @@ -8508,31 +7198,6 @@ "node": ">= 14.6" } }, - "node_modules/yargs": { - "version": "17.7.2", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "dev": true, diff --git a/package.json b/package.json index a4bc837..d854c1a 100644 --- a/package.json +++ b/package.json @@ -2,24 +2,21 @@ "name": "@mapbox/mcp-devkit-server", "version": "0.3.2", "description": "Mapbox MCP devkit server", - "main": "dist/index.js", - "module": "dist/index-esm.js", - "typings": "dist/index.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js", "type": "module", "bin": { - "mapbox-mcp-devkit": "dist/index.js" + "mapbox-mcp-devkit": "dist/esm/index.js" }, "scripts": { - "lint": "eslint \"./src/**/*.{ts,tsx}\"", - "lint:fix": "eslint \"./src/**/*.{ts,tsx}\" --fix", + "lint": "eslint \"./src/**/*.{ts,tsx}\" \"./test/**/*.{ts,tsx}\"", + "lint:fix": "eslint \"./src/**/*.{ts,tsx}\" \"./test/**/*.{ts,tsx}\" --fix", "fix-lint": "npm run lint:fix && npm run format:fix", - "format": "prettier --check \"./src/**/*.{ts,tsx,js,json,md}\"", - "format:fix": "prettier --write \"./src/**/*.{ts,tsx,js,json,md}\"", + "format": "prettier --check \"./src/**/*.{ts,tsx,js,json,md}\" \"./test/**/*.{ts,tsx,js,json,md}\"", + "format:fix": "prettier --write \"./src/**/*.{ts,tsx,js,json,md}\" \"./test/**/*.{ts,tsx,js,json,md}\"", "prepare": "husky && node .husky/setup-hooks.js", - "test": "jest", - "build": "npm run prepare && npm run sync-manifest-version && npm run build:esm && npm run build:cjs && npm run generate-version && node scripts/build-helpers.cjs copy-json && node scripts/add-shebang.cjs", - "build:esm": "node scripts/build-helpers.cjs esm-package && tsc -p tsconfig.json", - "build:cjs": "node scripts/build-helpers.cjs cjs-package && tsc -p tsconfig.json", + "test": "vitest", + "build": "npm run prepare && npm run sync-manifest-version && tshy && npm run generate-version && node scripts/build-helpers.cjs copy-json && node scripts/add-shebang.cjs", "generate-version": "node scripts/build-helpers.cjs generate-version", "sync-manifest-version": "node scripts/build-helpers.cjs sync-manifest-version", "dev": "tsc -p tsconfig.json --watch" @@ -40,41 +37,57 @@ "files": [ "dist" ], - "exports": { - ".": { - "import": "./dist/index-esm.js", - "require": "./dist/index.js", - "types": "./dist/index.d.ts" - } - }, "keywords": [ "mcp" ], "dependencies": { - "@modelcontextprotocol/sdk": "^1.12.1", + "@modelcontextprotocol/sdk": "^1.17.5", "zod": "^3.25.42" }, "devDependencies": { "@eslint/js": "^9.27.0", "@types/geojson": "^7946.0.16", - "@types/jest": "^29.0.1", "@types/node": "^22.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", + "@vitest/coverage-istanbul": "^3.2.4", "eslint": "^9.0.0", - "eslint-config-prettier": "^10.1.5", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-unused-imports": "^4.0.0", + "globals": "^16.3.0", "husky": "^9.0.0", - "jest": "^29.1.0", "lint-staged": "^16.1.0", "plop": "^4.0.1", "prettier": "^3.0.0", - "ts-jest": "^29.3.4", - "typescript": "^5.8.3" + "tshy": "^3.0.2", + "typescript": "^5.8.3", + "typescript-eslint": "^8.42.0", + "vitest": "^3.2.4" }, "prettier": { "singleQuote": true, "trailingComma": "none" - } + }, + "tshy": { + "project": "./tsconfig.src.json", + "exports": { + ".": "./src/index.ts" + }, + "dialects": [ + "esm", + "commonjs" + ], + "selfLink": false + }, + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" + } + } + }, + "types": "./dist/commonjs/index.d.ts" } diff --git a/scripts/add-shebang.cjs b/scripts/add-shebang.cjs index 4f23b61..bd2d38f 100644 --- a/scripts/add-shebang.cjs +++ b/scripts/add-shebang.cjs @@ -1,20 +1,21 @@ const fs = require('fs'); const path = require('path'); -const distPath = path.join(__dirname, '..', 'dist', 'index.js'); +const filePathCJS = path.resolve(__dirname, '../dist/commonjs/index.js'); +const filePathESM = path.resolve(__dirname, '../dist/esm/index.js'); +addShebang(filePathCJS); +addShebang(filePathESM); -// Read the file -let content = fs.readFileSync(distPath, 'utf8'); +function addShebang(filePath) { + const shebang = '#!/usr/bin/env node\n'; -// Add shebang if not already present -if (!content.startsWith('#!/usr/bin/env node')) { - content = '#!/usr/bin/env node\n' + content; - fs.writeFileSync(distPath, content); - - // Make the file executable - fs.chmodSync(distPath, '755'); - - console.log('Added shebang to dist/index.js'); -} else { - console.log('Shebang already present in dist/index.js'); -} \ No newline at end of file + let content = fs.readFileSync(filePath, 'utf-8'); + + if (!content.startsWith(shebang)) { + content = shebang + content; + fs.writeFileSync(filePath, content); + console.log(`Shebang added to ${filePath}`); + } else { + console.log(`Shebang already exists in ${filePath}`); + } +} diff --git a/scripts/build-helpers.cjs b/scripts/build-helpers.cjs index 7603a68..4a9ed07 100644 --- a/scripts/build-helpers.cjs +++ b/scripts/build-helpers.cjs @@ -1,7 +1,7 @@ // Cross-platform build helper script -const fs = require('fs'); -const path = require('path'); -const { execSync } = require('child_process'); +const fs = require('node:fs'); +const path = require('node:path'); +const { execSync } = require('node:child_process'); // Create directory recursively (cross-platform equivalent of mkdir -p) function mkdirp(dirPath) { @@ -11,18 +11,6 @@ function mkdirp(dirPath) { } } -// Create ESM package.json -function createEsmPackage() { - mkdirp('dist/esm'); - fs.writeFileSync('dist/esm/package.json', JSON.stringify({ type: 'module' }, null, 2)); -} - -// Create CJS package.json -function createCjsPackage() { - mkdirp('dist/cjs'); - fs.writeFileSync('dist/cjs/package.json', JSON.stringify({ type: 'commonjs' }, null, 2)); -} - // Generate version info function generateVersion() { mkdirp('dist'); @@ -39,7 +27,10 @@ function generateVersion() { version }; - fs.writeFileSync('dist/version.json', JSON.stringify(versionInfo, null, 2)); + fs.writeFileSync('dist/esm/version.json', JSON.stringify(versionInfo, null, 2)); + fs.writeFileSync('dist/commonjs/version.json', JSON.stringify(versionInfo, null, 2)); + + console.log('Generated version.json:', versionInfo); } // Sync version from package.json to manifest.json @@ -56,8 +47,9 @@ function syncManifestVersion() { // Copy JSON files to dist function copyJsonFiles() { const srcDir = 'src'; - const destDir = 'dist'; - + const destDirCjs = 'dist/commonjs'; + const destDirEsm = 'dist/esm'; + function copyJsonRecursive(srcPath, destPath) { const items = fs.readdirSync(srcPath); @@ -73,20 +65,15 @@ function copyJsonFiles() { } }); } - - copyJsonRecursive(srcDir, destDir); + + copyJsonRecursive(srcDir, destDirCjs); + copyJsonRecursive(srcDir, destDirEsm); } // Process command line arguments const command = process.argv[2]; switch (command) { - case 'esm-package': - createEsmPackage(); - break; - case 'cjs-package': - createCjsPackage(); - break; case 'generate-version': generateVersion(); break; @@ -99,4 +86,4 @@ switch (command) { default: console.error('Unknown command:', command); process.exit(1); -} \ No newline at end of file +} diff --git a/src/index.test.ts b/src/index.test.ts deleted file mode 100644 index 583e28d..0000000 --- a/src/index.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { describe, it, expect } from '@jest/globals'; - -describe('MCP Server', () => { - it('should pass a basic test', () => { - expect(true).toBe(true); - }); -}); diff --git a/src/index.ts b/src/index.ts index 234f2c2..6e5e6c2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,12 +2,10 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { parseToolConfigFromArgs, filterTools } from './config/toolConfig.js'; import { getAllTools } from './tools/toolRegistry.js'; -import { patchGlobalFetch } from './utils/requestUtils.js'; import { getVersionInfo } from './utils/versionUtils.js'; // Get version info and patch fetch const versionInfo = getVersionInfo(); -patchGlobalFetch(versionInfo); // Parse configuration from command-line arguments const config = parseToolConfigFromArgs(); @@ -35,6 +33,13 @@ enabledTools.forEach((tool) => { tool.installTo(server); }); -// Start the server -const transport = new StdioServerTransport(); -await server.connect(transport); +async function main() { + // Start receiving messages on stdin and sending messages on stdout + const transport = new StdioServerTransport(); + await server.connect(transport); +} + +main().catch((error) => { + console.error('Fatal error starting MCP server:', error); + process.exit(1); +}); diff --git a/src/tools/BaseTool.ts b/src/tools/BaseTool.ts index ed48a83..5ecbf9d 100644 --- a/src/tools/BaseTool.ts +++ b/src/tools/BaseTool.ts @@ -1,7 +1,7 @@ import { McpServer, RegisteredTool -} from '@modelcontextprotocol/sdk/server/mcp'; +} from '@modelcontextprotocol/sdk/server/mcp.js'; import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js'; import { z, ZodTypeAny } from 'zod'; diff --git a/src/tools/bounding-box-tool/BoundariesData-cjs.cts b/src/tools/bounding-box-tool/BoundariesData-cjs.cts new file mode 100644 index 0000000..732bed9 --- /dev/null +++ b/src/tools/bounding-box-tool/BoundariesData-cjs.cts @@ -0,0 +1,3 @@ +import boundariesData from './boundaries_v4_country_bbox_min.json'; + +export default boundariesData; diff --git a/src/tools/bounding-box-tool/BoundariesData.ts b/src/tools/bounding-box-tool/BoundariesData.ts new file mode 100644 index 0000000..1a5ba6a --- /dev/null +++ b/src/tools/bounding-box-tool/BoundariesData.ts @@ -0,0 +1,5 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import boundariesData from './boundaries_v4_country_bbox_min.json' with { type: 'json' }; + +export default boundariesData; diff --git a/src/tools/bounding-box-tool/CountryBoundingBoxTool.ts b/src/tools/bounding-box-tool/CountryBoundingBoxTool.ts index ae24f7d..2765e14 100644 --- a/src/tools/bounding-box-tool/CountryBoundingBoxTool.ts +++ b/src/tools/bounding-box-tool/CountryBoundingBoxTool.ts @@ -3,7 +3,7 @@ import { CountryBoundingBoxSchema, CountryBoundingBoxInput } from './CountryBoundingBoxTool.schema.js'; -import boundariesData from './boundaries_v4_country_bbox_min.json' with { type: 'json' }; +import boundariesData from './BoundariesData.js'; export class CountryBoundingBoxTool extends BaseTool< typeof CountryBoundingBoxSchema diff --git a/src/tools/create-style-tool/CreateStyleTool.ts b/src/tools/create-style-tool/CreateStyleTool.ts index 8c4e113..697780e 100644 --- a/src/tools/create-style-tool/CreateStyleTool.ts +++ b/src/tools/create-style-tool/CreateStyleTool.ts @@ -1,3 +1,4 @@ +import { fetchClient } from 'src/utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { CreateStyleSchema, @@ -10,7 +11,7 @@ export class CreateStyleTool extends MapboxApiBasedTool< name = 'create_style_tool'; description = 'Create a new Mapbox style'; - constructor() { + constructor(private fetchImpl: typeof fetch = fetchClient) { super({ inputSchema: CreateStyleSchema }); } @@ -26,7 +27,7 @@ export class CreateStyleTool extends MapboxApiBasedTool< ...input.style }; - const response = await fetch(url, { + const response = await this.fetchImpl(url, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/src/tools/create-token-tool/CreateTokenTool.ts b/src/tools/create-token-tool/CreateTokenTool.ts index debe9e4..479349d 100644 --- a/src/tools/create-token-tool/CreateTokenTool.ts +++ b/src/tools/create-token-tool/CreateTokenTool.ts @@ -1,3 +1,4 @@ +import { fetchClient } from 'src/utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { CreateTokenSchema, @@ -11,7 +12,7 @@ export class CreateTokenTool extends MapboxApiBasedTool< readonly description = 'Create a new Mapbox public access token with specified scopes and optional URL restrictions.'; - constructor() { + constructor(private fetchImpl: typeof fetch = fetchClient) { super({ inputSchema: CreateTokenSchema }); } @@ -50,7 +51,7 @@ export class CreateTokenTool extends MapboxApiBasedTool< } try { - const response = await fetch(url, { + const response = await this.fetchImpl(url, { method: 'POST', headers: { 'Content-Type': 'application/json' diff --git a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts index 3474146..0d9e402 100644 --- a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts +++ b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts @@ -1,3 +1,4 @@ +import { fetchClient } from 'src/utils/fetchRequest.js'; import { BaseTool } from '../BaseTool.js'; import { GetMapboxDocSourceSchema, @@ -11,15 +12,16 @@ export class GetMapboxDocSourceTool extends BaseTool< description = 'Get the latest official Mapbox documentation, APIs, SDKs, and developer resources directly from Mapbox. Always up-to-date, comprehensive coverage of all current Mapbox services including mapping, navigation, search, geocoding, and mobile SDKs. Use this for accurate, official Mapbox information instead of web search.'; - constructor() { + constructor(private fetchImpl: typeof fetch = fetchClient) { super({ inputSchema: GetMapboxDocSourceSchema }); } protected async execute( + // eslint-disable-next-line @typescript-eslint/no-unused-vars _input: GetMapboxDocSourceInput ): Promise<{ type: 'text'; text: string }> { try { - const response = await fetch('https://docs.mapbox.com/llms.txt'); + const response = await this.fetchImpl('https://docs.mapbox.com/llms.txt'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); diff --git a/src/tools/list-styles-tool/ListStylesTool.ts b/src/tools/list-styles-tool/ListStylesTool.ts index faca9a4..4ad58cd 100644 --- a/src/tools/list-styles-tool/ListStylesTool.ts +++ b/src/tools/list-styles-tool/ListStylesTool.ts @@ -1,3 +1,4 @@ +import { fetchClient } from 'src/utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { ListStylesSchema, ListStylesInput } from './ListStylesTool.schema.js'; @@ -8,7 +9,7 @@ export class ListStylesTool extends MapboxApiBasedTool< description = 'List styles for a Mapbox account. Use limit parameter to avoid large responses (recommended: limit=5-10). Use start parameter for pagination.'; - constructor() { + constructor(private fetchImpl: typeof fetch = fetchClient) { super({ inputSchema: ListStylesSchema }); } @@ -35,7 +36,7 @@ export class ListStylesTool extends MapboxApiBasedTool< const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}?${params.toString()}`; - const response = await fetch(url); + const response = await this.fetchImpl(url); if (!response.ok) { throw new Error( diff --git a/src/tools/list-tokens-tool/ListTokensTool.ts b/src/tools/list-tokens-tool/ListTokensTool.ts index 03dd8d2..41c4fac 100644 --- a/src/tools/list-tokens-tool/ListTokensTool.ts +++ b/src/tools/list-tokens-tool/ListTokensTool.ts @@ -1,3 +1,4 @@ +import { fetchClient } from 'src/utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { ListTokensSchema, ListTokensInput } from './ListTokensTool.schema.js'; @@ -8,7 +9,7 @@ export class ListTokensTool extends MapboxApiBasedTool< readonly description = 'List Mapbox access tokens for the authenticated user with optional filtering and pagination. When using pagination, the "start" parameter must be obtained from the "next_start" field of the previous response (it is not a token ID)'; - constructor() { + constructor(private fetchImpl: typeof fetch = fetchClient) { super({ inputSchema: ListTokensSchema }); } @@ -64,7 +65,7 @@ export class ListTokensTool extends MapboxApiBasedTool< this.log('info', `ListTokensTool: Fetching page ${pageCount}`); this.log('debug', `ListTokensTool: Fetching URL: ${url}`); - const response = await fetch(url, { + const response = await this.fetchImpl(url, { method: 'GET', headers: { 'Content-Type': 'application/json' diff --git a/src/utils/fetchRequest.ts b/src/utils/fetchRequest.ts new file mode 100644 index 0000000..6169c2e --- /dev/null +++ b/src/utils/fetchRequest.ts @@ -0,0 +1,125 @@ +import { getVersionInfo } from './versionUtils.js'; + +export interface FetchPolicy { + handle( + input: string | URL | Request, + init: RequestInit, + next: typeof fetch + ): Promise; +} + +export class PolicyPipeline { + private policies: FetchPolicy[] = []; + private fetchImpl: typeof fetch; + + constructor(fetchImpl?: typeof fetch) { + this.fetchImpl = fetchImpl ?? fetch; + } + + use(policy: FetchPolicy) { + this.policies.push(policy); + } + + async fetch( + input: string | URL | Request, + init: RequestInit = {} + ): Promise { + const dispatch = async ( + i: number, + req: string | URL | Request, + options: RequestInit + ): Promise => { + if (i < this.policies.length) { + return this.policies[i].handle(req, options, (nextReq, nextOptions) => + dispatch(i + 1, nextReq, nextOptions!) + ); + } + return this.fetchImpl(req, options); // Use injected fetch + }; + return dispatch(0, input, init); + } +} + +export class UserAgentPolicy implements FetchPolicy { + constructor(private userAgent: string) {} + async handle( + input: string | URL | Request, + init: RequestInit, + next: typeof fetch + ): Promise { + let headers: Headers | Record; + + if (init.headers instanceof Headers) { + headers = init.headers; + if (!headers.has('User-Agent')) { + headers.set('User-Agent', this.userAgent); + } + } else { + const h = (init.headers ?? {}) as Record; + if (!('User-Agent' in h)) { + h['User-Agent'] = this.userAgent; + } + headers = h; + } + + return next(input, { ...init, headers }); + } + + static fromVersionInfo(versionInfo: { + name: string; + version: string; + sha: string; + tag: string; + branch: string; + }): UserAgentPolicy { + const userAgent = `${versionInfo.name}/${versionInfo.version} (${versionInfo.branch}, ${versionInfo.tag}, ${versionInfo.sha})`; + return new UserAgentPolicy(userAgent); + } +} + +export class RetryPolicy implements FetchPolicy { + constructor( + private maxRetries: number = 3, + private baseDelayMs: number = 200, + private maxDelayMs: number = 2000 + ) {} + + async handle( + input: string | URL | Request, + init: RequestInit, + next: typeof fetch + ): Promise { + let attempt = 0; + let lastError: Response | undefined; + + while (attempt <= this.maxRetries) { + const response = await next(input, init); + + if (response.ok || (response.status < 500 && response.status !== 429)) { + return response; + } + + // Calculate exponential backoff with jitter + const expBackoff = Math.min( + this.baseDelayMs * 2 ** attempt, + this.maxDelayMs + ); + const jitter = Math.random() * expBackoff * 0.5; + const delay = expBackoff + jitter; + + await new Promise((resolve) => setTimeout(resolve, delay)); + attempt++; + lastError = response; + } + + // If all retries failed, return last response + return lastError!; + } +} + +const pipeline = new PolicyPipeline(); +const versionInfo = getVersionInfo(); +pipeline.use(UserAgentPolicy.fromVersionInfo(versionInfo)); +pipeline.use(new RetryPolicy(3, 200, 2000)); + +export const fetchClient = pipeline.fetch.bind(pipeline); diff --git a/src/utils/requestUtils.test-helpers.ts b/src/utils/requestUtils.test-helpers.ts deleted file mode 100644 index 355b36f..0000000 --- a/src/utils/requestUtils.test-helpers.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { patchGlobalFetch, cleanup } from './requestUtils.js'; - -let defaultHeaders: Record = {}; - -export function setupFetch(overrides?: any) { - // Clean up any previous patch state, but don't restore original fetch yet - cleanup(); - - // Set up mock fetch AFTER cleanup - const mockFetch = (global.fetch = jest.fn()); - - // Now patch with the mock in place - defaultHeaders = patchGlobalFetch({ - name: 'TestServer', - version: '1.0.0', - sha: 'abcdef', - tag: 'no-tag', - branch: 'default' - }); - mockFetch.mockResolvedValue({ - ok: true, - status: 200, - statusText: 'OK', - json: async () => ({ success: true }), - arrayBuffer: async () => new ArrayBuffer(0), - ...overrides - }); - return mockFetch; -} - -export function assertHeadersSent(mockFetch: jest.Mock) { - expect(mockFetch).toHaveBeenCalledTimes(1); - const callArgs = mockFetch.mock.calls[0]; - const requestInit = callArgs[1]; - expect(requestInit?.headers).toMatchObject(defaultHeaders); -} diff --git a/src/utils/requestUtils.test.ts b/src/utils/requestUtils.test.ts deleted file mode 100644 index 4ba8f1e..0000000 --- a/src/utils/requestUtils.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { patchGlobalFetch, cleanup } from './requestUtils.js'; - -describe('requestUtils', () => { - let originalGlobalFetch: typeof global.fetch; - - beforeEach(() => { - // Save original fetch - originalGlobalFetch = global.fetch; - }); - - afterEach(() => { - // Restore original fetch - global.fetch = originalGlobalFetch; - cleanup(); - }); - - describe('patchGlobalFetch', () => { - it('should handle case when global.fetch is undefined at module load time', () => { - // Simulate scenario where global.fetch doesn't exist initially - delete (global as any).fetch; - delete (globalThis as any).fetch; - - // This should throw because no fetch is available - expect(() => { - patchGlobalFetch({ - name: 'TestServer', - version: '1.0.0', - sha: 'abcdef', - tag: 'no-tag', - branch: 'default' - }); - }).toThrow('No fetch implementation available'); - }); - - it('should properly initialize originalFetch before patching', async () => { - // Mock fetch function - const mockFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - json: async () => ({ success: true }) - }); - - global.fetch = mockFetch; - - // Patch global fetch - patchGlobalFetch({ - name: 'TestServer', - version: '1.0.0', - sha: 'abcdef', - tag: 'no-tag', - branch: 'default' - }); - - // Make a fetch call - await global.fetch('https://example.com', { - headers: { 'Custom-Header': 'test' } - }); - - // Verify that the original fetch was called with User-Agent added - expect(mockFetch).toHaveBeenCalledWith('https://example.com', { - headers: { - 'Custom-Header': 'test', - 'User-Agent': 'TestServer/1.0.0 (default, no-tag, abcdef)' - } - }); - }); - - it('should not throw originalFetch is not a function error', async () => { - // Mock a scenario where fetch might be called before proper initialization - const mockFetch = jest.fn().mockResolvedValue({ - ok: true, - status: 200, - json: async () => ({ success: true }) - }); - - global.fetch = mockFetch; - - patchGlobalFetch({ - name: 'TestServer', - version: '1.0.0', - sha: 'abcdef', - tag: 'no-tag', - branch: 'default' - }); - - // This should not throw "originalFetch is not a function" - await expect(global.fetch('https://example.com')).resolves.toBeDefined(); - }); - - it('should handle multiple patch calls without breaking', () => { - const mockFetch = jest.fn(); - global.fetch = mockFetch; - - // First patch - patchGlobalFetch({ - name: 'TestServer', - version: '1.0.0', - sha: 'abcdef', - tag: 'no-tag', - branch: 'default' - }); - - // Second patch (should not break) - patchGlobalFetch({ - name: 'TestServer2', - version: '2.0.0', - sha: 'abcdef2', - tag: 'v2', - branch: 'main' - }); - - // Should still work - expect(typeof global.fetch).toBe('function'); - }); - - it('should restore original fetch on cleanup', () => { - const mockFetch = jest.fn(); - global.fetch = mockFetch; - - patchGlobalFetch({ - name: 'TestServer', - version: '1.0.0', - sha: 'abcdef', - tag: 'no-tag', - branch: 'default' - }); - - // Verify fetch was patched - expect(global.fetch).not.toBe(mockFetch); - - // Cleanup should restore original - cleanup(); - expect(global.fetch).toBe(mockFetch); - }); - }); -}); diff --git a/src/utils/requestUtils.ts b/src/utils/requestUtils.ts deleted file mode 100644 index f4e9899..0000000 --- a/src/utils/requestUtils.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { VersionInfo } from './versionUtils.js'; - -let isPatched = false; -let originalFetch: ( - input: string | URL | Request, - init?: RequestInit -) => Promise; - -export function patchGlobalFetch(versionInfo: VersionInfo): { - 'User-Agent': string; -} { - // Initialize originalFetch if not already done - if (!originalFetch) { - if (typeof global !== 'undefined' && typeof global.fetch === 'function') { - originalFetch = global.fetch; - } else if ( - typeof globalThis !== 'undefined' && - typeof globalThis.fetch === 'function' - ) { - originalFetch = globalThis.fetch; - } else if (typeof fetch === 'function') { - originalFetch = fetch; - } else { - throw new Error('No fetch implementation available'); - } - } - - // In test environments, update originalFetch to current global.fetch if it was mocked - if ( - typeof global !== 'undefined' && - typeof global.fetch === 'function' && - typeof (global.fetch as any).mockResolvedValue === 'function' - ) { - originalFetch = global.fetch; - } - - const headers = { - 'User-Agent': `${versionInfo.name}/${versionInfo.version} (${versionInfo.branch}, ${versionInfo.tag}, ${versionInfo.sha})` - }; - if (!isPatched) { - const patchedFetch = async function ( - input: string | URL | Request, - init?: RequestInit - ): Promise { - const modifiedInit: RequestInit = { - ...init, - headers: { - ...(init?.headers || {}), - ...headers - } - }; - return originalFetch(input, modifiedInit); - }; - - // Patch fetch in the same way we detected it during initialization - if (typeof global !== 'undefined' && typeof global.fetch === 'function') { - global.fetch = patchedFetch; - } else if ( - typeof globalThis !== 'undefined' && - typeof globalThis.fetch === 'function' - ) { - (globalThis as any).fetch = patchedFetch; - } - isPatched = true; - } - - return headers; -} - -export function cleanup() { - if (isPatched) { - global.fetch = originalFetch; - isPatched = false; - } -} diff --git a/src/utils/versionUtils-cjs.cts b/src/utils/versionUtils-cjs.cts new file mode 100644 index 0000000..ed6f7ce --- /dev/null +++ b/src/utils/versionUtils-cjs.cts @@ -0,0 +1,29 @@ +import { readFileSync } from 'fs'; +import path from 'path'; + +export interface VersionInfo { + name: string; + version: string; + sha: string; + tag: string; + branch: string; +} + +export function getVersionInfo(): VersionInfo { + const name = 'Mapbox Developer MCP server'; + try { + const filePath = path.resolve(__dirname, '..', 'version.json'); + const data = readFileSync(filePath, 'utf-8'); + const info = JSON.parse(data) as VersionInfo; + info.name = name; + return info; + } catch { + return { + name: name, + version: '0.0.0', + sha: 'unknown', + tag: 'unknown', + branch: 'unknown' + }; + } +} diff --git a/src/utils/versionUtils.ts b/src/utils/versionUtils.ts index 00b67fe..d4f06f8 100644 --- a/src/utils/versionUtils.ts +++ b/src/utils/versionUtils.ts @@ -13,15 +13,15 @@ export interface VersionInfo { export function getVersionInfo(): VersionInfo { const name = 'Mapbox Developer MCP server'; try { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore const dirname = path.dirname(fileURLToPath(import.meta.url)); const filePath = path.resolve(dirname, '..', 'version.json'); const data = readFileSync(filePath, 'utf-8'); - let info = JSON.parse(data) as VersionInfo; - info['name'] = name; + const info = JSON.parse(data) as VersionInfo; + info.name = name; return info; - } catch (error) { - // eslint-disable-next-line no-console - console.warn(`Failed to read version info: ${error}`); + } catch { return { name: name, version: '0.0.0', diff --git a/src/config/toolConfig.test.ts b/test/config/toolConfig.test.ts similarity index 96% rename from src/config/toolConfig.test.ts rename to test/config/toolConfig.test.ts index 8ff7aa4..74c34e9 100644 --- a/src/config/toolConfig.test.ts +++ b/test/config/toolConfig.test.ts @@ -1,20 +1,13 @@ -import { - describe, - it, - expect, - beforeEach, - afterAll, - jest -} from '@jest/globals'; +import { describe, it, expect, vi, beforeEach, afterAll } from 'vitest'; import { parseToolConfigFromArgs, filterTools, ToolConfig -} from './toolConfig.js'; +} from '../../src/config/toolConfig.js'; -// Mock getVersionInfo to avoid import.meta.url issues in Jest -jest.mock('../utils/versionUtils.js', () => ({ - getVersionInfo: jest.fn(() => ({ +// Mock getVersionInfo to avoid import.meta.url issues in vitest +vi.mock('../../src/utils/versionUtils.js', () => ({ + getVersionInfo: vi.fn(() => ({ name: 'Mapbox MCP devkit server', version: '1.0.0', sha: 'mock-sha', diff --git a/src/tools/MapboxApiBasedTool.test.ts b/test/tools/MapboxApiBasedTool.test.ts similarity index 51% rename from src/tools/MapboxApiBasedTool.test.ts rename to test/tools/MapboxApiBasedTool.test.ts index 9f0cb41..e037d00 100644 --- a/src/tools/MapboxApiBasedTool.test.ts +++ b/test/tools/MapboxApiBasedTool.test.ts @@ -4,8 +4,9 @@ const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( ); process.env.MAPBOX_ACCESS_TOKEN = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { z } from 'zod'; -import { MapboxApiBasedTool } from './MapboxApiBasedTool'; +import { MapboxApiBasedTool } from '../../src/tools/MapboxApiBasedTool.js'; // Create a minimal implementation of MapboxApiBasedTool for testing class TestTool extends MapboxApiBasedTool { @@ -32,15 +33,21 @@ describe('MapboxApiBasedTool', () => { const originalEnv = process.env; beforeEach(() => { + vi.stubEnv( + 'MAPBOX_ACCESS_TOKEN', + `eyJhbGciOiJIUzI1NiJ9.${payload}.signature` + ); + testTool = new TestTool(); // Mock the log method to test that errors are properly logged - testTool['log'] = jest.fn(); + testTool['log'] = vi.fn(); }); afterEach(() => { // Restore the process.env to its original state process.env = { ...originalEnv }; - jest.clearAllMocks(); + vi.clearAllMocks(); + vi.unstubAllEnvs(); }); describe('getUserNameFromToken', () => { @@ -48,140 +55,88 @@ describe('MapboxApiBasedTool', () => { const testPayload = Buffer.from( JSON.stringify({ u: 'myusername' }) ).toString('base64'); - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: `eyJhbGciOiJIUzI1NiJ9.${testPayload}.signature`, - writable: true, - configurable: true - }); - - const username = MapboxApiBasedTool.getUserNameFromToken(); - expect(username).toBe('myusername'); - } finally { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - } + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue(`eyJhbGciOiJIUzI1NiJ9.${testPayload}.signature`); + + const username = MapboxApiBasedTool.getUserNameFromToken(); + expect(username).toBe('myusername'); + + spy.mockRestore(); }); it('throws error when token is not set', () => { - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: undefined, - writable: true, - configurable: true - }); - - expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( - 'No access token provided. Please set MAPBOX_ACCESS_TOKEN environment variable or pass it as an argument.' - ); - } finally { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - } + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue(undefined); + + expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( + 'No access token provided. Please set MAPBOX_ACCESS_TOKEN environment variable or pass it as an argument.' + ); + + spy.mockRestore(); }); it('throws error when token has invalid format', () => { - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: 'invalid-token-format', - writable: true, - configurable: true - }); - - expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( - 'MAPBOX_ACCESS_TOKEN is not in valid JWT format' - ); - } finally { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - } + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue('invalid-token-format'); + + expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( + 'MAPBOX_ACCESS_TOKEN is not in valid JWT format' + ); + + spy.mockRestore(); }); it('throws error when payload does not contain username', () => { const invalidPayload = Buffer.from( JSON.stringify({ sub: 'test' }) ).toString('base64'); - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: `eyJhbGciOiJIUzI1NiJ9.${invalidPayload}.signature`, - writable: true, - configurable: true - }); - - expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( - 'MAPBOX_ACCESS_TOKEN does not contain username in payload' - ); - } finally { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - } + + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue(`eyJhbGciOiJIUzI1NiJ9.${invalidPayload}.signature`); + + expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( + 'MAPBOX_ACCESS_TOKEN does not contain username in payload' + ); + + spy.mockRestore(); }); }); describe('JWT token validation', () => { it('throws an error when the token is not in a valid JWT format', async () => { - // Test the private isValidJwtFormat method directly - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - // Temporarily modify the static property for testing - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: 'invalid-token-format', - writable: true, - configurable: true - }); - - // Create a new instance with the modified token - const toolWithInvalidToken = new TestTool(); - // Mock the log method separately for this instance - toolWithInvalidToken['log'] = jest.fn(); - - // Try to call the run method, it should throw an error due to invalid JWT format - const result = await toolWithInvalidToken.run({ testParam: 'test' }); - - // Verify the error response - expect(result.isError).toBe(true); - - // Check for error message content - if (process.env.VERBOSE_ERRORS === 'true') { - expect( - (result.content[0] as { type: 'text'; text: string }).text - ).toContain('not in valid JWT format'); - } - - // Verify the error was logged - expect(toolWithInvalidToken['log']).toHaveBeenCalledWith( - 'error', - expect.stringMatching(/.*not in valid JWT format.*/) - ); - } finally { - // Restore the original value - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue('invalid-token-format'); + + // Create a new instance with the modified token + const toolWithInvalidToken = new TestTool(); + // Mock the log method separately for this instance + toolWithInvalidToken['log'] = vi.fn(); + + // Try to call the run method, it should throw an error due to invalid JWT format + const result = await toolWithInvalidToken.run({ testParam: 'test' }); + + // Verify the error response + expect(result.isError).toBe(true); + + // Check for error message content + if (process.env.VERBOSE_ERRORS === 'true') { + expect( + (result.content[0] as { type: 'text'; text: string }).text + ).toContain('not in valid JWT format'); } + + // Verify the error was logged + expect(toolWithInvalidToken['log']).toHaveBeenCalledWith( + 'error', + expect.stringMatching(/.*not in valid JWT format.*/) + ); + + spy.mockRestore(); }); it('accepts a token with valid JWT format', async () => { @@ -192,7 +147,7 @@ describe('MapboxApiBasedTool', () => { process.env.MAPBOX_ACCESS_TOKEN = `eyJhbGciOiJIUzI1NiJ9.${validPayload}.signature`; // Override execute to return a success result instead of throwing an error - testTool['execute'] = jest.fn().mockResolvedValue({ success: true }); + testTool['execute'] = vi.fn().mockResolvedValue({ success: true }); const result = await testTool.run({ testParam: 'test' }); @@ -206,55 +161,31 @@ describe('MapboxApiBasedTool', () => { }); describe('username extraction from token', () => { - it('extracts username from valid token', () => { - const username = MapboxApiBasedTool.getUserNameFromToken(); - expect(username).toBe('testuser'); - }); - it('throws error for invalid JWT format', () => { - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: 'invalid-token', - writable: true, - configurable: true - }); - - expect(() => { - MapboxApiBasedTool.getUserNameFromToken(); - }).toThrow('MAPBOX_ACCESS_TOKEN is not in valid JWT format'); - } finally { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - } + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue('invalid-token'); + + expect(() => { + MapboxApiBasedTool.getUserNameFromToken(); + }).toThrow('MAPBOX_ACCESS_TOKEN is not in valid JWT format'); + + spy.mockRestore(); }); it('throws error when username field is missing', () => { const tokenWithoutUsername = 'eyJhbGciOiJIUzI1NiJ9.eyJhIjoidGVzdC1hcGkifQ.signature'; - const originalToken = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; - - try { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: tokenWithoutUsername, - writable: true, - configurable: true - }); - - expect(() => { - MapboxApiBasedTool.getUserNameFromToken(); - }).toThrow('MAPBOX_ACCESS_TOKEN does not contain username in payload'); - } finally { - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - } + + const spy = vi + .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .mockReturnValue(tokenWithoutUsername); + + expect(() => { + MapboxApiBasedTool.getUserNameFromToken(); + }).toThrow('MAPBOX_ACCESS_TOKEN does not contain username in payload'); + + spy.mockRestore(); }); }); @@ -324,7 +255,7 @@ describe('MapboxApiBasedTool', () => { it('handles non-Error objects thrown', async () => { // Override the execute method to throw a string instead of an Error - testTool['execute'] = jest.fn().mockImplementation(() => { + testTool['execute'] = vi.fn().mockImplementation(() => { throw 'String error message'; }); diff --git a/test/tools/__snapshots__/tool-naming-convention.test.ts.snap b/test/tools/__snapshots__/tool-naming-convention.test.ts.snap new file mode 100644 index 0000000..1de3a70 --- /dev/null +++ b/test/tools/__snapshots__/tool-naming-convention.test.ts.snap @@ -0,0 +1,86 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Tool Naming Convention > should maintain consistent tool list (snapshot test) 1`] = ` +[ + { + "className": "BoundingBoxTool", + "description": "Calculates bounding box of given GeoJSON content, returns as [minX, minY, maxX, maxY]", + "toolName": "bounding_box_tool", + }, + { + "className": "CoordinateConversionTool", + "description": "Converts coordinates between WGS84 (longitude/latitude) and EPSG:3857 (Web Mercator) coordinate systems", + "toolName": "coordinate_conversion_tool", + }, + { + "className": "CountryBoundingBoxTool", + "description": "Gets bounding box for a country by its ISO 3166-1 country code, returns as [minX, minY, maxX, maxY].", + "toolName": "country_bounding_box_tool", + }, + { + "className": "CreateStyleTool", + "description": "Create a new Mapbox style", + "toolName": "create_style_tool", + }, + { + "className": "CreateTokenTool", + "description": "Create a new Mapbox public access token with specified scopes and optional URL restrictions.", + "toolName": "create_token_tool", + }, + { + "className": "DeleteStyleTool", + "description": "Delete a Mapbox style by ID", + "toolName": "delete_style_tool", + }, + { + "className": "GeojsonPreviewTool", + "description": "Generate a geojson.io URL to visualize GeoJSON data. Returns only the URL link.", + "toolName": "geojson_preview_tool", + }, + { + "className": "GetMapboxDocSourceTool", + "description": "Get the latest official Mapbox documentation, APIs, SDKs, and developer resources directly from Mapbox. Always up-to-date, comprehensive coverage of all current Mapbox services including mapping, navigation, search, geocoding, and mobile SDKs. Use this for accurate, official Mapbox information instead of web search.", + "toolName": "get_latest_mapbox_docs_tool", + }, + { + "className": "ListStylesTool", + "description": "List styles for a Mapbox account. Use limit parameter to avoid large responses (recommended: limit=5-10). Use start parameter for pagination.", + "toolName": "list_styles_tool", + }, + { + "className": "ListTokensTool", + "description": "List Mapbox access tokens for the authenticated user with optional filtering and pagination. When using pagination, the "start" parameter must be obtained from the "next_start" field of the previous response (it is not a token ID)", + "toolName": "list_tokens_tool", + }, + { + "className": "PreviewStyleTool", + "description": "Generate preview URL for a Mapbox style using an existing public token", + "toolName": "preview_style_tool", + }, + { + "className": "RetrieveStyleTool", + "description": "Retrieve a specific Mapbox style by ID", + "toolName": "retrieve_style_tool", + }, + { + "className": "StyleComparisonTool", + "description": "Generate a comparison URL for comparing two Mapbox styles side-by-side", + "toolName": "style_comparison_tool", + }, + { + "className": "StyleHelperTool", + "description": "Interactive helper for creating custom Mapbox styles with specific features and colors", + "toolName": "style_helper_tool", + }, + { + "className": "TilequeryTool", + "description": "Query vector and raster data from Mapbox tilesets at geographic coordinates", + "toolName": "tilequery_tool", + }, + { + "className": "UpdateStyleTool", + "description": "Update an existing Mapbox style", + "toolName": "update_style_tool", + }, +] +`; diff --git a/src/tools/bounding-box-tool/BoundingBoxTool.test.ts b/test/tools/bounding-box-tool/BoundingBoxTool.test.ts similarity index 95% rename from src/tools/bounding-box-tool/BoundingBoxTool.test.ts rename to test/tools/bounding-box-tool/BoundingBoxTool.test.ts index ddd5282..85f130a 100644 --- a/src/tools/bounding-box-tool/BoundingBoxTool.test.ts +++ b/test/tools/bounding-box-tool/BoundingBoxTool.test.ts @@ -1,6 +1,5 @@ -// Set environment variables before any imports - -import { BoundingBoxTool } from './BoundingBoxTool.js'; +import { describe, it, expect, beforeEach } from 'vitest'; +import { BoundingBoxTool } from '../../../src/tools/bounding-box-tool/BoundingBoxTool.js'; type TextContent = { type: 'text'; text: string }; @@ -267,8 +266,10 @@ describe('BoundingBoxTool', () => { ); }); - it('should have correct input schema', () => { - const { BoundingBoxSchema } = require('./BoundingBoxTool.schema.js'); + it('should have correct input schema', async () => { + const { BoundingBoxSchema } = await import( + '../../../src/tools/bounding-box-tool/BoundingBoxTool.schema.js' + ); expect(BoundingBoxSchema).toBeDefined(); expect(BoundingBoxSchema.shape.geojson).toBeDefined(); }); diff --git a/src/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts b/test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts similarity index 94% rename from src/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts rename to test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts index c9b6d13..8d8d197 100644 --- a/src/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts +++ b/test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts @@ -1,6 +1,5 @@ -// Set environment variables before any imports - -import { CountryBoundingBoxTool } from './CountryBoundingBoxTool.js'; +import { describe, it, expect, beforeEach } from 'vitest'; +import { CountryBoundingBoxTool } from '../../../src/tools/bounding-box-tool/CountryBoundingBoxTool.js'; type TextContent = { type: 'text'; text: string }; @@ -137,10 +136,10 @@ describe('CountryBoundingBoxTool', () => { ); }); - it('should have correct input schema', () => { - const { - CountryBoundingBoxSchema - } = require('./CountryBoundingBoxTool.schema.js'); + it('should have correct input schema', async () => { + const { CountryBoundingBoxSchema } = await import( + '../../../src/tools/bounding-box-tool/CountryBoundingBoxTool.schema.js' + ); expect(CountryBoundingBoxSchema).toBeDefined(); }); }); diff --git a/src/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts b/test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts similarity index 94% rename from src/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts rename to test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts index b07ac8c..8e64cfb 100644 --- a/src/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts +++ b/test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts @@ -1,4 +1,5 @@ -import { CoordinateConversionTool } from './CoordinateConversionTool.js'; +import { describe, it, expect, beforeEach } from 'vitest'; +import { CoordinateConversionTool } from '../../../src/tools/coordinate-conversion-tool/CoordinateConversionTool.js'; describe('CoordinateConversionTool', () => { let tool: CoordinateConversionTool; @@ -15,10 +16,10 @@ describe('CoordinateConversionTool', () => { ); }); - it('should have correct input schema', () => { - const { - CoordinateConversionSchema - } = require('./CoordinateConversionTool.schema.ts'); + it('should have correct input schema', async () => { + const { CoordinateConversionSchema } = await import( + '../../../src/tools/coordinate-conversion-tool/CoordinateConversionTool.schema.js' + ); expect(CoordinateConversionSchema).toBeDefined(); }); }); @@ -242,7 +243,7 @@ describe('CoordinateConversionTool', () => { it('should require valid coordinate system names', async () => { const input = { coordinates: [0, 0], - from: 'invalid' as any, + from: 'invalid' as unknown as 'wgs84' | 'epsg3857', to: 'epsg3857' as const }; diff --git a/src/tools/create-style-tool/CreateStyleTool.test.ts b/test/tools/create-style-tool/CreateStyleTool.test.ts similarity index 67% rename from src/tools/create-style-tool/CreateStyleTool.test.ts rename to test/tools/create-style-tool/CreateStyleTool.test.ts index 4f2f0ad..a1b5e81 100644 --- a/src/tools/create-style-tool/CreateStyleTool.test.ts +++ b/test/tools/create-style-tool/CreateStyleTool.test.ts @@ -1,16 +1,16 @@ -// Use a token with valid JWT format for tests process.env.MAPBOX_ACCESS_TOKEN = 'eyJhbGciOiJIUzI1NiJ9.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import { setupFetch, assertHeadersSent -} from '../../utils/requestUtils.test-helpers.js'; -import { CreateStyleTool } from './CreateStyleTool.js'; +} from '../../utils/fetchRequestUtils.js'; +import { CreateStyleTool } from '../../../src/tools/create-style-tool/CreateStyleTool.js'; describe('CreateStyleTool', () => { afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('tool metadata', () => { @@ -20,19 +20,21 @@ describe('CreateStyleTool', () => { expect(tool.description).toBe('Create a new Mapbox style'); }); - it('should have correct input schema', () => { - const { CreateStyleSchema } = require('./CreateStyleTool.schema.ts'); + it('should have correct input schema', async () => { + const { CreateStyleSchema } = await import( + '../../../src/tools/create-style-tool/CreateStyleTool.schema.js' + ); expect(CreateStyleSchema).toBeDefined(); }); }); it('sends custom header', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => ({ id: 'new-style-id', name: 'Test Style' }) }); - await new CreateStyleTool().run({ + await new CreateStyleTool(fetch).run({ name: 'Test Style', style: { version: 8, sources: {}, layers: [] } }); @@ -40,13 +42,13 @@ describe('CreateStyleTool', () => { }); it('handles fetch errors gracefully', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: false, status: 400, statusText: 'Bad Request' }); - const result = await new CreateStyleTool().run({ + const result = await new CreateStyleTool(fetch).run({ name: 'Test Style', style: { version: 8, sources: {}, layers: [] } }); diff --git a/src/tools/create-token-tool/CreateTokenTool.test.ts b/test/tools/create-token-tool/CreateTokenTool.test.ts similarity index 81% rename from src/tools/create-token-tool/CreateTokenTool.test.ts rename to test/tools/create-token-tool/CreateTokenTool.test.ts index 3a21527..3590828 100644 --- a/src/tools/create-token-tool/CreateTokenTool.test.ts +++ b/test/tools/create-token-tool/CreateTokenTool.test.ts @@ -5,43 +5,47 @@ const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( ); process.env.MAPBOX_ACCESS_TOKEN = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; +import { describe, it, expect, vi, afterEach } from 'vitest'; import { setupFetch, assertHeadersSent -} from '../../utils/requestUtils.test-helpers.js'; -import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; -import { CreateTokenTool } from './CreateTokenTool.js'; +} from '../../utils/fetchRequestUtils.js'; +import { MapboxApiBasedTool } from '../../../src/tools/MapboxApiBasedTool.js'; +import { CreateTokenTool } from '../../../src/tools/create-token-tool/CreateTokenTool.js'; type TextContent = { type: 'text'; text: string }; describe('CreateTokenTool', () => { - let tool: CreateTokenTool; - - beforeEach(() => { - tool = new CreateTokenTool(); - tool['log'] = jest.fn(); - }); - afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); + function createTokenTool(fetchImpl?: typeof fetch) { + const instance = new CreateTokenTool(fetchImpl); + instance['log'] = vi.fn(); + return instance; + } + describe('tool metadata', () => { it('should have correct name and description', () => { + const tool = createTokenTool(); expect(tool.name).toBe('create_token_tool'); expect(tool.description).toBe( 'Create a new Mapbox public access token with specified scopes and optional URL restrictions.' ); }); - it('should have correct input schema', () => { - const { CreateTokenSchema } = require('./CreateTokenTool.schema.js'); + it('should have correct input schema', async () => { + const { CreateTokenSchema } = await import( + '../../../src/tools/create-token-tool/CreateTokenTool.schema.js' + ); expect(CreateTokenSchema).toBeDefined(); }); }); describe('validation', () => { it('validates required input fields', async () => { + const tool = createTokenTool(); const result = await tool.run({}); expect(result.isError).toBe(true); @@ -51,6 +55,8 @@ describe('CreateTokenTool', () => { }); it('validates allowedUrls array length', async () => { + const tool = createTokenTool(); + const urls = new Array(101).fill('https://example.com'); const result = await tool.run({ @@ -66,6 +72,8 @@ describe('CreateTokenTool', () => { }); it('validates invalid scopes', async () => { + const tool = createTokenTool(); + const result = await tool.run({ note: 'Test token', scopes: ['invalid:scope' as unknown as string] @@ -96,8 +104,8 @@ describe('CreateTokenTool', () => { process.env.MAPBOX_ACCESS_TOKEN = invalidToken; // Setup fetch mock to prevent actual API calls - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { fetch, mockFetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, status: 200, statusText: 'OK', @@ -105,8 +113,8 @@ describe('CreateTokenTool', () => { json: async () => ({ token: 'test-token' }) } as Response); - const toolWithInvalidToken = new CreateTokenTool(); - toolWithInvalidToken['log'] = jest.fn(); + const toolWithInvalidToken = new CreateTokenTool(fetch); + toolWithInvalidToken['log'] = vi.fn(); const result = await toolWithInvalidToken.run({ note: 'Test token', @@ -121,12 +129,12 @@ describe('CreateTokenTool', () => { ); } finally { // Restore + process.env.MAPBOX_ACCESS_TOKEN = originalEnvToken; Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { value: originalToken, writable: true, configurable: true }); - process.env.MAPBOX_ACCESS_TOKEN = originalEnvToken; } }); }); @@ -142,12 +150,14 @@ describe('CreateTokenTool', () => { modified: '2024-01-01T00:00:00.000Z' }; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { fetch, mockFetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse } as Response); + const tool = createTokenTool(fetch); + const result = await tool.run({ note: 'Test token', scopes: ['styles:read', 'fonts:read'] @@ -165,7 +175,7 @@ describe('CreateTokenTool', () => { }); // Verify the request - expect(fetchMock).toHaveBeenCalledWith( + expect(mockFetch).toHaveBeenCalledWith( `https://api.mapbox.com/tokens/v2/testuser?access_token=eyJhbGciOiJIUzI1NiJ9.${payload}.signature`, { method: 'POST', @@ -180,7 +190,7 @@ describe('CreateTokenTool', () => { ); // Verify User-Agent header was sent - assertHeadersSent(fetchMock); + assertHeadersSent(mockFetch); }); it('creates a token with allowed URLs', async () => { @@ -194,12 +204,14 @@ describe('CreateTokenTool', () => { allowedUrls: ['https://example.com', 'https://app.example.com'] }; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse } as Response); + const tool = createTokenTool(fetch); + const result = await tool.run({ note: 'Restricted token', scopes: ['styles:read'], @@ -211,7 +223,7 @@ describe('CreateTokenTool', () => { expect(responseData.allowedUrls).toEqual(mockResponse.allowedUrls); // Verify the request body included allowedUrls - const lastCall = fetchMock.mock.calls[0]; + const lastCall = mockFetch.mock.calls[0]; const requestBody = JSON.parse(lastCall[1].body as string); expect(requestBody.allowedUrls).toEqual([ 'https://example.com', @@ -231,12 +243,14 @@ describe('CreateTokenTool', () => { expires: expiresAt }; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse } as Response); + const tool = createTokenTool(fetch); + const result = await tool.run({ note: 'Token with expiration', scopes: ['styles:read'], @@ -248,14 +262,14 @@ describe('CreateTokenTool', () => { expect(responseData.expires).toEqual(expiresAt); // Verify the request body included expires - const lastCall = fetchMock.mock.calls[0]; + const lastCall = mockFetch.mock.calls[0]; const requestBody = JSON.parse(lastCall[1].body as string); expect(requestBody.expires).toEqual(expiresAt); }); it('handles API errors gracefully', async () => { - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: false, status: 401, statusText: 'Unauthorized', @@ -263,6 +277,8 @@ describe('CreateTokenTool', () => { '{"message": "Token does not have required scopes", "code": "TokenScopesInvalid"}' } as Response); + const tool = createTokenTool(fetch); + const result = await tool.run({ note: 'Test token', scopes: ['styles:read'] @@ -275,8 +291,10 @@ describe('CreateTokenTool', () => { }); it('handles network errors', async () => { - const fetchMock = setupFetch(); - fetchMock.mockRejectedValueOnce(new Error('Network error')); + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockRejectedValueOnce(new Error('Network error')); + + const tool = createTokenTool(fetch); const result = await tool.run({ note: 'Test token', @@ -300,9 +318,6 @@ describe('CreateTokenTool', () => { configurable: true }); - const toolWithCustomEndpoint = new CreateTokenTool(); - toolWithCustomEndpoint['log'] = jest.fn(); - const mockResponse = { token: 'pk.test', note: 'Test token', @@ -312,18 +327,21 @@ describe('CreateTokenTool', () => { modified: '2024-01-01T00:00:00.000Z' }; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse } as Response); + const toolWithCustomEndpoint = new CreateTokenTool(fetch); + toolWithCustomEndpoint['log'] = vi.fn(); + await toolWithCustomEndpoint.run({ note: 'Test token', scopes: ['styles:read'] }); - expect(fetchMock).toHaveBeenCalledWith( + expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining('https://api.staging.mapbox.com/tokens/v2/'), expect.any(Object) ); diff --git a/src/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts b/test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts similarity index 92% rename from src/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts rename to test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts index a4e49dd..e28159b 100644 --- a/src/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts +++ b/test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts @@ -1,8 +1,9 @@ -import { GeojsonPreviewTool } from './GeojsonPreviewTool.js'; +import { describe, it, expect, vi, afterEach } from 'vitest'; +import { GeojsonPreviewTool } from '../../../src/tools/geojson-preview-tool/GeojsonPreviewTool.js'; describe('GeojsonPreviewTool', () => { afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('tool metadata', () => { @@ -14,10 +15,10 @@ describe('GeojsonPreviewTool', () => { ); }); - it('should have correct input schema', () => { - const { - GeojsonPreviewSchema - } = require('./GeojsonPreviewTool.schema.ts'); + it('should have correct input schema', async () => { + const { GeojsonPreviewSchema } = await import( + '../../../src/tools/geojson-preview-tool/GeojsonPreviewTool.schema.js' + ); expect(GeojsonPreviewSchema).toBeDefined(); }); }); diff --git a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts b/test/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts similarity index 73% rename from src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts rename to test/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts index d857e42..848b666 100644 --- a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts +++ b/test/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts @@ -1,18 +1,11 @@ -import { GetMapboxDocSourceTool } from './GetMapboxDocSourceTool.js'; - -// Mock fetch for testing -global.fetch = jest.fn(); +import { describe, expect, it, vi, beforeEach } from 'vitest'; +import { GetMapboxDocSourceTool } from '../../../src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.js'; +import { setupFetch } from 'test/utils/fetchRequestUtils.js'; describe('GetMapboxDocSourceTool', () => { - let tool: GetMapboxDocSourceTool; - const mockFetch = global.fetch as jest.MockedFunction; - - beforeEach(() => { - tool = new GetMapboxDocSourceTool(); - mockFetch.mockClear(); - }); - it('should have correct name and description', () => { + const tool = new GetMapboxDocSourceTool(); + expect(tool.name).toBe('get_latest_mapbox_docs_tool'); expect(tool.description).toContain( 'Get the latest official Mapbox documentation' @@ -34,15 +27,20 @@ This is the Mapbox developer documentation for LLMs. - Geocoding API for address search - Directions API for routing`; - mockFetch.mockResolvedValueOnce({ + const { fetch, mockFetch } = setupFetch({ ok: true, status: 200, text: () => Promise.resolve(mockContent) - } as Response); + }); + const tool = new GetMapboxDocSourceTool(fetch); const result = await tool.run({}); - expect(mockFetch).toHaveBeenCalledWith('https://docs.mapbox.com/llms.txt'); + expect(mockFetch).toHaveBeenCalledWith('https://docs.mapbox.com/llms.txt', { + headers: { + 'User-Agent': 'TestServer/1.0.0 (default, no-tag, abcdef)' + } + }); expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); @@ -53,10 +51,12 @@ This is the Mapbox developer documentation for LLMs. }); it('should handle HTTP errors', async () => { - mockFetch.mockResolvedValueOnce({ + const { fetch } = setupFetch({ ok: false, status: 404 - } as Response); + }); + + const tool = new GetMapboxDocSourceTool(fetch); const result = await tool.run({}); @@ -72,7 +72,11 @@ This is the Mapbox developer documentation for LLMs. }); it('should handle network errors', async () => { - mockFetch.mockRejectedValueOnce(new Error('Network error')); + const { fetch } = setupFetch({ + text: () => Promise.reject(new Error('Network error')) + }); + + const tool = new GetMapboxDocSourceTool(fetch); const result = await tool.run({}); @@ -88,7 +92,11 @@ This is the Mapbox developer documentation for LLMs. }); it('should handle unknown errors', async () => { - mockFetch.mockRejectedValueOnce('Unknown error'); + const { fetch } = setupFetch({ + text: () => Promise.reject(new Error('Unknown error occurred')) + }); + + const tool = new GetMapboxDocSourceTool(fetch); const result = await tool.run({}); @@ -106,11 +114,13 @@ This is the Mapbox developer documentation for LLMs. it('should work with empty input object', async () => { const mockContent = 'Test documentation content'; - mockFetch.mockResolvedValueOnce({ + const { fetch } = setupFetch({ ok: true, status: 200, text: () => Promise.resolve(mockContent) - } as Response); + }); + + const tool = new GetMapboxDocSourceTool(fetch); const result = await tool.run({}); diff --git a/src/tools/list-styles-tool/ListStylesTool.test.ts b/test/tools/list-styles-tool/ListStylesTool.test.ts similarity index 74% rename from src/tools/list-styles-tool/ListStylesTool.test.ts rename to test/tools/list-styles-tool/ListStylesTool.test.ts index b4148ac..6dcc111 100644 --- a/src/tools/list-styles-tool/ListStylesTool.test.ts +++ b/test/tools/list-styles-tool/ListStylesTool.test.ts @@ -2,15 +2,16 @@ process.env.MAPBOX_ACCESS_TOKEN = 'sk.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; +import { describe, it, expect, vi, afterEach } from 'vitest'; import { setupFetch, assertHeadersSent -} from '../../utils/requestUtils.test-helpers.js'; -import { ListStylesTool } from './ListStylesTool.js'; +} from '../../utils/fetchRequestUtils.js'; +import { ListStylesTool } from '../../../src/tools/list-styles-tool/ListStylesTool.js'; describe('ListStylesTool', () => { afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe('tool metadata', () => { @@ -22,14 +23,16 @@ describe('ListStylesTool', () => { ); }); - it('should have correct input schema', () => { - const { ListStylesSchema } = require('./ListStylesTool.schema.ts'); + it('should have correct input schema', async () => { + const { ListStylesSchema } = await import( + '../../../src/tools/list-styles-tool/ListStylesTool.schema.js' + ); expect(ListStylesSchema).toBeDefined(); }); }); it('sends custom header', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => [ { id: 'style1', name: 'Test Style 1' }, @@ -37,18 +40,18 @@ describe('ListStylesTool', () => { ] }); - await new ListStylesTool().run({}); + await new ListStylesTool(fetch).run({}); assertHeadersSent(mockFetch); }); it('handles fetch errors gracefully', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: false, status: 404, statusText: 'Not Found' }); - const result = await new ListStylesTool().run({}); + const result = await new ListStylesTool(fetch).run({}); expect(result.isError).toBe(true); expect(result.content[0]).toMatchObject({ @@ -59,12 +62,12 @@ describe('ListStylesTool', () => { }); it('extracts username from token for API call', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => [] }); - await new ListStylesTool().run({}); + await new ListStylesTool(fetch).run({}); expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining('/styles/v1/test-user?access_token='), @@ -74,12 +77,12 @@ describe('ListStylesTool', () => { }); it('includes limit parameter when provided', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => [] }); - await new ListStylesTool().run({ limit: 10 }); + await new ListStylesTool(fetch).run({ limit: 10 }); expect(mockFetch).toHaveBeenCalledWith( expect.stringMatching(/\/styles\/v1\/test-user\?.*limit=10/), @@ -89,12 +92,12 @@ describe('ListStylesTool', () => { }); it('includes start parameter when provided', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => [] }); - await new ListStylesTool().run({ start: 'abc123' }); + await new ListStylesTool(fetch).run({ start: 'abc123' }); expect(mockFetch).toHaveBeenCalledWith( expect.stringMatching(/\/styles\/v1\/test-user\?.*start=abc123/), @@ -104,12 +107,12 @@ describe('ListStylesTool', () => { }); it('includes both limit and start parameters when provided', async () => { - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => [] }); - await new ListStylesTool().run({ limit: 5, start: 'xyz789' }); + await new ListStylesTool(fetch).run({ limit: 5, start: 'xyz789' }); const calledUrl = mockFetch.mock.calls[0][0]; expect(calledUrl).toMatch(/\/styles\/v1\/test-user\?/); @@ -125,12 +128,12 @@ describe('ListStylesTool', () => { { id: 'style2', name: 'Test Style 2', owner: 'testuser' } ]; - const mockFetch = setupFetch({ + const { fetch, mockFetch } = setupFetch({ ok: true, json: async () => mockStyles }); - const result = await new ListStylesTool().run({}); + const result = await new ListStylesTool(fetch).run({}); expect(result.isError).toBe(false); expect(result.content).toHaveLength(1); diff --git a/src/tools/list-tokens-tool/ListTokensTool.test.ts b/test/tools/list-tokens-tool/ListTokensTool.test.ts similarity index 82% rename from src/tools/list-tokens-tool/ListTokensTool.test.ts rename to test/tools/list-tokens-tool/ListTokensTool.test.ts index 582acff..f5a6dfa 100644 --- a/src/tools/list-tokens-tool/ListTokensTool.test.ts +++ b/test/tools/list-tokens-tool/ListTokensTool.test.ts @@ -5,43 +5,49 @@ const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( ); process.env.MAPBOX_ACCESS_TOKEN = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; +import { describe, it, expect, afterEach, vi } from 'vitest'; import { setupFetch, assertHeadersSent -} from '../../utils/requestUtils.test-helpers.js'; -import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; -import { ListTokensTool } from './ListTokensTool.js'; +} from '../../utils/fetchRequestUtils.js'; +import { MapboxApiBasedTool } from '../../../src/tools/MapboxApiBasedTool.js'; +import { ListTokensTool } from '../../../src/tools/list-tokens-tool/ListTokensTool.js'; type TextContent = { type: 'text'; text: string }; describe('ListTokensTool', () => { - let tool: ListTokensTool; - - beforeEach(() => { - tool = new ListTokensTool(); - tool['log'] = jest.fn(); - }); - afterEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); }); + function createListTokensTool(fetchImpl?: typeof fetch): ListTokensTool { + const tool = new ListTokensTool(fetchImpl); + // Mock the log method to prevent actual logging during tests + tool['log'] = vi.fn(); + return tool; + } + describe('tool metadata', () => { it('should have correct name and description', () => { + const tool = createListTokensTool(); + expect(tool.name).toBe('list_tokens_tool'); expect(tool.description).toBe( 'List Mapbox access tokens for the authenticated user with optional filtering and pagination. When using pagination, the "start" parameter must be obtained from the "next_start" field of the previous response (it is not a token ID)' ); }); - it('should have correct input schema', () => { - const { ListTokensSchema } = require('./ListTokensTool.schema.ts'); + it('should have correct input schema', async () => { + const { ListTokensSchema } = await import( + '../../../src/tools/list-tokens-tool/ListTokensTool.schema.js' + ); expect(ListTokensSchema).toBeDefined(); }); }); describe('validation', () => { it('validates limit range', async () => { + const tool = createListTokensTool(); const result = await tool.run({ limit: 101 }); expect(result.isError).toBe(true); @@ -51,6 +57,7 @@ describe('ListTokensTool', () => { }); it('validates sortby enum values', async () => { + const tool = createListTokensTool(); const result = await tool.run({ sortby: 'invalid' as unknown as 'created' | 'modified' }); @@ -60,6 +67,7 @@ describe('ListTokensTool', () => { }); it('validates usage enum values', async () => { + const tool = createListTokensTool(); const result = await tool.run({ usage: 'invalid' as unknown as 'pk' }); @@ -87,8 +95,8 @@ describe('ListTokensTool', () => { process.env.MAPBOX_ACCESS_TOKEN = invalidToken; // Setup fetch mock to prevent actual API calls - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, status: 200, statusText: 'OK', @@ -96,8 +104,7 @@ describe('ListTokensTool', () => { json: async () => [] } as Response); - const toolWithInvalidToken = new ListTokensTool(); - toolWithInvalidToken['log'] = jest.fn(); + const toolWithInvalidToken = createListTokensTool(fetch); const result = await toolWithInvalidToken.run({}); @@ -142,13 +149,15 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, headers: new Headers(), json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({}); expect(result.isError).toBe(false); @@ -161,7 +170,7 @@ describe('ListTokensTool', () => { expect(responseData.tokens[1].id).toBe('cktest456'); // Verify the request - expect(fetchMock).toHaveBeenCalledWith( + expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining( 'https://api.mapbox.com/tokens/v2/testuser?access_token=' ), @@ -174,7 +183,7 @@ describe('ListTokensTool', () => { ); // Verify User-Agent header was sent - assertHeadersSent(fetchMock); + assertHeadersSent(mockFetch); }); it('filters by default token', async () => { @@ -191,13 +200,14 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, headers: new Headers(), json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); const result = await tool.run({ default: true }); expect(result.isError).toBe(false); @@ -206,7 +216,7 @@ describe('ListTokensTool', () => { expect(responseData.tokens[0].default).toBe(true); // Verify the request included the default parameter - expect(fetchMock).toHaveBeenCalledWith( + expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining('default=true'), expect.any(Object) ); @@ -225,19 +235,20 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); + const { mockFetch, fetch } = setupFetch(); const headers = new Headers(); headers.set( 'Link', '; rel="next"' ); - fetchMock.mockResolvedValueOnce({ + mockFetch.mockResolvedValueOnce({ ok: true, headers, json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); const result = await tool.run({ limit: 10, start: 'cktest789', @@ -249,7 +260,7 @@ describe('ListTokensTool', () => { expect(responseData.tokens).toHaveLength(1); // Verify all parameters were included in the request - const callUrl = fetchMock.mock.calls[0][0] as string; + const callUrl = mockFetch.mock.calls[0][0] as string; expect(callUrl).toContain('limit=10'); expect(callUrl).toContain('start=cktest789'); expect(callUrl).toContain('sortby=created'); @@ -268,19 +279,21 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); + const { mockFetch, fetch } = setupFetch(); const headers = new Headers(); headers.set( 'Link', '; rel="next"' ); - fetchMock.mockResolvedValueOnce({ + mockFetch.mockResolvedValueOnce({ ok: true, headers, json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({ limit: 10 }); expect(result.isError).toBe(false); @@ -302,19 +315,21 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); + const { mockFetch, fetch } = setupFetch(); const headers = new Headers(); headers.set( 'Link', '; rel="next"' ); - fetchMock.mockResolvedValueOnce({ + mockFetch.mockResolvedValueOnce({ ok: true, headers, json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({ start: 'cktest789' }); expect(result.isError).toBe(false); @@ -336,7 +351,7 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); + const { mockFetch, fetch } = setupFetch(); // First page with Link header const headers1 = new Headers(); headers1.set( @@ -347,18 +362,20 @@ describe('ListTokensTool', () => { // Second page without Link header (end of results) const headers2 = new Headers(); - fetchMock.mockResolvedValueOnce({ + mockFetch.mockResolvedValueOnce({ ok: true, headers: headers1, json: async () => mockTokens } as Response); - fetchMock.mockResolvedValueOnce({ + mockFetch.mockResolvedValueOnce({ ok: true, headers: headers2, json: async () => [] // Empty array for second page } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({}); expect(result.isError).toBe(false); @@ -380,13 +397,15 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, headers: new Headers(), json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({ limit: 10 }); expect(result.isError).toBe(false); @@ -408,13 +427,15 @@ describe('ListTokensTool', () => { } ]; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, headers: new Headers(), json: async () => mockTokens } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({ usage: 'pk' }); expect(result.isError).toBe(false); @@ -423,15 +444,15 @@ describe('ListTokensTool', () => { expect(responseData.tokens[0].usage).toBe('pk'); // Verify the usage parameter was included - expect(fetchMock).toHaveBeenCalledWith( + expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining('usage=pk'), expect.any(Object) ); }); it('handles API errors gracefully', async () => { - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: false, status: 401, statusText: 'Unauthorized', @@ -439,6 +460,8 @@ describe('ListTokensTool', () => { '{"message": "Invalid access token", "code": "TokenInvalid"}' } as Response); + const tool = createListTokensTool(fetch); + const result = await tool.run({}); expect(result.isError).toBe(true); @@ -448,9 +471,10 @@ describe('ListTokensTool', () => { }); it('handles network errors', async () => { - const fetchMock = setupFetch(); - fetchMock.mockRejectedValueOnce(new Error('Network error')); + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockRejectedValueOnce(new Error('Network error')); + const tool = createListTokensTool(fetch); const result = await tool.run({}); expect(result.isError).toBe(true); @@ -470,21 +494,20 @@ describe('ListTokensTool', () => { configurable: true }); - const toolWithCustomEndpoint = new ListTokensTool(); - toolWithCustomEndpoint['log'] = jest.fn(); - const mockTokens: object[] = []; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, headers: new Headers(), json: async () => mockTokens } as Response); - await toolWithCustomEndpoint.run({}); + const tool = createListTokensTool(fetch); + + await tool.run({}); - expect(fetchMock).toHaveBeenCalledWith( + expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining('https://api.staging.mapbox.com/tokens/v2/'), expect.any(Object) ); @@ -511,13 +534,14 @@ describe('ListTokensTool', () => { ] }; - const fetchMock = setupFetch(); - fetchMock.mockResolvedValueOnce({ + const { mockFetch, fetch } = setupFetch(); + mockFetch.mockResolvedValueOnce({ ok: true, headers: new Headers(), json: async () => mockResponse } as Response); + const tool = createListTokensTool(fetch); const result = await tool.run({}); expect(result.isError).toBe(false); diff --git a/src/tools/preview-style-tool/PreviewStyleTool.test.ts b/test/tools/preview-style-tool/PreviewStyleTool.test.ts similarity index 92% rename from src/tools/preview-style-tool/PreviewStyleTool.test.ts rename to test/tools/preview-style-tool/PreviewStyleTool.test.ts index 50f6eca..d98b82c 100644 --- a/src/tools/preview-style-tool/PreviewStyleTool.test.ts +++ b/test/tools/preview-style-tool/PreviewStyleTool.test.ts @@ -1,8 +1,8 @@ -// Use a token with valid JWT format for tests process.env.MAPBOX_ACCESS_TOKEN = 'sk.eyJhbGciOiJIUzI1NiJ9.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; -import { PreviewStyleTool } from './PreviewStyleTool.js'; +import { describe, it, expect } from 'vitest'; +import { PreviewStyleTool } from '../../../src/tools/preview-style-tool/PreviewStyleTool.js'; describe('PreviewStyleTool', () => { const TEST_ACCESS_TOKEN = @@ -17,8 +17,10 @@ describe('PreviewStyleTool', () => { ); }); - it('should have correct input schema', () => { - const { PreviewStyleSchema } = require('./PreviewStyleTool.schema.ts'); + it('should have correct input schema', async () => { + const { PreviewStyleSchema } = await import( + '../../../src/tools/preview-style-tool/PreviewStyleTool.schema.js' + ); expect(PreviewStyleSchema).toBeDefined(); }); }); diff --git a/src/tools/style-comparison-tool/StyleComparisonTool.test.ts b/test/tools/style-comparison-tool/StyleComparisonTool.test.ts similarity index 92% rename from src/tools/style-comparison-tool/StyleComparisonTool.test.ts rename to test/tools/style-comparison-tool/StyleComparisonTool.test.ts index f57750f..4c07f21 100644 --- a/src/tools/style-comparison-tool/StyleComparisonTool.test.ts +++ b/test/tools/style-comparison-tool/StyleComparisonTool.test.ts @@ -1,5 +1,6 @@ -import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; -import { StyleComparisonTool } from './StyleComparisonTool.js'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { MapboxApiBasedTool } from '../../../src/tools/MapboxApiBasedTool.js'; +import { StyleComparisonTool } from '../../../src/tools/style-comparison-tool/StyleComparisonTool.js'; describe('StyleComparisonTool', () => { let tool: StyleComparisonTool; @@ -9,7 +10,7 @@ describe('StyleComparisonTool', () => { }); afterEach(() => { - jest.restoreAllMocks(); + vi.clearAllMocks(); }); describe('run', () => { @@ -38,7 +39,7 @@ describe('StyleComparisonTool', () => { // Missing accessToken }; - const result = await tool.run(input as any); + const result = await tool.run(input); expect(result.isError).toBe(true); expect( @@ -63,9 +64,9 @@ describe('StyleComparisonTool', () => { it('should handle just style IDs with valid public token', async () => { // Mock MapboxApiBasedTool.getUserNameFromToken to return a username - jest - .spyOn(MapboxApiBasedTool, 'getUserNameFromToken') - .mockReturnValue('testuser'); + vi.spyOn(MapboxApiBasedTool, 'getUserNameFromToken').mockReturnValue( + 'testuser' + ); const input = { before: 'style-id-1', @@ -116,13 +117,13 @@ describe('StyleComparisonTool', () => { it('should return error for style ID without valid username in token', async () => { // Mock getUserNameFromToken to throw an error - jest - .spyOn(MapboxApiBasedTool, 'getUserNameFromToken') - .mockImplementation(() => { + vi.spyOn(MapboxApiBasedTool, 'getUserNameFromToken').mockImplementation( + () => { throw new Error( 'MAPBOX_ACCESS_TOKEN does not contain username in payload' ); - }); + } + ); const input = { before: 'style-id-only', diff --git a/src/tools/tilequery-tool/TilequeryTool.test.ts b/test/tools/tilequery-tool/TilequeryTool.test.ts similarity index 91% rename from src/tools/tilequery-tool/TilequeryTool.test.ts rename to test/tools/tilequery-tool/TilequeryTool.test.ts index faf6c85..444d436 100644 --- a/src/tools/tilequery-tool/TilequeryTool.test.ts +++ b/test/tools/tilequery-tool/TilequeryTool.test.ts @@ -1,5 +1,6 @@ -import { TilequeryTool } from './TilequeryTool.js'; -import { TilequeryInput } from './TilequeryTool.schema.js'; +import { describe, it, expect, beforeEach } from 'vitest'; +import { TilequeryTool } from '../../../src/tools/tilequery-tool/TilequeryTool.js'; +import { TilequeryInput } from '../../../src/tools/tilequery-tool/TilequeryTool.schema.js'; describe('TilequeryTool', () => { let tool: TilequeryTool; diff --git a/src/tools/tool-naming-convention.test.ts b/test/tools/tool-naming-convention.test.ts similarity index 90% rename from src/tools/tool-naming-convention.test.ts rename to test/tools/tool-naming-convention.test.ts index 0b11a83..14d8a28 100644 --- a/src/tools/tool-naming-convention.test.ts +++ b/test/tools/tool-naming-convention.test.ts @@ -1,9 +1,14 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import { BaseTool } from './BaseTool.js'; +import { describe, it, expect } from 'vitest'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { BaseTool } from '../../src/tools/BaseTool.js'; +import { pathToFileURL } from 'node:url'; async function discoverTools(): Promise { - const toolsDir = __dirname; + const toolsDir = path.resolve( + new URL('.', import.meta.url).pathname, + '../../src/tools' + ); const tools: any[] = []; // Find all directories that end with '-tool' @@ -16,16 +21,15 @@ async function discoverTools(): Promise { for (const toolDir of toolDirectories) { const allFiles = fs.readdirSync(path.join(toolsDir, toolDir)); const toolFiles = allFiles.filter( - (file) => - file.endsWith('.ts') && - !file.endsWith('.test.ts') && - file.includes('Tool') + (file) => file.endsWith('.ts') && file.includes('Tool') ); // Import all tool files in the directory for (const toolFile of toolFiles) { try { - const modulePath = `./${toolDir}/${toolFile.replace('.ts', '.js')}`; + const modulePath = pathToFileURL( + path.join(toolsDir, toolDir, toolFile.replace('.ts', '.js')) + ).href; const module = await import(modulePath); // Find all exported tool classes diff --git a/test/utils/fetchRequest.test.ts b/test/utils/fetchRequest.test.ts new file mode 100644 index 0000000..63f3f66 --- /dev/null +++ b/test/utils/fetchRequest.test.ts @@ -0,0 +1,164 @@ +import { describe, it, expect, vi, afterEach } from 'vitest'; +import { + RetryPolicy, + PolicyPipeline, + UserAgentPolicy +} from '../../src/utils/fetchRequest.js'; +import type { Mock } from 'vitest'; + +function createMockFetch( + responses: Array<{ status: number; ok?: boolean }> +): typeof fetch { + let call = 0; + return vi.fn(async (input: string | URL | Request, init?: RequestInit) => { + const res = responses[Math.min(call, responses.length - 1)]; + call++; + return { + ok: res.ok ?? res.status < 400, + status: res.status, + statusText: `Status ${res.status}`, + json: async () => ({ status: res.status }) + } as Response; + }) as typeof fetch; +} + +describe('PolicyPipeline', () => { + describe('RetryPolicy', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('retries on 500 and returns last response after max retries', async () => { + const mockFetch = createMockFetch([ + { status: 500 }, + { status: 500 }, + { status: 500 }, + { status: 500 } + ]); + const pipeline = new PolicyPipeline(mockFetch); + pipeline.use(new RetryPolicy(3, 1, 10)); // Use small delays for test speed + + const response = await pipeline.fetch('http://test', {}); + + expect(mockFetch).toHaveBeenCalledTimes(4); + expect(response.status).toBe(500); + }); + + it('retries on 429 and succeeds if later response is ok', async () => { + const mockFetch = createMockFetch([ + { status: 429 }, + { status: 429 }, + { status: 200, ok: true } + ]); + const pipeline = new PolicyPipeline(mockFetch); + pipeline.use(new RetryPolicy(3, 1, 10)); + + const response = await pipeline.fetch('http://test', {}); + + expect(mockFetch).toHaveBeenCalledTimes(3); + expect(response.status).toBe(200); + expect(response.ok).toBe(true); + }); + + it('does not retry on 400 errors', async () => { + const mockFetch = createMockFetch([{ status: 400 }]); + const pipeline = new PolicyPipeline(mockFetch); + pipeline.use(new RetryPolicy(3, 1, 10)); + + const response = await pipeline.fetch('http://test', {}); + + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(response.status).toBe(400); + }); + + it('returns immediately on first success', async () => { + const mockFetch = createMockFetch([{ status: 200, ok: true }]); + const pipeline = new PolicyPipeline(mockFetch); + pipeline.use(new RetryPolicy(3, 1, 10)); + + const response = await pipeline.fetch('http://test', {}); + + expect(mockFetch).toHaveBeenCalledTimes(1); + expect(response.status).toBe(200); + expect(response.ok).toBe(true); + }); + }); + + describe('UserAgentPolicy', () => { + it('sets the User-Agent header if not present', async () => { + const mockFetch = vi.fn( + async (input: string | URL | Request, init?: RequestInit) => { + return { + ok: true, + status: 200, + statusText: 'OK', + json: async () => ({}), + headers: init?.headers + } as Response; + } + ) as Mock; + + const pipeline = new PolicyPipeline(mockFetch as unknown as typeof fetch); + pipeline.use(new UserAgentPolicy('TestAgent/1.0')); + + await pipeline.fetch('http://test', {}); + + const headers = mockFetch.mock.calls[0][1]?.headers as Record< + string, + string + >; + expect(headers['User-Agent']).toBe('TestAgent/1.0'); + }); + + it('does not overwrite an existing User-Agent header', async () => { + const mockFetch = vi.fn( + async (input: string | URL | Request, init?: RequestInit) => { + return { + ok: true, + status: 200, + statusText: 'OK', + json: async () => ({}), + headers: init?.headers + } as Response; + } + ) as Mock; + + const pipeline = new PolicyPipeline(mockFetch as unknown as typeof fetch); + pipeline.use(new UserAgentPolicy('TestAgent/1.0')); + + await pipeline.fetch('http://test', { + headers: { + 'User-Agent': 'CustomAgent/2.0' + } + }); + + const headers = mockFetch.mock.calls[0][1]?.headers as Record< + string, + string + >; + expect(headers['User-Agent']).toBe('CustomAgent/2.0'); + }); + + it('works with headers as Headers object', async () => { + const mockFetch = vi.fn( + async (_input: string | URL | Request, init?: RequestInit) => { + return { + ok: true, + status: 200, + statusText: 'OK', + json: async () => ({}), + headers: init?.headers + } as Response; + } + ) as Mock; + + const pipeline = new PolicyPipeline(mockFetch as unknown as typeof fetch); + pipeline.use(new UserAgentPolicy('TestAgent/1.0')); + + const headers = new Headers(); + await pipeline.fetch('http://test', { headers }); + + expect(headers.get('User-Agent')).toBe('TestAgent/1.0'); + }); + }); +}); diff --git a/test/utils/fetchRequestUtils.ts b/test/utils/fetchRequestUtils.ts new file mode 100644 index 0000000..de45e41 --- /dev/null +++ b/test/utils/fetchRequestUtils.ts @@ -0,0 +1,34 @@ +import { expect, vi } from 'vitest'; +import type { Mock } from 'vitest'; +import { + PolicyPipeline, + UserAgentPolicy +} from '../../src/utils/fetchRequest.js'; + +export function setupFetch(overrides?: any) { + const mockFetch = vi.fn(); + mockFetch.mockResolvedValue({ + ok: true, + status: 200, + statusText: 'OK', + json: async () => ({ success: true }), + arrayBuffer: async () => new ArrayBuffer(0), + ...overrides + }); + + // Build a real pipeline with UserAgentPolicy + const userAgent = 'TestServer/1.0.0 (default, no-tag, abcdef)'; + const pipeline = new PolicyPipeline(mockFetch); + pipeline.use(new UserAgentPolicy(userAgent)); + + return { fetch: pipeline.fetch.bind(pipeline), mockFetch }; +} + +export function assertHeadersSent(mockFetch: Mock) { + expect(mockFetch).toHaveBeenCalledTimes(1); + const callArgs = mockFetch.mock.calls[0]; + const requestInit = callArgs[1]; + expect(requestInit?.headers).toMatchObject({ + 'User-Agent': expect.any(String) + }); +} diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..8c0d782 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "target": "ES2022", + "moduleResolution": "NodeNext", + "lib": [ + "ES2022", + "ESNext" + ], + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "skipLibCheck": true, + "baseUrl": "." + }, +} diff --git a/tsconfig.json b/tsconfig.json index feee848..8fb0041 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,30 +1,11 @@ { - "compilerOptions": { - "module": "esnext", - "target": "ES2022", - "moduleResolution": "node", - "lib": [ - "ES2022", - "ESNext" - ], - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "outDir": "./dist", - "strict": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "isolatedModules": true, - "skipLibCheck": true, - "baseUrl": "." - }, - "include": [ - "src/**/*" + "references": [ + { + "path": "./tsconfig.src.json" + }, + { + "path": "./tsconfig.test.json" + } ], - "exclude": [ - "node_modules", - "dist/*", - "dist/**/*" - ] + "files": [] } \ No newline at end of file diff --git a/tsconfig.src.json b/tsconfig.src.json new file mode 100644 index 0000000..ee12229 --- /dev/null +++ b/tsconfig.src.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "composite": true + }, + "include": ["src", "test/tools/MapboxApiBasedTool.test.ts", "test/tools/preview-style-tool/PreviewStyleTool.test.ts", "test/tools/tool-naming-convention.test.ts"] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..64c3b90 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "skipLibCheck": true, + "lib": ["ESNext"], + "resolveJsonModule": true + }, + "include": ["test", "src"] +} \ No newline at end of file diff --git a/tsconfig.types.json b/tsconfig.types.json deleted file mode 100644 index 595026f..0000000 --- a/tsconfig.types.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "declaration": true, - "emitDeclarationOnly": true, - "outDir": "./dist" - }, - "include": ["src/*", "src/**/*"] -} \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..37ca52a --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + testTimeout: 1200000, + hookTimeout: 1200000, + reporters: ['default', 'junit'], + outputFile: { + junit: 'test-results.xml' + }, + watch: false, + include: ['test/**/*.test.ts'], + coverage: { + include: ['src/**/*.ts'], + exclude: ['src/**/*-cjs.cts', 'vitest*.config.ts'], + provider: 'istanbul', + reporter: ['text', 'json', 'html'], + reportsDirectory: 'coverage' + } + } +}); From 5d454eb5ca496a6bbbe74c219eef3b4a11751453 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Mon, 8 Sep 2025 17:46:55 -0400 Subject: [PATCH 2/6] [chore] Update MCP DevKit server to use ESM/vitest --- package-lock.json | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 807f143..6959417 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@typescript-eslint/parser": "^8.0.0", "@vitest/coverage-istanbul": "^3.2.4", "eslint": "^9.0.0", + "globals": "^16.3.0", "husky": "^9.0.0", "lint-staged": "^16.1.0", "plop": "^4.0.1", @@ -822,6 +823,19 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/eslintrc/node_modules/ignore": { "version": "5.3.2", "dev": true, @@ -3661,7 +3675,9 @@ } }, "node_modules/globals": { - "version": "14.0.0", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, "license": "MIT", "engines": { From 54ab296945a4113791488cb8c44a712de91f6d73 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Tue, 9 Sep 2025 15:36:26 -0400 Subject: [PATCH 3/6] [core] Merge from main --- Dockerfile | 4 +- README.md | 47 ++++++++++++------- TOOL_CONFIGURATION.md | 10 ++-- docs/claude-code-integration.md | 2 +- docs/claude-desktop-integration.md | 2 +- manifest.json | 4 +- .../create-style-tool/CreateStyleTool.ts | 2 +- .../create-token-tool/CreateTokenTool.ts | 2 +- .../GetMapboxDocSourceTool.ts | 2 +- src/tools/list-styles-tool/ListStylesTool.ts | 2 +- src/tools/list-tokens-tool/ListTokensTool.ts | 2 +- 11 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Dockerfile b/Dockerfile index 49ccd3f..a916741 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ COPY . . RUN mkdir -p dist && echo '{"sha":"unknown","tag":"unknown","branch":"docker","version":"0.0.1"}' > dist/version.json # Build the application, overriding the git commands to avoid errors -RUN npm run build:esm && npm run build:cjs +RUN npx tshy # Command to run the server -CMD ["node", "dist/index.js"] \ No newline at end of file +CMD ["node", "dist/esm/index.js"] diff --git a/README.md b/README.md index 94c4885..5ec1076 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,32 @@ A Model Context Protocol (MCP) server that provides AI assistants with direct ac ## Table of Contents -- [Quick Start](#quick-start) - - [Integration with Developer Tools](#integration-with-developer-tools) - - [DXT Package Distribution](#dxt-package-distribution) - - [Getting Your Mapbox Access Token](#getting-your-mapbox-access-token) -- [Tools](#tools) - - [Documentation Tools](#documentation-tools) - - [Style Management Tools](#style-management-tools) - - [Token Management Tools](#token-management-tools) - - [Local Processing Tools](#local-processing-tools) -- [Development](#development) - - [Testing](#testing) - - [Inspecting Server](#inspecting-server) - - [Creating New Tools](#creating-new-tools) - - [Environment Variables](#environment-variables) +- [Mapbox Developer MCP Server](#mapbox-developer-mcp-server) + - [Table of Contents](#table-of-contents) + - [Quick Start](#quick-start) + - [Integration with Developer Tools](#integration-with-developer-tools) + - [DXT Package Distribution](#dxt-package-distribution) + - [Creating the DXT Package](#creating-the-dxt-package) + - [Getting Your Mapbox Access Token](#getting-your-mapbox-access-token) + - [Tools](#tools) + - [Documentation Tools](#documentation-tools) + - [Style Management Tools](#style-management-tools) + - [Token Management Tools](#token-management-tools) + - [create-token](#create-token) + - [list-tokens](#list-tokens) + - [Local Processing Tools](#local-processing-tools) + - [GeoJSON Preview tool (Beta)](#geojson-preview-tool-beta) + - [Coordinate Conversion tool](#coordinate-conversion-tool) + - [Bounding Box tool](#bounding-box-tool) + - [Development](#development) + - [Testing](#testing) + - [Tool Snapshot Tests](#tool-snapshot-tests) + - [Inspecting Server](#inspecting-server) + - [Using Node.js](#using-nodejs) + - [Using Docker](#using-docker) + - [Creating New Tools](#creating-new-tools) + - [Environment Variables](#environment-variables) + - [VERBOSE_ERRORS](#verbose_errors) ## Quick Start @@ -53,7 +65,7 @@ This will generate `mcp-devkit-server.dxt` using the configuration in `manifest. The DXT package includes: -- Pre-built server code (`dist/index.js`) +- Pre-built server code (`dist/esm/index.js`) - Server metadata and configuration - User configuration schema for the Mapbox access token - Automatic environment variable setup @@ -82,7 +94,6 @@ The `MAPBOX_ACCESS_TOKEN` environment variable is required. **Each tool requires **get_latest_mapbox_docs_tool** - Access the latest official Mapbox documentation directly from the source. This tool fetches comprehensive, up-to-date information about all Mapbox APIs, SDKs, and developer resources from docs.mapbox.com/llms.txt. - **Example prompts:** - "What are the latest Mapbox APIs available for developers?" @@ -368,7 +379,7 @@ The project includes snapshot tests to ensure tool integrity and prevent acciden 1. **Adding a new tool**: After creating a new tool, run the test with snapshot update flag: ```sh - npm test -- src/tools/tool-naming-convention.test.ts --updateSnapshot + npm test -- test/tools/tool-naming-convention.test.ts --updateSnapshot ``` 2. **Removing a tool**: After removing a tool, update the snapshot: @@ -403,7 +414,7 @@ npm test -- --updateSnapshot npm run build # Inspect -npx @modelcontextprotocol/inspector node dist/index.js +npx @modelcontextprotocol/inspector node dist/esm/index.js ``` #### Using Docker diff --git a/TOOL_CONFIGURATION.md b/TOOL_CONFIGURATION.md index f94dffd..f6726e8 100644 --- a/TOOL_CONFIGURATION.md +++ b/TOOL_CONFIGURATION.md @@ -53,7 +53,7 @@ The following tools are available in the Mapbox MCP Devkit Server: ### Node.js ```bash -node dist/index.js --enable-tools list_styles_tool,create_style_tool,preview_style_tool +node dist/esm/index.js --enable-tools list_styles_tool,create_style_tool,preview_style_tool ``` ### NPX @@ -78,7 +78,7 @@ In your Claude Desktop configuration file: "mapbox-devkit": { "command": "node", "args": [ - "/path/to/mcp-devkit-server/dist/index.js", + "/path/to/mcp-devkit-server/dist/esm/index.js", "--enable-tools", "list_styles_tool,create_style_tool,preview_style_tool" ], @@ -95,19 +95,19 @@ In your Claude Desktop configuration file: ### Enable only read-only tools (safe mode) ```bash -node dist/index.js --enable-tools list_styles_tool,retrieve_style_tool,list_tokens_tool,preview_style_tool +node dist/esm/index.js --enable-tools list_styles_tool,retrieve_style_tool,list_tokens_tool,preview_style_tool ``` ### Enable only style management tools ```bash -node dist/index.js --enable-tools list_styles_tool,create_style_tool,retrieve_style_tool,update_style_tool,delete_style_tool,preview_style_tool +node dist/esm/index.js --enable-tools list_styles_tool,create_style_tool,retrieve_style_tool,update_style_tool,delete_style_tool,preview_style_tool ``` ### Disable dangerous operations ```bash -node dist/index.js --disable-tools delete_style_tool,create_token_tool +node dist/esm/index.js --disable-tools delete_style_tool,create_token_tool ``` ## Notes diff --git a/docs/claude-code-integration.md b/docs/claude-code-integration.md index 823e970..a3d48fb 100644 --- a/docs/claude-code-integration.md +++ b/docs/claude-code-integration.md @@ -96,7 +96,7 @@ If you want to use a local version (need to clone and build from this repo): "mcpServers": { "mapbox-devkit": { "command": "/path/to/your/node", - "args": ["/path/to/mapbox-mcp-devkit/dist/index.js"], + "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here" } diff --git a/docs/claude-desktop-integration.md b/docs/claude-desktop-integration.md index 4cd8726..7987263 100644 --- a/docs/claude-desktop-integration.md +++ b/docs/claude-desktop-integration.md @@ -107,7 +107,7 @@ If you want to use a local version (need to clone and build from this repo): "mcpServers": { "mapbox-devkit": { "command": "/path/to/your/node", - "args": ["/path/to/mapbox-mcp-devkit/dist/index.js"], + "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here" } diff --git a/manifest.json b/manifest.json index e23fbdd..ec265a7 100644 --- a/manifest.json +++ b/manifest.json @@ -9,11 +9,11 @@ }, "server": { "type": "node", - "entry_point": "dist/index.js", + "entry_point": "dist/esm/index.js", "mcp_config": { "command": "node", "args": [ - "${__dirname}/dist/index.js" + "${__dirname}/dist/esm/index.js" ], "env": { "MAPBOX_ACCESS_TOKEN": "${user_config.MAPBOX_ACCESS_TOKEN}" diff --git a/src/tools/create-style-tool/CreateStyleTool.ts b/src/tools/create-style-tool/CreateStyleTool.ts index 697780e..94c0529 100644 --- a/src/tools/create-style-tool/CreateStyleTool.ts +++ b/src/tools/create-style-tool/CreateStyleTool.ts @@ -1,4 +1,4 @@ -import { fetchClient } from 'src/utils/fetchRequest.js'; +import { fetchClient } from '../../utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { CreateStyleSchema, diff --git a/src/tools/create-token-tool/CreateTokenTool.ts b/src/tools/create-token-tool/CreateTokenTool.ts index 479349d..94421d6 100644 --- a/src/tools/create-token-tool/CreateTokenTool.ts +++ b/src/tools/create-token-tool/CreateTokenTool.ts @@ -1,4 +1,4 @@ -import { fetchClient } from 'src/utils/fetchRequest.js'; +import { fetchClient } from '../../utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { CreateTokenSchema, diff --git a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts index 0d9e402..2462ab6 100644 --- a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts +++ b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts @@ -1,4 +1,4 @@ -import { fetchClient } from 'src/utils/fetchRequest.js'; +import { fetchClient } from '../../utils/fetchRequest.js'; import { BaseTool } from '../BaseTool.js'; import { GetMapboxDocSourceSchema, diff --git a/src/tools/list-styles-tool/ListStylesTool.ts b/src/tools/list-styles-tool/ListStylesTool.ts index 4ad58cd..5533d06 100644 --- a/src/tools/list-styles-tool/ListStylesTool.ts +++ b/src/tools/list-styles-tool/ListStylesTool.ts @@ -1,4 +1,4 @@ -import { fetchClient } from 'src/utils/fetchRequest.js'; +import { fetchClient } from '../../utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { ListStylesSchema, ListStylesInput } from './ListStylesTool.schema.js'; diff --git a/src/tools/list-tokens-tool/ListTokensTool.ts b/src/tools/list-tokens-tool/ListTokensTool.ts index 41c4fac..9283709 100644 --- a/src/tools/list-tokens-tool/ListTokensTool.ts +++ b/src/tools/list-tokens-tool/ListTokensTool.ts @@ -1,4 +1,4 @@ -import { fetchClient } from 'src/utils/fetchRequest.js'; +import { fetchClient } from '../../utils/fetchRequest.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { ListTokensSchema, ListTokensInput } from './ListTokensTool.schema.js'; From bdeee5e3a3ca9a530835068c706b40ac022ec46a Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Tue, 9 Sep 2025 18:13:27 -0400 Subject: [PATCH 4/6] [chore] Update changelog --- CHANGELOG.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b152be6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,14 @@ +## 0.4.0 (Unreleased) + +### Features Added + +- New fetch pipeline with automatic retry behavior + +### Bug Fixes + +- Dual emits ESM and CommonJS bundles with types per target + +### Other Features + +- Migrated from Jest to vitest +- Added EditorConfig support for development work diff --git a/package.json b/package.json index d854c1a..98dd4da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mapbox/mcp-devkit-server", - "version": "0.3.2", + "version": "0.4.0", "description": "Mapbox MCP devkit server", "main": "./dist/commonjs/index.js", "module": "./dist/esm/index.js", From 4992d04bc0e6c781abd0e6d60eeeb47a7ef6fc73 Mon Sep 17 00:00:00 2001 From: jussi-sa Date: Wed, 10 Sep 2025 11:11:02 +0300 Subject: [PATCH 5/6] fix token issues --- src/tools/MapboxApiBasedTool.ts | 16 +++--- .../create-style-tool/CreateStyleTool.ts | 2 +- .../create-token-tool/CreateTokenTool.ts | 2 +- .../delete-style-tool/DeleteStyleTool.ts | 2 +- src/tools/list-styles-tool/ListStylesTool.ts | 2 +- src/tools/list-tokens-tool/ListTokensTool.ts | 2 +- .../preview-style-tool/PreviewStyleTool.ts | 2 +- .../retrieve-style-tool/RetrieveStyleTool.ts | 2 +- src/tools/tilequery-tool/TilequeryTool.ts | 2 +- .../update-style-tool/UpdateStyleTool.ts | 2 +- test/tools/MapboxApiBasedTool.test.ts | 27 ++++++---- .../create-style-tool/CreateStyleTool.test.ts | 12 +++-- .../create-token-tool/CreateTokenTool.test.ts | 51 ++++++++----------- .../list-styles-tool/ListStylesTool.test.ts | 12 +++-- .../list-tokens-tool/ListTokensTool.test.ts | 51 ++++++++----------- 15 files changed, 92 insertions(+), 95 deletions(-) diff --git a/src/tools/MapboxApiBasedTool.ts b/src/tools/MapboxApiBasedTool.ts index 4af8479..2f1a16a 100644 --- a/src/tools/MapboxApiBasedTool.ts +++ b/src/tools/MapboxApiBasedTool.ts @@ -5,9 +5,13 @@ import { BaseTool, OutputSchema } from './BaseTool.js'; export abstract class MapboxApiBasedTool< InputSchema extends ZodTypeAny > extends BaseTool { - static readonly MAPBOX_ACCESS_TOKEN = process.env.MAPBOX_ACCESS_TOKEN; - static readonly MAPBOX_API_ENDPOINT = - process.env.MAPBOX_API_ENDPOINT || 'https://api.mapbox.com/'; + static get mapboxAccessToken() { + return process.env.MAPBOX_ACCESS_TOKEN; + } + + static get mapboxApiEndpoint() { + return process.env.MAPBOX_API_ENDPOINT || 'https://api.mapbox.com/'; + } constructor(params: { inputSchema: InputSchema }) { super(params); @@ -20,12 +24,12 @@ export abstract class MapboxApiBasedTool< */ static getUserNameFromToken(access_token?: string): string { if (!access_token) { - if (!MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN) { + if (!MapboxApiBasedTool.mapboxAccessToken) { throw new Error( 'No access token provided. Please set MAPBOX_ACCESS_TOKEN environment variable or pass it as an argument.' ); } - access_token = MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; + access_token = MapboxApiBasedTool.mapboxAccessToken; } try { @@ -84,7 +88,7 @@ export abstract class MapboxApiBasedTool< // In the streamableHttp, the authInfo is injected into extra from `req.auth` // https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/server/streamableHttp.ts#L405 const authToken = extra?.authInfo?.token; - const accessToken = authToken || MapboxApiBasedTool.MAPBOX_ACCESS_TOKEN; + const accessToken = authToken || MapboxApiBasedTool.mapboxAccessToken; if (!accessToken) { throw new Error( 'No access token available. Please provide via Bearer auth or MAPBOX_ACCESS_TOKEN env var' diff --git a/src/tools/create-style-tool/CreateStyleTool.ts b/src/tools/create-style-tool/CreateStyleTool.ts index 94c0529..7419db0 100644 --- a/src/tools/create-style-tool/CreateStyleTool.ts +++ b/src/tools/create-style-tool/CreateStyleTool.ts @@ -20,7 +20,7 @@ export class CreateStyleTool extends MapboxApiBasedTool< accessToken?: string ): Promise { const username = MapboxApiBasedTool.getUserNameFromToken(accessToken); - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}?access_token=${accessToken}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}?access_token=${accessToken}`; const payload = { name: input.name, diff --git a/src/tools/create-token-tool/CreateTokenTool.ts b/src/tools/create-token-tool/CreateTokenTool.ts index 94421d6..3256678 100644 --- a/src/tools/create-token-tool/CreateTokenTool.ts +++ b/src/tools/create-token-tool/CreateTokenTool.ts @@ -27,7 +27,7 @@ export class CreateTokenTool extends MapboxApiBasedTool< `CreateTokenTool: Creating public token with note: "${input.note}", scopes: ${JSON.stringify(input.scopes)}` ); - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}tokens/v2/${username}?access_token=${accessToken}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}tokens/v2/${username}?access_token=${accessToken}`; const body: { note: string; diff --git a/src/tools/delete-style-tool/DeleteStyleTool.ts b/src/tools/delete-style-tool/DeleteStyleTool.ts index 276027e..4b08121 100644 --- a/src/tools/delete-style-tool/DeleteStyleTool.ts +++ b/src/tools/delete-style-tool/DeleteStyleTool.ts @@ -19,7 +19,7 @@ export class DeleteStyleTool extends MapboxApiBasedTool< accessToken?: string ): Promise { const username = MapboxApiBasedTool.getUserNameFromToken(accessToken); - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}/${input.styleId}?access_token=${accessToken}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}/${input.styleId}?access_token=${accessToken}`; const response = await fetch(url, { method: 'DELETE' diff --git a/src/tools/list-styles-tool/ListStylesTool.ts b/src/tools/list-styles-tool/ListStylesTool.ts index 5533d06..5d217bd 100644 --- a/src/tools/list-styles-tool/ListStylesTool.ts +++ b/src/tools/list-styles-tool/ListStylesTool.ts @@ -34,7 +34,7 @@ export class ListStylesTool extends MapboxApiBasedTool< params.append('start', input.start); } - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}?${params.toString()}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}?${params.toString()}`; const response = await this.fetchImpl(url); diff --git a/src/tools/list-tokens-tool/ListTokensTool.ts b/src/tools/list-tokens-tool/ListTokensTool.ts index 9283709..2e235d4 100644 --- a/src/tools/list-tokens-tool/ListTokensTool.ts +++ b/src/tools/list-tokens-tool/ListTokensTool.ts @@ -49,7 +49,7 @@ export class ListTokensTool extends MapboxApiBasedTool< } let url: string | null = - `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}tokens/v2/${username}?${params.toString()}`; + `${MapboxApiBasedTool.mapboxApiEndpoint}tokens/v2/${username}?${params.toString()}`; const allTokens: unknown[] = []; let pageCount = 0; let nextPageUrl: string | null = null; diff --git a/src/tools/preview-style-tool/PreviewStyleTool.ts b/src/tools/preview-style-tool/PreviewStyleTool.ts index 32783cd..564d334 100644 --- a/src/tools/preview-style-tool/PreviewStyleTool.ts +++ b/src/tools/preview-style-tool/PreviewStyleTool.ts @@ -41,7 +41,7 @@ export class PreviewStyleTool extends BaseTool { const hashFragment = hashParams.length > 0 ? `#${hashParams.join('/')}` : ''; - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}/${input.styleId}.html?${params.toString()}${hashFragment}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}/${input.styleId}.html?${params.toString()}${hashFragment}`; return { type: 'text', diff --git a/src/tools/retrieve-style-tool/RetrieveStyleTool.ts b/src/tools/retrieve-style-tool/RetrieveStyleTool.ts index b0c59bf..b1fe316 100644 --- a/src/tools/retrieve-style-tool/RetrieveStyleTool.ts +++ b/src/tools/retrieve-style-tool/RetrieveStyleTool.ts @@ -19,7 +19,7 @@ export class RetrieveStyleTool extends MapboxApiBasedTool< accessToken?: string ): Promise { const username = MapboxApiBasedTool.getUserNameFromToken(accessToken); - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}/${input.styleId}?access_token=${accessToken}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}/${input.styleId}?access_token=${accessToken}`; const response = await fetch(url); diff --git a/src/tools/tilequery-tool/TilequeryTool.ts b/src/tools/tilequery-tool/TilequeryTool.ts index 9042dc3..c04f294 100644 --- a/src/tools/tilequery-tool/TilequeryTool.ts +++ b/src/tools/tilequery-tool/TilequeryTool.ts @@ -16,7 +16,7 @@ export class TilequeryTool extends MapboxApiBasedTool { ): Promise { const { tilesetId, longitude, latitude, ...queryParams } = input; const url = new URL( - `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}v4/${tilesetId}/tilequery/${longitude},${latitude}.json` + `${MapboxApiBasedTool.mapboxApiEndpoint}v4/${tilesetId}/tilequery/${longitude},${latitude}.json` ); if (queryParams.radius !== undefined) { diff --git a/src/tools/update-style-tool/UpdateStyleTool.ts b/src/tools/update-style-tool/UpdateStyleTool.ts index 56f9f6a..6fc3e41 100644 --- a/src/tools/update-style-tool/UpdateStyleTool.ts +++ b/src/tools/update-style-tool/UpdateStyleTool.ts @@ -19,7 +19,7 @@ export class UpdateStyleTool extends MapboxApiBasedTool< accessToken?: string ): Promise { const username = MapboxApiBasedTool.getUserNameFromToken(accessToken); - const url = `${MapboxApiBasedTool.MAPBOX_API_ENDPOINT}styles/v1/${username}/${input.styleId}?access_token=${accessToken}`; + const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}/${input.styleId}?access_token=${accessToken}`; const payload: any = {}; if (input.name) payload.name = input.name; diff --git a/test/tools/MapboxApiBasedTool.test.ts b/test/tools/MapboxApiBasedTool.test.ts index e037d00..ff6ed04 100644 --- a/test/tools/MapboxApiBasedTool.test.ts +++ b/test/tools/MapboxApiBasedTool.test.ts @@ -33,10 +33,15 @@ describe('MapboxApiBasedTool', () => { const originalEnv = process.env; beforeEach(() => { - vi.stubEnv( - 'MAPBOX_ACCESS_TOKEN', - `eyJhbGciOiJIUzI1NiJ9.${payload}.signature` - ); + const mockToken = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; + vi.stubEnv('mapboxAccessToken', mockToken); + + // Reset the static property to pick up the new environment variable + Object.defineProperty(MapboxApiBasedTool, 'mapboxAccessToken', { + value: mockToken, + writable: true, + configurable: true + }); testTool = new TestTool(); // Mock the log method to test that errors are properly logged @@ -56,7 +61,7 @@ describe('MapboxApiBasedTool', () => { JSON.stringify({ u: 'myusername' }) ).toString('base64'); const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue(`eyJhbGciOiJIUzI1NiJ9.${testPayload}.signature`); const username = MapboxApiBasedTool.getUserNameFromToken(); @@ -67,7 +72,7 @@ describe('MapboxApiBasedTool', () => { it('throws error when token is not set', () => { const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue(undefined); expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( @@ -79,7 +84,7 @@ describe('MapboxApiBasedTool', () => { it('throws error when token has invalid format', () => { const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue('invalid-token-format'); expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( @@ -95,7 +100,7 @@ describe('MapboxApiBasedTool', () => { ).toString('base64'); const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue(`eyJhbGciOiJIUzI1NiJ9.${invalidPayload}.signature`); expect(() => MapboxApiBasedTool.getUserNameFromToken()).toThrow( @@ -109,7 +114,7 @@ describe('MapboxApiBasedTool', () => { describe('JWT token validation', () => { it('throws an error when the token is not in a valid JWT format', async () => { const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue('invalid-token-format'); // Create a new instance with the modified token @@ -163,7 +168,7 @@ describe('MapboxApiBasedTool', () => { describe('username extraction from token', () => { it('throws error for invalid JWT format', () => { const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue('invalid-token'); expect(() => { @@ -178,7 +183,7 @@ describe('MapboxApiBasedTool', () => { 'eyJhbGciOiJIUzI1NiJ9.eyJhIjoidGVzdC1hcGkifQ.signature'; const spy = vi - .spyOn(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', 'get') + .spyOn(MapboxApiBasedTool, 'mapboxAccessToken', 'get') .mockReturnValue(tokenWithoutUsername); expect(() => { diff --git a/test/tools/create-style-tool/CreateStyleTool.test.ts b/test/tools/create-style-tool/CreateStyleTool.test.ts index a1b5e81..f5beb61 100644 --- a/test/tools/create-style-tool/CreateStyleTool.test.ts +++ b/test/tools/create-style-tool/CreateStyleTool.test.ts @@ -1,13 +1,17 @@ -process.env.MAPBOX_ACCESS_TOKEN = - 'eyJhbGciOiJIUzI1NiJ9.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; - -import { describe, it, expect, vi, afterEach } from 'vitest'; +import { describe, it, expect, vi, afterEach, beforeAll } from 'vitest'; import { setupFetch, assertHeadersSent } from '../../utils/fetchRequestUtils.js'; import { CreateStyleTool } from '../../../src/tools/create-style-tool/CreateStyleTool.js'; +const mockToken = + 'eyJhbGciOiJIUzI1NiJ9.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; + +beforeAll(() => { + process.env.MAPBOX_ACCESS_TOKEN = mockToken; +}); + describe('CreateStyleTool', () => { afterEach(() => { vi.restoreAllMocks(); diff --git a/test/tools/create-token-tool/CreateTokenTool.test.ts b/test/tools/create-token-tool/CreateTokenTool.test.ts index 3590828..6d960c9 100644 --- a/test/tools/create-token-tool/CreateTokenTool.test.ts +++ b/test/tools/create-token-tool/CreateTokenTool.test.ts @@ -1,11 +1,4 @@ -// Set environment variables before any imports -// Create a token with username in the payload -const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( - 'base64' -); -process.env.MAPBOX_ACCESS_TOKEN = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; - -import { describe, it, expect, vi, afterEach } from 'vitest'; +import { describe, it, expect, vi, afterEach, beforeAll } from 'vitest'; import { setupFetch, assertHeadersSent @@ -13,6 +6,16 @@ import { import { MapboxApiBasedTool } from '../../../src/tools/MapboxApiBasedTool.js'; import { CreateTokenTool } from '../../../src/tools/create-token-tool/CreateTokenTool.js'; +// Create a token with username in the payload +const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( + 'base64' +); +const mockToken = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; + +beforeAll(() => { + process.env.MAPBOX_ACCESS_TOKEN = mockToken; +}); + type TextContent = { type: 'text'; text: string }; describe('CreateTokenTool', () => { @@ -96,12 +99,7 @@ describe('CreateTokenTool', () => { ).toString('base64'); const invalidToken = `eyJhbGciOiJIUzI1NiJ9.${invalidPayload}.signature`; - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: invalidToken, - writable: true, - configurable: true - }); - process.env.MAPBOX_ACCESS_TOKEN = invalidToken; + vi.stubEnv('MAPBOX_ACCESS_TOKEN', invalidToken); // Setup fetch mock to prevent actual API calls const { fetch, mockFetch } = setupFetch(); @@ -129,12 +127,10 @@ describe('CreateTokenTool', () => { ); } finally { // Restore - process.env.MAPBOX_ACCESS_TOKEN = originalEnvToken; - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); + vi.unstubAllEnvs(); + if (originalEnvToken) { + vi.stubEnv('MAPBOX_ACCESS_TOKEN', originalEnvToken); + } } }); }); @@ -312,11 +308,7 @@ describe('CreateTokenTool', () => { try { // Temporarily modify the static property - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_API_ENDPOINT', { - value: 'https://api.staging.mapbox.com/', - writable: true, - configurable: true - }); + vi.stubEnv('MAPBOX_API_ENDPOINT', 'https://api.staging.mapbox.com/'); const mockResponse = { token: 'pk.test', @@ -347,11 +339,10 @@ describe('CreateTokenTool', () => { ); } finally { // Restore - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_API_ENDPOINT', { - value: originalEndpoint, - writable: true, - configurable: true - }); + vi.unstubAllEnvs(); + if (originalEndpoint) { + vi.stubEnv('MAPBOX_API_ENDPOINT', originalEndpoint); + } } }); }); diff --git a/test/tools/list-styles-tool/ListStylesTool.test.ts b/test/tools/list-styles-tool/ListStylesTool.test.ts index 6dcc111..2db891e 100644 --- a/test/tools/list-styles-tool/ListStylesTool.test.ts +++ b/test/tools/list-styles-tool/ListStylesTool.test.ts @@ -1,14 +1,16 @@ -// Use a token with valid JWT format for tests -process.env.MAPBOX_ACCESS_TOKEN = - 'sk.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; - -import { describe, it, expect, vi, afterEach } from 'vitest'; +import { describe, it, expect, vi, afterEach, beforeAll } from 'vitest'; import { setupFetch, assertHeadersSent } from '../../utils/fetchRequestUtils.js'; import { ListStylesTool } from '../../../src/tools/list-styles-tool/ListStylesTool.js'; +const mockToken = 'sk.eyJ1IjoidGVzdC11c2VyIiwiYSI6InRlc3QtYXBpIn0.signature'; + +beforeAll(() => { + process.env.MAPBOX_ACCESS_TOKEN = mockToken; +}); + describe('ListStylesTool', () => { afterEach(() => { vi.restoreAllMocks(); diff --git a/test/tools/list-tokens-tool/ListTokensTool.test.ts b/test/tools/list-tokens-tool/ListTokensTool.test.ts index f5a6dfa..ed31e35 100644 --- a/test/tools/list-tokens-tool/ListTokensTool.test.ts +++ b/test/tools/list-tokens-tool/ListTokensTool.test.ts @@ -1,11 +1,4 @@ -// Set environment variables before any imports -// Create a token with username in the payload -const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( - 'base64' -); -process.env.MAPBOX_ACCESS_TOKEN = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; - -import { describe, it, expect, afterEach, vi } from 'vitest'; +import { describe, it, expect, afterEach, vi, beforeAll } from 'vitest'; import { setupFetch, assertHeadersSent @@ -13,6 +6,16 @@ import { import { MapboxApiBasedTool } from '../../../src/tools/MapboxApiBasedTool.js'; import { ListTokensTool } from '../../../src/tools/list-tokens-tool/ListTokensTool.js'; +// Create a token with username in the payload +const payload = Buffer.from(JSON.stringify({ u: 'testuser' })).toString( + 'base64' +); +const mockToken = `eyJhbGciOiJIUzI1NiJ9.${payload}.signature`; + +beforeAll(() => { + process.env.MAPBOX_ACCESS_TOKEN = mockToken; +}); + type TextContent = { type: 'text'; text: string }; describe('ListTokensTool', () => { @@ -87,12 +90,7 @@ describe('ListTokensTool', () => { ).toString('base64'); const invalidToken = `eyJhbGciOiJIUzI1NiJ9.${invalidPayload}.signature`; - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: invalidToken, - writable: true, - configurable: true - }); - process.env.MAPBOX_ACCESS_TOKEN = invalidToken; + vi.stubEnv('MAPBOX_ACCESS_TOKEN', invalidToken); // Setup fetch mock to prevent actual API calls const { mockFetch, fetch } = setupFetch(); @@ -116,12 +114,10 @@ describe('ListTokensTool', () => { ); } finally { // Restore - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_ACCESS_TOKEN', { - value: originalToken, - writable: true, - configurable: true - }); - process.env.MAPBOX_ACCESS_TOKEN = originalEnvToken; + vi.unstubAllEnvs(); + if (originalEnvToken) { + vi.stubEnv('MAPBOX_ACCESS_TOKEN', originalEnvToken); + } } }); }); @@ -488,11 +484,7 @@ describe('ListTokensTool', () => { try { // Temporarily modify the static property - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_API_ENDPOINT', { - value: 'https://api.staging.mapbox.com/', - writable: true, - configurable: true - }); + vi.stubEnv('MAPBOX_API_ENDPOINT', 'https://api.staging.mapbox.com/'); const mockTokens: object[] = []; @@ -513,11 +505,10 @@ describe('ListTokensTool', () => { ); } finally { // Restore - Object.defineProperty(MapboxApiBasedTool, 'MAPBOX_API_ENDPOINT', { - value: originalEndpoint, - writable: true, - configurable: true - }); + vi.unstubAllEnvs(); + if (originalEndpoint) { + vi.stubEnv('MAPBOX_API_ENDPOINT', originalEndpoint); + } } }); From 3a946c0735ea17813676c092c5e2a14f3499ca31 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 10 Sep 2025 09:23:04 -0400 Subject: [PATCH 6/6] [chore] Update manifest --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index ec265a7..974a4f0 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "dxt_version": "0.1", "name": "@mapbox/mcp-devkit-server", "display_name": "Mapbox MCP DevKit Server", - "version": "0.3.2", + "version": "0.4.0", "description": "Mapbox MCP devkit server", "author": { "name": "Mapbox, Inc."