├── .dockerignore ├── .github └── workflows │ └── release.yaml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── eslint.config.mjs ├── package.json ├── pnpm-lock.yaml ├── prettier.config.mjs ├── smithery.yaml ├── src ├── config.ts ├── http.ts ├── index.ts ├── init.ts ├── log.ts ├── middlewares.ts ├── server.ts ├── settings.ts ├── test-connection.ts ├── tool.test.ts ├── tool.ts ├── tools │ ├── index.ts │ ├── redis │ │ ├── backup.ts │ │ ├── command.ts │ │ ├── db.ts │ │ ├── index.ts │ │ └── types.ts │ └── utils.ts └── utils.ts ├── tsconfig.json └── tsup.config.ts /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repo 14 | uses: actions/checkout@v3 15 | 16 | - name: Set env 17 | run: echo "VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV 18 | 19 | - name: Setup pnpm 20 | uses: pnpm/action-setup@v4 21 | with: 22 | version: 10 23 | run_install: false 24 | 25 | - name: Install Node.js 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version: 20 29 | cache: 'pnpm' 30 | 31 | - name: Set package version 32 | run: echo $(jq --arg v "${{ env.VERSION }}" '(.version) = $v' package.json) > package.json 33 | 34 | - name: Install Dependencies 35 | run: pnpm install 36 | 37 | - name: Build 38 | run: pnpm run build 39 | 40 | - name: Set NPM_TOKEN 41 | run: npm set "//registry.npmjs.org/:_authToken" ${{ secrets.NPM_TOKEN }} 42 | 43 | - name: Publish 44 | if: "!github.event.release.prerelease" 45 | run: | 46 | npm publish --access public 47 | 48 | - name: Publish release candidate 49 | if: "github.event.release.prerelease" 50 | run: | 51 | npm publish --access public --tag=canary 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-alpine AS builder 2 | 3 | RUN npm install -g pnpm 4 | 5 | WORKDIR /app 6 | 7 | # Install deps 8 | COPY package.json ./ 9 | COPY pnpm-lock.yaml ./ 10 | 11 | RUN pnpm install 12 | 13 | # Copy rest 14 | COPY . . 15 | 16 | RUN pnpm run build 17 | 18 | FROM node:20-alpine AS release 19 | 20 | RUN npm install -g pnpm 21 | 22 | WORKDIR /app 23 | 24 | # Copy only the necessary files from the builder 25 | COPY --from=builder /app/dist /app/dist 26 | COPY --from=builder /app/package.json /app/package.json 27 | COPY --from=builder /app/pnpm-lock.yaml /app/pnpm-lock.yaml 28 | 29 | # Install only production dependencies 30 | RUN pnpm install --prod 31 | 32 | ENTRYPOINT ["sh", "-c", "if [ -z \"$UPSTASH_EMAIL\" ] || [ -z \"$UPSTASH_API_KEY\" ]; then echo 'Error: Missing required environment variables UPSTASH_EMAIL and UPSTASH_API_KEY'; exit 1; fi; exec node dist/index.js run \"$UPSTASH_EMAIL\" \"$UPSTASH_API_KEY\""] 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021 Upstash, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Upstash MCP Server 2 | 3 | [![smithery badge](https://smithery.ai/badge/@upstash/mcp-server)](https://smithery.ai/server/@upstash/mcp-server) 4 | 5 | Model Context Protocol (MCP) is a [new, standardized protocol](https://modelcontextprotocol.io/introduction) for managing context between large language models (LLMs) and external systems. In this repository, we provide an installer as well as an MCP Server for [Upstash Developer API's](https://upstash.com/docs/devops/developer-api). 6 | 7 | This allows you to use any MCP Client to interact with your Upstash account using natural language, e.g.: 8 | 9 | - "Create a new Redis database in us-east-1" 10 | - "List my databases" 11 | - "List keys starting with "user:" in users-db" 12 | - "Create a backup" 13 | - "Give me the spikes in throughput during the last 7 days" 14 | 15 | # Usage 16 | 17 | ## Requirements 18 | 19 | - Node.js >= v18.0.0 20 | - [Upstash API key](https://upstash.com/docs/devops/developer-api) - You can create one from [here](https://console.upstash.com/account/api). 21 | 22 | ## How to use locally 23 | 24 | ### Installing for Claude Desktop 25 | 26 | To install Upstash MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server) run the following command: 27 | 28 | ```bash 29 | npx -y @smithery/cli@latest install @upstash/mcp-server --client claude 30 | ``` 31 | 32 |
33 | Install without Smithery 34 | 35 | ```bash 36 | npx @upstash/mcp-server init 37 | ``` 38 | 39 | This will edit your MCP config file and add an entry for Upstash. 40 | 41 |
42 | 43 | ### Installing for Cursor 44 | 45 | To install Upstash MCP Server for Cursor automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server) run the following command: 46 | 47 | ```bash 48 | npx -y @smithery/cli@latest install @upstash/mcp-server --client cursor 49 | ``` 50 | 51 |
52 | Install without Smithery 53 | 54 | Add the following command to the MCP config in Cursor. For more info, check the [Cursor MCP docs](https://docs.cursor.com/context/model-context-protocol#configuring-mcp-servers). 55 | 56 | ```bash 57 | npx -y @upstash/mcp-server run 58 | ``` 59 | 60 |
61 | 62 | ### Installing for Windsurf 63 | 64 | To install Upstash MCP Server for Windsurf automatically via [Smithery](https://smithery.ai/server/@upstash/mcp-server) run the following command: 65 | 66 | ```bash 67 | npx -y @smithery/cli@latest install @upstash/mcp-server --client windsurf 68 | ``` 69 | 70 |
71 | Install without Smithery 72 | 73 | Add the following command to the MCP config in Windsurf. For more info, check out the [Windsurf MCP docs](https://docs.windsurf.com/windsurf/mcp#mcp-config-json). 74 | 75 | ```bash 76 | npx -y @upstash/mcp-server run 77 | ``` 78 | 79 |
80 | 81 | ### Running with Docker 82 | 83 | You can also use the provided Docker image to run the server. 84 | 85 | ```bash 86 | docker build -t upstash-mcp . 87 | 88 | # Run the stdio server, add this command to you MCP config 89 | docker run --rm -i \ 90 | -e UPSTASH_EMAIL= \ 91 | -e UPSTASH_API_KEY= \ 92 | upstash-mcp 93 | ``` 94 | 95 | ### Troubleshooting 96 | 97 | #### Common Issues 98 | 99 | Your mcp client might have trouble finding the right binaries because of the differences between your shell and system `PATH`. 100 | 101 | To fix this, you can get the full path of the binaries by running `which npx` or `which docker` in your shell, and replace the `npx` or `docker` command in the MCP config with the full binary path. 102 | 103 | #### Node Version Manager 104 | 105 | If you are using a node version manager like nvm or fnm, please check [this issue](https://github.com/modelcontextprotocol/servers/issues/64#issuecomment-2530337743). You should change the `node` command in the MCP config to the absolute path of the node binary. 106 | 107 | #### Additional Troubleshooting 108 | 109 | See the [troubleshooting guide](https://modelcontextprotocol.io/quickstart#troubleshooting) in the MCP documentation. You can also reach out to us at [Discord](https://discord.com/invite/w9SenAtbme). 110 | 111 | ## Tools 112 | 113 | ### Redis 114 | 115 | - `redis_database_create_backup` 116 | - `redis_database_create_new` 117 | - `redis_database_delete` 118 | - `redis_database_delete_backup` 119 | - `redis_database_get_details` 120 | - `redis_database_list_backups` 121 | - `redis_database_list_databases` 122 | - `redis_database_reset_password` 123 | - `redis_database_restore_backup` 124 | - `redis_database_run_multiple_redis_commands` 125 | - `redis_database_run_single_redis_command` 126 | - `redis_database_set_daily_backup` 127 | - `redis_database_update_regions` 128 | - `redis_database_get_usage_last_5_days` 129 | - `redis_database_get_stats` 130 | 131 | ## Development 132 | 133 | Clone the project and run: 134 | 135 | ```bash 136 | pnpm install 137 | pnpm run watch 138 | ``` 139 | 140 | This will continuously build the project and watch for changes. 141 | 142 | For testing, you can create a `.env` file in the same directory as the project with the following content: 143 | 144 | ```bash 145 | UPSTASH_EMAIL= 146 | UPSTASH_API_KEY= 147 | ``` 148 | 149 | This will be used for setting the Claude config and running mcp inspector. 150 | 151 | ### Testing with Claude Desktop 152 | 153 | To install the Claude Desktop config for local development, run the following command: 154 | 155 | ```bash 156 | pnpm run setup 157 | ``` 158 | 159 | This will add an `upstash` entry to your MCP config file that points to the local build of the package. 160 | 161 | ```json 162 | { 163 | "upstash": { 164 | "command": "node", 165 | "args": ["/dist/index.js", "run", "", ""] 166 | } 167 | } 168 | ``` 169 | 170 | > NOTE: The same issue with node version manager applies here. Please look at the note in the usage section if you are using a node version manager. 171 | 172 | You can now use Claude Desktop to run Upstash commands. 173 | 174 | To view the logs from the MCP Server in real time, run the following command: 175 | 176 | ```bash 177 | pnpm run logs 178 | ``` 179 | 180 | ### Testing with MCP Inspector 181 | 182 | You can also use the MCP Inspector to test the tools. 183 | 184 | ```bash 185 | pnpm run inspector 186 | ``` 187 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import typescriptEslint from "@typescript-eslint/eslint-plugin"; 2 | import unicorn from "eslint-plugin-unicorn"; 3 | import path from "node:path"; 4 | import { fileURLToPath } from "node:url"; 5 | import js from "@eslint/js"; 6 | import { FlatCompat } from "@eslint/eslintrc"; 7 | 8 | const __filename = fileURLToPath(import.meta.url); 9 | const __dirname = path.dirname(__filename); 10 | const compat = new FlatCompat({ 11 | baseDirectory: __dirname, 12 | recommendedConfig: js.configs.recommended, 13 | allConfig: js.configs.all, 14 | }); 15 | 16 | export default [ 17 | { 18 | ignores: ["**/*.config.*", "**/examples", "**/dist"], 19 | }, 20 | ...compat.extends( 21 | "eslint:recommended", 22 | "plugin:unicorn/recommended", 23 | "plugin:@typescript-eslint/recommended" 24 | ), 25 | { 26 | plugins: { 27 | "@typescript-eslint": typescriptEslint, 28 | unicorn, 29 | }, 30 | 31 | languageOptions: { 32 | globals: {}, 33 | ecmaVersion: 5, 34 | sourceType: "script", 35 | 36 | parserOptions: { 37 | project: "./tsconfig.json", 38 | }, 39 | }, 40 | 41 | rules: { 42 | "no-console": [ 43 | "error", 44 | { 45 | allow: ["warn", "error"], 46 | }, 47 | ], 48 | 49 | "@typescript-eslint/no-magic-numbers": "off", 50 | "@typescript-eslint/unbound-method": "off", 51 | "@typescript-eslint/prefer-as-const": "error", 52 | "@typescript-eslint/consistent-type-imports": "error", 53 | "@typescript-eslint/no-explicit-any": "off", 54 | "@typescript-eslint/restrict-template-expressions": "off", 55 | 56 | "@typescript-eslint/no-unused-vars": [ 57 | "error", 58 | { 59 | varsIgnorePattern: "^_", 60 | argsIgnorePattern: "^_", 61 | }, 62 | ], 63 | 64 | "@typescript-eslint/prefer-ts-expect-error": "off", 65 | 66 | "@typescript-eslint/no-misused-promises": [ 67 | "error", 68 | { 69 | checksVoidReturn: false, 70 | }, 71 | ], 72 | 73 | "unicorn/prevent-abbreviations": "off", 74 | 75 | "no-implicit-coercion": [ 76 | "error", 77 | { 78 | boolean: true, 79 | }, 80 | ], 81 | 82 | "no-extra-boolean-cast": [ 83 | "error", 84 | { 85 | enforceForLogicalOperands: true, 86 | }, 87 | ], 88 | 89 | "no-unneeded-ternary": [ 90 | "error", 91 | { 92 | defaultAssignment: true, 93 | }, 94 | ], 95 | 96 | "unicorn/no-array-reduce": ["off"], 97 | "unicorn/no-nested-ternary": "off", 98 | "unicorn/no-null": "off", 99 | "unicorn/filename-case": "off", 100 | }, 101 | }, 102 | ]; 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "name": "@upstash/mcp-server", 4 | "description": "MCP server for Upstash", 5 | "license": "MIT", 6 | "type": "module", 7 | "bin": { 8 | "mcp-server": "./dist/index.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/upstash/mcp-server.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/upstash/mcp-server/issues" 16 | }, 17 | "scripts": { 18 | "build": "tsup && node -e \"require('fs').chmodSync('dist/index.js', '755')\"", 19 | "watch": "npm run build && tsup --watch", 20 | "inspector": "npx @modelcontextprotocol/inspector node --enable-source-maps dist/index.js run", 21 | "setup": "node ./dist/index.js init", 22 | "logs": "tail -n 20 -f ~/Library/Logs/Claude/mcp*.log", 23 | "fmt": "prettier --write .", 24 | "test": "vitest", 25 | "lint": "eslint \"**/*.{js,ts,tsx}\" --quiet --fix" 26 | }, 27 | "files": [ 28 | "dist" 29 | ], 30 | "devDependencies": { 31 | "@typescript-eslint/eslint-plugin": "8.4.0", 32 | "@typescript-eslint/parser": "8.4.0", 33 | "eslint": "9.10.0", 34 | "eslint-plugin-unicorn": "55.0.0", 35 | "prettier": "^3.4.2", 36 | "tsup": "^8.3.5", 37 | "vitest": "^3.1.1" 38 | }, 39 | "dependencies": { 40 | "@modelcontextprotocol/sdk": "^1.8.0", 41 | "@types/node": "15", 42 | "chalk": "^5.3.0", 43 | "dotenv": "^16.4.7", 44 | "node-fetch": "^3.3.2", 45 | "zod": "^3.24.1", 46 | "zod-to-json-schema": "^3.24.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@modelcontextprotocol/sdk': 12 | specifier: ^1.8.0 13 | version: 1.8.0 14 | '@types/node': 15 | specifier: '15' 16 | version: 15.14.9 17 | chalk: 18 | specifier: ^5.3.0 19 | version: 5.3.0 20 | dotenv: 21 | specifier: ^16.4.7 22 | version: 16.4.7 23 | node-fetch: 24 | specifier: ^3.3.2 25 | version: 3.3.2 26 | zod: 27 | specifier: ^3.24.1 28 | version: 3.24.1 29 | zod-to-json-schema: 30 | specifier: ^3.24.1 31 | version: 3.24.1(zod@3.24.1) 32 | devDependencies: 33 | '@typescript-eslint/eslint-plugin': 34 | specifier: 8.4.0 35 | version: 8.4.0(@typescript-eslint/parser@8.4.0(eslint@9.10.0)(typescript@5.8.2))(eslint@9.10.0)(typescript@5.8.2) 36 | '@typescript-eslint/parser': 37 | specifier: 8.4.0 38 | version: 8.4.0(eslint@9.10.0)(typescript@5.8.2) 39 | eslint: 40 | specifier: 9.10.0 41 | version: 9.10.0 42 | eslint-plugin-unicorn: 43 | specifier: 55.0.0 44 | version: 55.0.0(eslint@9.10.0) 45 | prettier: 46 | specifier: ^3.4.2 47 | version: 3.4.2 48 | tsup: 49 | specifier: ^8.3.5 50 | version: 8.4.0(postcss@8.5.3)(typescript@5.8.2) 51 | vitest: 52 | specifier: ^3.1.1 53 | version: 3.1.1(@types/node@15.14.9) 54 | 55 | packages: 56 | 57 | '@babel/code-frame@7.26.2': 58 | resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} 59 | engines: {node: '>=6.9.0'} 60 | 61 | '@babel/helper-validator-identifier@7.25.9': 62 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 63 | engines: {node: '>=6.9.0'} 64 | 65 | '@esbuild/aix-ppc64@0.25.2': 66 | resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} 67 | engines: {node: '>=18'} 68 | cpu: [ppc64] 69 | os: [aix] 70 | 71 | '@esbuild/android-arm64@0.25.2': 72 | resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} 73 | engines: {node: '>=18'} 74 | cpu: [arm64] 75 | os: [android] 76 | 77 | '@esbuild/android-arm@0.25.2': 78 | resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} 79 | engines: {node: '>=18'} 80 | cpu: [arm] 81 | os: [android] 82 | 83 | '@esbuild/android-x64@0.25.2': 84 | resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} 85 | engines: {node: '>=18'} 86 | cpu: [x64] 87 | os: [android] 88 | 89 | '@esbuild/darwin-arm64@0.25.2': 90 | resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} 91 | engines: {node: '>=18'} 92 | cpu: [arm64] 93 | os: [darwin] 94 | 95 | '@esbuild/darwin-x64@0.25.2': 96 | resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} 97 | engines: {node: '>=18'} 98 | cpu: [x64] 99 | os: [darwin] 100 | 101 | '@esbuild/freebsd-arm64@0.25.2': 102 | resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} 103 | engines: {node: '>=18'} 104 | cpu: [arm64] 105 | os: [freebsd] 106 | 107 | '@esbuild/freebsd-x64@0.25.2': 108 | resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} 109 | engines: {node: '>=18'} 110 | cpu: [x64] 111 | os: [freebsd] 112 | 113 | '@esbuild/linux-arm64@0.25.2': 114 | resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} 115 | engines: {node: '>=18'} 116 | cpu: [arm64] 117 | os: [linux] 118 | 119 | '@esbuild/linux-arm@0.25.2': 120 | resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} 121 | engines: {node: '>=18'} 122 | cpu: [arm] 123 | os: [linux] 124 | 125 | '@esbuild/linux-ia32@0.25.2': 126 | resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} 127 | engines: {node: '>=18'} 128 | cpu: [ia32] 129 | os: [linux] 130 | 131 | '@esbuild/linux-loong64@0.25.2': 132 | resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} 133 | engines: {node: '>=18'} 134 | cpu: [loong64] 135 | os: [linux] 136 | 137 | '@esbuild/linux-mips64el@0.25.2': 138 | resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} 139 | engines: {node: '>=18'} 140 | cpu: [mips64el] 141 | os: [linux] 142 | 143 | '@esbuild/linux-ppc64@0.25.2': 144 | resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} 145 | engines: {node: '>=18'} 146 | cpu: [ppc64] 147 | os: [linux] 148 | 149 | '@esbuild/linux-riscv64@0.25.2': 150 | resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} 151 | engines: {node: '>=18'} 152 | cpu: [riscv64] 153 | os: [linux] 154 | 155 | '@esbuild/linux-s390x@0.25.2': 156 | resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} 157 | engines: {node: '>=18'} 158 | cpu: [s390x] 159 | os: [linux] 160 | 161 | '@esbuild/linux-x64@0.25.2': 162 | resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} 163 | engines: {node: '>=18'} 164 | cpu: [x64] 165 | os: [linux] 166 | 167 | '@esbuild/netbsd-arm64@0.25.2': 168 | resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} 169 | engines: {node: '>=18'} 170 | cpu: [arm64] 171 | os: [netbsd] 172 | 173 | '@esbuild/netbsd-x64@0.25.2': 174 | resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} 175 | engines: {node: '>=18'} 176 | cpu: [x64] 177 | os: [netbsd] 178 | 179 | '@esbuild/openbsd-arm64@0.25.2': 180 | resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} 181 | engines: {node: '>=18'} 182 | cpu: [arm64] 183 | os: [openbsd] 184 | 185 | '@esbuild/openbsd-x64@0.25.2': 186 | resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} 187 | engines: {node: '>=18'} 188 | cpu: [x64] 189 | os: [openbsd] 190 | 191 | '@esbuild/sunos-x64@0.25.2': 192 | resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} 193 | engines: {node: '>=18'} 194 | cpu: [x64] 195 | os: [sunos] 196 | 197 | '@esbuild/win32-arm64@0.25.2': 198 | resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} 199 | engines: {node: '>=18'} 200 | cpu: [arm64] 201 | os: [win32] 202 | 203 | '@esbuild/win32-ia32@0.25.2': 204 | resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} 205 | engines: {node: '>=18'} 206 | cpu: [ia32] 207 | os: [win32] 208 | 209 | '@esbuild/win32-x64@0.25.2': 210 | resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} 211 | engines: {node: '>=18'} 212 | cpu: [x64] 213 | os: [win32] 214 | 215 | '@eslint-community/eslint-utils@4.5.1': 216 | resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} 217 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 218 | peerDependencies: 219 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 220 | 221 | '@eslint-community/regexpp@4.12.1': 222 | resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 223 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 224 | 225 | '@eslint/config-array@0.18.0': 226 | resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} 227 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 228 | 229 | '@eslint/eslintrc@3.3.1': 230 | resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 231 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 232 | 233 | '@eslint/js@9.10.0': 234 | resolution: {integrity: sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==} 235 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 236 | 237 | '@eslint/object-schema@2.1.6': 238 | resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} 239 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 240 | 241 | '@eslint/plugin-kit@0.1.0': 242 | resolution: {integrity: sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==} 243 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 244 | 245 | '@humanwhocodes/module-importer@1.0.1': 246 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 247 | engines: {node: '>=12.22'} 248 | 249 | '@humanwhocodes/retry@0.3.1': 250 | resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} 251 | engines: {node: '>=18.18'} 252 | 253 | '@isaacs/cliui@8.0.2': 254 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 255 | engines: {node: '>=12'} 256 | 257 | '@jridgewell/gen-mapping@0.3.8': 258 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} 259 | engines: {node: '>=6.0.0'} 260 | 261 | '@jridgewell/resolve-uri@3.1.2': 262 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 263 | engines: {node: '>=6.0.0'} 264 | 265 | '@jridgewell/set-array@1.2.1': 266 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 267 | engines: {node: '>=6.0.0'} 268 | 269 | '@jridgewell/sourcemap-codec@1.5.0': 270 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 271 | 272 | '@jridgewell/trace-mapping@0.3.25': 273 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 274 | 275 | '@modelcontextprotocol/sdk@1.8.0': 276 | resolution: {integrity: sha512-e06W7SwrontJDHwCawNO5SGxG+nU9AAx+jpHHZqGl/WrDBdWOpvirC+s58VpJTB5QemI4jTRcjWT4Pt3Q1NPQQ==} 277 | engines: {node: '>=18'} 278 | 279 | '@nodelib/fs.scandir@2.1.5': 280 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 281 | engines: {node: '>= 8'} 282 | 283 | '@nodelib/fs.stat@2.0.5': 284 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 285 | engines: {node: '>= 8'} 286 | 287 | '@nodelib/fs.walk@1.2.8': 288 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 289 | engines: {node: '>= 8'} 290 | 291 | '@pkgjs/parseargs@0.11.0': 292 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 293 | engines: {node: '>=14'} 294 | 295 | '@rollup/rollup-android-arm-eabi@4.38.0': 296 | resolution: {integrity: sha512-ldomqc4/jDZu/xpYU+aRxo3V4mGCV9HeTgUBANI3oIQMOL+SsxB+S2lxMpkFp5UamSS3XuTMQVbsS24R4J4Qjg==} 297 | cpu: [arm] 298 | os: [android] 299 | 300 | '@rollup/rollup-android-arm64@4.38.0': 301 | resolution: {integrity: sha512-VUsgcy4GhhT7rokwzYQP+aV9XnSLkkhlEJ0St8pbasuWO/vwphhZQxYEKUP3ayeCYLhk6gEtacRpYP/cj3GjyQ==} 302 | cpu: [arm64] 303 | os: [android] 304 | 305 | '@rollup/rollup-darwin-arm64@4.38.0': 306 | resolution: {integrity: sha512-buA17AYXlW9Rn091sWMq1xGUvWQFOH4N1rqUxGJtEQzhChxWjldGCCup7r/wUnaI6Au8sKXpoh0xg58a7cgcpg==} 307 | cpu: [arm64] 308 | os: [darwin] 309 | 310 | '@rollup/rollup-darwin-x64@4.38.0': 311 | resolution: {integrity: sha512-Mgcmc78AjunP1SKXl624vVBOF2bzwNWFPMP4fpOu05vS0amnLcX8gHIge7q/lDAHy3T2HeR0TqrriZDQS2Woeg==} 312 | cpu: [x64] 313 | os: [darwin] 314 | 315 | '@rollup/rollup-freebsd-arm64@4.38.0': 316 | resolution: {integrity: sha512-zzJACgjLbQTsscxWqvrEQAEh28hqhebpRz5q/uUd1T7VTwUNZ4VIXQt5hE7ncs0GrF+s7d3S4on4TiXUY8KoQA==} 317 | cpu: [arm64] 318 | os: [freebsd] 319 | 320 | '@rollup/rollup-freebsd-x64@4.38.0': 321 | resolution: {integrity: sha512-hCY/KAeYMCyDpEE4pTETam0XZS4/5GXzlLgpi5f0IaPExw9kuB+PDTOTLuPtM10TlRG0U9OSmXJ+Wq9J39LvAg==} 322 | cpu: [x64] 323 | os: [freebsd] 324 | 325 | '@rollup/rollup-linux-arm-gnueabihf@4.38.0': 326 | resolution: {integrity: sha512-mimPH43mHl4JdOTD7bUMFhBdrg6f9HzMTOEnzRmXbOZqjijCw8LA5z8uL6LCjxSa67H2xiLFvvO67PT05PRKGg==} 327 | cpu: [arm] 328 | os: [linux] 329 | 330 | '@rollup/rollup-linux-arm-musleabihf@4.38.0': 331 | resolution: {integrity: sha512-tPiJtiOoNuIH8XGG8sWoMMkAMm98PUwlriOFCCbZGc9WCax+GLeVRhmaxjJtz6WxrPKACgrwoZ5ia/uapq3ZVg==} 332 | cpu: [arm] 333 | os: [linux] 334 | 335 | '@rollup/rollup-linux-arm64-gnu@4.38.0': 336 | resolution: {integrity: sha512-wZco59rIVuB0tjQS0CSHTTUcEde+pXQWugZVxWaQFdQQ1VYub/sTrNdY76D1MKdN2NB48JDuGABP6o6fqos8mA==} 337 | cpu: [arm64] 338 | os: [linux] 339 | 340 | '@rollup/rollup-linux-arm64-musl@4.38.0': 341 | resolution: {integrity: sha512-fQgqwKmW0REM4LomQ+87PP8w8xvU9LZfeLBKybeli+0yHT7VKILINzFEuggvnV9M3x1Ed4gUBmGUzCo/ikmFbQ==} 342 | cpu: [arm64] 343 | os: [linux] 344 | 345 | '@rollup/rollup-linux-loongarch64-gnu@4.38.0': 346 | resolution: {integrity: sha512-hz5oqQLXTB3SbXpfkKHKXLdIp02/w3M+ajp8p4yWOWwQRtHWiEOCKtc9U+YXahrwdk+3qHdFMDWR5k+4dIlddg==} 347 | cpu: [loong64] 348 | os: [linux] 349 | 350 | '@rollup/rollup-linux-powerpc64le-gnu@4.38.0': 351 | resolution: {integrity: sha512-NXqygK/dTSibQ+0pzxsL3r4Xl8oPqVoWbZV9niqOnIHV/J92fe65pOir0xjkUZDRSPyFRvu+4YOpJF9BZHQImw==} 352 | cpu: [ppc64] 353 | os: [linux] 354 | 355 | '@rollup/rollup-linux-riscv64-gnu@4.38.0': 356 | resolution: {integrity: sha512-GEAIabR1uFyvf/jW/5jfu8gjM06/4kZ1W+j1nWTSSB3w6moZEBm7iBtzwQ3a1Pxos2F7Gz+58aVEnZHU295QTg==} 357 | cpu: [riscv64] 358 | os: [linux] 359 | 360 | '@rollup/rollup-linux-riscv64-musl@4.38.0': 361 | resolution: {integrity: sha512-9EYTX+Gus2EGPbfs+fh7l95wVADtSQyYw4DfSBcYdUEAmP2lqSZY0Y17yX/3m5VKGGJ4UmIH5LHLkMJft3bYoA==} 362 | cpu: [riscv64] 363 | os: [linux] 364 | 365 | '@rollup/rollup-linux-s390x-gnu@4.38.0': 366 | resolution: {integrity: sha512-Mpp6+Z5VhB9VDk7RwZXoG2qMdERm3Jw07RNlXHE0bOnEeX+l7Fy4bg+NxfyN15ruuY3/7Vrbpm75J9QHFqj5+Q==} 367 | cpu: [s390x] 368 | os: [linux] 369 | 370 | '@rollup/rollup-linux-x64-gnu@4.38.0': 371 | resolution: {integrity: sha512-vPvNgFlZRAgO7rwncMeE0+8c4Hmc+qixnp00/Uv3ht2x7KYrJ6ERVd3/R0nUtlE6/hu7/HiiNHJ/rP6knRFt1w==} 372 | cpu: [x64] 373 | os: [linux] 374 | 375 | '@rollup/rollup-linux-x64-musl@4.38.0': 376 | resolution: {integrity: sha512-q5Zv+goWvQUGCaL7fU8NuTw8aydIL/C9abAVGCzRReuj5h30TPx4LumBtAidrVOtXnlB+RZkBtExMsfqkMfb8g==} 377 | cpu: [x64] 378 | os: [linux] 379 | 380 | '@rollup/rollup-win32-arm64-msvc@4.38.0': 381 | resolution: {integrity: sha512-u/Jbm1BU89Vftqyqbmxdq14nBaQjQX1HhmsdBWqSdGClNaKwhjsg5TpW+5Ibs1mb8Es9wJiMdl86BcmtUVXNZg==} 382 | cpu: [arm64] 383 | os: [win32] 384 | 385 | '@rollup/rollup-win32-ia32-msvc@4.38.0': 386 | resolution: {integrity: sha512-mqu4PzTrlpNHHbu5qleGvXJoGgHpChBlrBx/mEhTPpnAL1ZAYFlvHD7rLK839LLKQzqEQMFJfGrrOHItN4ZQqA==} 387 | cpu: [ia32] 388 | os: [win32] 389 | 390 | '@rollup/rollup-win32-x64-msvc@4.38.0': 391 | resolution: {integrity: sha512-jjqy3uWlecfB98Psxb5cD6Fny9Fupv9LrDSPTQZUROqjvZmcCqNu4UMl7qqhlUUGpwiAkotj6GYu4SZdcr/nLw==} 392 | cpu: [x64] 393 | os: [win32] 394 | 395 | '@types/estree@1.0.7': 396 | resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} 397 | 398 | '@types/node@15.14.9': 399 | resolution: {integrity: sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==} 400 | 401 | '@types/normalize-package-data@2.4.4': 402 | resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} 403 | 404 | '@typescript-eslint/eslint-plugin@8.4.0': 405 | resolution: {integrity: sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==} 406 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 407 | peerDependencies: 408 | '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 409 | eslint: ^8.57.0 || ^9.0.0 410 | typescript: '*' 411 | peerDependenciesMeta: 412 | typescript: 413 | optional: true 414 | 415 | '@typescript-eslint/parser@8.4.0': 416 | resolution: {integrity: sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==} 417 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 418 | peerDependencies: 419 | eslint: ^8.57.0 || ^9.0.0 420 | typescript: '*' 421 | peerDependenciesMeta: 422 | typescript: 423 | optional: true 424 | 425 | '@typescript-eslint/scope-manager@8.4.0': 426 | resolution: {integrity: sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==} 427 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 428 | 429 | '@typescript-eslint/type-utils@8.4.0': 430 | resolution: {integrity: sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==} 431 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 432 | peerDependencies: 433 | typescript: '*' 434 | peerDependenciesMeta: 435 | typescript: 436 | optional: true 437 | 438 | '@typescript-eslint/types@8.4.0': 439 | resolution: {integrity: sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==} 440 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 441 | 442 | '@typescript-eslint/typescript-estree@8.4.0': 443 | resolution: {integrity: sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==} 444 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 445 | peerDependencies: 446 | typescript: '*' 447 | peerDependenciesMeta: 448 | typescript: 449 | optional: true 450 | 451 | '@typescript-eslint/utils@8.4.0': 452 | resolution: {integrity: sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==} 453 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 454 | peerDependencies: 455 | eslint: ^8.57.0 || ^9.0.0 456 | 457 | '@typescript-eslint/visitor-keys@8.4.0': 458 | resolution: {integrity: sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==} 459 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 460 | 461 | '@vitest/expect@3.1.1': 462 | resolution: {integrity: sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==} 463 | 464 | '@vitest/mocker@3.1.1': 465 | resolution: {integrity: sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==} 466 | peerDependencies: 467 | msw: ^2.4.9 468 | vite: ^5.0.0 || ^6.0.0 469 | peerDependenciesMeta: 470 | msw: 471 | optional: true 472 | vite: 473 | optional: true 474 | 475 | '@vitest/pretty-format@3.1.1': 476 | resolution: {integrity: sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==} 477 | 478 | '@vitest/runner@3.1.1': 479 | resolution: {integrity: sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==} 480 | 481 | '@vitest/snapshot@3.1.1': 482 | resolution: {integrity: sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==} 483 | 484 | '@vitest/spy@3.1.1': 485 | resolution: {integrity: sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==} 486 | 487 | '@vitest/utils@3.1.1': 488 | resolution: {integrity: sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==} 489 | 490 | accepts@2.0.0: 491 | resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} 492 | engines: {node: '>= 0.6'} 493 | 494 | acorn-jsx@5.3.2: 495 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 496 | peerDependencies: 497 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 498 | 499 | acorn@8.14.1: 500 | resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} 501 | engines: {node: '>=0.4.0'} 502 | hasBin: true 503 | 504 | ajv@6.12.6: 505 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 506 | 507 | ansi-regex@5.0.1: 508 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 509 | engines: {node: '>=8'} 510 | 511 | ansi-regex@6.1.0: 512 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 513 | engines: {node: '>=12'} 514 | 515 | ansi-styles@4.3.0: 516 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 517 | engines: {node: '>=8'} 518 | 519 | ansi-styles@6.2.1: 520 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 521 | engines: {node: '>=12'} 522 | 523 | any-promise@1.3.0: 524 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 525 | 526 | argparse@2.0.1: 527 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 528 | 529 | assertion-error@2.0.1: 530 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 531 | engines: {node: '>=12'} 532 | 533 | balanced-match@1.0.2: 534 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 535 | 536 | body-parser@2.2.0: 537 | resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} 538 | engines: {node: '>=18'} 539 | 540 | brace-expansion@1.1.11: 541 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} 542 | 543 | brace-expansion@2.0.1: 544 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 545 | 546 | braces@3.0.3: 547 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 548 | engines: {node: '>=8'} 549 | 550 | browserslist@4.24.4: 551 | resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} 552 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 553 | hasBin: true 554 | 555 | builtin-modules@3.3.0: 556 | resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} 557 | engines: {node: '>=6'} 558 | 559 | bundle-require@5.1.0: 560 | resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} 561 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 562 | peerDependencies: 563 | esbuild: '>=0.18' 564 | 565 | bytes@3.1.2: 566 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} 567 | engines: {node: '>= 0.8'} 568 | 569 | cac@6.7.14: 570 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 571 | engines: {node: '>=8'} 572 | 573 | call-bind-apply-helpers@1.0.2: 574 | resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} 575 | engines: {node: '>= 0.4'} 576 | 577 | call-bound@1.0.4: 578 | resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} 579 | engines: {node: '>= 0.4'} 580 | 581 | callsites@3.1.0: 582 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 583 | engines: {node: '>=6'} 584 | 585 | caniuse-lite@1.0.30001707: 586 | resolution: {integrity: sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==} 587 | 588 | chai@5.2.0: 589 | resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} 590 | engines: {node: '>=12'} 591 | 592 | chalk@4.1.2: 593 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 594 | engines: {node: '>=10'} 595 | 596 | chalk@5.3.0: 597 | resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} 598 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 599 | 600 | check-error@2.1.1: 601 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 602 | engines: {node: '>= 16'} 603 | 604 | chokidar@4.0.3: 605 | resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} 606 | engines: {node: '>= 14.16.0'} 607 | 608 | ci-info@4.2.0: 609 | resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} 610 | engines: {node: '>=8'} 611 | 612 | clean-regexp@1.0.0: 613 | resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} 614 | engines: {node: '>=4'} 615 | 616 | color-convert@2.0.1: 617 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 618 | engines: {node: '>=7.0.0'} 619 | 620 | color-name@1.1.4: 621 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 622 | 623 | commander@4.1.1: 624 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 625 | engines: {node: '>= 6'} 626 | 627 | concat-map@0.0.1: 628 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 629 | 630 | consola@3.4.2: 631 | resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} 632 | engines: {node: ^14.18.0 || >=16.10.0} 633 | 634 | content-disposition@1.0.0: 635 | resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} 636 | engines: {node: '>= 0.6'} 637 | 638 | content-type@1.0.5: 639 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} 640 | engines: {node: '>= 0.6'} 641 | 642 | cookie-signature@1.2.2: 643 | resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} 644 | engines: {node: '>=6.6.0'} 645 | 646 | cookie@0.7.2: 647 | resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} 648 | engines: {node: '>= 0.6'} 649 | 650 | core-js-compat@3.41.0: 651 | resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} 652 | 653 | cors@2.8.5: 654 | resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} 655 | engines: {node: '>= 0.10'} 656 | 657 | cross-spawn@7.0.6: 658 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 659 | engines: {node: '>= 8'} 660 | 661 | data-uri-to-buffer@4.0.1: 662 | resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} 663 | engines: {node: '>= 12'} 664 | 665 | debug@4.4.0: 666 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 667 | engines: {node: '>=6.0'} 668 | peerDependencies: 669 | supports-color: '*' 670 | peerDependenciesMeta: 671 | supports-color: 672 | optional: true 673 | 674 | deep-eql@5.0.2: 675 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 676 | engines: {node: '>=6'} 677 | 678 | deep-is@0.1.4: 679 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 680 | 681 | depd@2.0.0: 682 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} 683 | engines: {node: '>= 0.8'} 684 | 685 | dotenv@16.4.7: 686 | resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} 687 | engines: {node: '>=12'} 688 | 689 | dunder-proto@1.0.1: 690 | resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} 691 | engines: {node: '>= 0.4'} 692 | 693 | eastasianwidth@0.2.0: 694 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 695 | 696 | ee-first@1.1.1: 697 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} 698 | 699 | electron-to-chromium@1.5.129: 700 | resolution: {integrity: sha512-JlXUemX4s0+9f8mLqib/bHH8gOHf5elKS6KeWG3sk3xozb/JTq/RLXIv8OKUWiK4Ah00Wm88EFj5PYkFr4RUPA==} 701 | 702 | emoji-regex@8.0.0: 703 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 704 | 705 | emoji-regex@9.2.2: 706 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 707 | 708 | encodeurl@2.0.0: 709 | resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} 710 | engines: {node: '>= 0.8'} 711 | 712 | error-ex@1.3.2: 713 | resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} 714 | 715 | es-define-property@1.0.1: 716 | resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} 717 | engines: {node: '>= 0.4'} 718 | 719 | es-errors@1.3.0: 720 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} 721 | engines: {node: '>= 0.4'} 722 | 723 | es-module-lexer@1.6.0: 724 | resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} 725 | 726 | es-object-atoms@1.1.1: 727 | resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} 728 | engines: {node: '>= 0.4'} 729 | 730 | esbuild@0.25.2: 731 | resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} 732 | engines: {node: '>=18'} 733 | hasBin: true 734 | 735 | escalade@3.2.0: 736 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 737 | engines: {node: '>=6'} 738 | 739 | escape-html@1.0.3: 740 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} 741 | 742 | escape-string-regexp@1.0.5: 743 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 744 | engines: {node: '>=0.8.0'} 745 | 746 | escape-string-regexp@4.0.0: 747 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 748 | engines: {node: '>=10'} 749 | 750 | eslint-plugin-unicorn@55.0.0: 751 | resolution: {integrity: sha512-n3AKiVpY2/uDcGrS3+QsYDkjPfaOrNrsfQxU9nt5nitd9KuvVXrfAvgCO9DYPSfap+Gqjw9EOrXIsBp5tlHZjA==} 752 | engines: {node: '>=18.18'} 753 | peerDependencies: 754 | eslint: '>=8.56.0' 755 | 756 | eslint-scope@8.3.0: 757 | resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} 758 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 759 | 760 | eslint-visitor-keys@3.4.3: 761 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 762 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 763 | 764 | eslint-visitor-keys@4.2.0: 765 | resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} 766 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 767 | 768 | eslint@9.10.0: 769 | resolution: {integrity: sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==} 770 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 771 | hasBin: true 772 | peerDependencies: 773 | jiti: '*' 774 | peerDependenciesMeta: 775 | jiti: 776 | optional: true 777 | 778 | espree@10.3.0: 779 | resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} 780 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 781 | 782 | esquery@1.6.0: 783 | resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 784 | engines: {node: '>=0.10'} 785 | 786 | esrecurse@4.3.0: 787 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 788 | engines: {node: '>=4.0'} 789 | 790 | estraverse@5.3.0: 791 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 792 | engines: {node: '>=4.0'} 793 | 794 | estree-walker@3.0.3: 795 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 796 | 797 | esutils@2.0.3: 798 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 799 | engines: {node: '>=0.10.0'} 800 | 801 | etag@1.8.1: 802 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} 803 | engines: {node: '>= 0.6'} 804 | 805 | eventsource-parser@3.0.1: 806 | resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==} 807 | engines: {node: '>=18.0.0'} 808 | 809 | eventsource@3.0.6: 810 | resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==} 811 | engines: {node: '>=18.0.0'} 812 | 813 | expect-type@1.2.1: 814 | resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} 815 | engines: {node: '>=12.0.0'} 816 | 817 | express-rate-limit@7.5.0: 818 | resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} 819 | engines: {node: '>= 16'} 820 | peerDependencies: 821 | express: ^4.11 || 5 || ^5.0.0-beta.1 822 | 823 | express@5.1.0: 824 | resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} 825 | engines: {node: '>= 18'} 826 | 827 | fast-deep-equal@3.1.3: 828 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 829 | 830 | fast-glob@3.3.3: 831 | resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 832 | engines: {node: '>=8.6.0'} 833 | 834 | fast-json-stable-stringify@2.1.0: 835 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 836 | 837 | fast-levenshtein@2.0.6: 838 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 839 | 840 | fastq@1.19.1: 841 | resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 842 | 843 | fdir@6.4.3: 844 | resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} 845 | peerDependencies: 846 | picomatch: ^3 || ^4 847 | peerDependenciesMeta: 848 | picomatch: 849 | optional: true 850 | 851 | fetch-blob@3.2.0: 852 | resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} 853 | engines: {node: ^12.20 || >= 14.13} 854 | 855 | file-entry-cache@8.0.0: 856 | resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 857 | engines: {node: '>=16.0.0'} 858 | 859 | fill-range@7.1.1: 860 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 861 | engines: {node: '>=8'} 862 | 863 | finalhandler@2.1.0: 864 | resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} 865 | engines: {node: '>= 0.8'} 866 | 867 | find-up@4.1.0: 868 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 869 | engines: {node: '>=8'} 870 | 871 | find-up@5.0.0: 872 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 873 | engines: {node: '>=10'} 874 | 875 | flat-cache@4.0.1: 876 | resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 877 | engines: {node: '>=16'} 878 | 879 | flatted@3.3.3: 880 | resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 881 | 882 | foreground-child@3.3.1: 883 | resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} 884 | engines: {node: '>=14'} 885 | 886 | formdata-polyfill@4.0.10: 887 | resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} 888 | engines: {node: '>=12.20.0'} 889 | 890 | forwarded@0.2.0: 891 | resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} 892 | engines: {node: '>= 0.6'} 893 | 894 | fresh@2.0.0: 895 | resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} 896 | engines: {node: '>= 0.8'} 897 | 898 | fsevents@2.3.3: 899 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 900 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 901 | os: [darwin] 902 | 903 | function-bind@1.1.2: 904 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 905 | 906 | get-intrinsic@1.3.0: 907 | resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} 908 | engines: {node: '>= 0.4'} 909 | 910 | get-proto@1.0.1: 911 | resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} 912 | engines: {node: '>= 0.4'} 913 | 914 | glob-parent@5.1.2: 915 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 916 | engines: {node: '>= 6'} 917 | 918 | glob-parent@6.0.2: 919 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 920 | engines: {node: '>=10.13.0'} 921 | 922 | glob@10.4.5: 923 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 924 | hasBin: true 925 | 926 | globals@14.0.0: 927 | resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 928 | engines: {node: '>=18'} 929 | 930 | globals@15.15.0: 931 | resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} 932 | engines: {node: '>=18'} 933 | 934 | gopd@1.2.0: 935 | resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} 936 | engines: {node: '>= 0.4'} 937 | 938 | graphemer@1.4.0: 939 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 940 | 941 | has-flag@4.0.0: 942 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 943 | engines: {node: '>=8'} 944 | 945 | has-symbols@1.1.0: 946 | resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} 947 | engines: {node: '>= 0.4'} 948 | 949 | hasown@2.0.2: 950 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 951 | engines: {node: '>= 0.4'} 952 | 953 | hosted-git-info@2.8.9: 954 | resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} 955 | 956 | http-errors@2.0.0: 957 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} 958 | engines: {node: '>= 0.8'} 959 | 960 | iconv-lite@0.6.3: 961 | resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} 962 | engines: {node: '>=0.10.0'} 963 | 964 | ignore@5.3.2: 965 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 966 | engines: {node: '>= 4'} 967 | 968 | import-fresh@3.3.1: 969 | resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 970 | engines: {node: '>=6'} 971 | 972 | imurmurhash@0.1.4: 973 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 974 | engines: {node: '>=0.8.19'} 975 | 976 | indent-string@4.0.0: 977 | resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} 978 | engines: {node: '>=8'} 979 | 980 | inherits@2.0.4: 981 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 982 | 983 | ipaddr.js@1.9.1: 984 | resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} 985 | engines: {node: '>= 0.10'} 986 | 987 | is-arrayish@0.2.1: 988 | resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} 989 | 990 | is-builtin-module@3.2.1: 991 | resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} 992 | engines: {node: '>=6'} 993 | 994 | is-core-module@2.16.1: 995 | resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} 996 | engines: {node: '>= 0.4'} 997 | 998 | is-extglob@2.1.1: 999 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1000 | engines: {node: '>=0.10.0'} 1001 | 1002 | is-fullwidth-code-point@3.0.0: 1003 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1004 | engines: {node: '>=8'} 1005 | 1006 | is-glob@4.0.3: 1007 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1008 | engines: {node: '>=0.10.0'} 1009 | 1010 | is-number@7.0.0: 1011 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1012 | engines: {node: '>=0.12.0'} 1013 | 1014 | is-path-inside@3.0.3: 1015 | resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} 1016 | engines: {node: '>=8'} 1017 | 1018 | is-promise@4.0.0: 1019 | resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} 1020 | 1021 | isexe@2.0.0: 1022 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1023 | 1024 | jackspeak@3.4.3: 1025 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 1026 | 1027 | joycon@3.1.1: 1028 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 1029 | engines: {node: '>=10'} 1030 | 1031 | js-tokens@4.0.0: 1032 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1033 | 1034 | js-yaml@4.1.0: 1035 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1036 | hasBin: true 1037 | 1038 | jsesc@0.5.0: 1039 | resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} 1040 | hasBin: true 1041 | 1042 | jsesc@3.1.0: 1043 | resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} 1044 | engines: {node: '>=6'} 1045 | hasBin: true 1046 | 1047 | json-buffer@3.0.1: 1048 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 1049 | 1050 | json-parse-even-better-errors@2.3.1: 1051 | resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} 1052 | 1053 | json-schema-traverse@0.4.1: 1054 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1055 | 1056 | json-stable-stringify-without-jsonify@1.0.1: 1057 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 1058 | 1059 | keyv@4.5.4: 1060 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 1061 | 1062 | levn@0.4.1: 1063 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1064 | engines: {node: '>= 0.8.0'} 1065 | 1066 | lilconfig@3.1.3: 1067 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} 1068 | engines: {node: '>=14'} 1069 | 1070 | lines-and-columns@1.2.4: 1071 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 1072 | 1073 | load-tsconfig@0.2.5: 1074 | resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 1075 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1076 | 1077 | locate-path@5.0.0: 1078 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 1079 | engines: {node: '>=8'} 1080 | 1081 | locate-path@6.0.0: 1082 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 1083 | engines: {node: '>=10'} 1084 | 1085 | lodash.merge@4.6.2: 1086 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1087 | 1088 | lodash.sortby@4.7.0: 1089 | resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} 1090 | 1091 | loupe@3.1.3: 1092 | resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} 1093 | 1094 | lru-cache@10.4.3: 1095 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 1096 | 1097 | magic-string@0.30.17: 1098 | resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} 1099 | 1100 | math-intrinsics@1.1.0: 1101 | resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} 1102 | engines: {node: '>= 0.4'} 1103 | 1104 | media-typer@1.1.0: 1105 | resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} 1106 | engines: {node: '>= 0.8'} 1107 | 1108 | merge-descriptors@2.0.0: 1109 | resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} 1110 | engines: {node: '>=18'} 1111 | 1112 | merge2@1.4.1: 1113 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1114 | engines: {node: '>= 8'} 1115 | 1116 | micromatch@4.0.8: 1117 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1118 | engines: {node: '>=8.6'} 1119 | 1120 | mime-db@1.54.0: 1121 | resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} 1122 | engines: {node: '>= 0.6'} 1123 | 1124 | mime-types@3.0.1: 1125 | resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} 1126 | engines: {node: '>= 0.6'} 1127 | 1128 | min-indent@1.0.1: 1129 | resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} 1130 | engines: {node: '>=4'} 1131 | 1132 | minimatch@3.1.2: 1133 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1134 | 1135 | minimatch@9.0.5: 1136 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1137 | engines: {node: '>=16 || 14 >=14.17'} 1138 | 1139 | minipass@7.1.2: 1140 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1141 | engines: {node: '>=16 || 14 >=14.17'} 1142 | 1143 | ms@2.1.3: 1144 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1145 | 1146 | mz@2.7.0: 1147 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 1148 | 1149 | nanoid@3.3.11: 1150 | resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 1151 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1152 | hasBin: true 1153 | 1154 | natural-compare@1.4.0: 1155 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1156 | 1157 | negotiator@1.0.0: 1158 | resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} 1159 | engines: {node: '>= 0.6'} 1160 | 1161 | node-domexception@1.0.0: 1162 | resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} 1163 | engines: {node: '>=10.5.0'} 1164 | 1165 | node-fetch@3.3.2: 1166 | resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} 1167 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1168 | 1169 | node-releases@2.0.19: 1170 | resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 1171 | 1172 | normalize-package-data@2.5.0: 1173 | resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} 1174 | 1175 | object-assign@4.1.1: 1176 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1177 | engines: {node: '>=0.10.0'} 1178 | 1179 | object-inspect@1.13.4: 1180 | resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} 1181 | engines: {node: '>= 0.4'} 1182 | 1183 | on-finished@2.4.1: 1184 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} 1185 | engines: {node: '>= 0.8'} 1186 | 1187 | once@1.4.0: 1188 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1189 | 1190 | optionator@0.9.4: 1191 | resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 1192 | engines: {node: '>= 0.8.0'} 1193 | 1194 | p-limit@2.3.0: 1195 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 1196 | engines: {node: '>=6'} 1197 | 1198 | p-limit@3.1.0: 1199 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1200 | engines: {node: '>=10'} 1201 | 1202 | p-locate@4.1.0: 1203 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 1204 | engines: {node: '>=8'} 1205 | 1206 | p-locate@5.0.0: 1207 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1208 | engines: {node: '>=10'} 1209 | 1210 | p-try@2.2.0: 1211 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 1212 | engines: {node: '>=6'} 1213 | 1214 | package-json-from-dist@1.0.1: 1215 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1216 | 1217 | parent-module@1.0.1: 1218 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1219 | engines: {node: '>=6'} 1220 | 1221 | parse-json@5.2.0: 1222 | resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} 1223 | engines: {node: '>=8'} 1224 | 1225 | parseurl@1.3.3: 1226 | resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} 1227 | engines: {node: '>= 0.8'} 1228 | 1229 | path-exists@4.0.0: 1230 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1231 | engines: {node: '>=8'} 1232 | 1233 | path-key@3.1.1: 1234 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1235 | engines: {node: '>=8'} 1236 | 1237 | path-parse@1.0.7: 1238 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1239 | 1240 | path-scurry@1.11.1: 1241 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1242 | engines: {node: '>=16 || 14 >=14.18'} 1243 | 1244 | path-to-regexp@8.2.0: 1245 | resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} 1246 | engines: {node: '>=16'} 1247 | 1248 | pathe@2.0.3: 1249 | resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1250 | 1251 | pathval@2.0.0: 1252 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} 1253 | engines: {node: '>= 14.16'} 1254 | 1255 | picocolors@1.1.1: 1256 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1257 | 1258 | picomatch@2.3.1: 1259 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1260 | engines: {node: '>=8.6'} 1261 | 1262 | picomatch@4.0.2: 1263 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1264 | engines: {node: '>=12'} 1265 | 1266 | pirates@4.0.7: 1267 | resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} 1268 | engines: {node: '>= 6'} 1269 | 1270 | pkce-challenge@4.1.0: 1271 | resolution: {integrity: sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ==} 1272 | engines: {node: '>=16.20.0'} 1273 | 1274 | pluralize@8.0.0: 1275 | resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} 1276 | engines: {node: '>=4'} 1277 | 1278 | postcss-load-config@6.0.1: 1279 | resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} 1280 | engines: {node: '>= 18'} 1281 | peerDependencies: 1282 | jiti: '>=1.21.0' 1283 | postcss: '>=8.0.9' 1284 | tsx: ^4.8.1 1285 | yaml: ^2.4.2 1286 | peerDependenciesMeta: 1287 | jiti: 1288 | optional: true 1289 | postcss: 1290 | optional: true 1291 | tsx: 1292 | optional: true 1293 | yaml: 1294 | optional: true 1295 | 1296 | postcss@8.5.3: 1297 | resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} 1298 | engines: {node: ^10 || ^12 || >=14} 1299 | 1300 | prelude-ls@1.2.1: 1301 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1302 | engines: {node: '>= 0.8.0'} 1303 | 1304 | prettier@3.4.2: 1305 | resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} 1306 | engines: {node: '>=14'} 1307 | hasBin: true 1308 | 1309 | proxy-addr@2.0.7: 1310 | resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} 1311 | engines: {node: '>= 0.10'} 1312 | 1313 | punycode@2.3.1: 1314 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1315 | engines: {node: '>=6'} 1316 | 1317 | qs@6.14.0: 1318 | resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} 1319 | engines: {node: '>=0.6'} 1320 | 1321 | queue-microtask@1.2.3: 1322 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1323 | 1324 | range-parser@1.2.1: 1325 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} 1326 | engines: {node: '>= 0.6'} 1327 | 1328 | raw-body@3.0.0: 1329 | resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} 1330 | engines: {node: '>= 0.8'} 1331 | 1332 | read-pkg-up@7.0.1: 1333 | resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} 1334 | engines: {node: '>=8'} 1335 | 1336 | read-pkg@5.2.0: 1337 | resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} 1338 | engines: {node: '>=8'} 1339 | 1340 | readdirp@4.1.2: 1341 | resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} 1342 | engines: {node: '>= 14.18.0'} 1343 | 1344 | regexp-tree@0.1.27: 1345 | resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} 1346 | hasBin: true 1347 | 1348 | regjsparser@0.10.0: 1349 | resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} 1350 | hasBin: true 1351 | 1352 | resolve-from@4.0.0: 1353 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1354 | engines: {node: '>=4'} 1355 | 1356 | resolve-from@5.0.0: 1357 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1358 | engines: {node: '>=8'} 1359 | 1360 | resolve@1.22.10: 1361 | resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} 1362 | engines: {node: '>= 0.4'} 1363 | hasBin: true 1364 | 1365 | reusify@1.1.0: 1366 | resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1367 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1368 | 1369 | rollup@4.38.0: 1370 | resolution: {integrity: sha512-5SsIRtJy9bf1ErAOiFMFzl64Ex9X5V7bnJ+WlFMb+zmP459OSWCEG7b0ERZ+PEU7xPt4OG3RHbrp1LJlXxYTrw==} 1371 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1372 | hasBin: true 1373 | 1374 | router@2.2.0: 1375 | resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} 1376 | engines: {node: '>= 18'} 1377 | 1378 | run-parallel@1.2.0: 1379 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1380 | 1381 | safe-buffer@5.2.1: 1382 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} 1383 | 1384 | safer-buffer@2.1.2: 1385 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1386 | 1387 | semver@5.7.2: 1388 | resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} 1389 | hasBin: true 1390 | 1391 | semver@7.7.1: 1392 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} 1393 | engines: {node: '>=10'} 1394 | hasBin: true 1395 | 1396 | send@1.2.0: 1397 | resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} 1398 | engines: {node: '>= 18'} 1399 | 1400 | serve-static@2.2.0: 1401 | resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} 1402 | engines: {node: '>= 18'} 1403 | 1404 | setprototypeof@1.2.0: 1405 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} 1406 | 1407 | shebang-command@2.0.0: 1408 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1409 | engines: {node: '>=8'} 1410 | 1411 | shebang-regex@3.0.0: 1412 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1413 | engines: {node: '>=8'} 1414 | 1415 | side-channel-list@1.0.0: 1416 | resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} 1417 | engines: {node: '>= 0.4'} 1418 | 1419 | side-channel-map@1.0.1: 1420 | resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} 1421 | engines: {node: '>= 0.4'} 1422 | 1423 | side-channel-weakmap@1.0.2: 1424 | resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} 1425 | engines: {node: '>= 0.4'} 1426 | 1427 | side-channel@1.1.0: 1428 | resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} 1429 | engines: {node: '>= 0.4'} 1430 | 1431 | siginfo@2.0.0: 1432 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1433 | 1434 | signal-exit@4.1.0: 1435 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1436 | engines: {node: '>=14'} 1437 | 1438 | source-map-js@1.2.1: 1439 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1440 | engines: {node: '>=0.10.0'} 1441 | 1442 | source-map@0.8.0-beta.0: 1443 | resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} 1444 | engines: {node: '>= 8'} 1445 | 1446 | spdx-correct@3.2.0: 1447 | resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} 1448 | 1449 | spdx-exceptions@2.5.0: 1450 | resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} 1451 | 1452 | spdx-expression-parse@3.0.1: 1453 | resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} 1454 | 1455 | spdx-license-ids@3.0.21: 1456 | resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} 1457 | 1458 | stackback@0.0.2: 1459 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1460 | 1461 | statuses@2.0.1: 1462 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} 1463 | engines: {node: '>= 0.8'} 1464 | 1465 | std-env@3.8.1: 1466 | resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} 1467 | 1468 | string-width@4.2.3: 1469 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1470 | engines: {node: '>=8'} 1471 | 1472 | string-width@5.1.2: 1473 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1474 | engines: {node: '>=12'} 1475 | 1476 | strip-ansi@6.0.1: 1477 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1478 | engines: {node: '>=8'} 1479 | 1480 | strip-ansi@7.1.0: 1481 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1482 | engines: {node: '>=12'} 1483 | 1484 | strip-indent@3.0.0: 1485 | resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} 1486 | engines: {node: '>=8'} 1487 | 1488 | strip-json-comments@3.1.1: 1489 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1490 | engines: {node: '>=8'} 1491 | 1492 | sucrase@3.35.0: 1493 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1494 | engines: {node: '>=16 || 14 >=14.17'} 1495 | hasBin: true 1496 | 1497 | supports-color@7.2.0: 1498 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1499 | engines: {node: '>=8'} 1500 | 1501 | supports-preserve-symlinks-flag@1.0.0: 1502 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1503 | engines: {node: '>= 0.4'} 1504 | 1505 | text-table@0.2.0: 1506 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} 1507 | 1508 | thenify-all@1.6.0: 1509 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1510 | engines: {node: '>=0.8'} 1511 | 1512 | thenify@3.3.1: 1513 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1514 | 1515 | tinybench@2.9.0: 1516 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1517 | 1518 | tinyexec@0.3.2: 1519 | resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} 1520 | 1521 | tinyglobby@0.2.12: 1522 | resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} 1523 | engines: {node: '>=12.0.0'} 1524 | 1525 | tinypool@1.0.2: 1526 | resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} 1527 | engines: {node: ^18.0.0 || >=20.0.0} 1528 | 1529 | tinyrainbow@2.0.0: 1530 | resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} 1531 | engines: {node: '>=14.0.0'} 1532 | 1533 | tinyspy@3.0.2: 1534 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1535 | engines: {node: '>=14.0.0'} 1536 | 1537 | to-regex-range@5.0.1: 1538 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1539 | engines: {node: '>=8.0'} 1540 | 1541 | toidentifier@1.0.1: 1542 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} 1543 | engines: {node: '>=0.6'} 1544 | 1545 | tr46@1.0.1: 1546 | resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} 1547 | 1548 | tree-kill@1.2.2: 1549 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 1550 | hasBin: true 1551 | 1552 | ts-api-utils@1.4.3: 1553 | resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} 1554 | engines: {node: '>=16'} 1555 | peerDependencies: 1556 | typescript: '>=4.2.0' 1557 | 1558 | ts-interface-checker@0.1.13: 1559 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1560 | 1561 | tsup@8.4.0: 1562 | resolution: {integrity: sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==} 1563 | engines: {node: '>=18'} 1564 | hasBin: true 1565 | peerDependencies: 1566 | '@microsoft/api-extractor': ^7.36.0 1567 | '@swc/core': ^1 1568 | postcss: ^8.4.12 1569 | typescript: '>=4.5.0' 1570 | peerDependenciesMeta: 1571 | '@microsoft/api-extractor': 1572 | optional: true 1573 | '@swc/core': 1574 | optional: true 1575 | postcss: 1576 | optional: true 1577 | typescript: 1578 | optional: true 1579 | 1580 | type-check@0.4.0: 1581 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1582 | engines: {node: '>= 0.8.0'} 1583 | 1584 | type-fest@0.6.0: 1585 | resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} 1586 | engines: {node: '>=8'} 1587 | 1588 | type-fest@0.8.1: 1589 | resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} 1590 | engines: {node: '>=8'} 1591 | 1592 | type-is@2.0.1: 1593 | resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} 1594 | engines: {node: '>= 0.6'} 1595 | 1596 | typescript@5.8.2: 1597 | resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 1598 | engines: {node: '>=14.17'} 1599 | hasBin: true 1600 | 1601 | unpipe@1.0.0: 1602 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} 1603 | engines: {node: '>= 0.8'} 1604 | 1605 | update-browserslist-db@1.1.3: 1606 | resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 1607 | hasBin: true 1608 | peerDependencies: 1609 | browserslist: '>= 4.21.0' 1610 | 1611 | uri-js@4.4.1: 1612 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1613 | 1614 | validate-npm-package-license@3.0.4: 1615 | resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} 1616 | 1617 | vary@1.1.2: 1618 | resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} 1619 | engines: {node: '>= 0.8'} 1620 | 1621 | vite-node@3.1.1: 1622 | resolution: {integrity: sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==} 1623 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1624 | hasBin: true 1625 | 1626 | vite@6.2.4: 1627 | resolution: {integrity: sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==} 1628 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1629 | hasBin: true 1630 | peerDependencies: 1631 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1632 | jiti: '>=1.21.0' 1633 | less: '*' 1634 | lightningcss: ^1.21.0 1635 | sass: '*' 1636 | sass-embedded: '*' 1637 | stylus: '*' 1638 | sugarss: '*' 1639 | terser: ^5.16.0 1640 | tsx: ^4.8.1 1641 | yaml: ^2.4.2 1642 | peerDependenciesMeta: 1643 | '@types/node': 1644 | optional: true 1645 | jiti: 1646 | optional: true 1647 | less: 1648 | optional: true 1649 | lightningcss: 1650 | optional: true 1651 | sass: 1652 | optional: true 1653 | sass-embedded: 1654 | optional: true 1655 | stylus: 1656 | optional: true 1657 | sugarss: 1658 | optional: true 1659 | terser: 1660 | optional: true 1661 | tsx: 1662 | optional: true 1663 | yaml: 1664 | optional: true 1665 | 1666 | vitest@3.1.1: 1667 | resolution: {integrity: sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==} 1668 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1669 | hasBin: true 1670 | peerDependencies: 1671 | '@edge-runtime/vm': '*' 1672 | '@types/debug': ^4.1.12 1673 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1674 | '@vitest/browser': 3.1.1 1675 | '@vitest/ui': 3.1.1 1676 | happy-dom: '*' 1677 | jsdom: '*' 1678 | peerDependenciesMeta: 1679 | '@edge-runtime/vm': 1680 | optional: true 1681 | '@types/debug': 1682 | optional: true 1683 | '@types/node': 1684 | optional: true 1685 | '@vitest/browser': 1686 | optional: true 1687 | '@vitest/ui': 1688 | optional: true 1689 | happy-dom: 1690 | optional: true 1691 | jsdom: 1692 | optional: true 1693 | 1694 | web-streams-polyfill@3.3.3: 1695 | resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} 1696 | engines: {node: '>= 8'} 1697 | 1698 | webidl-conversions@4.0.2: 1699 | resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} 1700 | 1701 | whatwg-url@7.1.0: 1702 | resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} 1703 | 1704 | which@2.0.2: 1705 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1706 | engines: {node: '>= 8'} 1707 | hasBin: true 1708 | 1709 | why-is-node-running@2.3.0: 1710 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1711 | engines: {node: '>=8'} 1712 | hasBin: true 1713 | 1714 | word-wrap@1.2.5: 1715 | resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 1716 | engines: {node: '>=0.10.0'} 1717 | 1718 | wrap-ansi@7.0.0: 1719 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1720 | engines: {node: '>=10'} 1721 | 1722 | wrap-ansi@8.1.0: 1723 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1724 | engines: {node: '>=12'} 1725 | 1726 | wrappy@1.0.2: 1727 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1728 | 1729 | yocto-queue@0.1.0: 1730 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1731 | engines: {node: '>=10'} 1732 | 1733 | zod-to-json-schema@3.24.1: 1734 | resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} 1735 | peerDependencies: 1736 | zod: ^3.24.1 1737 | 1738 | zod@3.24.1: 1739 | resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} 1740 | 1741 | snapshots: 1742 | 1743 | '@babel/code-frame@7.26.2': 1744 | dependencies: 1745 | '@babel/helper-validator-identifier': 7.25.9 1746 | js-tokens: 4.0.0 1747 | picocolors: 1.1.1 1748 | 1749 | '@babel/helper-validator-identifier@7.25.9': {} 1750 | 1751 | '@esbuild/aix-ppc64@0.25.2': 1752 | optional: true 1753 | 1754 | '@esbuild/android-arm64@0.25.2': 1755 | optional: true 1756 | 1757 | '@esbuild/android-arm@0.25.2': 1758 | optional: true 1759 | 1760 | '@esbuild/android-x64@0.25.2': 1761 | optional: true 1762 | 1763 | '@esbuild/darwin-arm64@0.25.2': 1764 | optional: true 1765 | 1766 | '@esbuild/darwin-x64@0.25.2': 1767 | optional: true 1768 | 1769 | '@esbuild/freebsd-arm64@0.25.2': 1770 | optional: true 1771 | 1772 | '@esbuild/freebsd-x64@0.25.2': 1773 | optional: true 1774 | 1775 | '@esbuild/linux-arm64@0.25.2': 1776 | optional: true 1777 | 1778 | '@esbuild/linux-arm@0.25.2': 1779 | optional: true 1780 | 1781 | '@esbuild/linux-ia32@0.25.2': 1782 | optional: true 1783 | 1784 | '@esbuild/linux-loong64@0.25.2': 1785 | optional: true 1786 | 1787 | '@esbuild/linux-mips64el@0.25.2': 1788 | optional: true 1789 | 1790 | '@esbuild/linux-ppc64@0.25.2': 1791 | optional: true 1792 | 1793 | '@esbuild/linux-riscv64@0.25.2': 1794 | optional: true 1795 | 1796 | '@esbuild/linux-s390x@0.25.2': 1797 | optional: true 1798 | 1799 | '@esbuild/linux-x64@0.25.2': 1800 | optional: true 1801 | 1802 | '@esbuild/netbsd-arm64@0.25.2': 1803 | optional: true 1804 | 1805 | '@esbuild/netbsd-x64@0.25.2': 1806 | optional: true 1807 | 1808 | '@esbuild/openbsd-arm64@0.25.2': 1809 | optional: true 1810 | 1811 | '@esbuild/openbsd-x64@0.25.2': 1812 | optional: true 1813 | 1814 | '@esbuild/sunos-x64@0.25.2': 1815 | optional: true 1816 | 1817 | '@esbuild/win32-arm64@0.25.2': 1818 | optional: true 1819 | 1820 | '@esbuild/win32-ia32@0.25.2': 1821 | optional: true 1822 | 1823 | '@esbuild/win32-x64@0.25.2': 1824 | optional: true 1825 | 1826 | '@eslint-community/eslint-utils@4.5.1(eslint@9.10.0)': 1827 | dependencies: 1828 | eslint: 9.10.0 1829 | eslint-visitor-keys: 3.4.3 1830 | 1831 | '@eslint-community/regexpp@4.12.1': {} 1832 | 1833 | '@eslint/config-array@0.18.0': 1834 | dependencies: 1835 | '@eslint/object-schema': 2.1.6 1836 | debug: 4.4.0 1837 | minimatch: 3.1.2 1838 | transitivePeerDependencies: 1839 | - supports-color 1840 | 1841 | '@eslint/eslintrc@3.3.1': 1842 | dependencies: 1843 | ajv: 6.12.6 1844 | debug: 4.4.0 1845 | espree: 10.3.0 1846 | globals: 14.0.0 1847 | ignore: 5.3.2 1848 | import-fresh: 3.3.1 1849 | js-yaml: 4.1.0 1850 | minimatch: 3.1.2 1851 | strip-json-comments: 3.1.1 1852 | transitivePeerDependencies: 1853 | - supports-color 1854 | 1855 | '@eslint/js@9.10.0': {} 1856 | 1857 | '@eslint/object-schema@2.1.6': {} 1858 | 1859 | '@eslint/plugin-kit@0.1.0': 1860 | dependencies: 1861 | levn: 0.4.1 1862 | 1863 | '@humanwhocodes/module-importer@1.0.1': {} 1864 | 1865 | '@humanwhocodes/retry@0.3.1': {} 1866 | 1867 | '@isaacs/cliui@8.0.2': 1868 | dependencies: 1869 | string-width: 5.1.2 1870 | string-width-cjs: string-width@4.2.3 1871 | strip-ansi: 7.1.0 1872 | strip-ansi-cjs: strip-ansi@6.0.1 1873 | wrap-ansi: 8.1.0 1874 | wrap-ansi-cjs: wrap-ansi@7.0.0 1875 | 1876 | '@jridgewell/gen-mapping@0.3.8': 1877 | dependencies: 1878 | '@jridgewell/set-array': 1.2.1 1879 | '@jridgewell/sourcemap-codec': 1.5.0 1880 | '@jridgewell/trace-mapping': 0.3.25 1881 | 1882 | '@jridgewell/resolve-uri@3.1.2': {} 1883 | 1884 | '@jridgewell/set-array@1.2.1': {} 1885 | 1886 | '@jridgewell/sourcemap-codec@1.5.0': {} 1887 | 1888 | '@jridgewell/trace-mapping@0.3.25': 1889 | dependencies: 1890 | '@jridgewell/resolve-uri': 3.1.2 1891 | '@jridgewell/sourcemap-codec': 1.5.0 1892 | 1893 | '@modelcontextprotocol/sdk@1.8.0': 1894 | dependencies: 1895 | content-type: 1.0.5 1896 | cors: 2.8.5 1897 | cross-spawn: 7.0.6 1898 | eventsource: 3.0.6 1899 | express: 5.1.0 1900 | express-rate-limit: 7.5.0(express@5.1.0) 1901 | pkce-challenge: 4.1.0 1902 | raw-body: 3.0.0 1903 | zod: 3.24.1 1904 | zod-to-json-schema: 3.24.1(zod@3.24.1) 1905 | transitivePeerDependencies: 1906 | - supports-color 1907 | 1908 | '@nodelib/fs.scandir@2.1.5': 1909 | dependencies: 1910 | '@nodelib/fs.stat': 2.0.5 1911 | run-parallel: 1.2.0 1912 | 1913 | '@nodelib/fs.stat@2.0.5': {} 1914 | 1915 | '@nodelib/fs.walk@1.2.8': 1916 | dependencies: 1917 | '@nodelib/fs.scandir': 2.1.5 1918 | fastq: 1.19.1 1919 | 1920 | '@pkgjs/parseargs@0.11.0': 1921 | optional: true 1922 | 1923 | '@rollup/rollup-android-arm-eabi@4.38.0': 1924 | optional: true 1925 | 1926 | '@rollup/rollup-android-arm64@4.38.0': 1927 | optional: true 1928 | 1929 | '@rollup/rollup-darwin-arm64@4.38.0': 1930 | optional: true 1931 | 1932 | '@rollup/rollup-darwin-x64@4.38.0': 1933 | optional: true 1934 | 1935 | '@rollup/rollup-freebsd-arm64@4.38.0': 1936 | optional: true 1937 | 1938 | '@rollup/rollup-freebsd-x64@4.38.0': 1939 | optional: true 1940 | 1941 | '@rollup/rollup-linux-arm-gnueabihf@4.38.0': 1942 | optional: true 1943 | 1944 | '@rollup/rollup-linux-arm-musleabihf@4.38.0': 1945 | optional: true 1946 | 1947 | '@rollup/rollup-linux-arm64-gnu@4.38.0': 1948 | optional: true 1949 | 1950 | '@rollup/rollup-linux-arm64-musl@4.38.0': 1951 | optional: true 1952 | 1953 | '@rollup/rollup-linux-loongarch64-gnu@4.38.0': 1954 | optional: true 1955 | 1956 | '@rollup/rollup-linux-powerpc64le-gnu@4.38.0': 1957 | optional: true 1958 | 1959 | '@rollup/rollup-linux-riscv64-gnu@4.38.0': 1960 | optional: true 1961 | 1962 | '@rollup/rollup-linux-riscv64-musl@4.38.0': 1963 | optional: true 1964 | 1965 | '@rollup/rollup-linux-s390x-gnu@4.38.0': 1966 | optional: true 1967 | 1968 | '@rollup/rollup-linux-x64-gnu@4.38.0': 1969 | optional: true 1970 | 1971 | '@rollup/rollup-linux-x64-musl@4.38.0': 1972 | optional: true 1973 | 1974 | '@rollup/rollup-win32-arm64-msvc@4.38.0': 1975 | optional: true 1976 | 1977 | '@rollup/rollup-win32-ia32-msvc@4.38.0': 1978 | optional: true 1979 | 1980 | '@rollup/rollup-win32-x64-msvc@4.38.0': 1981 | optional: true 1982 | 1983 | '@types/estree@1.0.7': {} 1984 | 1985 | '@types/node@15.14.9': {} 1986 | 1987 | '@types/normalize-package-data@2.4.4': {} 1988 | 1989 | '@typescript-eslint/eslint-plugin@8.4.0(@typescript-eslint/parser@8.4.0(eslint@9.10.0)(typescript@5.8.2))(eslint@9.10.0)(typescript@5.8.2)': 1990 | dependencies: 1991 | '@eslint-community/regexpp': 4.12.1 1992 | '@typescript-eslint/parser': 8.4.0(eslint@9.10.0)(typescript@5.8.2) 1993 | '@typescript-eslint/scope-manager': 8.4.0 1994 | '@typescript-eslint/type-utils': 8.4.0(eslint@9.10.0)(typescript@5.8.2) 1995 | '@typescript-eslint/utils': 8.4.0(eslint@9.10.0)(typescript@5.8.2) 1996 | '@typescript-eslint/visitor-keys': 8.4.0 1997 | eslint: 9.10.0 1998 | graphemer: 1.4.0 1999 | ignore: 5.3.2 2000 | natural-compare: 1.4.0 2001 | ts-api-utils: 1.4.3(typescript@5.8.2) 2002 | optionalDependencies: 2003 | typescript: 5.8.2 2004 | transitivePeerDependencies: 2005 | - supports-color 2006 | 2007 | '@typescript-eslint/parser@8.4.0(eslint@9.10.0)(typescript@5.8.2)': 2008 | dependencies: 2009 | '@typescript-eslint/scope-manager': 8.4.0 2010 | '@typescript-eslint/types': 8.4.0 2011 | '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.8.2) 2012 | '@typescript-eslint/visitor-keys': 8.4.0 2013 | debug: 4.4.0 2014 | eslint: 9.10.0 2015 | optionalDependencies: 2016 | typescript: 5.8.2 2017 | transitivePeerDependencies: 2018 | - supports-color 2019 | 2020 | '@typescript-eslint/scope-manager@8.4.0': 2021 | dependencies: 2022 | '@typescript-eslint/types': 8.4.0 2023 | '@typescript-eslint/visitor-keys': 8.4.0 2024 | 2025 | '@typescript-eslint/type-utils@8.4.0(eslint@9.10.0)(typescript@5.8.2)': 2026 | dependencies: 2027 | '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.8.2) 2028 | '@typescript-eslint/utils': 8.4.0(eslint@9.10.0)(typescript@5.8.2) 2029 | debug: 4.4.0 2030 | ts-api-utils: 1.4.3(typescript@5.8.2) 2031 | optionalDependencies: 2032 | typescript: 5.8.2 2033 | transitivePeerDependencies: 2034 | - eslint 2035 | - supports-color 2036 | 2037 | '@typescript-eslint/types@8.4.0': {} 2038 | 2039 | '@typescript-eslint/typescript-estree@8.4.0(typescript@5.8.2)': 2040 | dependencies: 2041 | '@typescript-eslint/types': 8.4.0 2042 | '@typescript-eslint/visitor-keys': 8.4.0 2043 | debug: 4.4.0 2044 | fast-glob: 3.3.3 2045 | is-glob: 4.0.3 2046 | minimatch: 9.0.5 2047 | semver: 7.7.1 2048 | ts-api-utils: 1.4.3(typescript@5.8.2) 2049 | optionalDependencies: 2050 | typescript: 5.8.2 2051 | transitivePeerDependencies: 2052 | - supports-color 2053 | 2054 | '@typescript-eslint/utils@8.4.0(eslint@9.10.0)(typescript@5.8.2)': 2055 | dependencies: 2056 | '@eslint-community/eslint-utils': 4.5.1(eslint@9.10.0) 2057 | '@typescript-eslint/scope-manager': 8.4.0 2058 | '@typescript-eslint/types': 8.4.0 2059 | '@typescript-eslint/typescript-estree': 8.4.0(typescript@5.8.2) 2060 | eslint: 9.10.0 2061 | transitivePeerDependencies: 2062 | - supports-color 2063 | - typescript 2064 | 2065 | '@typescript-eslint/visitor-keys@8.4.0': 2066 | dependencies: 2067 | '@typescript-eslint/types': 8.4.0 2068 | eslint-visitor-keys: 3.4.3 2069 | 2070 | '@vitest/expect@3.1.1': 2071 | dependencies: 2072 | '@vitest/spy': 3.1.1 2073 | '@vitest/utils': 3.1.1 2074 | chai: 5.2.0 2075 | tinyrainbow: 2.0.0 2076 | 2077 | '@vitest/mocker@3.1.1(vite@6.2.4(@types/node@15.14.9))': 2078 | dependencies: 2079 | '@vitest/spy': 3.1.1 2080 | estree-walker: 3.0.3 2081 | magic-string: 0.30.17 2082 | optionalDependencies: 2083 | vite: 6.2.4(@types/node@15.14.9) 2084 | 2085 | '@vitest/pretty-format@3.1.1': 2086 | dependencies: 2087 | tinyrainbow: 2.0.0 2088 | 2089 | '@vitest/runner@3.1.1': 2090 | dependencies: 2091 | '@vitest/utils': 3.1.1 2092 | pathe: 2.0.3 2093 | 2094 | '@vitest/snapshot@3.1.1': 2095 | dependencies: 2096 | '@vitest/pretty-format': 3.1.1 2097 | magic-string: 0.30.17 2098 | pathe: 2.0.3 2099 | 2100 | '@vitest/spy@3.1.1': 2101 | dependencies: 2102 | tinyspy: 3.0.2 2103 | 2104 | '@vitest/utils@3.1.1': 2105 | dependencies: 2106 | '@vitest/pretty-format': 3.1.1 2107 | loupe: 3.1.3 2108 | tinyrainbow: 2.0.0 2109 | 2110 | accepts@2.0.0: 2111 | dependencies: 2112 | mime-types: 3.0.1 2113 | negotiator: 1.0.0 2114 | 2115 | acorn-jsx@5.3.2(acorn@8.14.1): 2116 | dependencies: 2117 | acorn: 8.14.1 2118 | 2119 | acorn@8.14.1: {} 2120 | 2121 | ajv@6.12.6: 2122 | dependencies: 2123 | fast-deep-equal: 3.1.3 2124 | fast-json-stable-stringify: 2.1.0 2125 | json-schema-traverse: 0.4.1 2126 | uri-js: 4.4.1 2127 | 2128 | ansi-regex@5.0.1: {} 2129 | 2130 | ansi-regex@6.1.0: {} 2131 | 2132 | ansi-styles@4.3.0: 2133 | dependencies: 2134 | color-convert: 2.0.1 2135 | 2136 | ansi-styles@6.2.1: {} 2137 | 2138 | any-promise@1.3.0: {} 2139 | 2140 | argparse@2.0.1: {} 2141 | 2142 | assertion-error@2.0.1: {} 2143 | 2144 | balanced-match@1.0.2: {} 2145 | 2146 | body-parser@2.2.0: 2147 | dependencies: 2148 | bytes: 3.1.2 2149 | content-type: 1.0.5 2150 | debug: 4.4.0 2151 | http-errors: 2.0.0 2152 | iconv-lite: 0.6.3 2153 | on-finished: 2.4.1 2154 | qs: 6.14.0 2155 | raw-body: 3.0.0 2156 | type-is: 2.0.1 2157 | transitivePeerDependencies: 2158 | - supports-color 2159 | 2160 | brace-expansion@1.1.11: 2161 | dependencies: 2162 | balanced-match: 1.0.2 2163 | concat-map: 0.0.1 2164 | 2165 | brace-expansion@2.0.1: 2166 | dependencies: 2167 | balanced-match: 1.0.2 2168 | 2169 | braces@3.0.3: 2170 | dependencies: 2171 | fill-range: 7.1.1 2172 | 2173 | browserslist@4.24.4: 2174 | dependencies: 2175 | caniuse-lite: 1.0.30001707 2176 | electron-to-chromium: 1.5.129 2177 | node-releases: 2.0.19 2178 | update-browserslist-db: 1.1.3(browserslist@4.24.4) 2179 | 2180 | builtin-modules@3.3.0: {} 2181 | 2182 | bundle-require@5.1.0(esbuild@0.25.2): 2183 | dependencies: 2184 | esbuild: 0.25.2 2185 | load-tsconfig: 0.2.5 2186 | 2187 | bytes@3.1.2: {} 2188 | 2189 | cac@6.7.14: {} 2190 | 2191 | call-bind-apply-helpers@1.0.2: 2192 | dependencies: 2193 | es-errors: 1.3.0 2194 | function-bind: 1.1.2 2195 | 2196 | call-bound@1.0.4: 2197 | dependencies: 2198 | call-bind-apply-helpers: 1.0.2 2199 | get-intrinsic: 1.3.0 2200 | 2201 | callsites@3.1.0: {} 2202 | 2203 | caniuse-lite@1.0.30001707: {} 2204 | 2205 | chai@5.2.0: 2206 | dependencies: 2207 | assertion-error: 2.0.1 2208 | check-error: 2.1.1 2209 | deep-eql: 5.0.2 2210 | loupe: 3.1.3 2211 | pathval: 2.0.0 2212 | 2213 | chalk@4.1.2: 2214 | dependencies: 2215 | ansi-styles: 4.3.0 2216 | supports-color: 7.2.0 2217 | 2218 | chalk@5.3.0: {} 2219 | 2220 | check-error@2.1.1: {} 2221 | 2222 | chokidar@4.0.3: 2223 | dependencies: 2224 | readdirp: 4.1.2 2225 | 2226 | ci-info@4.2.0: {} 2227 | 2228 | clean-regexp@1.0.0: 2229 | dependencies: 2230 | escape-string-regexp: 1.0.5 2231 | 2232 | color-convert@2.0.1: 2233 | dependencies: 2234 | color-name: 1.1.4 2235 | 2236 | color-name@1.1.4: {} 2237 | 2238 | commander@4.1.1: {} 2239 | 2240 | concat-map@0.0.1: {} 2241 | 2242 | consola@3.4.2: {} 2243 | 2244 | content-disposition@1.0.0: 2245 | dependencies: 2246 | safe-buffer: 5.2.1 2247 | 2248 | content-type@1.0.5: {} 2249 | 2250 | cookie-signature@1.2.2: {} 2251 | 2252 | cookie@0.7.2: {} 2253 | 2254 | core-js-compat@3.41.0: 2255 | dependencies: 2256 | browserslist: 4.24.4 2257 | 2258 | cors@2.8.5: 2259 | dependencies: 2260 | object-assign: 4.1.1 2261 | vary: 1.1.2 2262 | 2263 | cross-spawn@7.0.6: 2264 | dependencies: 2265 | path-key: 3.1.1 2266 | shebang-command: 2.0.0 2267 | which: 2.0.2 2268 | 2269 | data-uri-to-buffer@4.0.1: {} 2270 | 2271 | debug@4.4.0: 2272 | dependencies: 2273 | ms: 2.1.3 2274 | 2275 | deep-eql@5.0.2: {} 2276 | 2277 | deep-is@0.1.4: {} 2278 | 2279 | depd@2.0.0: {} 2280 | 2281 | dotenv@16.4.7: {} 2282 | 2283 | dunder-proto@1.0.1: 2284 | dependencies: 2285 | call-bind-apply-helpers: 1.0.2 2286 | es-errors: 1.3.0 2287 | gopd: 1.2.0 2288 | 2289 | eastasianwidth@0.2.0: {} 2290 | 2291 | ee-first@1.1.1: {} 2292 | 2293 | electron-to-chromium@1.5.129: {} 2294 | 2295 | emoji-regex@8.0.0: {} 2296 | 2297 | emoji-regex@9.2.2: {} 2298 | 2299 | encodeurl@2.0.0: {} 2300 | 2301 | error-ex@1.3.2: 2302 | dependencies: 2303 | is-arrayish: 0.2.1 2304 | 2305 | es-define-property@1.0.1: {} 2306 | 2307 | es-errors@1.3.0: {} 2308 | 2309 | es-module-lexer@1.6.0: {} 2310 | 2311 | es-object-atoms@1.1.1: 2312 | dependencies: 2313 | es-errors: 1.3.0 2314 | 2315 | esbuild@0.25.2: 2316 | optionalDependencies: 2317 | '@esbuild/aix-ppc64': 0.25.2 2318 | '@esbuild/android-arm': 0.25.2 2319 | '@esbuild/android-arm64': 0.25.2 2320 | '@esbuild/android-x64': 0.25.2 2321 | '@esbuild/darwin-arm64': 0.25.2 2322 | '@esbuild/darwin-x64': 0.25.2 2323 | '@esbuild/freebsd-arm64': 0.25.2 2324 | '@esbuild/freebsd-x64': 0.25.2 2325 | '@esbuild/linux-arm': 0.25.2 2326 | '@esbuild/linux-arm64': 0.25.2 2327 | '@esbuild/linux-ia32': 0.25.2 2328 | '@esbuild/linux-loong64': 0.25.2 2329 | '@esbuild/linux-mips64el': 0.25.2 2330 | '@esbuild/linux-ppc64': 0.25.2 2331 | '@esbuild/linux-riscv64': 0.25.2 2332 | '@esbuild/linux-s390x': 0.25.2 2333 | '@esbuild/linux-x64': 0.25.2 2334 | '@esbuild/netbsd-arm64': 0.25.2 2335 | '@esbuild/netbsd-x64': 0.25.2 2336 | '@esbuild/openbsd-arm64': 0.25.2 2337 | '@esbuild/openbsd-x64': 0.25.2 2338 | '@esbuild/sunos-x64': 0.25.2 2339 | '@esbuild/win32-arm64': 0.25.2 2340 | '@esbuild/win32-ia32': 0.25.2 2341 | '@esbuild/win32-x64': 0.25.2 2342 | 2343 | escalade@3.2.0: {} 2344 | 2345 | escape-html@1.0.3: {} 2346 | 2347 | escape-string-regexp@1.0.5: {} 2348 | 2349 | escape-string-regexp@4.0.0: {} 2350 | 2351 | eslint-plugin-unicorn@55.0.0(eslint@9.10.0): 2352 | dependencies: 2353 | '@babel/helper-validator-identifier': 7.25.9 2354 | '@eslint-community/eslint-utils': 4.5.1(eslint@9.10.0) 2355 | ci-info: 4.2.0 2356 | clean-regexp: 1.0.0 2357 | core-js-compat: 3.41.0 2358 | eslint: 9.10.0 2359 | esquery: 1.6.0 2360 | globals: 15.15.0 2361 | indent-string: 4.0.0 2362 | is-builtin-module: 3.2.1 2363 | jsesc: 3.1.0 2364 | pluralize: 8.0.0 2365 | read-pkg-up: 7.0.1 2366 | regexp-tree: 0.1.27 2367 | regjsparser: 0.10.0 2368 | semver: 7.7.1 2369 | strip-indent: 3.0.0 2370 | 2371 | eslint-scope@8.3.0: 2372 | dependencies: 2373 | esrecurse: 4.3.0 2374 | estraverse: 5.3.0 2375 | 2376 | eslint-visitor-keys@3.4.3: {} 2377 | 2378 | eslint-visitor-keys@4.2.0: {} 2379 | 2380 | eslint@9.10.0: 2381 | dependencies: 2382 | '@eslint-community/eslint-utils': 4.5.1(eslint@9.10.0) 2383 | '@eslint-community/regexpp': 4.12.1 2384 | '@eslint/config-array': 0.18.0 2385 | '@eslint/eslintrc': 3.3.1 2386 | '@eslint/js': 9.10.0 2387 | '@eslint/plugin-kit': 0.1.0 2388 | '@humanwhocodes/module-importer': 1.0.1 2389 | '@humanwhocodes/retry': 0.3.1 2390 | '@nodelib/fs.walk': 1.2.8 2391 | ajv: 6.12.6 2392 | chalk: 4.1.2 2393 | cross-spawn: 7.0.6 2394 | debug: 4.4.0 2395 | escape-string-regexp: 4.0.0 2396 | eslint-scope: 8.3.0 2397 | eslint-visitor-keys: 4.2.0 2398 | espree: 10.3.0 2399 | esquery: 1.6.0 2400 | esutils: 2.0.3 2401 | fast-deep-equal: 3.1.3 2402 | file-entry-cache: 8.0.0 2403 | find-up: 5.0.0 2404 | glob-parent: 6.0.2 2405 | ignore: 5.3.2 2406 | imurmurhash: 0.1.4 2407 | is-glob: 4.0.3 2408 | is-path-inside: 3.0.3 2409 | json-stable-stringify-without-jsonify: 1.0.1 2410 | lodash.merge: 4.6.2 2411 | minimatch: 3.1.2 2412 | natural-compare: 1.4.0 2413 | optionator: 0.9.4 2414 | strip-ansi: 6.0.1 2415 | text-table: 0.2.0 2416 | transitivePeerDependencies: 2417 | - supports-color 2418 | 2419 | espree@10.3.0: 2420 | dependencies: 2421 | acorn: 8.14.1 2422 | acorn-jsx: 5.3.2(acorn@8.14.1) 2423 | eslint-visitor-keys: 4.2.0 2424 | 2425 | esquery@1.6.0: 2426 | dependencies: 2427 | estraverse: 5.3.0 2428 | 2429 | esrecurse@4.3.0: 2430 | dependencies: 2431 | estraverse: 5.3.0 2432 | 2433 | estraverse@5.3.0: {} 2434 | 2435 | estree-walker@3.0.3: 2436 | dependencies: 2437 | '@types/estree': 1.0.7 2438 | 2439 | esutils@2.0.3: {} 2440 | 2441 | etag@1.8.1: {} 2442 | 2443 | eventsource-parser@3.0.1: {} 2444 | 2445 | eventsource@3.0.6: 2446 | dependencies: 2447 | eventsource-parser: 3.0.1 2448 | 2449 | expect-type@1.2.1: {} 2450 | 2451 | express-rate-limit@7.5.0(express@5.1.0): 2452 | dependencies: 2453 | express: 5.1.0 2454 | 2455 | express@5.1.0: 2456 | dependencies: 2457 | accepts: 2.0.0 2458 | body-parser: 2.2.0 2459 | content-disposition: 1.0.0 2460 | content-type: 1.0.5 2461 | cookie: 0.7.2 2462 | cookie-signature: 1.2.2 2463 | debug: 4.4.0 2464 | encodeurl: 2.0.0 2465 | escape-html: 1.0.3 2466 | etag: 1.8.1 2467 | finalhandler: 2.1.0 2468 | fresh: 2.0.0 2469 | http-errors: 2.0.0 2470 | merge-descriptors: 2.0.0 2471 | mime-types: 3.0.1 2472 | on-finished: 2.4.1 2473 | once: 1.4.0 2474 | parseurl: 1.3.3 2475 | proxy-addr: 2.0.7 2476 | qs: 6.14.0 2477 | range-parser: 1.2.1 2478 | router: 2.2.0 2479 | send: 1.2.0 2480 | serve-static: 2.2.0 2481 | statuses: 2.0.1 2482 | type-is: 2.0.1 2483 | vary: 1.1.2 2484 | transitivePeerDependencies: 2485 | - supports-color 2486 | 2487 | fast-deep-equal@3.1.3: {} 2488 | 2489 | fast-glob@3.3.3: 2490 | dependencies: 2491 | '@nodelib/fs.stat': 2.0.5 2492 | '@nodelib/fs.walk': 1.2.8 2493 | glob-parent: 5.1.2 2494 | merge2: 1.4.1 2495 | micromatch: 4.0.8 2496 | 2497 | fast-json-stable-stringify@2.1.0: {} 2498 | 2499 | fast-levenshtein@2.0.6: {} 2500 | 2501 | fastq@1.19.1: 2502 | dependencies: 2503 | reusify: 1.1.0 2504 | 2505 | fdir@6.4.3(picomatch@4.0.2): 2506 | optionalDependencies: 2507 | picomatch: 4.0.2 2508 | 2509 | fetch-blob@3.2.0: 2510 | dependencies: 2511 | node-domexception: 1.0.0 2512 | web-streams-polyfill: 3.3.3 2513 | 2514 | file-entry-cache@8.0.0: 2515 | dependencies: 2516 | flat-cache: 4.0.1 2517 | 2518 | fill-range@7.1.1: 2519 | dependencies: 2520 | to-regex-range: 5.0.1 2521 | 2522 | finalhandler@2.1.0: 2523 | dependencies: 2524 | debug: 4.4.0 2525 | encodeurl: 2.0.0 2526 | escape-html: 1.0.3 2527 | on-finished: 2.4.1 2528 | parseurl: 1.3.3 2529 | statuses: 2.0.1 2530 | transitivePeerDependencies: 2531 | - supports-color 2532 | 2533 | find-up@4.1.0: 2534 | dependencies: 2535 | locate-path: 5.0.0 2536 | path-exists: 4.0.0 2537 | 2538 | find-up@5.0.0: 2539 | dependencies: 2540 | locate-path: 6.0.0 2541 | path-exists: 4.0.0 2542 | 2543 | flat-cache@4.0.1: 2544 | dependencies: 2545 | flatted: 3.3.3 2546 | keyv: 4.5.4 2547 | 2548 | flatted@3.3.3: {} 2549 | 2550 | foreground-child@3.3.1: 2551 | dependencies: 2552 | cross-spawn: 7.0.6 2553 | signal-exit: 4.1.0 2554 | 2555 | formdata-polyfill@4.0.10: 2556 | dependencies: 2557 | fetch-blob: 3.2.0 2558 | 2559 | forwarded@0.2.0: {} 2560 | 2561 | fresh@2.0.0: {} 2562 | 2563 | fsevents@2.3.3: 2564 | optional: true 2565 | 2566 | function-bind@1.1.2: {} 2567 | 2568 | get-intrinsic@1.3.0: 2569 | dependencies: 2570 | call-bind-apply-helpers: 1.0.2 2571 | es-define-property: 1.0.1 2572 | es-errors: 1.3.0 2573 | es-object-atoms: 1.1.1 2574 | function-bind: 1.1.2 2575 | get-proto: 1.0.1 2576 | gopd: 1.2.0 2577 | has-symbols: 1.1.0 2578 | hasown: 2.0.2 2579 | math-intrinsics: 1.1.0 2580 | 2581 | get-proto@1.0.1: 2582 | dependencies: 2583 | dunder-proto: 1.0.1 2584 | es-object-atoms: 1.1.1 2585 | 2586 | glob-parent@5.1.2: 2587 | dependencies: 2588 | is-glob: 4.0.3 2589 | 2590 | glob-parent@6.0.2: 2591 | dependencies: 2592 | is-glob: 4.0.3 2593 | 2594 | glob@10.4.5: 2595 | dependencies: 2596 | foreground-child: 3.3.1 2597 | jackspeak: 3.4.3 2598 | minimatch: 9.0.5 2599 | minipass: 7.1.2 2600 | package-json-from-dist: 1.0.1 2601 | path-scurry: 1.11.1 2602 | 2603 | globals@14.0.0: {} 2604 | 2605 | globals@15.15.0: {} 2606 | 2607 | gopd@1.2.0: {} 2608 | 2609 | graphemer@1.4.0: {} 2610 | 2611 | has-flag@4.0.0: {} 2612 | 2613 | has-symbols@1.1.0: {} 2614 | 2615 | hasown@2.0.2: 2616 | dependencies: 2617 | function-bind: 1.1.2 2618 | 2619 | hosted-git-info@2.8.9: {} 2620 | 2621 | http-errors@2.0.0: 2622 | dependencies: 2623 | depd: 2.0.0 2624 | inherits: 2.0.4 2625 | setprototypeof: 1.2.0 2626 | statuses: 2.0.1 2627 | toidentifier: 1.0.1 2628 | 2629 | iconv-lite@0.6.3: 2630 | dependencies: 2631 | safer-buffer: 2.1.2 2632 | 2633 | ignore@5.3.2: {} 2634 | 2635 | import-fresh@3.3.1: 2636 | dependencies: 2637 | parent-module: 1.0.1 2638 | resolve-from: 4.0.0 2639 | 2640 | imurmurhash@0.1.4: {} 2641 | 2642 | indent-string@4.0.0: {} 2643 | 2644 | inherits@2.0.4: {} 2645 | 2646 | ipaddr.js@1.9.1: {} 2647 | 2648 | is-arrayish@0.2.1: {} 2649 | 2650 | is-builtin-module@3.2.1: 2651 | dependencies: 2652 | builtin-modules: 3.3.0 2653 | 2654 | is-core-module@2.16.1: 2655 | dependencies: 2656 | hasown: 2.0.2 2657 | 2658 | is-extglob@2.1.1: {} 2659 | 2660 | is-fullwidth-code-point@3.0.0: {} 2661 | 2662 | is-glob@4.0.3: 2663 | dependencies: 2664 | is-extglob: 2.1.1 2665 | 2666 | is-number@7.0.0: {} 2667 | 2668 | is-path-inside@3.0.3: {} 2669 | 2670 | is-promise@4.0.0: {} 2671 | 2672 | isexe@2.0.0: {} 2673 | 2674 | jackspeak@3.4.3: 2675 | dependencies: 2676 | '@isaacs/cliui': 8.0.2 2677 | optionalDependencies: 2678 | '@pkgjs/parseargs': 0.11.0 2679 | 2680 | joycon@3.1.1: {} 2681 | 2682 | js-tokens@4.0.0: {} 2683 | 2684 | js-yaml@4.1.0: 2685 | dependencies: 2686 | argparse: 2.0.1 2687 | 2688 | jsesc@0.5.0: {} 2689 | 2690 | jsesc@3.1.0: {} 2691 | 2692 | json-buffer@3.0.1: {} 2693 | 2694 | json-parse-even-better-errors@2.3.1: {} 2695 | 2696 | json-schema-traverse@0.4.1: {} 2697 | 2698 | json-stable-stringify-without-jsonify@1.0.1: {} 2699 | 2700 | keyv@4.5.4: 2701 | dependencies: 2702 | json-buffer: 3.0.1 2703 | 2704 | levn@0.4.1: 2705 | dependencies: 2706 | prelude-ls: 1.2.1 2707 | type-check: 0.4.0 2708 | 2709 | lilconfig@3.1.3: {} 2710 | 2711 | lines-and-columns@1.2.4: {} 2712 | 2713 | load-tsconfig@0.2.5: {} 2714 | 2715 | locate-path@5.0.0: 2716 | dependencies: 2717 | p-locate: 4.1.0 2718 | 2719 | locate-path@6.0.0: 2720 | dependencies: 2721 | p-locate: 5.0.0 2722 | 2723 | lodash.merge@4.6.2: {} 2724 | 2725 | lodash.sortby@4.7.0: {} 2726 | 2727 | loupe@3.1.3: {} 2728 | 2729 | lru-cache@10.4.3: {} 2730 | 2731 | magic-string@0.30.17: 2732 | dependencies: 2733 | '@jridgewell/sourcemap-codec': 1.5.0 2734 | 2735 | math-intrinsics@1.1.0: {} 2736 | 2737 | media-typer@1.1.0: {} 2738 | 2739 | merge-descriptors@2.0.0: {} 2740 | 2741 | merge2@1.4.1: {} 2742 | 2743 | micromatch@4.0.8: 2744 | dependencies: 2745 | braces: 3.0.3 2746 | picomatch: 2.3.1 2747 | 2748 | mime-db@1.54.0: {} 2749 | 2750 | mime-types@3.0.1: 2751 | dependencies: 2752 | mime-db: 1.54.0 2753 | 2754 | min-indent@1.0.1: {} 2755 | 2756 | minimatch@3.1.2: 2757 | dependencies: 2758 | brace-expansion: 1.1.11 2759 | 2760 | minimatch@9.0.5: 2761 | dependencies: 2762 | brace-expansion: 2.0.1 2763 | 2764 | minipass@7.1.2: {} 2765 | 2766 | ms@2.1.3: {} 2767 | 2768 | mz@2.7.0: 2769 | dependencies: 2770 | any-promise: 1.3.0 2771 | object-assign: 4.1.1 2772 | thenify-all: 1.6.0 2773 | 2774 | nanoid@3.3.11: {} 2775 | 2776 | natural-compare@1.4.0: {} 2777 | 2778 | negotiator@1.0.0: {} 2779 | 2780 | node-domexception@1.0.0: {} 2781 | 2782 | node-fetch@3.3.2: 2783 | dependencies: 2784 | data-uri-to-buffer: 4.0.1 2785 | fetch-blob: 3.2.0 2786 | formdata-polyfill: 4.0.10 2787 | 2788 | node-releases@2.0.19: {} 2789 | 2790 | normalize-package-data@2.5.0: 2791 | dependencies: 2792 | hosted-git-info: 2.8.9 2793 | resolve: 1.22.10 2794 | semver: 5.7.2 2795 | validate-npm-package-license: 3.0.4 2796 | 2797 | object-assign@4.1.1: {} 2798 | 2799 | object-inspect@1.13.4: {} 2800 | 2801 | on-finished@2.4.1: 2802 | dependencies: 2803 | ee-first: 1.1.1 2804 | 2805 | once@1.4.0: 2806 | dependencies: 2807 | wrappy: 1.0.2 2808 | 2809 | optionator@0.9.4: 2810 | dependencies: 2811 | deep-is: 0.1.4 2812 | fast-levenshtein: 2.0.6 2813 | levn: 0.4.1 2814 | prelude-ls: 1.2.1 2815 | type-check: 0.4.0 2816 | word-wrap: 1.2.5 2817 | 2818 | p-limit@2.3.0: 2819 | dependencies: 2820 | p-try: 2.2.0 2821 | 2822 | p-limit@3.1.0: 2823 | dependencies: 2824 | yocto-queue: 0.1.0 2825 | 2826 | p-locate@4.1.0: 2827 | dependencies: 2828 | p-limit: 2.3.0 2829 | 2830 | p-locate@5.0.0: 2831 | dependencies: 2832 | p-limit: 3.1.0 2833 | 2834 | p-try@2.2.0: {} 2835 | 2836 | package-json-from-dist@1.0.1: {} 2837 | 2838 | parent-module@1.0.1: 2839 | dependencies: 2840 | callsites: 3.1.0 2841 | 2842 | parse-json@5.2.0: 2843 | dependencies: 2844 | '@babel/code-frame': 7.26.2 2845 | error-ex: 1.3.2 2846 | json-parse-even-better-errors: 2.3.1 2847 | lines-and-columns: 1.2.4 2848 | 2849 | parseurl@1.3.3: {} 2850 | 2851 | path-exists@4.0.0: {} 2852 | 2853 | path-key@3.1.1: {} 2854 | 2855 | path-parse@1.0.7: {} 2856 | 2857 | path-scurry@1.11.1: 2858 | dependencies: 2859 | lru-cache: 10.4.3 2860 | minipass: 7.1.2 2861 | 2862 | path-to-regexp@8.2.0: {} 2863 | 2864 | pathe@2.0.3: {} 2865 | 2866 | pathval@2.0.0: {} 2867 | 2868 | picocolors@1.1.1: {} 2869 | 2870 | picomatch@2.3.1: {} 2871 | 2872 | picomatch@4.0.2: {} 2873 | 2874 | pirates@4.0.7: {} 2875 | 2876 | pkce-challenge@4.1.0: {} 2877 | 2878 | pluralize@8.0.0: {} 2879 | 2880 | postcss-load-config@6.0.1(postcss@8.5.3): 2881 | dependencies: 2882 | lilconfig: 3.1.3 2883 | optionalDependencies: 2884 | postcss: 8.5.3 2885 | 2886 | postcss@8.5.3: 2887 | dependencies: 2888 | nanoid: 3.3.11 2889 | picocolors: 1.1.1 2890 | source-map-js: 1.2.1 2891 | 2892 | prelude-ls@1.2.1: {} 2893 | 2894 | prettier@3.4.2: {} 2895 | 2896 | proxy-addr@2.0.7: 2897 | dependencies: 2898 | forwarded: 0.2.0 2899 | ipaddr.js: 1.9.1 2900 | 2901 | punycode@2.3.1: {} 2902 | 2903 | qs@6.14.0: 2904 | dependencies: 2905 | side-channel: 1.1.0 2906 | 2907 | queue-microtask@1.2.3: {} 2908 | 2909 | range-parser@1.2.1: {} 2910 | 2911 | raw-body@3.0.0: 2912 | dependencies: 2913 | bytes: 3.1.2 2914 | http-errors: 2.0.0 2915 | iconv-lite: 0.6.3 2916 | unpipe: 1.0.0 2917 | 2918 | read-pkg-up@7.0.1: 2919 | dependencies: 2920 | find-up: 4.1.0 2921 | read-pkg: 5.2.0 2922 | type-fest: 0.8.1 2923 | 2924 | read-pkg@5.2.0: 2925 | dependencies: 2926 | '@types/normalize-package-data': 2.4.4 2927 | normalize-package-data: 2.5.0 2928 | parse-json: 5.2.0 2929 | type-fest: 0.6.0 2930 | 2931 | readdirp@4.1.2: {} 2932 | 2933 | regexp-tree@0.1.27: {} 2934 | 2935 | regjsparser@0.10.0: 2936 | dependencies: 2937 | jsesc: 0.5.0 2938 | 2939 | resolve-from@4.0.0: {} 2940 | 2941 | resolve-from@5.0.0: {} 2942 | 2943 | resolve@1.22.10: 2944 | dependencies: 2945 | is-core-module: 2.16.1 2946 | path-parse: 1.0.7 2947 | supports-preserve-symlinks-flag: 1.0.0 2948 | 2949 | reusify@1.1.0: {} 2950 | 2951 | rollup@4.38.0: 2952 | dependencies: 2953 | '@types/estree': 1.0.7 2954 | optionalDependencies: 2955 | '@rollup/rollup-android-arm-eabi': 4.38.0 2956 | '@rollup/rollup-android-arm64': 4.38.0 2957 | '@rollup/rollup-darwin-arm64': 4.38.0 2958 | '@rollup/rollup-darwin-x64': 4.38.0 2959 | '@rollup/rollup-freebsd-arm64': 4.38.0 2960 | '@rollup/rollup-freebsd-x64': 4.38.0 2961 | '@rollup/rollup-linux-arm-gnueabihf': 4.38.0 2962 | '@rollup/rollup-linux-arm-musleabihf': 4.38.0 2963 | '@rollup/rollup-linux-arm64-gnu': 4.38.0 2964 | '@rollup/rollup-linux-arm64-musl': 4.38.0 2965 | '@rollup/rollup-linux-loongarch64-gnu': 4.38.0 2966 | '@rollup/rollup-linux-powerpc64le-gnu': 4.38.0 2967 | '@rollup/rollup-linux-riscv64-gnu': 4.38.0 2968 | '@rollup/rollup-linux-riscv64-musl': 4.38.0 2969 | '@rollup/rollup-linux-s390x-gnu': 4.38.0 2970 | '@rollup/rollup-linux-x64-gnu': 4.38.0 2971 | '@rollup/rollup-linux-x64-musl': 4.38.0 2972 | '@rollup/rollup-win32-arm64-msvc': 4.38.0 2973 | '@rollup/rollup-win32-ia32-msvc': 4.38.0 2974 | '@rollup/rollup-win32-x64-msvc': 4.38.0 2975 | fsevents: 2.3.3 2976 | 2977 | router@2.2.0: 2978 | dependencies: 2979 | debug: 4.4.0 2980 | depd: 2.0.0 2981 | is-promise: 4.0.0 2982 | parseurl: 1.3.3 2983 | path-to-regexp: 8.2.0 2984 | transitivePeerDependencies: 2985 | - supports-color 2986 | 2987 | run-parallel@1.2.0: 2988 | dependencies: 2989 | queue-microtask: 1.2.3 2990 | 2991 | safe-buffer@5.2.1: {} 2992 | 2993 | safer-buffer@2.1.2: {} 2994 | 2995 | semver@5.7.2: {} 2996 | 2997 | semver@7.7.1: {} 2998 | 2999 | send@1.2.0: 3000 | dependencies: 3001 | debug: 4.4.0 3002 | encodeurl: 2.0.0 3003 | escape-html: 1.0.3 3004 | etag: 1.8.1 3005 | fresh: 2.0.0 3006 | http-errors: 2.0.0 3007 | mime-types: 3.0.1 3008 | ms: 2.1.3 3009 | on-finished: 2.4.1 3010 | range-parser: 1.2.1 3011 | statuses: 2.0.1 3012 | transitivePeerDependencies: 3013 | - supports-color 3014 | 3015 | serve-static@2.2.0: 3016 | dependencies: 3017 | encodeurl: 2.0.0 3018 | escape-html: 1.0.3 3019 | parseurl: 1.3.3 3020 | send: 1.2.0 3021 | transitivePeerDependencies: 3022 | - supports-color 3023 | 3024 | setprototypeof@1.2.0: {} 3025 | 3026 | shebang-command@2.0.0: 3027 | dependencies: 3028 | shebang-regex: 3.0.0 3029 | 3030 | shebang-regex@3.0.0: {} 3031 | 3032 | side-channel-list@1.0.0: 3033 | dependencies: 3034 | es-errors: 1.3.0 3035 | object-inspect: 1.13.4 3036 | 3037 | side-channel-map@1.0.1: 3038 | dependencies: 3039 | call-bound: 1.0.4 3040 | es-errors: 1.3.0 3041 | get-intrinsic: 1.3.0 3042 | object-inspect: 1.13.4 3043 | 3044 | side-channel-weakmap@1.0.2: 3045 | dependencies: 3046 | call-bound: 1.0.4 3047 | es-errors: 1.3.0 3048 | get-intrinsic: 1.3.0 3049 | object-inspect: 1.13.4 3050 | side-channel-map: 1.0.1 3051 | 3052 | side-channel@1.1.0: 3053 | dependencies: 3054 | es-errors: 1.3.0 3055 | object-inspect: 1.13.4 3056 | side-channel-list: 1.0.0 3057 | side-channel-map: 1.0.1 3058 | side-channel-weakmap: 1.0.2 3059 | 3060 | siginfo@2.0.0: {} 3061 | 3062 | signal-exit@4.1.0: {} 3063 | 3064 | source-map-js@1.2.1: {} 3065 | 3066 | source-map@0.8.0-beta.0: 3067 | dependencies: 3068 | whatwg-url: 7.1.0 3069 | 3070 | spdx-correct@3.2.0: 3071 | dependencies: 3072 | spdx-expression-parse: 3.0.1 3073 | spdx-license-ids: 3.0.21 3074 | 3075 | spdx-exceptions@2.5.0: {} 3076 | 3077 | spdx-expression-parse@3.0.1: 3078 | dependencies: 3079 | spdx-exceptions: 2.5.0 3080 | spdx-license-ids: 3.0.21 3081 | 3082 | spdx-license-ids@3.0.21: {} 3083 | 3084 | stackback@0.0.2: {} 3085 | 3086 | statuses@2.0.1: {} 3087 | 3088 | std-env@3.8.1: {} 3089 | 3090 | string-width@4.2.3: 3091 | dependencies: 3092 | emoji-regex: 8.0.0 3093 | is-fullwidth-code-point: 3.0.0 3094 | strip-ansi: 6.0.1 3095 | 3096 | string-width@5.1.2: 3097 | dependencies: 3098 | eastasianwidth: 0.2.0 3099 | emoji-regex: 9.2.2 3100 | strip-ansi: 7.1.0 3101 | 3102 | strip-ansi@6.0.1: 3103 | dependencies: 3104 | ansi-regex: 5.0.1 3105 | 3106 | strip-ansi@7.1.0: 3107 | dependencies: 3108 | ansi-regex: 6.1.0 3109 | 3110 | strip-indent@3.0.0: 3111 | dependencies: 3112 | min-indent: 1.0.1 3113 | 3114 | strip-json-comments@3.1.1: {} 3115 | 3116 | sucrase@3.35.0: 3117 | dependencies: 3118 | '@jridgewell/gen-mapping': 0.3.8 3119 | commander: 4.1.1 3120 | glob: 10.4.5 3121 | lines-and-columns: 1.2.4 3122 | mz: 2.7.0 3123 | pirates: 4.0.7 3124 | ts-interface-checker: 0.1.13 3125 | 3126 | supports-color@7.2.0: 3127 | dependencies: 3128 | has-flag: 4.0.0 3129 | 3130 | supports-preserve-symlinks-flag@1.0.0: {} 3131 | 3132 | text-table@0.2.0: {} 3133 | 3134 | thenify-all@1.6.0: 3135 | dependencies: 3136 | thenify: 3.3.1 3137 | 3138 | thenify@3.3.1: 3139 | dependencies: 3140 | any-promise: 1.3.0 3141 | 3142 | tinybench@2.9.0: {} 3143 | 3144 | tinyexec@0.3.2: {} 3145 | 3146 | tinyglobby@0.2.12: 3147 | dependencies: 3148 | fdir: 6.4.3(picomatch@4.0.2) 3149 | picomatch: 4.0.2 3150 | 3151 | tinypool@1.0.2: {} 3152 | 3153 | tinyrainbow@2.0.0: {} 3154 | 3155 | tinyspy@3.0.2: {} 3156 | 3157 | to-regex-range@5.0.1: 3158 | dependencies: 3159 | is-number: 7.0.0 3160 | 3161 | toidentifier@1.0.1: {} 3162 | 3163 | tr46@1.0.1: 3164 | dependencies: 3165 | punycode: 2.3.1 3166 | 3167 | tree-kill@1.2.2: {} 3168 | 3169 | ts-api-utils@1.4.3(typescript@5.8.2): 3170 | dependencies: 3171 | typescript: 5.8.2 3172 | 3173 | ts-interface-checker@0.1.13: {} 3174 | 3175 | tsup@8.4.0(postcss@8.5.3)(typescript@5.8.2): 3176 | dependencies: 3177 | bundle-require: 5.1.0(esbuild@0.25.2) 3178 | cac: 6.7.14 3179 | chokidar: 4.0.3 3180 | consola: 3.4.2 3181 | debug: 4.4.0 3182 | esbuild: 0.25.2 3183 | joycon: 3.1.1 3184 | picocolors: 1.1.1 3185 | postcss-load-config: 6.0.1(postcss@8.5.3) 3186 | resolve-from: 5.0.0 3187 | rollup: 4.38.0 3188 | source-map: 0.8.0-beta.0 3189 | sucrase: 3.35.0 3190 | tinyexec: 0.3.2 3191 | tinyglobby: 0.2.12 3192 | tree-kill: 1.2.2 3193 | optionalDependencies: 3194 | postcss: 8.5.3 3195 | typescript: 5.8.2 3196 | transitivePeerDependencies: 3197 | - jiti 3198 | - supports-color 3199 | - tsx 3200 | - yaml 3201 | 3202 | type-check@0.4.0: 3203 | dependencies: 3204 | prelude-ls: 1.2.1 3205 | 3206 | type-fest@0.6.0: {} 3207 | 3208 | type-fest@0.8.1: {} 3209 | 3210 | type-is@2.0.1: 3211 | dependencies: 3212 | content-type: 1.0.5 3213 | media-typer: 1.1.0 3214 | mime-types: 3.0.1 3215 | 3216 | typescript@5.8.2: {} 3217 | 3218 | unpipe@1.0.0: {} 3219 | 3220 | update-browserslist-db@1.1.3(browserslist@4.24.4): 3221 | dependencies: 3222 | browserslist: 4.24.4 3223 | escalade: 3.2.0 3224 | picocolors: 1.1.1 3225 | 3226 | uri-js@4.4.1: 3227 | dependencies: 3228 | punycode: 2.3.1 3229 | 3230 | validate-npm-package-license@3.0.4: 3231 | dependencies: 3232 | spdx-correct: 3.2.0 3233 | spdx-expression-parse: 3.0.1 3234 | 3235 | vary@1.1.2: {} 3236 | 3237 | vite-node@3.1.1(@types/node@15.14.9): 3238 | dependencies: 3239 | cac: 6.7.14 3240 | debug: 4.4.0 3241 | es-module-lexer: 1.6.0 3242 | pathe: 2.0.3 3243 | vite: 6.2.4(@types/node@15.14.9) 3244 | transitivePeerDependencies: 3245 | - '@types/node' 3246 | - jiti 3247 | - less 3248 | - lightningcss 3249 | - sass 3250 | - sass-embedded 3251 | - stylus 3252 | - sugarss 3253 | - supports-color 3254 | - terser 3255 | - tsx 3256 | - yaml 3257 | 3258 | vite@6.2.4(@types/node@15.14.9): 3259 | dependencies: 3260 | esbuild: 0.25.2 3261 | postcss: 8.5.3 3262 | rollup: 4.38.0 3263 | optionalDependencies: 3264 | '@types/node': 15.14.9 3265 | fsevents: 2.3.3 3266 | 3267 | vitest@3.1.1(@types/node@15.14.9): 3268 | dependencies: 3269 | '@vitest/expect': 3.1.1 3270 | '@vitest/mocker': 3.1.1(vite@6.2.4(@types/node@15.14.9)) 3271 | '@vitest/pretty-format': 3.1.1 3272 | '@vitest/runner': 3.1.1 3273 | '@vitest/snapshot': 3.1.1 3274 | '@vitest/spy': 3.1.1 3275 | '@vitest/utils': 3.1.1 3276 | chai: 5.2.0 3277 | debug: 4.4.0 3278 | expect-type: 1.2.1 3279 | magic-string: 0.30.17 3280 | pathe: 2.0.3 3281 | std-env: 3.8.1 3282 | tinybench: 2.9.0 3283 | tinyexec: 0.3.2 3284 | tinypool: 1.0.2 3285 | tinyrainbow: 2.0.0 3286 | vite: 6.2.4(@types/node@15.14.9) 3287 | vite-node: 3.1.1(@types/node@15.14.9) 3288 | why-is-node-running: 2.3.0 3289 | optionalDependencies: 3290 | '@types/node': 15.14.9 3291 | transitivePeerDependencies: 3292 | - jiti 3293 | - less 3294 | - lightningcss 3295 | - msw 3296 | - sass 3297 | - sass-embedded 3298 | - stylus 3299 | - sugarss 3300 | - supports-color 3301 | - terser 3302 | - tsx 3303 | - yaml 3304 | 3305 | web-streams-polyfill@3.3.3: {} 3306 | 3307 | webidl-conversions@4.0.2: {} 3308 | 3309 | whatwg-url@7.1.0: 3310 | dependencies: 3311 | lodash.sortby: 4.7.0 3312 | tr46: 1.0.1 3313 | webidl-conversions: 4.0.2 3314 | 3315 | which@2.0.2: 3316 | dependencies: 3317 | isexe: 2.0.0 3318 | 3319 | why-is-node-running@2.3.0: 3320 | dependencies: 3321 | siginfo: 2.0.0 3322 | stackback: 0.0.2 3323 | 3324 | word-wrap@1.2.5: {} 3325 | 3326 | wrap-ansi@7.0.0: 3327 | dependencies: 3328 | ansi-styles: 4.3.0 3329 | string-width: 4.2.3 3330 | strip-ansi: 6.0.1 3331 | 3332 | wrap-ansi@8.1.0: 3333 | dependencies: 3334 | ansi-styles: 6.2.1 3335 | string-width: 5.1.2 3336 | strip-ansi: 7.1.0 3337 | 3338 | wrappy@1.0.2: {} 3339 | 3340 | yocto-queue@0.1.0: {} 3341 | 3342 | zod-to-json-schema@3.24.1(zod@3.24.1): 3343 | dependencies: 3344 | zod: 3.24.1 3345 | 3346 | zod@3.24.1: {} 3347 | -------------------------------------------------------------------------------- /prettier.config.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('prettier').Config} 3 | */ 4 | const config = { 5 | endOfLine: "lf", 6 | singleQuote: false, 7 | tabWidth: 2, 8 | trailingComma: "es5", 9 | printWidth: 100, 10 | arrowParens: "always", 11 | }; 12 | 13 | export default config; 14 | -------------------------------------------------------------------------------- /smithery.yaml: -------------------------------------------------------------------------------- 1 | startCommand: 2 | type: stdio 3 | configSchema: 4 | { 5 | "type": "object", 6 | "properties": { 7 | "email": { 8 | "type": "string", 9 | "description": "Your Upstash email address" 10 | }, 11 | "token": { 12 | "type": "string", 13 | "description": "Your Upstash management API key" 14 | } 15 | }, 16 | "required": ["email", "token"], 17 | "additionalProperties": false 18 | } 19 | commandFunction: 20 | |- 21 | (config) => ({ 22 | "command": "node", 23 | "args": [ 24 | "dist/index.js", 25 | "run", 26 | config.email, 27 | config.token 28 | ] 29 | }) 30 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | export const config = { 2 | apiKey: "", 3 | email: "", 4 | }; 5 | -------------------------------------------------------------------------------- /src/http.ts: -------------------------------------------------------------------------------- 1 | import { config } from "./config"; 2 | import { log } from "./log"; 3 | import { applyMiddlewares } from "./middlewares"; 4 | import type { RequestInit } from "node-fetch"; 5 | import fetch from "node-fetch"; 6 | 7 | export type UpstashRequest = { 8 | method: string; 9 | path?: string[] | string; 10 | /** 11 | * Request body will be serialized to json 12 | */ 13 | body?: unknown; 14 | }; 15 | 16 | type HttpClientConfig = { 17 | baseUrl: string; 18 | }; 19 | 20 | class HttpClient { 21 | private readonly baseUrl: string; 22 | 23 | public constructor(config: HttpClientConfig) { 24 | this.baseUrl = config.baseUrl.replace(/\/$/, ""); 25 | } 26 | 27 | public async get(path: string[] | string): Promise { 28 | return this.requestWithMiddleware({ method: "GET", path }); 29 | } 30 | 31 | public async post(path: string[] | string, body: unknown): Promise { 32 | return this.requestWithMiddleware({ method: "POST", path, body }); 33 | } 34 | 35 | public async patch(path: string[] | string, body?: unknown): Promise { 36 | return this.requestWithMiddleware({ method: "PATCH", path, body }); 37 | } 38 | 39 | public async delete(path: string[] | string): Promise { 40 | return this.requestWithMiddleware({ method: "DELETE", path }); 41 | } 42 | 43 | private async requestWithMiddleware(req: UpstashRequest): Promise { 44 | const res = await applyMiddlewares(req, async (req) => { 45 | return this.request(req); 46 | }); 47 | 48 | return res as TResponse; 49 | } 50 | 51 | private async request(req: UpstashRequest): Promise { 52 | if (!req.path) { 53 | req.path = []; 54 | } else if (typeof req.path === "string") { 55 | req.path = [req.path]; 56 | } 57 | 58 | const url = [this.baseUrl, ...req.path].join("/"); 59 | const token = [config.email, config.apiKey].join(":"); 60 | 61 | const init: RequestInit = { 62 | method: req.method, 63 | headers: { 64 | "Content-Type": "application/json", 65 | Authorization: `Basic ${Buffer.from(token).toString("base64")}`, 66 | }, 67 | }; 68 | 69 | if (req.method !== "GET") { 70 | init.body = JSON.stringify(req.body); 71 | } 72 | 73 | log("Sending request", { 74 | url, 75 | ...init, 76 | headers: { ...init.headers, Authorization: "***" }, 77 | }); 78 | 79 | // fetch is defined by isomorphic fetch 80 | const res = await fetch(url, init); 81 | if (!res.ok) { 82 | throw new Error(`Request failed (${res.status} ${res.statusText}): ${await res.text()}`); 83 | } 84 | return (await res.json()) as TResponse; 85 | } 86 | } 87 | 88 | export const http = new HttpClient({ baseUrl: "https://api.upstash.com" }); 89 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 4 | import { init } from "./init"; 5 | import { log } from "./log"; 6 | import { server } from "./server"; 7 | import { config } from "./config"; 8 | import "dotenv/config"; 9 | import { testConnection } from "./test-connection"; 10 | 11 | process.on("uncaughtException", (error) => { 12 | log("Uncaught exception:", error.name, error.message, error.stack); 13 | }); 14 | 15 | process.on("unhandledRejection", (error) => { 16 | if (error instanceof Error) log("Unhandled rejection:", error.name, error.message, error.stack); 17 | else log("Unhandled rejection:", error); 18 | }); 19 | 20 | const envApiKey = process.env.UPSTASH_API_KEY; 21 | const envEmail = process.env.UPSTASH_EMAIL; 22 | 23 | const USAGE_GENERAL = `Usage: npx @upstash/mcp-server (init|run) `; 24 | const USAGE_RUN = `Usage: npx @upstash/mcp-server run `; 25 | const USAGE_INIT = `Usage: npx @upstash/mcp-server init `; 26 | 27 | async function parseArguments() { 28 | const [cmd, ...args] = process.argv.slice(2); 29 | if (!cmd) throw new Error(USAGE_GENERAL); 30 | else if (cmd === "init") { 31 | const [email, apiKey, ...rest] = args; 32 | const finalApiKey = apiKey || envApiKey; 33 | const finalEmail = email || envEmail; 34 | 35 | if (rest.length > 0) throw new Error(`Too many arguments. ${USAGE_INIT}`); 36 | if (!finalApiKey) throw new Error(`Missing API key. ${USAGE_INIT}`); 37 | if (!finalEmail) throw new Error(`Missing email. ${USAGE_INIT}`); 38 | 39 | config.apiKey = finalApiKey; 40 | config.email = finalEmail; 41 | 42 | await testConnection(); 43 | 44 | await init({ 45 | executablePath: process.argv[1], 46 | }); 47 | } else if (cmd === "run") { 48 | const [email, apiKey, ...rest] = args; 49 | const finalApiKey = apiKey || envApiKey; 50 | const finalEmail = email || envEmail; 51 | 52 | if (!finalApiKey) throw new Error(`Missing API key. ${USAGE_RUN}`); 53 | if (!finalEmail) throw new Error(`Missing email. ${USAGE_RUN}`); 54 | if (rest.length > 0) throw new Error(`Too many arguments. ${USAGE_RUN}`); 55 | log("Starting MCP server"); 56 | 57 | config.apiKey = finalApiKey; 58 | config.email = finalEmail; 59 | 60 | await testConnection(); 61 | 62 | // Start the server 63 | await main(); 64 | } else { 65 | throw new Error(`Unknown command: ${cmd}. Expected 'init' or 'run'. ${USAGE_GENERAL}`); 66 | } 67 | } 68 | 69 | async function main() { 70 | const transport = new StdioServerTransport(); 71 | await server.connect(transport); 72 | } 73 | 74 | // eslint-disable-next-line unicorn/prefer-top-level-await 75 | parseArguments().catch((error) => { 76 | if (!(error instanceof Error)) throw error; 77 | console.error(error.message); 78 | process.exit(1); 79 | }); 80 | -------------------------------------------------------------------------------- /src/init.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable unicorn/prefer-node-protocol */ 2 | import path from "path"; 3 | import os from "os"; 4 | import fs from "fs"; 5 | import chalk from "chalk"; 6 | 7 | import { log } from "./log"; 8 | import { config } from "./config"; 9 | 10 | const claudeConfigPath = path.join( 11 | os.homedir(), 12 | "Library", 13 | "Application Support", 14 | "Claude", 15 | "claude_desktop_config.json" 16 | ); 17 | 18 | const UPSTASH_MCP_KEY = "upstash"; 19 | 20 | export async function init({ executablePath }: { executablePath: string }) { 21 | const isLocal = executablePath.includes("dist/index.js"); 22 | const upstashConfig = isLocal 23 | ? { 24 | command: "node", 25 | args: [executablePath, "run", config.email, config.apiKey], 26 | } 27 | : { 28 | command: "npx", 29 | args: ["-y", "@upstash/mcp-server", "run", config.email, config.apiKey], 30 | }; 31 | 32 | const configDir = path.dirname(claudeConfigPath); 33 | if (!fs.existsSync(configDir)) { 34 | log(chalk.blue("Creating Claude config directory...")); 35 | fs.mkdirSync(configDir, { recursive: true }); 36 | } 37 | 38 | const existingConfig = fs.existsSync(claudeConfigPath) 39 | ? (JSON.parse(fs.readFileSync(claudeConfigPath, "utf8")) as { 40 | mcpServers?: Record; 41 | }) 42 | : { mcpServers: {} }; 43 | 44 | if (UPSTASH_MCP_KEY in (existingConfig?.mcpServers || {})) { 45 | log(chalk.yellow("Upstash entry already exists. Overriding it.")); 46 | } 47 | 48 | if (isLocal) { 49 | log( 50 | chalk.yellow( 51 | "Local executable detected. Using 'node' and absolute path instead of 'npx' for development." 52 | ) 53 | ); 54 | } 55 | 56 | const newConfig = { 57 | ...existingConfig, 58 | mcpServers: { 59 | ...existingConfig.mcpServers, 60 | [UPSTASH_MCP_KEY]: upstashConfig, 61 | }, 62 | }; 63 | 64 | fs.writeFileSync(claudeConfigPath, JSON.stringify(newConfig, null, 2)); 65 | 66 | log( 67 | chalk.blue( 68 | "\n" + 69 | JSON.stringify( 70 | { 71 | [UPSTASH_MCP_KEY]: upstashConfig, 72 | }, 73 | null, 74 | 2 75 | ).replaceAll(config.apiKey, "********") 76 | ) 77 | ); 78 | log(chalk.green(`Config written to: "${claudeConfigPath.replace(os.homedir(), "~")}"`)); 79 | } 80 | -------------------------------------------------------------------------------- /src/log.ts: -------------------------------------------------------------------------------- 1 | export function log(...args: unknown[]) { 2 | const msg = `[DEBUG ${new Date().toISOString()}] ${args.map((arg) => (typeof arg === "string" ? arg : JSON.stringify(arg))).join(" ")}\n`; 3 | process.stderr.write(msg); 4 | } 5 | -------------------------------------------------------------------------------- /src/middlewares.ts: -------------------------------------------------------------------------------- 1 | import type { UpstashRequest } from "./http"; 2 | 3 | type Middleware = (req: UpstashRequest, next: () => Promise) => Promise; 4 | 5 | const formatCreationTime = (obj: unknown) => { 6 | if ( 7 | obj && 8 | typeof obj === "object" && 9 | "creation_time" in obj && 10 | typeof obj.creation_time === "number" && 11 | obj.creation_time > 0 12 | ) { 13 | obj.creation_time = new Date(obj.creation_time * 1000).toLocaleString(); 14 | } 15 | }; 16 | 17 | const middlewares: Middleware[] = [ 18 | // Middleware to format creation_time field to human readable format 19 | async (req, next) => { 20 | const res = await next(); 21 | if (Array.isArray(res)) { 22 | for (const element of res) { 23 | formatCreationTime(element); 24 | } 25 | } else { 26 | formatCreationTime(res); 27 | } 28 | return res; 29 | }, 30 | ]; 31 | 32 | export const applyMiddlewares = async ( 33 | req: UpstashRequest, 34 | func: (req: UpstashRequest) => Promise 35 | ) => { 36 | let next = async () => func(req); 37 | for (const middleware of middlewares.reverse()) { 38 | const prevNext = next; 39 | next = async () => middleware(req, prevNext); 40 | } 41 | return next(); 42 | }; 43 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | import { Server } from "@modelcontextprotocol/sdk/server/index.js"; 2 | import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js"; 3 | import { log } from "./log"; 4 | import { tools } from "./tools"; 5 | import { convertToTools, handlerResponseToCallResult } from "./tool"; 6 | 7 | export const server = new Server( 8 | { name: "upstash", version: "0.1.0" }, 9 | { capabilities: { tools: {} } } 10 | ); 11 | 12 | const toolsList = convertToTools(tools); 13 | 14 | server.setRequestHandler(ListToolsRequestSchema, async () => { 15 | log("Received list tools request", toolsList); 16 | return { tools: toolsList }; 17 | }); 18 | 19 | server.setRequestHandler(CallToolRequestSchema, async (request) => { 20 | const toolName = request.params.name; 21 | log("< received tool call:", toolName, request.params.arguments); 22 | try { 23 | if (toolName in tools) { 24 | const tool = tools[toolName]; 25 | const result = await tool.handler(request.params.arguments); 26 | 27 | const response = handlerResponseToCallResult(result); 28 | log("> tool result:", response.content.map((item) => item.text).join("\n")); 29 | 30 | return response; 31 | } 32 | throw new Error(`Unknown tool: ${toolName}`); 33 | } catch (error) { 34 | const msg = error instanceof Error ? error.message : String(error); 35 | log("> error in tool call:", msg); 36 | return { 37 | content: [ 38 | { 39 | type: "text", 40 | text: `Error: ${msg}`, 41 | }, 42 | ], 43 | isError: true, 44 | }; 45 | } 46 | }); 47 | -------------------------------------------------------------------------------- /src/settings.ts: -------------------------------------------------------------------------------- 1 | export const MAX_MESSAGE_LENGTH = 8000; 2 | -------------------------------------------------------------------------------- /src/test-connection.ts: -------------------------------------------------------------------------------- 1 | import { http } from "./http"; 2 | import { log } from "./log"; 3 | 4 | export async function testConnection() { 5 | log("🧪 Testing connection to Upstash API"); 6 | // TODO: Test the connection to the Upstash API here 7 | // to check if the token is valid 8 | const res = await http.get<[]>("v2/teams"); 9 | 10 | if (!Array.isArray(res)) 11 | throw new Error("Invalid response from Upstash API. Check your API key and email."); 12 | 13 | log("✅ Connection to Upstash API is successful"); 14 | } 15 | -------------------------------------------------------------------------------- /src/tool.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import type { CustomTool } from "./tool"; 3 | import { convertToTools } from "./tool"; 4 | import { z } from "zod"; 5 | 6 | describe("convertToTools", () => { 7 | it("should convert Zod schema to JSON schema", () => { 8 | const toolsObj: Record = { 9 | foo_method: { 10 | description: "Foo method", 11 | inputSchema: z.object({ 12 | name: z.string().describe("Name of the user"), 13 | age: z.number().describe("Age of the user"), 14 | }), 15 | handler: async () => {}, 16 | }, 17 | }; 18 | 19 | const result = convertToTools(toolsObj); 20 | expect(result).toEqual([ 21 | { 22 | name: "foo_method", 23 | description: "Foo method", 24 | inputSchema: { 25 | type: "object", 26 | properties: { 27 | name: { 28 | type: "string", 29 | description: "Name of the user", 30 | }, 31 | age: { 32 | type: "number", 33 | description: "Age of the user", 34 | }, 35 | }, 36 | required: ["name", "age"], 37 | }, 38 | }, 39 | ]); 40 | }); 41 | 42 | it("should convert multiple Zod schemas to JSON schemas", () => { 43 | const toolsObj: Record = { 44 | foo_method: { 45 | description: "Foo method", 46 | inputSchema: z.object({ 47 | name: z.string().describe("Name of the user"), 48 | age: z.number().describe("Age of the user"), 49 | }), 50 | handler: async () => {}, 51 | }, 52 | bar_method: { 53 | description: "Bar method", 54 | inputSchema: z.object({ 55 | email: z.string().describe("Email of the user"), 56 | nested: z 57 | .object({ 58 | count: z.number().describe("Count of the user"), 59 | }) 60 | .describe("Nested object"), 61 | }), 62 | handler: async () => {}, 63 | }, 64 | }; 65 | 66 | const result = convertToTools(toolsObj); 67 | 68 | expect(result).toEqual([ 69 | { 70 | name: "foo_method", 71 | description: "Foo method", 72 | inputSchema: { 73 | type: "object", 74 | properties: { 75 | name: { 76 | type: "string", 77 | description: "Name of the user", 78 | }, 79 | age: { 80 | type: "number", 81 | description: "Age of the user", 82 | }, 83 | }, 84 | required: ["name", "age"], 85 | }, 86 | }, 87 | { 88 | name: "bar_method", 89 | description: "Bar method", 90 | inputSchema: { 91 | type: "object", 92 | properties: { 93 | email: { 94 | type: "string", 95 | description: "Email of the user", 96 | }, 97 | nested: { 98 | type: "object", 99 | properties: { 100 | count: { 101 | type: "number", 102 | description: "Count of the user", 103 | }, 104 | }, 105 | required: ["count"], 106 | description: "Nested object", 107 | }, 108 | }, 109 | required: ["email", "nested"], 110 | }, 111 | }, 112 | ]); 113 | }); 114 | }); 115 | -------------------------------------------------------------------------------- /src/tool.ts: -------------------------------------------------------------------------------- 1 | import type { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js"; 2 | import type { ZodSchema } from "zod"; 3 | import { z } from "zod"; 4 | import { zodToJsonSchema } from "zod-to-json-schema"; 5 | import { MAX_MESSAGE_LENGTH } from "./settings"; 6 | 7 | type HandlerResponse = string | string[] | z.infer; 8 | 9 | export type CustomTool = { 10 | description: string; 11 | 12 | /** 13 | * Zod schema for the input of the tool. 14 | */ 15 | inputSchema?: TSchema; 16 | 17 | /** 18 | * The handler function for the tool. 19 | * @param input Parsed input according to the input schema. 20 | * @returns 21 | * If result is a string, it will be displayed as a single text block. 22 | * If result is an array of strings, each string will be displayed as a separate text block. 23 | * You can also return a CallToolResult object to display more complex content. 24 | */ 25 | handler: (input: z.infer) => Promise; 26 | }; 27 | 28 | export function handlerResponseToCallResult( 29 | response: HandlerResponse 30 | ): z.infer { 31 | if (typeof response === "string" || Array.isArray(response)) { 32 | const array = Array.isArray(response) ? response : [response]; 33 | 34 | // Truncate messages that are too long 35 | const truncatedArray = array.map((item) => 36 | item.length > MAX_MESSAGE_LENGTH 37 | ? `${item.slice(0, MAX_MESSAGE_LENGTH)}... (MESSAGE TRUNCATED, MENTION THIS TO USER)` 38 | : item 39 | ); 40 | 41 | return { 42 | content: truncatedArray.map((text) => ({ type: "text", text })), 43 | }; 44 | } else return response; 45 | } 46 | 47 | function convertToJsonSchema(schema: ZodSchema) { 48 | const jsonSchema = zodToJsonSchema(schema); 49 | delete jsonSchema.$schema; 50 | 51 | // Remove additionalProperties field from all objects, as it's not needed 52 | const removeAdditionalProperties = (schema: any) => { 53 | if (schema.type !== "object") return; 54 | 55 | delete schema.additionalProperties; 56 | for (const value of Object.values(schema.properties)) { 57 | removeAdditionalProperties(value); 58 | } 59 | }; 60 | 61 | removeAdditionalProperties(jsonSchema); 62 | 63 | return jsonSchema; 64 | } 65 | 66 | export function convertToTools(tools: Record) { 67 | return Object.entries(tools).map(([name, tool]) => ({ 68 | name, 69 | description: tool.description, 70 | inputSchema: convertToJsonSchema(tool.inputSchema ?? z.object({})), 71 | })); 72 | } 73 | -------------------------------------------------------------------------------- /src/tools/index.ts: -------------------------------------------------------------------------------- 1 | import type { ZodSchema } from "zod"; 2 | import type { CustomTool } from "../tool"; 3 | import { redisTools } from "./redis"; 4 | 5 | export const json = (json: unknown) => 6 | typeof json === "string" ? json : JSON.stringify(json, null, 2); 7 | 8 | export const tools = { 9 | ...redisTools, 10 | } as unknown as Record; 11 | 12 | // Only used for type inference 13 | export function tool(tool: CustomTool) { 14 | return tool; 15 | } 16 | -------------------------------------------------------------------------------- /src/tools/redis/backup.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { json, tool } from ".."; 3 | import { http } from "../../http"; 4 | import type { RedisBackup } from "./types"; 5 | 6 | export const redisBackupTools = { 7 | redis_database_create_backup: tool({ 8 | description: `Create a backup of a specific Upstash redis database. 9 | NOTE: Ask user to choose a name for the backup`, 10 | inputSchema: z.object({ 11 | database_id: z.string().describe("The ID of the database to create a backup for."), 12 | backup_name: z.string().describe("A name for the backup."), 13 | }), 14 | handler: async ({ database_id, backup_name }) => { 15 | await http.post(["v2/redis/create-backup", database_id], { 16 | name: backup_name, 17 | }); 18 | 19 | return "OK"; 20 | }, 21 | }), 22 | 23 | redis_database_delete_backup: tool({ 24 | description: `Delete a backup of a specific Upstash redis database.`, 25 | inputSchema: z.object({ 26 | database_id: z.string().describe("The ID of the database to delete a backup from."), 27 | backup_id: z.string().describe("The ID of the backup to delete."), 28 | }), 29 | handler: async ({ database_id, backup_id }) => { 30 | await http.delete(["v2/redis/delete-backup", database_id, backup_id]); 31 | 32 | return "OK"; 33 | }, 34 | }), 35 | 36 | redis_database_restore_backup: tool({ 37 | description: `Restore a backup of a specific Upstash redis database. A backup can only be restored to the same database it was created from.`, 38 | inputSchema: z.object({ 39 | database_id: z.string().describe("The ID of the database to restore a backup to."), 40 | backup_id: z.string().describe("The ID of the backup to restore."), 41 | }), 42 | handler: async ({ database_id, backup_id }) => { 43 | await http.post(["v2/redis/restore-backup", database_id], { 44 | backup_id, 45 | }); 46 | 47 | return "OK"; 48 | }, 49 | }), 50 | 51 | redis_database_list_backups: tool({ 52 | // TODO: Add explanation for fields 53 | // TODO: Is this in bytes? 54 | description: `List all backups of a specific Upstash redis database.`, 55 | inputSchema: z.object({ 56 | database_id: z.string().describe("The ID of the database to list backups for."), 57 | }), 58 | handler: async ({ database_id }) => { 59 | const backups = await http.get(["v2/redis/list-backup", database_id]); 60 | 61 | return json(backups); 62 | }, 63 | }), 64 | 65 | redis_database_set_daily_backup: tool({ 66 | description: `Enable or disable daily backups for a specific Upstash redis database.`, 67 | inputSchema: z.object({ 68 | database_id: z 69 | .string() 70 | .describe("The ID of the database to enable or disable daily backups for."), 71 | enable: z.boolean().describe("Whether to enable or disable daily backups."), 72 | }), 73 | handler: async ({ database_id, enable }) => { 74 | await http.patch([ 75 | `v2/redis/${enable ? "enable-dailybackup" : "disable-dailybackup"}`, 76 | database_id, 77 | ]); 78 | 79 | return "OK"; 80 | }, 81 | }), 82 | }; 83 | -------------------------------------------------------------------------------- /src/tools/redis/command.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { json, tool } from ".."; 3 | import { log } from "../../log"; 4 | import fetch from "node-fetch"; 5 | 6 | type RedisCommandResult = 7 | | { 8 | result: unknown; 9 | } 10 | | { 11 | error: string; 12 | }; 13 | 14 | export const redisCommandTools = { 15 | redis_database_run_single_redis_command: tool({ 16 | description: `Run a single Redis command on a specific Upstash redis database. 17 | NOTE: For discovery, use SCAN over KEYS. Use TYPE to get the type of a key. 18 | NOTE: SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]`, 19 | inputSchema: z.object({ 20 | database_rest_url: z 21 | .string() 22 | .describe("The REST URL of the database. Example: https://***.upstash.io"), 23 | database_rest_token: z.string().describe("The REST token of the database."), 24 | command: z 25 | .array(z.string()) 26 | .describe("The Redis command to run. Example: ['SET', 'foo', 'bar', 'EX', 100]"), 27 | }), 28 | 29 | handler: async ({ database_rest_url, database_rest_token, command }) => { 30 | const req = await fetch(database_rest_url, { 31 | method: "POST", 32 | body: JSON.stringify(command), 33 | headers: { 34 | "Content-Type": "application/json", 35 | Authorization: `Bearer ${database_rest_token}`, 36 | }, 37 | }); 38 | 39 | const result = (await req.json()) as RedisCommandResult; 40 | 41 | log("command result:", result); 42 | 43 | if ("error" in result) { 44 | throw new Error("Redis error: " + result.error); 45 | } 46 | 47 | const isScanCommand = command[0].toLocaleLowerCase().includes("scan"); 48 | const messages = [json(result)]; 49 | 50 | if (isScanCommand) 51 | messages.push(`NOTE: Use the returned cursor to get the next set of keys. 52 | NOTE: The result might be too large to be returned. If applicable, stop after the second SCAN command and ask the user if they want to continue.`); 53 | 54 | return messages; 55 | }, 56 | }), 57 | 58 | redis_database_run_multiple_redis_commands: tool({ 59 | description: `Run multiple Redis commands on a specific Upstash redis database`, 60 | inputSchema: z.object({ 61 | database_rest_url: z 62 | .string() 63 | .describe("The REST URL of the database. Example: https://***.upstash.io"), 64 | database_rest_token: z.string().describe("The REST token of the database."), 65 | commands: z 66 | .array(z.array(z.string())) 67 | .describe("The Redis commands to run. Example: [['SET', 'foo', 'bar'], ['GET', 'foo']]"), 68 | }), 69 | 70 | handler: async ({ database_rest_url, database_rest_token, commands }) => { 71 | const req = await fetch(database_rest_url + "/pipeline", { 72 | method: "POST", 73 | body: JSON.stringify(commands), 74 | headers: { 75 | "Content-Type": "application/json", 76 | Authorization: `Bearer ${database_rest_token}`, 77 | }, 78 | }); 79 | 80 | const result = (await req.json()) as RedisCommandResult[]; 81 | 82 | log("commands result:", result); 83 | 84 | if (result.some((r) => "error" in r)) { 85 | throw new Error("Some commands in the pipeline resulted in an error:\n" + json(result)); 86 | } 87 | 88 | return json(result); 89 | }, 90 | }), 91 | }; 92 | -------------------------------------------------------------------------------- /src/tools/redis/db.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { json, tool } from ".."; 3 | import { http } from "../../http"; 4 | import type { RedisDatabase, RedisUsageResponse, UsageData } from "./types"; 5 | import { pruneFalsy } from "../../utils"; 6 | 7 | const readRegionSchema = z.union([ 8 | z.literal("us-east-1"), 9 | z.literal("us-west-1"), 10 | z.literal("us-west-2"), 11 | z.literal("eu-west-1"), 12 | z.literal("eu-central-1"), 13 | z.literal("ap-southeast-1"), 14 | z.literal("ap-southeast-2"), 15 | z.literal("sa-east-1"), 16 | ]); 17 | 18 | const GENERIC_DATABASE_NOTES = 19 | "\nNOTE: Don't show the database ID from the response to the user unless explicitly asked or needed.\n"; 20 | 21 | export const redisDbOpsTools = { 22 | redis_database_create_new: tool({ 23 | description: `Create a new Upstash redis database. 24 | NOTE: Ask user for the region and name of the database.${GENERIC_DATABASE_NOTES}`, 25 | inputSchema: z.object({ 26 | name: z.string().describe("Name of the database."), 27 | primary_region: readRegionSchema.describe(`Primary Region of the Global Database.`), 28 | read_regions: z 29 | .array(readRegionSchema) 30 | .optional() 31 | .describe(`Array of read regions of the db`), 32 | }), 33 | handler: async ({ name, primary_region, read_regions }) => { 34 | const newDb = await http.post("v2/redis/database", { 35 | name, 36 | region: "global", 37 | primary_region, 38 | read_regions, 39 | }); 40 | 41 | return [ 42 | json(newDb), 43 | `Upstash console url: https://console.upstash.com/redis/${newDb.database_id}`, 44 | ]; 45 | }, 46 | }), 47 | 48 | redis_database_delete: tool({ 49 | description: `Delete an Upstash redis database.`, 50 | inputSchema: z.object({ 51 | database_id: z.string().describe("The ID of the database to delete."), 52 | }), 53 | handler: async ({ database_id }) => { 54 | await http.delete(["v2/redis/database", database_id]); 55 | 56 | return "Database deleted successfully."; 57 | }, 58 | }), 59 | 60 | redis_database_list_databases: tool({ 61 | description: `List all Upstash redis databases. Only their names and ids.${GENERIC_DATABASE_NOTES}`, 62 | handler: async () => { 63 | const dbs = await http.get("v2/redis/databases"); 64 | 65 | const messages = [ 66 | json( 67 | dbs.map((db) => { 68 | const result = { 69 | database_id: db.database_id, 70 | database_name: db.database_name, 71 | state: db.state === "active" ? undefined : db.state, 72 | }; 73 | return pruneFalsy(result); 74 | }) 75 | ), 76 | ]; 77 | 78 | if (dbs.length > 2) 79 | messages.push( 80 | `NOTE: If the user did not specify a database name for the next command, ask them to choose a database from the list.` 81 | ); 82 | messages.push( 83 | "NOTE: If the user wants to see dbs in another team, mention that they need to create a new management api key for that team and initialize MCP server with the newly created key." 84 | ); 85 | 86 | return messages; 87 | }, 88 | }), 89 | 90 | redis_database_get_details: tool({ 91 | description: `Get further details of a specific Upstash redis database. Includes all details of the database including usage statistics. 92 | db_disk_threshold: Total disk usage limit. 93 | db_memory_threshold: Maximum memory usage. 94 | db_daily_bandwidth_limit: Maximum daily network bandwidth usage. 95 | db_request_limit: Total number of commands allowed. 96 | All sizes are in bytes 97 | ${GENERIC_DATABASE_NOTES} 98 | `, 99 | inputSchema: z.object({ 100 | database_id: z.string().describe("The ID of the database to get details for."), 101 | }), 102 | handler: async ({ database_id }) => { 103 | const db = await http.get(["v2/redis/database", database_id]); 104 | 105 | return json(db); 106 | }, 107 | }), 108 | 109 | redis_database_update_regions: tool({ 110 | description: `Update the read regions of an Upstash redis database.`, 111 | inputSchema: z.object({ 112 | id: z.string().describe("The ID of your database."), 113 | read_regions: z 114 | .array(readRegionSchema) 115 | .describe( 116 | "Array of the new read regions of the database. This will replace the old regions array. Available regions: us-east-1, us-west-1, us-west-2, eu-west-1, eu-central-1, ap-southeast-1, ap-southeast-2, sa-east-1" 117 | ), 118 | }), 119 | handler: async ({ id, read_regions }) => { 120 | const updatedDb = await http.post(["v2/redis/update-regions", id], { 121 | read_regions, 122 | }); 123 | 124 | return json(updatedDb); 125 | }, 126 | }), 127 | 128 | redis_database_reset_password: tool({ 129 | description: `Reset the password of an Upstash redis database.`, 130 | inputSchema: z.object({ 131 | id: z.string().describe("The ID of your database."), 132 | }), 133 | handler: async ({ id }) => { 134 | const updatedDb = await http.post(["v2/redis/reset-password", id], {}); 135 | 136 | return json(updatedDb); 137 | }, 138 | }), 139 | 140 | redis_database_get_usage_last_5_days: tool({ 141 | description: `Get PRECISE command count and bandwidth usage statistics of an Upstash redis database over the last 5 days. This is a precise stat, not an average. 142 | NOTE: Ask user first if they want to see stats for each database seperately or just for one.`, 143 | inputSchema: z.object({ 144 | id: z.string().describe("The ID of your database."), 145 | }), 146 | handler: async ({ id }) => { 147 | const stats = await http.get(["v2/redis/stats", `${id}?period=3h`]); 148 | 149 | return [ 150 | json({ 151 | days: stats.days, 152 | command_usage: stats.dailyrequests, 153 | bandwidth_usage: stats.bandwidths, 154 | }), 155 | `NOTE: Times are calculated according to UTC+0`, 156 | ]; 157 | }, 158 | }), 159 | 160 | redis_database_get_stats: tool({ 161 | description: `Get SAMPLED usage statistics of an Upstash redis database over a period of time (1h, 3h, 12h, 1d, 3d, 7d). Use this to check for peak usages and latency problems. 162 | Includes: read_latency_mean, write_latency_mean, keyspace, throughput (cmds/sec), diskusage 163 | NOTE: If the user does not specify which stat to get, use throughput as default.`, 164 | inputSchema: z.object({ 165 | id: z.string().describe("The ID of your database."), 166 | period: z 167 | .union([ 168 | z.literal("1h"), 169 | z.literal("3h"), 170 | z.literal("12h"), 171 | z.literal("1d"), 172 | z.literal("3d"), 173 | z.literal("7d"), 174 | ]) 175 | .describe("The period of the stats."), 176 | type: z 177 | .union([ 178 | z.literal("read_latency_mean"), 179 | z.literal("write_latency_mean"), 180 | z.literal("keyspace").describe("Number of keys in db"), 181 | z 182 | .literal("throughput") 183 | .describe("commands per second (sampled), calculate area for estimated count"), 184 | z.literal("diskusage").describe("Current disk usage in bytes"), 185 | ]) 186 | .describe("The type of stat to get"), 187 | }), 188 | handler: async ({ id, period, type }) => { 189 | const stats = await http.get([ 190 | "v2/redis/stats", 191 | `${id}?period=${period}`, 192 | ]); 193 | 194 | const stat = stats[type]; 195 | 196 | if (!Array.isArray(stat)) 197 | throw new Error( 198 | `Invalid key provided: ${type}. Valid keys are: ${Object.keys(stats).join(", ")}` 199 | ); 200 | 201 | return [ 202 | JSON.stringify(parseUsageData(stat)), 203 | `NOTE: Use the timestamps_to_date tool to parse timestamps if needed`, 204 | `NOTE: Don't try to plot multiple stats in the same chart`, 205 | ]; 206 | }, 207 | }), 208 | }; 209 | 210 | const parseUsageData = (data: UsageData) => { 211 | if (!data) return "NO DATA"; 212 | if (!Array.isArray(data)) return "INVALID DATA"; 213 | if (data.length === 0 || data.length === 1) return "NO DATA"; 214 | const filteredData = data.filter((d) => d.x && d.y); 215 | return { 216 | start: filteredData[0].x, 217 | // last one can be null, so use the second last 218 | // eslint-disable-next-line unicorn/prefer-at 219 | end: filteredData[filteredData.length - 1]?.x, 220 | data: data.map((d) => [new Date(d.x).getTime(), d.y]), 221 | }; 222 | }; 223 | -------------------------------------------------------------------------------- /src/tools/redis/index.ts: -------------------------------------------------------------------------------- 1 | import { utilTools } from "../utils"; 2 | import { redisBackupTools } from "./backup"; 3 | import { redisCommandTools } from "./command"; 4 | import { redisDbOpsTools } from "./db"; 5 | 6 | export const redisTools = { 7 | ...redisDbOpsTools, 8 | ...redisBackupTools, 9 | ...redisCommandTools, 10 | ...utilTools, 11 | }; 12 | -------------------------------------------------------------------------------- /src/tools/redis/types.ts: -------------------------------------------------------------------------------- 1 | export type RedisDatabase = { 2 | database_id: string; 3 | database_name: string; 4 | database_type: string; 5 | region: string; 6 | type: string; 7 | primary_members: string[]; 8 | all_members: string[]; 9 | primary_region: string; 10 | read_regions: string[]; 11 | port: number; 12 | creation_time: string; 13 | budget: number; 14 | state: string; 15 | password: string; 16 | user_email: string; 17 | endpoint: string; 18 | tls: boolean; 19 | eviction: boolean; 20 | auto_upgrade: boolean; 21 | consistent: boolean; 22 | reserved_per_region_price: number; 23 | modifying_state: string; 24 | rest_token: string; 25 | read_only_rest_token: string; 26 | db_max_clients: number; 27 | db_max_request_size: number; 28 | db_resource_size: string; 29 | db_type: string; 30 | db_disk_threshold: number; 31 | db_max_entry_size: number; 32 | db_memory_threshold: number; 33 | db_conn_idle_timeout: number; 34 | db_lua_timeout: number; 35 | db_lua_credits_per_min: number; 36 | db_store_max_idle: number; 37 | db_max_loads_per_sec: number; 38 | db_max_commands_per_second: number; 39 | db_request_limit: number; 40 | db_acl_enabled: string; 41 | db_acl_default_user_status: string; 42 | }; 43 | 44 | export type RedisBackup = { 45 | backup_id: string; 46 | database_id: string; 47 | name: string; 48 | creation_time: number; 49 | state: string; 50 | backup_size: number; 51 | daily_backup: boolean; 52 | hourly_backup: boolean; 53 | }; 54 | 55 | export type UsageData = { x: string; y: number }[]; 56 | 57 | export type RedisUsageResponse = { 58 | read_latency_mean: UsageData; 59 | write_latency_mean: UsageData; 60 | keyspace: UsageData; 61 | throughput: UsageData; 62 | daily_net_commands: number; 63 | diskusage: UsageData; 64 | command_counts: { 65 | metric_identifier: string; 66 | data_points: UsageData; 67 | }[]; 68 | 69 | // For last 5 days 70 | dailyrequests: UsageData; 71 | bandwidths: UsageData; 72 | days: string[]; 73 | }; 74 | -------------------------------------------------------------------------------- /src/tools/utils.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { tool } from "."; 3 | 4 | export const utilTools = { 5 | timestamps_to_date: tool({ 6 | description: `Use this tool to convert a timestamp to a human-readable date`, 7 | inputSchema: z.object({ 8 | timestamps: z.array(z.number()).describe("Array of timestamps to convert"), 9 | }), 10 | handler: async ({ timestamps }) => { 11 | return timestamps.map((timestamp) => new Date(timestamp).toUTCString()); 12 | }, 13 | }), 14 | } -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | export function pruneFalsy(obj: Record) { 2 | return Object.fromEntries(Object.entries(obj).filter(([, value]) => value)); 3 | } 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ES2015"], 4 | "module": "esnext", 5 | "target": "ES2015", 6 | "moduleResolution": "bundler", 7 | "allowImportingTsExtensions": true, 8 | "noEmit": true, 9 | "strict": true, 10 | "downlevelIteration": true, 11 | "skipLibCheck": true, 12 | "jsx": "react-jsx", 13 | "allowSyntheticDefaultImports": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "allowJs": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | export default defineConfig({ 4 | entry: ["src/index.ts"], 5 | format: ["esm"], 6 | clean: true, 7 | dts: true, 8 | sourcemap: true, 9 | target: "node15", 10 | }); 11 | --------------------------------------------------------------------------------