diff --git a/.github/workflows/code_health.yaml b/.github/workflows/code_health.yaml index 5a99be15..25d81b74 100644 --- a/.github/workflows/code_health.yaml +++ b/.github/workflows/code_health.yaml @@ -20,6 +20,19 @@ jobs: - name: Run style check run: npm run check + check-generate: + runs-on: ubuntu-latest + steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + cache: "npm" + - name: Install dependencies + run: npm ci + - run: npm run generate + run-tests: strategy: matrix: @@ -29,12 +42,6 @@ jobs: steps: - uses: GitHubSecurityLab/actions-permissions/monitor@v1 if: matrix.os != 'windows-latest' - - name: Install keyring deps on Ubuntu - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt update -y - sudo apt install -y gnome-keyring libdbus-1-dev - - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: @@ -44,3 +51,64 @@ jobs: run: npm ci - name: Run tests run: npm test + - name: Upload test results + if: always() && matrix.os == 'ubuntu-latest' + uses: actions/upload-artifact@v4 + with: + name: test-results + path: coverage/lcov.info + + run-atlas-tests: + runs-on: ubuntu-latest + steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + cache: "npm" + - name: Install dependencies + run: npm ci + - name: Run tests + env: + MDB_MCP_API_CLIENT_ID: ${{ secrets.TEST_ATLAS_CLIENT_ID }} + MDB_MCP_API_CLIENT_SECRET: ${{ secrets.TEST_ATLAS_CLIENT_SECRET }} + MDB_MCP_API_BASE_URL: ${{ vars.TEST_ATLAS_BASE_URL }} + run: npm test -- --testPathIgnorePatterns "tests/integration/tools/mongodb" --testPathIgnorePatterns "tests/integration/[^/]+\.ts" + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: atlas-test-results + path: coverage/lcov.info + coverage: + runs-on: ubuntu-latest + needs: [run-tests, run-atlas-tests] + if: always() + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + cache: "npm" + - name: Install dependencies + run: npm ci + - name: Download test results + uses: actions/download-artifact@v4 + with: + name: test-results + path: coverage/mongodb + - name: Download atlas test results + uses: actions/download-artifact@v4 + with: + name: atlas-test-results + path: coverage/atlas + - name: Merge coverage reports + run: | + npx -y lcov-result-merger@5.0.1 "coverage/*/lcov.info" "coverage/lcov.info" + - name: Coveralls GitHub Action + uses: coverallsapp/github-action@v2.3.6 + with: + file: coverage/lcov.info + git-branch: ${{ github.head_ref || github.ref_name }} + git-commit: ${{ github.event.pull_request.head.sha || github.sha }} diff --git a/.github/workflows/prepare_release.yaml b/.github/workflows/prepare_release.yaml new file mode 100644 index 00000000..b016237f --- /dev/null +++ b/.github/workflows/prepare_release.yaml @@ -0,0 +1,45 @@ +name: Prepare release +description: | + Bumps the version in package.json and creates a release PR. Once merged, the new + version will be published to npm. +on: + workflow_dispatch: + inputs: + version: + description: "Exact version to bump to or one of major, minor, patch" + required: true + default: "patch" + +jobs: + create-pr: + runs-on: ubuntu-latest + steps: + - uses: mongodb-js/devtools-shared/actions/setup-bot-token@main + id: app-token + with: + app-id: ${{ vars.DEVTOOLS_BOT_APP_ID }} + private-key: ${{ secrets.DEVTOOLS_BOT_PRIVATE_KEY }} + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + registry-url: "https://registry.npmjs.org" + cache: "npm" + - name: Bump version + id: bump-version + run: | + echo "NEW_VERSION=$(npm version ${{ inputs.version }} --no-git-tag-version)" >> $GITHUB_OUTPUT + - name: Create release PR + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # 7.0.8 + with: + title: "Release v${{ steps.bump-version.outputs.NEW_VERSION }}" + token: ${{ steps.app-token.outputs.token }} + commit-message: "Bump version to v${{ steps.bump-version.outputs.NEW_VERSION }}" + body: | + This PR bumps the package version to v${{ steps.bump-version.outputs.NEW_VERSION }}. + Once merged, the new version will be published to npm. + base: main + branch: release/v${{ steps.bump-version.outputs.NEW_VERSION }} + author: "${{ steps.app-token.outputs.app-slug}}[bot] <${{ steps.app-token.outputs.app-email }}>" + committer: "${{ steps.app-token.outputs.app-slug}}[bot] <${{ steps.app-token.outputs.app-email }}>" diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 77d6dbdf..2742c649 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -63,14 +63,8 @@ jobs: run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Publish git tag - run: | - git config --global user.name 'github-actions[bot]' - git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' - git tag ${{ needs.check.outputs.VERSION }} - git push origin --tags - name: Publish git release env: GH_TOKEN: ${{ github.token }} run: | - gh release create ${{ needs.check.outputs.VERSION }} --title "${{ needs.check.outputs.VERSION }}" --generate-notes + gh release create ${{ needs.check.outputs.VERSION }} --title "${{ needs.check.outputs.VERSION }}" --generate-notes --target ${{ github.sha }} diff --git a/.gitignore b/.gitignore index ec17480c..4e3f7a54 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ node_modules state.json tests/tmp +coverage diff --git a/README.md b/README.md index b21a4759..8c625566 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Atlas MCP Server +# MongoDB MCP Server A Model Context Protocol server for interacting with MongoDB Atlas. This project implements a Model Context Protocol (MCP) server enabling AI assistants to interact with MongoDB Atlas resources through natural language. @@ -40,7 +40,7 @@ Step 1: Add the mcp server to VSCode configuration - Press `Cmd + Shift + P` and type `MCP: Add MCP Server` and select it. - Select command (Stdio). -- Input command `npx -y @mongodb-js/mongodb-mcp-server`. +- Input command `npx -y mongodb-mcp-server`. - Choose between user / workspace - Add arguments to the file @@ -54,7 +54,7 @@ Note: the file should look like: "command": "npx", "args": [ "-y", - "@mongodb-js/mongodb-mcp-server" + "mongodb-mcp-server" ] } } @@ -82,7 +82,7 @@ Paste the mcp server configuration into the file "mcpServers": { "MongoDB": { "command": "npx", - "args": ["-y", "@mongodb-js/mongodb-mcp-server"] + "args": ["-y", "mongodb-mcp-server"] } } } @@ -98,15 +98,19 @@ You may experiment asking `Can you connect to my mongodb instance?`. #### MongoDB Atlas Tools -- `atlas-list-clusters` - Lists MongoDB Atlas clusters +- `atlas-list-orgs` - Lists MongoDB Atlas organizations - `atlas-list-projects` - Lists MongoDB Atlas projects +- `atlas-create-project` - Creates a new MongoDB Atlas project +- `atlas-list-clusters` - Lists MongoDB Atlas clusters - `atlas-inspect-cluster` - Inspect a specific MongoDB Atlas cluster - `atlas-create-free-cluster` - Create a free MongoDB Atlas cluster -- `atlas-create-access-list` - Configure IP/CIDR access list for MongoDB Atlas clusters - `atlas-inspect-access-list` - Inspect IP/CIDR ranges with access to MongoDB Atlas clusters +- `atlas-create-access-list` - Configure IP/CIDR access list for MongoDB Atlas clusters - `atlas-list-db-users` - List MongoDB Atlas database users - `atlas-create-db-user` - List MongoDB Atlas database users +NOTE: atlas tools are only available when you set credentials on [configuration](#configuration) section. + #### MongoDB Database Tools - `connect` - Connect to a MongoDB instance @@ -145,12 +149,38 @@ The MongoDB MCP Server can be configured using multiple methods, with the follow | `apiClientSecret` | Atlas API client secret for authentication | | `connectionString` | MongoDB connection string for direct database connections (optional users may choose to inform it on every tool call) | | `logPath` | Folder to store logs | +| `disabledTools` | An array of tool names, operation types, and/or categories of tools that will be disabled. | + +#### `logPath` -**Default Log Path:** +Default log location is as follows: - Windows: `%LOCALAPPDATA%\mongodb\mongodb-mcp\.app-logs` - macOS/Linux: `~/.mongodb/mongodb-mcp/.app-logs` +#### Disabled Tools + +You can disable specific tools or categories of tools by using the `disabledTools` option. This option accepts an array of strings, +where each string can be a tool name, operation type, or category. + +The way the array is constructed depends on the type of configuration method you use: + +- For **environment variable** configuration, use a comma-separated string: `export MDB_MCP_DISABLED_TOOLS="create,update,delete,atlas,collectionSchema"`. +- For **command-line argument** configuration, use a space-separated string: `--disabledTools create update delete atlas collectionSchema`. + +Categories of tools: + +- `atlas` - MongoDB Atlas tools, such as list clusters, create cluster, etc. +- `mongodb` - MongoDB database tools, such as find, aggregate, etc. + +Operation types: + +- `create` - Tools that create resources, such as create cluster, insert document, etc. +- `update` - Tools that update resources, such as update document, rename collection, etc. +- `delete` - Tools that delete resources, such as delete document, drop collection, etc. +- `read` - Tools that read resources, such as find, aggregate, list clusters, etc. +- `metadata` - Tools that read metadata, such as list databases, list collections, collection schema, etc. + ### Atlas API Access To use the Atlas API tools, you'll need to create a service account in MongoDB Atlas: @@ -198,7 +228,7 @@ export MDB_MCP_LOG_PATH="/path/to/logs" Pass configuration options as command-line arguments when starting the server: ```shell -npx -y @mongodb-js/mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret="your-atlas-client-secret" --connectionString="mongodb+srv://username:password@cluster.mongodb.net/myDatabase" --logPath=/path/to/logs +npx -y mongodb-mcp-server --apiClientId="your-atlas-client-id" --apiClientSecret="your-atlas-client-secret" --connectionString="mongodb+srv://username:password@cluster.mongodb.net/myDatabase" --logPath=/path/to/logs ``` ## 🤝 Contributing diff --git a/eslint.config.js b/eslint.config.js index da617263..b6263450 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -30,6 +30,6 @@ export default defineConfig([ // TODO: Configure tests and scripts to work with this. ignores: ["eslint.config.js", "jest.config.js", "tests/**/*.ts", "scripts/**/*.ts"], }), - globalIgnores(["node_modules", "dist", "src/common/atlas/openapi.d.ts"]), + globalIgnores(["node_modules", "dist", "src/common/atlas/openapi.d.ts", "coverage"]), eslintConfigPrettier, ]); diff --git a/jest.config.js b/jest.config.js index 88e80263..5b06aaed 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,6 +3,7 @@ export default { preset: "ts-jest/presets/default-esm", testEnvironment: "node", extensionsToTreatAsEsm: [".ts"], + testTimeout: 3600000, // 3600 seconds moduleNameMapper: { "^(\\.{1,2}/.*)\\.js$": "$1", // Map .js to real paths for ESM }, @@ -16,4 +17,6 @@ export default { ], }, moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], + setupFilesAfterEnv: ["jest-extended/all"], + coveragePathIgnorePatterns: ["node_modules", "tests", "dist"], }; diff --git a/package-lock.json b/package-lock.json index f5e0be10..85d46171 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@mongodb-js/mongodb-mcp-server", + "name": "mongodb-mcp-server", "version": "0.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@mongodb-js/mongodb-mcp-server", + "name": "mongodb-mcp-server", "version": "0.0.3", "license": "Apache-2.0", "dependencies": { @@ -13,6 +13,7 @@ "@mongodb-js/devtools-connect": "^3.7.2", "@mongosh/service-provider-node-driver": "^3.6.0", "bson": "^6.10.3", + "lru-cache": "^11.1.0", "mongodb": "^6.15.0", "mongodb-log-writer": "^2.4.1", "mongodb-redact": "^1.1.6", @@ -39,14 +40,17 @@ "globals": "^16.0.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", + "jest-extended": "^4.0.2", "mongodb-runner": "^5.8.2", + "native-machine-id": "^0.0.8", "openapi-types": "^12.1.3", "openapi-typescript": "^7.6.1", "prettier": "^3.5.3", "ts-jest": "^29.3.1", "tsx": "^4.19.3", "typescript": "^5.8.2", - "typescript-eslint": "^8.29.1" + "typescript-eslint": "^8.29.1", + "yaml": "^2.7.1" }, "engines": { "node": ">=20.0.0" @@ -66,17 +70,6 @@ "node": ">=6.0.0" } }, - "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", @@ -203,24 +196,24 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.782.0.tgz", - "integrity": "sha512-Zad5x3L5K+PuhdY2v8Q0tsafmVBa2SJJxNukPzXM1APxW7FpDVMxcdSzjfCfX7CvSpohR8zDIEROqMfoUisaTw==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.787.0.tgz", + "integrity": "sha512-7v6nywZ5wcQxX7qdZ5M1ld15QdkzLU6fAKiEqbvJKu4dM8cFW6As+DbS990Mg46pp1xM/yvme+51xZDTfTfJZA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/credential-provider-node": "3.782.0", + "@aws-sdk/credential-provider-node": "3.787.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.782.0", + "@aws-sdk/middleware-user-agent": "3.787.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.782.0", + "@aws-sdk/util-endpoints": "3.787.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.782.0", + "@aws-sdk/util-user-agent-node": "3.787.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -253,9 +246,9 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.782.0.tgz", - "integrity": "sha512-5GlJBejo8wqMpSSEKb45WE82YxI2k73YuebjLH/eWDNQeE6VI5Bh9lA1YQ7xNkLLH8hIsb0pSfKVuwh0VEzVrg==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.787.0.tgz", + "integrity": "sha512-L8R+Mh258G0DC73ktpSVrG4TT9i2vmDLecARTDR/4q5sRivdDQSL5bUp3LKcK80Bx+FRw3UETIlX6mYMLL9PJQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -264,12 +257,12 @@ "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.782.0", + "@aws-sdk/middleware-user-agent": "3.787.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.782.0", + "@aws-sdk/util-endpoints": "3.787.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.782.0", + "@aws-sdk/util-user-agent-node": "3.787.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -324,12 +317,12 @@ } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.782.0.tgz", - "integrity": "sha512-rWUmO9yZUBkM2CrTN9lm5X7Ubl7bRPBKyq5hvWpVNSa6BpUcmAQ6CUwEACOc+9cXmUqmKFhP6MGT2GpVlRrzDQ==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.787.0.tgz", + "integrity": "sha512-nF5XjgvZHFuyttOeTjMgfEsg6slZPQ6uI34yzq12Kq4icFgcD4bQsijnQClMN7A0u5qR8Ad8kume4b7+I2++Ig==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.782.0", + "@aws-sdk/client-cognito-identity": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", @@ -377,18 +370,18 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.782.0.tgz", - "integrity": "sha512-wd4KdRy2YjLsE4Y7pz00470Iip06GlRHkG4dyLW7/hFMzEO2o7ixswCWp6J2VGZVAX64acknlv2Q0z02ebjmhw==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.787.0.tgz", + "integrity": "sha512-hc2taRoDlXn2uuNuHWDJljVWYrp3r9JF1a/8XmOAZhVUNY+ImeeStylHXhXXKEA4JOjW+5PdJj0f1UDkVCHJiQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/credential-provider-env": "3.775.0", "@aws-sdk/credential-provider-http": "3.775.0", "@aws-sdk/credential-provider-process": "3.775.0", - "@aws-sdk/credential-provider-sso": "3.782.0", - "@aws-sdk/credential-provider-web-identity": "3.782.0", - "@aws-sdk/nested-clients": "3.782.0", + "@aws-sdk/credential-provider-sso": "3.787.0", + "@aws-sdk/credential-provider-web-identity": "3.787.0", + "@aws-sdk/nested-clients": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/credential-provider-imds": "^4.0.2", "@smithy/property-provider": "^4.0.2", @@ -401,17 +394,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.782.0.tgz", - "integrity": "sha512-HZiAF+TCEyKjju9dgysjiPIWgt/+VerGaeEp18mvKLNfgKz1d+/82A2USEpNKTze7v3cMFASx3CvL8yYyF7mJw==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.787.0.tgz", + "integrity": "sha512-JioVi44B1vDMaK2CdzqimwvJD3uzvzbQhaEWXsGMBcMcNHajXAXf08EF50JG3ZhLrhhUsT1ObXpbTaPINOhh+g==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-provider-env": "3.775.0", "@aws-sdk/credential-provider-http": "3.775.0", - "@aws-sdk/credential-provider-ini": "3.782.0", + "@aws-sdk/credential-provider-ini": "3.787.0", "@aws-sdk/credential-provider-process": "3.775.0", - "@aws-sdk/credential-provider-sso": "3.782.0", - "@aws-sdk/credential-provider-web-identity": "3.782.0", + "@aws-sdk/credential-provider-sso": "3.787.0", + "@aws-sdk/credential-provider-web-identity": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/credential-provider-imds": "^4.0.2", "@smithy/property-provider": "^4.0.2", @@ -441,14 +434,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.782.0.tgz", - "integrity": "sha512-1y1ucxTtTIGDSNSNxriQY8msinilhe9gGvQpUDYW9gboyC7WQJPDw66imy258V6osdtdi+xoHzVCbCz3WhosMQ==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.787.0.tgz", + "integrity": "sha512-fHc08bsvwm4+dEMEQKnQ7c1irEQmmxbgS+Fq41y09pPvPh31nAhoMcjBSTWAaPHvvsRbTYvmP4Mf12ZGr8/nfg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.782.0", + "@aws-sdk/client-sso": "3.787.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/token-providers": "3.782.0", + "@aws-sdk/token-providers": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", @@ -460,13 +453,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.782.0.tgz", - "integrity": "sha512-xCna0opVPaueEbJoclj5C6OpDNi0Gynj+4d7tnuXGgQhTHPyAz8ZyClkVqpi5qvHTgxROdUEDxWqEO5jqRHZHQ==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.787.0.tgz", + "integrity": "sha512-SobmCwNbk6TfEsF283mZPQEI5vV2j6eY5tOCj8Er4Lzraxu9fBPADV+Bib2A8F6jlB1lMPJzOuDCbEasSt/RIw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "3.775.0", - "@aws-sdk/nested-clients": "3.782.0", + "@aws-sdk/nested-clients": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", @@ -477,22 +470,22 @@ } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.782.0.tgz", - "integrity": "sha512-EP0viOqgw9hU8Lt25Rc7nPlPKMCsO7ntVGSA5TDdjaOHU9wN1LdKwRmFWYE+ii0FIPmagJmgJJoHdpq85oqsUw==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.787.0.tgz", + "integrity": "sha512-kR3RtI7drOc9pho13vWbUC2Bvrx9A0G4iizBDGmTs08NOdg4w3c1I4kdLG9tyPiIMeVnH+wYrsli5CM7xIfqiA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.782.0", + "@aws-sdk/client-cognito-identity": "3.787.0", "@aws-sdk/core": "3.775.0", - "@aws-sdk/credential-provider-cognito-identity": "3.782.0", + "@aws-sdk/credential-provider-cognito-identity": "3.787.0", "@aws-sdk/credential-provider-env": "3.775.0", "@aws-sdk/credential-provider-http": "3.775.0", - "@aws-sdk/credential-provider-ini": "3.782.0", - "@aws-sdk/credential-provider-node": "3.782.0", + "@aws-sdk/credential-provider-ini": "3.787.0", + "@aws-sdk/credential-provider-node": "3.787.0", "@aws-sdk/credential-provider-process": "3.775.0", - "@aws-sdk/credential-provider-sso": "3.782.0", - "@aws-sdk/credential-provider-web-identity": "3.782.0", - "@aws-sdk/nested-clients": "3.782.0", + "@aws-sdk/credential-provider-sso": "3.787.0", + "@aws-sdk/credential-provider-web-identity": "3.787.0", + "@aws-sdk/nested-clients": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", @@ -551,14 +544,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.782.0.tgz", - "integrity": "sha512-i32H2R6IItX+bQ2p4+v2gGO2jA80jQoJO2m1xjU9rYWQW3+ErWy4I5YIuQHTBfb6hSdAHbaRfqPDgbv9J2rjEg==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.787.0.tgz", + "integrity": "sha512-Lnfj8SmPLYtrDFthNIaNj66zZsBCam+E4XiUDr55DIHTGstH6qZ/q6vg0GfbukxwSmUcGMwSR4Qbn8rb8yd77g==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.782.0", + "@aws-sdk/util-endpoints": "3.787.0", "@smithy/core": "^3.2.0", "@smithy/protocol-http": "^5.1.0", "@smithy/types": "^4.2.0", @@ -569,9 +562,9 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.782.0.tgz", - "integrity": "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.787.0.tgz", + "integrity": "sha512-xk03q1xpKNHgbuo+trEf1dFrI239kuMmjKKsqLEsHlAZbuFq4yRGMlHBrVMnKYOPBhVFDS/VineM991XI52fKg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", @@ -580,12 +573,12 @@ "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", - "@aws-sdk/middleware-user-agent": "3.782.0", + "@aws-sdk/middleware-user-agent": "3.787.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", - "@aws-sdk/util-endpoints": "3.782.0", + "@aws-sdk/util-endpoints": "3.787.0", "@aws-sdk/util-user-agent-browser": "3.775.0", - "@aws-sdk/util-user-agent-node": "3.782.0", + "@aws-sdk/util-user-agent-node": "3.787.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", @@ -635,12 +628,12 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.782.0.tgz", - "integrity": "sha512-4tPuk/3+THPrzKaXW4jE2R67UyGwHLFizZ47pcjJWbhb78IIJAy94vbeqEQ+veS84KF5TXcU7g5jGTXC0D70Wg==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.787.0.tgz", + "integrity": "sha512-d7/NIqxq308Zg0RPMNrmn0QvzniL4Hx8Qdwzr6YZWLYAbUSvZYS2ppLR3BFWSkV6SsTJUx8BuDaj3P8vttkrog==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/nested-clients": "3.782.0", + "@aws-sdk/nested-clients": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/shared-ini-file-loader": "^4.0.2", @@ -665,9 +658,9 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.782.0.tgz", - "integrity": "sha512-/RJOAO7o7HI6lEa4ASbFFLHGU9iPK876BhsVfnl54MvApPVYWQ9sHO0anOUim2S5lQTwd/6ghuH3rFYSq/+rdw==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.787.0.tgz", + "integrity": "sha512-fd3zkiOkwnbdbN0Xp9TsP5SWrmv0SpT70YEdbb8wAj2DWQwiCmFszaSs+YCvhoCdmlR3Wl9Spu0pGpSAGKeYvQ==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "3.775.0", @@ -704,12 +697,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.782.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.782.0.tgz", - "integrity": "sha512-dMFkUBgh2Bxuw8fYZQoH/u3H4afQ12VSkzEi//qFiDTwbKYq+u+RYjc8GLDM6JSK1BShMu5AVR7HD4ap1TYUnA==", + "version": "3.787.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.787.0.tgz", + "integrity": "sha512-mG7Lz8ydfG4SF9e8WSXiPQ/Lsn3n8A5B5jtPROidafi06I3ckV2WxyMLdwG14m919NoS6IOfWHyRGSqWIwbVKA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.782.0", + "@aws-sdk/middleware-user-agent": "3.787.0", "@aws-sdk/types": "3.775.0", "@smithy/node-config-provider": "^4.0.2", "@smithy/types": "^4.2.0", @@ -810,17 +803,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", @@ -1297,6 +1279,17 @@ "node": ">=12" } }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@emotion/is-prop-valid": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", @@ -1747,9 +1740,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", + "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", "dev": true, "license": "MIT", "dependencies": { @@ -1803,6 +1796,30 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/config-helpers": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", @@ -1814,9 +1831,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1850,6 +1867,34 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -1863,10 +1908,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", - "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", + "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", "dev": true, "license": "MIT", "engines": { @@ -1897,19 +1962,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@exodus/schemasafe": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", @@ -2404,17 +2456,6 @@ } } }, - "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2443,17 +2484,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@jest/test-result": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", @@ -2513,17 +2543,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -2557,17 +2576,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -2596,14 +2604,14 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@jsep-plugin/assignment": { @@ -2708,50 +2716,64 @@ "mcp-inspector-server": "build/index.js" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.10.2.tgz", + "integrity": "sha512-rb6AMp2DR4SN+kc6L1ta2NCpApyA9WYNx3CrTSZvGxq9wH71bRur+zRqPfg0vQ9mjywR7qZdX2RGHOPq3ss+tA==", "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" }, "engines": { "node": ">= 0.6" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=18" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -2760,664 +2782,162 @@ "node": ">= 0.6" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=6.6.0" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" }, "engines": { "node": ">= 0.8" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "mime-db": "^1.54.0" }, "engines": { "node": ">= 0.6" } }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/@modelcontextprotocol/inspector-server/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, "engines": { "node": ">= 0.6" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz", - "integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==", + "node_modules/@modelcontextprotocol/sdk/node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.3", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/pkce-challenge": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", - "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/@mongodb-js/devtools-connect": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.7.2.tgz", - "integrity": "sha512-fT5QPn/hR9xl5yfFUMcBbI8smidq3JHZDlV4//srqZVxqtor2ofHdxua1kDnQEpv8sclTY/5o6TjoYQ8IiNaIQ==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/devtools-proxy-support": "^0.4.4", - "@mongodb-js/oidc-http-server-pages": "1.1.4", - "lodash.merge": "^4.6.2", - "mongodb-connection-string-url": "^3.0.0", - "socks": "^2.7.3" - }, - "optionalDependencies": { - "kerberos": "^2.1.0", - "mongodb-client-encryption": "^6.1.0", - "os-dns-native": "^1.2.0", - "resolve-mongodb-srv": "^1.1.1" - }, - "peerDependencies": { - "@mongodb-js/oidc-plugin": "^1.1.0", - "mongodb": "^6.9.0", - "mongodb-log-writer": "^2.4.1" - } - }, - "node_modules/@mongodb-js/devtools-proxy-support": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.4.4.tgz", - "integrity": "sha512-klRFd33bjUntPJuEY86NB0xYd64SaEYN0ABbE5fjU8+lO94ItvxTAWyHUmerPFAk8OLyz1MFyDoTXOvdOs9NAQ==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/socksv5": "^0.0.10", - "agent-base": "^7.1.1", - "debug": "^4.4.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "lru-cache": "^11.0.0", - "node-fetch": "^3.3.2", - "pac-proxy-agent": "^7.0.2", - "socks-proxy-agent": "^8.0.4", - "ssh2": "^1.15.0", - "system-ca": "^2.0.1" - } - }, - "node_modules/@mongodb-js/mongodb-downloader": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.9.tgz", - "integrity": "sha512-6lEIESINiIAeQUw95+hkfxG6129r6KiPU2TNOcxb30PsGgFHPJFg7QY8UoSQXjDE9YaENlr6oQm3c1XDixWeEg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.4.0", - "decompress": "^4.2.1", - "mongodb-download-url": "^1.5.7", - "node-fetch": "^2.7.0", - "tar": "^6.1.15" - } - }, - "node_modules/@mongodb-js/mongodb-downloader/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/@mongodb-js/mongodb-downloader/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@mongodb-js/mongodb-downloader/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/@mongodb-js/mongodb-downloader/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/@mongodb-js/oidc-http-server-pages": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@mongodb-js/oidc-http-server-pages/-/oidc-http-server-pages-1.1.4.tgz", - "integrity": "sha512-fPwS1cERLGNSz8D1kBw2RJ0GNn1Ud2IIBehvV8OmOZzSXEx6hjwgvKG8XdHT7tpXns7iSkw9gSj84yHJkAlOnQ==", - "license": "Apache-2.0" - }, - "node_modules/@mongodb-js/oidc-plugin": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@mongodb-js/oidc-plugin/-/oidc-plugin-1.1.6.tgz", - "integrity": "sha512-fuL4B9x1njcqdJqV+V3pt8s/9PX4uy9ojhcsP12BavDcg61ju6WEqCkDmUZCykDIvsDbb8tIhO97aCKDxcXROw==", - "license": "Apache-2.0", - "dependencies": { - "express": "^4.18.2", - "open": "^9.1.0", - "openid-client": "^5.6.4" - }, - "engines": { - "node": ">= 16.20.1" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" + "engines": { + "node": ">=16.20.0" + } }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -3426,80 +2946,178 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">= 18" } }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 18" } }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "node_modules/@mongodb-js/devtools-connect": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-connect/-/devtools-connect-3.7.2.tgz", + "integrity": "sha512-fT5QPn/hR9xl5yfFUMcBbI8smidq3JHZDlV4//srqZVxqtor2ofHdxua1kDnQEpv8sclTY/5o6TjoYQ8IiNaIQ==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/devtools-proxy-support": "^0.4.4", + "@mongodb-js/oidc-http-server-pages": "1.1.4", + "lodash.merge": "^4.6.2", + "mongodb-connection-string-url": "^3.0.0", + "socks": "^2.7.3" + }, + "optionalDependencies": { + "kerberos": "^2.1.0", + "mongodb-client-encryption": "^6.1.0", + "os-dns-native": "^1.2.0", + "resolve-mongodb-srv": "^1.1.1" + }, + "peerDependencies": { + "@mongodb-js/oidc-plugin": "^1.1.0", + "mongodb": "^6.9.0", + "mongodb-log-writer": "^2.4.1" + } + }, + "node_modules/@mongodb-js/devtools-proxy-support": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/devtools-proxy-support/-/devtools-proxy-support-0.4.4.tgz", + "integrity": "sha512-klRFd33bjUntPJuEY86NB0xYd64SaEYN0ABbE5fjU8+lO94ItvxTAWyHUmerPFAk8OLyz1MFyDoTXOvdOs9NAQ==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/socksv5": "^0.0.10", + "agent-base": "^7.1.1", + "debug": "^4.4.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "lru-cache": "^11.0.0", + "node-fetch": "^3.3.2", + "pac-proxy-agent": "^7.0.2", + "socks-proxy-agent": "^8.0.4", + "ssh2": "^1.15.0", + "system-ca": "^2.0.1" + } + }, + "node_modules/@mongodb-js/mongodb-downloader": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.3.9.tgz", + "integrity": "sha512-6lEIESINiIAeQUw95+hkfxG6129r6KiPU2TNOcxb30PsGgFHPJFg7QY8UoSQXjDE9YaENlr6oQm3c1XDixWeEg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.0", + "decompress": "^4.2.1", + "mongodb-download-url": "^1.5.7", + "node-fetch": "^2.7.0", + "tar": "^6.1.15" + } + }, + "node_modules/@mongodb-js/mongodb-downloader/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/@mongodb-js/oidc-plugin/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/@mongodb-js/mongodb-downloader/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@mongodb-js/mongodb-downloader/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/@mongodb-js/mongodb-downloader/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/@mongodb-js/oidc-http-server-pages": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/oidc-http-server-pages/-/oidc-http-server-pages-1.1.4.tgz", + "integrity": "sha512-fPwS1cERLGNSz8D1kBw2RJ0GNn1Ud2IIBehvV8OmOZzSXEx6hjwgvKG8XdHT7tpXns7iSkw9gSj84yHJkAlOnQ==", + "license": "Apache-2.0" + }, + "node_modules/@mongodb-js/oidc-plugin": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@mongodb-js/oidc-plugin/-/oidc-plugin-1.1.6.tgz", + "integrity": "sha512-fuL4B9x1njcqdJqV+V3pt8s/9PX4uy9ojhcsP12BavDcg61ju6WEqCkDmUZCykDIvsDbb8tIhO97aCKDxcXROw==", + "license": "Apache-2.0", + "dependencies": { + "express": "^4.18.2", + "open": "^9.1.0", + "openid-client": "^5.6.4" }, "engines": { - "node": ">= 0.6" + "node": ">= 16.20.1" } }, "node_modules/@mongodb-js/saslprep": { @@ -3533,9 +3151,9 @@ } }, "node_modules/@mongosh/service-provider-core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mongosh/service-provider-core/-/service-provider-core-3.1.0.tgz", - "integrity": "sha512-QSmTzmiD1Tlj9liWSqZJni12B8Afrqii3BoB96LMLHxPRkzTu+H9nWwYOF0d+IQaab7wW2HWDlpSJYhzgQdCKA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@mongosh/service-provider-core/-/service-provider-core-3.3.0.tgz", + "integrity": "sha512-gzVO33L4hqZqw3dKuJyXXQbTJsibW6k4U01WeaV+H2OzIyqaNPxdMHK+slrM7rizYM+5UG+F0YNYvFDrenjAIw==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-providers": "^3.525.0", @@ -3553,15 +3171,15 @@ } }, "node_modules/@mongosh/service-provider-node-driver": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@mongosh/service-provider-node-driver/-/service-provider-node-driver-3.6.0.tgz", - "integrity": "sha512-VOmOQ11qcz+nYjOyB/6nXuoZcLRSDLc+tVjt/ePtdC/5XQKSZB/Pwn9riBmnqOXleST8ATmmf6z9m44viSNpQg==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@mongosh/service-provider-node-driver/-/service-provider-node-driver-3.8.0.tgz", + "integrity": "sha512-r+SfWIT6HlJsYuDJcHJX6upcifEisqKtafEmjXkbw69ObnrHfyj0PRFa+ymeE3xFRiGSLpw7rI/39bz2g6rsBA==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/devtools-connect": "^3.4.1", "@mongodb-js/oidc-plugin": "^1.1.6", "@mongosh/errors": "2.4.0", - "@mongosh/service-provider-core": "3.1.0", + "@mongosh/service-provider-core": "3.3.0", "@mongosh/types": "3.6.0", "aws4": "^1.12.0", "mongodb": "^6.14.2", @@ -3573,7 +3191,7 @@ }, "optionalDependencies": { "kerberos": "2.1.0", - "mongodb-client-encryption": "^6.1.1" + "mongodb-client-encryption": "^6.3.0" } }, "node_modules/@mongosh/service-provider-node-driver/node_modules/kerberos": { @@ -3995,27 +3613,27 @@ "license": "BSD-3-Clause" }, "node_modules/@radix-ui/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", - "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", "dev": true, "license": "MIT" }, "node_modules/@radix-ui/primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", - "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz", + "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==", "dev": true, "license": "MIT" }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz", - "integrity": "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.4.tgz", + "integrity": "sha512-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.0" }, "peerDependencies": { "@types/react": "*", @@ -4033,20 +3651,20 @@ } }, "node_modules/@radix-ui/react-checkbox": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz", - "integrity": "sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.2.2.tgz", + "integrity": "sha512-pMxzQLK+m/tkDRXJg7VUjRx6ozsBdzNLOV4vexfVBU57qT2Gvf4cw2gKKhOohJxjadQ+WcUXCKosTIxcZzi03A==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-use-size": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.3", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4064,16 +3682,16 @@ } }, "node_modules/@radix-ui/react-collection": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", - "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.4.tgz", + "integrity": "sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", @@ -4091,9 +3709,9 @@ } }, "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", - "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4107,9 +3725,9 @@ } }, "node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4123,24 +3741,24 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.6.tgz", - "integrity": "sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.10.tgz", + "integrity": "sha512-m6pZb0gEM5uHPSb+i2nKKGQi/HMSVjARMsLMWQfKDP+eJ6B+uqryHnXhpnohTWElw+vEcMk/o4wJODtdRKHwqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.7", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.4", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-presence": "1.1.3", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -4160,9 +3778,9 @@ } }, "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4176,17 +3794,17 @@ } }, "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz", - "integrity": "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.7.tgz", + "integrity": "sha512-j5+WBUdhccJsmH5/H0K6RncjDtoALSEr6jbkaZu+bjw6hOPOhHycr6vEUujl+HBK8kjUfWcoCJXxP6e4lUlMZw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4204,9 +3822,9 @@ } }, "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz", + "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4220,15 +3838,15 @@ } }, "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz", - "integrity": "sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.4.tgz", + "integrity": "sha512-r2annK27lIW5w9Ho5NyQgqs0MmgZSTIKXWpVCJaLC1q2kZrZkcqnmHkCHMEmv8XLvsLlurKMPT+kbKkRkm/xVA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4256,13 +3874,13 @@ } }, "node_modules/@radix-ui/react-id": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4275,13 +3893,13 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.2.tgz", - "integrity": "sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.4.tgz", + "integrity": "sha512-wy3dqizZnZVV4ja0FNnUhIWNwWdoldXrneEyUcVtLYDAt8ovGS4ridtMAOGgXBBIfggL4BOveVWsjXDORdGEQg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.0" }, "peerDependencies": { "@types/react": "*", @@ -4299,25 +3917,25 @@ } }, "node_modules/@radix-ui/react-popover": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.6.tgz", - "integrity": "sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.10.tgz", + "integrity": "sha512-IZN7b3sXqajiPsOzKuNJBSP9obF4MX5/5UhTgWNofw4r1H+eATWb0SyMlaxPD/kzA4vadFgy1s7Z1AEJ6WMyHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.7", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.4", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.4", + "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-presence": "1.1.3", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -4337,22 +3955,22 @@ } }, "node_modules/@radix-ui/react-popper": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.2.tgz", - "integrity": "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.4.tgz", + "integrity": "sha512-3p2Rgm/a1cK0r/UVkx5F/K9v/EplfjAeIFCGOPYPO4lZ0jtg4iSQXt/YGTSLWaf4x7NG6Z4+uKFcylcTZjeqDA==", "dev": true, "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@radix-ui/react-arrow": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4370,14 +3988,14 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.4.tgz", - "integrity": "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.6.tgz", + "integrity": "sha512-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4395,14 +4013,14 @@ } }, "node_modules/@radix-ui/react-presence": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", - "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.3.tgz", + "integrity": "sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4420,13 +4038,13 @@ } }, "node_modules/@radix-ui/react-primitive": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", - "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.0.tgz", + "integrity": "sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.1.2" + "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", @@ -4444,21 +4062,21 @@ } }, "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.2.tgz", - "integrity": "sha512-zgMQWkNO169GtGqRvYrzb0Zf8NhMHS2DuEB/TiEmVnpr5OqPU3i8lfbxaAmC2J/KYuIQxyoQQ6DxepyXp61/xw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.7.tgz", + "integrity": "sha512-C6oAg451/fQT3EGbWHbCQjYTtbyjNO1uzQgMzwyivcHT3GKNEmu1q3UuREhN+HzHAVtv3ivMVK08QlC+PkYw9Q==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -4476,31 +4094,31 @@ } }, "node_modules/@radix-ui/react-select": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz", - "integrity": "sha512-T6ajELxRvTuAMWH0YmRJ1qez+x4/7Nq7QIx7zJ0VK3qaEWdnWpNbEDnmWldG1zBDwqrLy5aLMUWcoGirVj5kMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.0", - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-focus-guards": "1.1.1", - "@radix-ui/react-focus-scope": "1.1.2", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-previous": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.2", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.2.tgz", + "integrity": "sha512-HjkVHtBkuq+r3zUAZ/CvNWUGKPfuicGDbgtZgiQuFmNcV5F+Tgy24ep2nsAW2nFgvhGPJVqeBZa6KyVN0EyrBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.7", + "@radix-ui/react-focus-guards": "1.1.2", + "@radix-ui/react-focus-scope": "1.1.4", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.4", + "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.0", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -4520,13 +4138,13 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz", + "integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -4539,20 +4157,20 @@ } }, "node_modules/@radix-ui/react-tabs": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.3.tgz", - "integrity": "sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.8.tgz", + "integrity": "sha512-4iUaN9SYtG+/E+hJ7jRks/Nv90f+uAsRHbLYA6BcA9EsR6GNWgsvtS4iwU2SP0tOZfDGAyqIT0yz7ckgohEIFA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-roving-focus": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.3", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-roving-focus": "1.1.7", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -4570,24 +4188,24 @@ } }, "node_modules/@radix-ui/react-toast": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.6.tgz", - "integrity": "sha512-gN4dpuIVKEgpLn1z5FhzT9mYRUitbfZq9XqN/7kkBMUgFTzTG8x/KszWJugJXHcwxckY8xcKDZPz7kG3o6DsUA==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.10.tgz", + "integrity": "sha512-lVe1mQL8Di8KPQp62CDaLgttqyUGTchPuwDiCnaZz40HGxngJKB/fOJCHYxHZh2p1BtcuiPOYOKrxTVEmrnV5A==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-collection": "1.1.2", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.2" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-collection": "1.1.4", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.7", + "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-presence": "1.1.3", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.0" }, "peerDependencies": { "@types/react": "*", @@ -4605,24 +4223,24 @@ } }, "node_modules/@radix-ui/react-tooltip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.8.tgz", - "integrity": "sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.3.tgz", + "integrity": "sha512-0KX7jUYFA02np01Y11NWkk6Ip6TqMNmD4ijLelYAzeIndl2aVeltjJFJ2gwjNa1P8U/dgjQ+8cr9Y3Ni+ZNoRA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.1", - "@radix-ui/react-compose-refs": "1.1.1", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.5", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.2", - "@radix-ui/react-portal": "1.1.4", - "@radix-ui/react-presence": "1.1.2", - "@radix-ui/react-primitive": "2.0.2", - "@radix-ui/react-slot": "1.1.2", - "@radix-ui/react-use-controllable-state": "1.1.0", - "@radix-ui/react-visually-hidden": "1.1.2" + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.4", + "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-presence": "1.1.3", + "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.0" }, "peerDependencies": { "@types/react": "*", @@ -4639,12 +4257,32 @@ } } }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", - "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "dev": true, "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -4655,14 +4293,14 @@ } } }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", - "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4675,13 +4313,13 @@ } }, "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", - "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4694,9 +4332,9 @@ } }, "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", - "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4710,9 +4348,9 @@ } }, "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz", - "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4726,13 +4364,13 @@ } }, "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", - "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/rect": "1.1.0" + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4745,13 +4383,13 @@ } }, "node_modules/@radix-ui/react-use-size": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", - "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", @@ -4764,13 +4402,13 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", - "integrity": "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.0.tgz", + "integrity": "sha512-rQj0aAWOpCdCMRbI6pLQm8r7S2BM3YhTa0SzOYD55k+hJA8oo9J+H+9wLM9oMlZWOX/wJWPTzfDfmZkf7LvCfg==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.2" + "@radix-ui/react-primitive": "2.1.0" }, "peerDependencies": { "@types/react": "*", @@ -4788,9 +4426,9 @@ } }, "node_modules/@radix-ui/rect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", - "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "dev": true, "license": "MIT" }, @@ -4811,13 +4449,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@redocly/ajv/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, "node_modules/@redocly/cli": { "version": "1.34.2", "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-1.34.2.tgz", @@ -4861,47 +4492,6 @@ "npm": ">=9.5.0" } }, - "node_modules/@redocly/cli/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/@redocly/cli/node_modules/yargs": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz", - "integrity": "sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@redocly/cli/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/@redocly/config": { "version": "0.22.2", "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.2.tgz", @@ -4931,29 +4521,6 @@ "npm": ">=9.5.0" } }, - "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@redocly/openapi-core/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@redocly/respect-core": { "version": "1.34.2", "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-1.34.2.tgz", @@ -5083,33 +4650,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@redocly/respect-core/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@redocly/respect-core/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@redocly/respect-core/node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.1.tgz", + "integrity": "sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA==", "dev": true, "license": "MIT", "dependencies": { @@ -5899,9 +5443,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", - "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "dev": true, "license": "MIT", "dependencies": { @@ -5977,17 +5521,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.1.tgz", - "integrity": "sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", + "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.29.1", - "@typescript-eslint/type-utils": "8.29.1", - "@typescript-eslint/utils": "8.29.1", - "@typescript-eslint/visitor-keys": "8.29.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/type-utils": "8.31.0", + "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -6007,16 +5551,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.1.tgz", - "integrity": "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz", + "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.29.1", - "@typescript-eslint/types": "8.29.1", - "@typescript-eslint/typescript-estree": "8.29.1", - "@typescript-eslint/visitor-keys": "8.29.1", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "engines": { @@ -6032,14 +5576,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.1.tgz", - "integrity": "sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", + "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.29.1", - "@typescript-eslint/visitor-keys": "8.29.1" + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6050,14 +5594,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.1.tgz", - "integrity": "sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", + "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.29.1", - "@typescript-eslint/utils": "8.29.1", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -6074,9 +5618,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.1.tgz", - "integrity": "sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz", + "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", "dev": true, "license": "MIT", "engines": { @@ -6088,14 +5632,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.1.tgz", - "integrity": "sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", + "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.29.1", - "@typescript-eslint/visitor-keys": "8.29.1", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -6114,16 +5658,6 @@ "typescript": ">=4.8.4 <5.9.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -6141,16 +5675,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.1.tgz", - "integrity": "sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz", + "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.29.1", - "@typescript-eslint/types": "8.29.1", - "@typescript-eslint/typescript-estree": "8.29.1" + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6165,13 +5699,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.1.tgz", - "integrity": "sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", + "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.29.1", + "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -6196,13 +5730,13 @@ } }, "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" @@ -6254,16 +5788,17 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -6296,19 +5831,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -6641,42 +6163,108 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "file-uri-to-path": "1.0.0" } }, "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">=18" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/bowser": { @@ -6698,14 +6286,13 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -6953,9 +6540,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001712", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001712.tgz", - "integrity": "sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==", + "version": "1.0.30001715", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", + "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", "dev": true, "funding": [ { @@ -7032,26 +6619,16 @@ "fsevents": "~2.3.2" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC", - "optional": true - }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -7108,18 +6685,15 @@ } }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "devOptional": true, + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", + "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" } }, "node_modules/clsx": { @@ -7273,6 +6847,21 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, + "node_modules/concurrently/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/concurrently/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -7289,10 +6878,29 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/concurrently/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -7327,13 +6935,10 @@ } }, "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/core-js": { "version": "3.41.0", @@ -7536,17 +7141,6 @@ "node": ">=4" } }, - "node_modules/decompress-tar/node_modules/bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, "node_modules/decompress-tar/node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -7557,58 +7151,6 @@ "node": ">=0.10.0" } }, - "node_modules/decompress-tar/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/decompress-tar/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/decompress-tar/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/decompress-tar/node_modules/tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/decompress-tarbz2": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", @@ -7731,78 +7273,188 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=4" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "license": "MIT", + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "license": "MIT", + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "dev": true, + "node_modules/default-browser/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "license": "MIT", - "optional": true, + "dependencies": { + "path-key": "^4.0.0" + }, "engines": { - "node": ">=4.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, + "node_modules/default-browser/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-browser": { + "node_modules/default-browser/node_modules/path-key": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "license": "MIT", - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-browser-id": { + "node_modules/default-browser/node_modules/strip-final-newline": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "license": "MIT", - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, "engines": { "node": ">=12" }, @@ -7866,9 +7518,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", "license": "Apache-2.0", "optional": true, "engines": { @@ -7923,9 +7575,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -7972,9 +7624,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.134", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.134.tgz", - "integrity": "sha512-zSwzrLg3jNP3bwsLqWHmS5z2nIOQ5ngMnfMZOWWtXnqqQkPVyOipxK98w+1beLw1TB+EImPNcG8wVP/cLVs2Og==", + "version": "1.5.140", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.140.tgz", + "integrity": "sha512-o82Rj+ONp4Ip7Cl1r7lrqx/pXhbp/lh9DpKcMNscFJdh8ebyRofnc7Sh01B4jx403RI0oqTBvlZ7OBIZLMr2+Q==", "dev": true, "license": "ISC" }, @@ -8172,20 +7824,20 @@ } }, "node_modules/eslint": { - "version": "9.24.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", - "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "version": "9.25.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", + "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.0", - "@eslint/core": "^0.12.0", + "@eslint/config-helpers": "^0.2.1", + "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.24.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/js": "9.25.1", + "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -8233,9 +7885,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", - "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz", + "integrity": "sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==", "dev": true, "license": "MIT", "bin": { @@ -8275,6 +7927,67 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", @@ -8398,23 +8111,23 @@ } }, "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=10" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" @@ -8457,41 +8170,45 @@ } }, "node_modules/express": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.0", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 18" + "node": ">= 0.10.0" }, "funding": { "type": "opencollective", @@ -8513,6 +8230,30 @@ "express": "^4.11 || 5 || ^5.0.0-beta.1" } }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -8537,19 +8278,6 @@ "node": ">=8.6.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -8571,6 +8299,24 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "peer": true + }, "node_modules/fast-xml-parser": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", @@ -8673,8 +8419,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/filelist": { "version": "1.0.4", @@ -8686,29 +8432,6 @@ "minimatch": "^5.0.1" } }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -8723,22 +8446,38 @@ } }, "node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "license": "MIT", "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -8800,29 +8539,6 @@ "node": ">= 6" } }, - "node_modules/form-data/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/form-data/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -8845,12 +8561,12 @@ } }, "node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, "node_modules/fs-constants": { @@ -9079,16 +8795,40 @@ } }, "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/globals": { @@ -9268,21 +9008,21 @@ } }, "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "license": "Apache-2.0", "engines": { - "node": ">=14.18.0" + "node": ">=10.17.0" } }, "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" @@ -9569,12 +9309,12 @@ "license": "MIT" }, "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9712,147 +9452,75 @@ }, "bin": { "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/jest-changed-files/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/jest-changed-files/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + }, + "engines": { + "node": ">=10" } }, - "node_modules/jest-changed-files/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/jest-changed-files/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "path-key": "^3.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/jest-changed-files/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/jest-changed-files/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus": { @@ -9921,6 +9589,40 @@ } } }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -9967,25 +9669,6 @@ } } }, - "node_modules/jest-config/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -10050,6 +9733,28 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-extended": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-4.0.2.tgz", + "integrity": "sha512-FH7aaPgtGYHc9mRjriS0ZEHYM5/W69tLrFTIdzm+yJgeoCmmrSB/luSfMSqWP9O29QWHPEmJ4qmU6EwsZideog==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-diff": "^29.0.0", + "jest-get-type": "^29.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "jest": ">=27.2.5" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -10527,9 +10232,9 @@ } }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, @@ -10685,9 +10390,9 @@ "license": "MIT" }, "node_modules/long": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz", - "integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "dev": true, "license": "Apache-2.0" }, @@ -10815,12 +10520,12 @@ } }, "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, "node_modules/memory-pager": { @@ -10830,13 +10535,10 @@ "license": "MIT" }, "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "license": "MIT", - "engines": { - "node": ">=18" - }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -10893,36 +10595,33 @@ } }, "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { - "mime-db": "^1.54.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/mimic-response": { @@ -10939,16 +10638,16 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=10" } }, "node_modules/minimist": { @@ -11082,9 +10781,9 @@ } }, "node_modules/mongodb": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.15.0.tgz", - "integrity": "sha512-ifBhQ0rRzHDzqp9jAQP6OwHSH7dbYIQjD3SbJs9YYk9AikKEettW/9s/tbSFDTpXcRbF+u1aLrhHxDFaYtZpFQ==", + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.16.0.tgz", + "integrity": "sha512-D1PNcdT0y4Grhou5Zi/qgipZOYeWrhLEpk33n3nm6LGtz61jvO88WlrWCK/bigMjpnOdAUKKQwsGIl0NtWMyYw==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/saslprep": "^1.1.9", @@ -11273,27 +10972,95 @@ "mongodb-runner": "bin/runner.js" } }, + "node_modules/mongodb-runner/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-runner/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/mongodb-schema": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.6.2.tgz", "integrity": "sha512-uKjkTAx6MqJi0Xj0aeYRjvYr3O7LrUQgXH1c0WQCOByPoYbNG9RAhWoc4IwriIqTHyBw1RJn0C/p7DISOPYpMg==", "license": "Apache-2.0", "dependencies": { - "reservoir": "^0.1.2" - }, - "bin": { - "mongodb-schema": "bin/mongodb-schema" + "reservoir": "^0.1.2" + }, + "bin": { + "mongodb-schema": "bin/mongodb-schema" + }, + "optionalDependencies": { + "bson": "^6.7.0", + "cli-table": "^0.3.4", + "js-yaml": "^4.0.0", + "mongodb": "^6.6.1", + "mongodb-ns": "^2.4.0", + "numeral": "^2.0.6", + "progress": "^2.0.3", + "stats-lite": "^2.0.0", + "yargs": "^17.6.2" + } + }, + "node_modules/mongodb-schema/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-schema/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "optionalDependencies": { - "bson": "^6.7.0", - "cli-table": "^0.3.4", - "js-yaml": "^4.0.0", - "mongodb": "^6.6.1", - "mongodb-ns": "^2.4.0", - "numeral": "^2.0.6", - "progress": "^2.0.3", - "stats-lite": "^2.0.0", - "yargs": "^17.6.2" + "engines": { + "node": ">=12" } }, "node_modules/ms": { @@ -11335,6 +11102,31 @@ "license": "MIT", "optional": true }, + "node_modules/native-machine-id": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/native-machine-id/-/native-machine-id-0.0.8.tgz", + "integrity": "sha512-0sMw6WHfG1A7N59C1odmge9K/F9uC+1dgXHjMW57w319ii/nI05FDFwlXSjPMAHHB7hU7OInpVuH+Sgjz5enog==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^8.0.0" + }, + "bin": { + "native-machine-id": "dist/bin/machine-id.js" + } + }, + "node_modules/native-machine-id/node_modules/node-addon-api": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz", + "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -11343,9 +11135,9 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -11391,6 +11183,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", "funding": [ { "type": "github", @@ -11472,30 +11265,15 @@ } }, "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "license": "MIT", "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "path-key": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/numeral": { @@ -11674,15 +11452,15 @@ } }, "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "license": "MIT", "dependencies": { - "mimic-fn": "^4.0.0" + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=12" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11780,6 +11558,24 @@ "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==", "license": "MIT" }, + "node_modules/openapi-typescript/node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openapi-typescript/node_modules/supports-color": { "version": "9.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", @@ -11793,6 +11589,19 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/openapi-typescript/node_modules/type-fest": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", + "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/openid-client": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", @@ -11954,18 +11763,19 @@ } }, "node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=18" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12031,13 +11841,10 @@ "license": "MIT" }, "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "license": "MIT", - "engines": { - "node": ">=16" - } + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" }, "node_modules/pend": { "version": "1.2.0", @@ -12396,9 +12203,9 @@ "license": "MIT" }, "node_modules/protobufjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.0.tgz", + "integrity": "sha512-Z2E/kOY1QjoMlCytmexzYfDm/w5fKAiRwpSzGtdnXW1zC88Z2yXazHHrOtwCzn+7wSxyE8PYM4rvVcMphF9sOA==", "dev": true, "hasInstallScript": true, "license": "BSD-3-Clause", @@ -12471,12 +12278,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -12540,6 +12347,18 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -12923,6 +12742,15 @@ "node": ">= 18" } }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, "node_modules/run-applescript": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", @@ -12938,95 +12766,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/run-applescript/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -13121,29 +12860,55 @@ "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { - "node": ">= 18" + "node": ">= 0.8" } }, "node_modules/serve-handler": { @@ -13162,6 +12927,17 @@ "range-parser": "1.2.0" } }, + "node_modules/serve-handler/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/serve-handler/node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -13205,6 +12981,19 @@ "node": ">= 0.6" } }, + "node_modules/serve-handler/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/serve-handler/node_modules/path-to-regexp": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", @@ -13223,18 +13012,18 @@ } }, "node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "license": "MIT", "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">= 18" + "node": ">= 0.8.0" } }, "node_modules/set-cookie-parser": { @@ -13801,15 +13590,12 @@ } }, "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/strip-json-comments": { @@ -14012,9 +13798,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.3.tgz", - "integrity": "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz", + "integrity": "sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==", "dev": true, "license": "MIT", "peer": true @@ -14060,7 +13846,26 @@ "tar-stream": "^2.1.4" } }, - "node_modules/tar-stream": { + "node_modules/tar-fs/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC", + "optional": true + }, + "node_modules/tar-fs/node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", @@ -14077,14 +13882,56 @@ "node": ">=6" } }, - "node_modules/tar/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tar-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/test-exclude": { @@ -14102,6 +13949,30 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -14158,9 +14029,9 @@ } }, "node_modules/tr46": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz", - "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -14193,9 +14064,9 @@ } }, "node_modules/ts-jest": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.1.tgz", - "integrity": "sha512-FT2PIRtZABwl6+ZCry8IY7JZ3xMuppsEV9qFVHOVe8jDzggwUZ9TsM4chyJxL9yi6LvkqcZYU3LmapEE454zBQ==", + "version": "29.3.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz", + "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==", "dev": true, "license": "MIT", "dependencies": { @@ -14207,7 +14078,7 @@ "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", "semver": "^7.7.1", - "type-fest": "^4.38.0", + "type-fest": "^4.39.1", "yargs-parser": "^21.1.1" }, "bin": { @@ -14242,6 +14113,19 @@ } } }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.40.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", + "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -14355,27 +14239,26 @@ } }, "node_modules/type-fest": { - "version": "4.39.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz", - "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=16" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "license": "MIT", "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { "node": ">= 0.6" @@ -14389,9 +14272,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -14403,15 +14286,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.29.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.1.tgz", - "integrity": "sha512-f8cDkvndhbQMPcysk6CUSGBWV+g1utqdn71P5YKwMumVMOG/5k7cHq0KyG4O52nB0oKS4aN2Tp5+wB4APJGC+w==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.0.tgz", + "integrity": "sha512-u+93F0sB0An8WEAPtwxVhFby573E8ckdjwUUQUj9QA4v8JAvgtoDdIyYR3XFwFHq2W1KJ1AurwJCO+w+Y1ixyQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.29.1", - "@typescript-eslint/parser": "8.29.1", - "@typescript-eslint/utils": "8.29.1" + "@typescript-eslint/eslint-plugin": "8.31.0", + "@typescript-eslint/parser": "8.31.0", + "@typescript-eslint/utils": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -14646,17 +14529,6 @@ "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -14847,6 +14719,19 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yaml-ast-parser": { "version": "0.0.43", "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", @@ -14855,19 +14740,19 @@ "license": "Apache-2.0" }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "devOptional": true, + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.0.1.tgz", + "integrity": "sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==", + "dev": true, "license": "MIT", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^4.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^20.2.2" }, "engines": { "node": ">=12" @@ -14882,6 +14767,16 @@ "node": ">=12" } }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -14917,9 +14812,9 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "version": "3.24.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", + "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index bdbeed63..c9e52549 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "@mongodb-js/mongodb-mcp-server", + "name": "mongodb-mcp-server", "description": "MongoDB Model Context Protocol Server", - "version": "0.0.3", + "version": "0.0.4", "main": "dist/index.js", "author": "MongoDB ", "homepage": "https://github.com/mongodb-js/mongodb-mcp-server", @@ -28,7 +28,7 @@ "check:format": "prettier -c .", "reformat": "prettier --write .", "generate": "./scripts/generate.sh", - "test": "jest" + "test": "jest --coverage" }, "license": "Apache-2.0", "devDependencies": { @@ -45,20 +45,24 @@ "globals": "^16.0.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", + "jest-extended": "^4.0.2", "mongodb-runner": "^5.8.2", + "native-machine-id": "^0.0.8", "openapi-types": "^12.1.3", "openapi-typescript": "^7.6.1", "prettier": "^3.5.3", "ts-jest": "^29.3.1", "tsx": "^4.19.3", "typescript": "^5.8.2", - "typescript-eslint": "^8.29.1" + "typescript-eslint": "^8.29.1", + "yaml": "^2.7.1" }, "dependencies": { + "@modelcontextprotocol/sdk": "^1.8.0", "@mongodb-js/devtools-connect": "^3.7.2", "@mongosh/service-provider-node-driver": "^3.6.0", - "@modelcontextprotocol/sdk": "^1.8.0", "bson": "^6.10.3", + "lru-cache": "^11.1.0", "mongodb": "^6.15.0", "mongodb-log-writer": "^2.4.1", "mongodb-redact": "^1.1.6", diff --git a/scripts/apply.ts b/scripts/apply.ts index e8ef94f4..420a31d0 100755 --- a/scripts/apply.ts +++ b/scripts/apply.ts @@ -2,18 +2,22 @@ import fs from "fs/promises"; import { OpenAPIV3_1 } from "openapi-types"; import argv from "yargs-parser"; -function findParamFromRef(ref: string, openapi: OpenAPIV3_1.Document): OpenAPIV3_1.ParameterObject { +function findObjectFromRef(obj: T | OpenAPIV3_1.ReferenceObject, openapi: OpenAPIV3_1.Document): T { + const ref = (obj as OpenAPIV3_1.ReferenceObject).$ref; + if (ref === undefined) { + return obj as T; + } const paramParts = ref.split("/"); paramParts.shift(); // Remove the first part which is always '#' - let param: any = openapi; // eslint-disable-line @typescript-eslint/no-explicit-any + let foundObj: any = openapi; // eslint-disable-line @typescript-eslint/no-explicit-any while (true) { const part = paramParts.shift(); if (!part) { break; } - param = param[part]; + foundObj = foundObj[part]; } - return param; + return foundObj as T; } async function main() { @@ -32,6 +36,7 @@ async function main() { operationId: string; requiredParams: boolean; tag: string; + hasResponseBody: boolean; }[] = []; const openapi = JSON.parse(specFile) as OpenAPIV3_1.Document; @@ -44,13 +49,27 @@ async function main() { } let requiredParams = !!operation.requestBody; + let hasResponseBody = false; + for (const code in operation.responses) { + try { + const httpCode = parseInt(code, 10); + if (httpCode >= 200 && httpCode < 300) { + const response = operation.responses[code]; + const responseObject = findObjectFromRef(response, openapi); + if (responseObject.content) { + for (const contentType in responseObject.content) { + const content = responseObject.content[contentType]; + hasResponseBody = !!content.schema; + } + } + } + } catch { + continue; + } + } for (const param of operation.parameters || []) { - const ref = (param as OpenAPIV3_1.ReferenceObject).$ref as string | undefined; - let paramObject: OpenAPIV3_1.ParameterObject = param as OpenAPIV3_1.ParameterObject; - if (ref) { - paramObject = findParamFromRef(ref, openapi); - } + const paramObject = findObjectFromRef(param, openapi); if (paramObject.in === "path") { requiredParams = true; } @@ -61,6 +80,7 @@ async function main() { method: method.toUpperCase(), operationId: operation.operationId || "", requiredParams, + hasResponseBody, tag: operation.tags[0], }); } @@ -68,20 +88,37 @@ async function main() { const operationOutput = operations .map((operation) => { - const { operationId, method, path, requiredParams } = operation; + const { operationId, method, path, requiredParams, hasResponseBody } = operation; return `async ${operationId}(options${requiredParams ? "" : "?"}: FetchOptions) { - const { data } = await this.client.${method}("${path}", options); - return data; -} + ${hasResponseBody ? `const { data } = ` : ``}await this.client.${method}("${path}", options); + ${ + hasResponseBody + ? `return data; +` + : `` + }} `; }) .join("\n"); const templateFile = (await fs.readFile(file, "utf8")) as string; - const output = templateFile.replace( - /\/\/ DO NOT EDIT\. This is auto-generated code\.\n.*\/\/ DO NOT EDIT\. This is auto-generated code\./g, - operationOutput - ); + const templateLines = templateFile.split("\n"); + let outputLines: string[] = []; + let addLines = true; + for (const line of templateLines) { + if (line.includes("DO NOT EDIT. This is auto-generated code.")) { + addLines = !addLines; + outputLines.push(line); + if (!addLines) { + outputLines.push(operationOutput); + } + continue; + } + if (addLines) { + outputLines.push(line); + } + } + const output = outputLines.join("\n"); await fs.writeFile(file, output, "utf8"); } diff --git a/scripts/filter.ts b/scripts/filter.ts index 7379a2d9..34a69f7a 100755 --- a/scripts/filter.ts +++ b/scripts/filter.ts @@ -19,16 +19,22 @@ async function readStdin() { function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document { const allowedOperations = [ "listProjects", + "listOrganizations", "getProject", "createProject", + "deleteProject", "listClusters", "getCluster", "createCluster", + "deleteCluster", "listClustersForAllProjects", "createDatabaseUser", + "deleteDatabaseUser", "listDatabaseUsers", "listProjectIpAccessLists", "createProjectIpAccessList", + "deleteProjectIpAccessList", + "listOrganizationProjects", ]; const filteredPaths = {}; diff --git a/src/common/atlas/apiClient.ts b/src/common/atlas/apiClient.ts index b784e43e..f71e1162 100644 --- a/src/common/atlas/apiClient.ts +++ b/src/common/atlas/apiClient.ts @@ -1,16 +1,22 @@ -import config from "../../config.js"; -import createClient, { Client, FetchOptions, Middleware } from "openapi-fetch"; +import createClient, { Client, Middleware } from "openapi-fetch"; +import type { FetchOptions } from "openapi-fetch"; import { AccessToken, ClientCredentials } from "simple-oauth2"; import { ApiClientError } from "./apiClientError.js"; import { paths, operations } from "./openapi.js"; +import { BaseEvent } from "../../telemetry/types.js"; +import { mongoLogId } from "mongodb-log-writer"; +import logger from "../../logger.js"; +import { packageInfo } from "../../packageInfo.js"; const ATLAS_API_VERSION = "2025-03-12"; +export interface ApiClientCredentials { + clientId: string; + clientSecret: string; +} + export interface ApiClientOptions { - credentials?: { - clientId: string; - clientSecret: string; - }; + credentials?: ApiClientCredentials; baseUrl?: string; userAgent?: string; } @@ -65,7 +71,7 @@ export class ApiClient { baseUrl: options?.baseUrl || "https://cloud.mongodb.com/", userAgent: options?.userAgent || - `AtlasMCP/${config.version} (${process.platform}; ${process.arch}; ${process.env.HOSTNAME || "unknown"})`, + `AtlasMCP/${packageInfo.version} (${process.platform}; ${process.arch}; ${process.env.HOSTNAME || "unknown"})`, }; this.client = createClient({ @@ -91,6 +97,15 @@ export class ApiClient { this.client.use(this.errorMiddleware); } + public hasCredentials(): boolean { + logger.info( + mongoLogId(1_000_000), + "api-client", + `Checking if API client has credentials: ${!!(this.oauth2Client && this.accessToken)}` + ); + return !!(this.oauth2Client && this.accessToken); + } + public async getIpInfo(): Promise<{ currentIpv4Address: string; }> { @@ -116,6 +131,32 @@ export class ApiClient { }>; } + async sendEvents(events: BaseEvent[]): Promise { + let endpoint = "api/private/unauth/telemetry/events"; + const headers: Record = { + Accept: "application/json", + "Content-Type": "application/json", + "User-Agent": this.options.userAgent, + }; + + const accessToken = await this.getAccessToken(); + if (accessToken) { + endpoint = "api/private/v1.0/telemetry/events"; + headers["Authorization"] = `Bearer ${accessToken}`; + } + + const url = new URL(endpoint, this.options.baseUrl); + const response = await fetch(url, { + method: "POST", + headers, + body: JSON.stringify(events), + }); + + if (!response.ok) { + throw await ApiClientError.fromResponse(response); + } + } + // DO NOT EDIT. This is auto-generated code. async listClustersForAllProjects(options?: FetchOptions) { const { data } = await this.client.GET("/api/atlas/v2/clusters", options); @@ -132,6 +173,10 @@ export class ApiClient { return data; } + async deleteProject(options: FetchOptions) { + await this.client.DELETE("/api/atlas/v2/groups/{groupId}", options); + } + async getProject(options: FetchOptions) { const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}", options); return data; @@ -147,6 +192,10 @@ export class ApiClient { return data; } + async deleteProjectIpAccessList(options: FetchOptions) { + await this.client.DELETE("/api/atlas/v2/groups/{groupId}/accessList/{entryValue}", options); + } + async listClusters(options: FetchOptions) { const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options); return data; @@ -157,6 +206,10 @@ export class ApiClient { return data; } + async deleteCluster(options: FetchOptions) { + await this.client.DELETE("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options); + } + async getCluster(options: FetchOptions) { const { data } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters/{clusterName}", options); return data; @@ -171,5 +224,20 @@ export class ApiClient { const { data } = await this.client.POST("/api/atlas/v2/groups/{groupId}/databaseUsers", options); return data; } + + async deleteDatabaseUser(options: FetchOptions) { + await this.client.DELETE("/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}", options); + } + + async listOrganizations(options?: FetchOptions) { + const { data } = await this.client.GET("/api/atlas/v2/orgs", options); + return data; + } + + async listOrganizationProjects(options: FetchOptions) { + const { data } = await this.client.GET("/api/atlas/v2/orgs/{orgId}/groups", options); + return data; + } + // DO NOT EDIT. This is auto-generated code. } diff --git a/src/common/atlas/openapi.d.ts b/src/common/atlas/openapi.d.ts index c55f53ae..3534bf93 100644 --- a/src/common/atlas/openapi.d.ts +++ b/src/common/atlas/openapi.d.ts @@ -62,7 +62,11 @@ export interface paths { get: operations["getProject"]; put?: never; post?: never; - delete?: never; + /** + * Remove One Project + * @description Removes the specified project. Projects group clusters into logical collections that support an application environment, workload, or both. Each project can have its own users, teams, security, tags, and alert settings. You can delete a project only if there are no Online Archives for the clusters in the project. To use this resource, the requesting Service Account or API Key must have the Project Owner role. + */ + delete: operations["deleteProject"]; options?: never; head?: never; patch?: never; @@ -92,6 +96,26 @@ export interface paths { patch?: never; trace?: never; }; + "/api/atlas/v2/groups/{groupId}/accessList/{entryValue}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Remove One Entry from One Project IP Access List + * @description Removes one access list entry from the specified project's IP access list. Each entry in the project's IP access list contains one IP address, one CIDR-notated block of IP addresses, or one AWS Security Group ID. MongoDB Cloud only allows client connections to the cluster from entries in the project's IP access list. To use this resource, the requesting Service Account or API Key must have the Project Owner role. This resource replaces the whitelist resource. MongoDB Cloud removed whitelists in July 2021. Update your applications to use this new resource. The `/groups/{GROUP-ID}/accessList` endpoint manages the database IP access list. This endpoint is distinct from the `orgs/{ORG-ID}/apiKeys/{API-KEY-ID}/accesslist` endpoint, which manages the access list for MongoDB Cloud organizations. + */ + delete: operations["deleteProjectIpAccessList"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/atlas/v2/groups/{groupId}/clusters": { parameters: { query?: never; @@ -136,7 +160,13 @@ export interface paths { get: operations["getCluster"]; put?: never; post?: never; - delete?: never; + /** + * Remove One Cluster from One Project + * @description Removes one cluster from the specified project. The cluster must have termination protection disabled in order to be deleted. To use this resource, the requesting Service Account or API Key must have the Project Owner role. This feature is not available for serverless clusters. + * + * This endpoint can also be used on Flex clusters that were created using the [createCluster](https://www.mongodb.com/docs/atlas/reference/api-resources-spec/v2/#tag/Clusters/operation/createCluster) endpoint or former M2/M5 clusters that have been migrated to Flex clusters until January 2026. Please use the deleteFlexCluster endpoint for Flex clusters instead. Deprecated versions: v2-{2023-01-01} + */ + delete: operations["deleteCluster"]; options?: never; head?: never; patch?: never; @@ -166,6 +196,73 @@ export interface paths { patch?: never; trace?: never; }; + "/api/atlas/v2/groups/{groupId}/databaseUsers/{databaseName}/{username}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + /** + * Remove One Database User from One Project + * @description Removes one database user from the specified project. To use this resource, the requesting Service Account or API Key must have the Project Owner role, the Project Stream Processing Owner role, or the Project Database Access Admin role. + */ + delete: operations["deleteDatabaseUser"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/atlas/v2/orgs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return All Organizations + * @description Returns all organizations to which the requesting Service Account or API Key has access. To use this resource, the requesting Service Account or API Key must have the Organization Member role. + */ + get: operations["listOrganizations"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/atlas/v2/orgs/{orgId}/groups": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return One or More Projects in One Organization + * @description Returns multiple projects in the specified organization. Each organization can have multiple projects. Use projects to: + * + * - Isolate different environments, such as development, test, or production environments, from each other. + * - Associate different MongoDB Cloud users or teams with different environments, or give different permission to MongoDB Cloud users in different environments. + * - Maintain separate cluster security configurations. + * - Create different alert settings. + * + * To use this resource, the requesting Service Account or API Key must have the Organization Member role. + */ + get: operations["listOrganizationProjects"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; } export type webhooks = Record; export interface components { @@ -192,44 +289,7 @@ export interface components { * @description Geographic area that Amazon Web Services (AWS) defines to which MongoDB Cloud deployed this network peering container. * @enum {string} */ - regionName: - | "US_EAST_1" - | "US_EAST_2" - | "US_WEST_1" - | "US_WEST_2" - | "CA_CENTRAL_1" - | "EU_NORTH_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_WEST_3" - | "EU_CENTRAL_1" - | "EU_CENTRAL_2" - | "SA_EAST_1" - | "AP_EAST_1" - | "AP_SOUTHEAST_2" - | "AP_SOUTHEAST_3" - | "AP_SOUTHEAST_4" - | "AP_NORTHEAST_1" - | "AP_NORTHEAST_2" - | "AP_NORTHEAST_3" - | "AP_SOUTHEAST_1" - | "AP_SOUTH_1" - | "AP_SOUTH_2" - | "CN_NORTH_1" - | "CN_NORTHWEST_1" - | "ME_CENTRAL_1" - | "ME_SOUTH_1" - | "AF_SOUTH_1" - | "EU_SOUTH_1" - | "EU_SOUTH_2" - | "IL_CENTRAL_1" - | "CA_WEST_1" - | "AP_SOUTHEAST_5" - | "AP_SOUTHEAST_7" - | "MX_CENTRAL_1" - | "GLOBAL" - | "US_GOV_WEST_1" - | "US_GOV_EAST_1"; + regionName: "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "SA_EAST_1" | "AP_EAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTH_1" | "AP_SOUTH_2" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_CENTRAL_1" | "ME_SOUTH_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL" | "US_GOV_WEST_1" | "US_GOV_EAST_1"; /** * @description Unique string that identifies the MongoDB Cloud VPC on AWS. * @example vpc-b555d3b0d9cb783b0 @@ -241,7 +301,13 @@ export interface components { * @enum {string} */ providerName: "AWS"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AWS"; + }; AWSCloudProviderSettings: Omit & { autoScaling?: components["schemas"]["CloudProviderAWSAutoScaling"]; /** @@ -260,75 +326,13 @@ export interface components { * @description Cluster tier, with a default storage and memory capacity, that applies to all the data-bearing hosts in your cluster. * @enum {string} */ - instanceSizeName?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M100" - | "M140" - | "M200" - | "M300" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R700" - | "M40_NVME" - | "M50_NVME" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M400_NVME"; + instanceSizeName?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M100" | "M140" | "M200" | "M300" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R700" | "M40_NVME" | "M50_NVME" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M400_NVME"; /** * AWS Regions * @description Physical location where MongoDB Cloud deploys your AWS-hosted MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. MongoDB Cloud assigns the VPC a CIDR block. To limit a new VPC peering connection to one CIDR block and region, create the connection first. Deploy the cluster after the connection starts. * @enum {string} */ - regionName?: - | "US_GOV_WEST_1" - | "US_GOV_EAST_1" - | "US_EAST_1" - | "US_EAST_2" - | "US_WEST_1" - | "US_WEST_2" - | "CA_CENTRAL_1" - | "EU_NORTH_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_WEST_3" - | "EU_CENTRAL_1" - | "EU_CENTRAL_2" - | "AP_EAST_1" - | "AP_NORTHEAST_1" - | "AP_NORTHEAST_2" - | "AP_NORTHEAST_3" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2" - | "AP_SOUTHEAST_3" - | "AP_SOUTHEAST_4" - | "AP_SOUTH_1" - | "AP_SOUTH_2" - | "SA_EAST_1" - | "CN_NORTH_1" - | "CN_NORTHWEST_1" - | "ME_SOUTH_1" - | "ME_CENTRAL_1" - | "AF_SOUTH_1" - | "EU_SOUTH_1" - | "EU_SOUTH_2" - | "IL_CENTRAL_1" - | "CA_WEST_1" - | "AP_SOUTHEAST_5" - | "AP_SOUTHEAST_7" - | "MX_CENTRAL_1" - | "GLOBAL"; + regionName?: "US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL"; /** * @description Disk Input/Output Operations per Second (IOPS) setting for Amazon Web Services (AWS) storage that you configure only for abbr title="Amazon Web Services">AWS. Specify whether Disk Input/Output Operations per Second (IOPS) must not exceed the default Input/Output Operations per Second (IOPS) rate for the selected volume size (`STANDARD`), or must fall within the allowable Input/Output Operations per Second (IOPS) range for the selected volume size (`PROVISIONED`). You must set this value to (`PROVISIONED`) for NVMe clusters. * @enum {string} @@ -340,7 +344,13 @@ export interface components { * @enum {string} */ providerName: "AWS"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AWS"; + }; /** * AWS * @description Collection of settings that configures how a cluster might scale its cluster tier and whether the cluster can scale down. Cluster tier auto-scaling is unavailable for clusters using Low CPU or NVME storage classes. @@ -351,79 +361,20 @@ export interface components { * @description Maximum instance size to which your cluster can automatically scale. * @enum {string} */ - maxInstanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M100" - | "M140" - | "M200" - | "M300" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R700" - | "M40_NVME" - | "M50_NVME" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M400_NVME"; + maxInstanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M100" | "M140" | "M200" | "M300" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R700" | "M40_NVME" | "M50_NVME" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M400_NVME"; /** * AWS Instance Sizes * @description Minimum instance size to which your cluster can automatically scale. * @enum {string} */ - minInstanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M100" - | "M140" - | "M200" - | "M300" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R700" - | "M40_NVME" - | "M50_NVME" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M400_NVME"; + minInstanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M100" | "M140" | "M200" | "M300" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R700" | "M40_NVME" | "M50_NVME" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M400_NVME"; }; AWSCreateDataProcessRegionView: Omit & { /** * @description Human-readable label that identifies the geographic location of the region where you wish to store your archived data. * @enum {string} */ - region?: - | "US_EAST_1" - | "US_WEST_2" - | "SA_EAST_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_CENTRAL_1" - | "AP_SOUTH_1" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2"; + region?: "US_EAST_1" | "US_WEST_2" | "SA_EAST_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_CENTRAL_1" | "AP_SOUTH_1" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2"; } & { /** * @description discriminator enum property added by openapi-typescript @@ -436,16 +387,7 @@ export interface components { * @description Human-readable label that identifies the geographic location of the region where you store your archived data. * @enum {string} */ - readonly region?: - | "US_EAST_1" - | "US_WEST_2" - | "SA_EAST_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_CENTRAL_1" - | "AP_SOUTH_1" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2"; + readonly region?: "US_EAST_1" | "US_WEST_2" | "SA_EAST_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_CENTRAL_1" | "AP_SOUTH_1" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2"; } & { /** * @description discriminator enum property added by openapi-typescript @@ -493,32 +435,7 @@ export interface components { * @description Hardware specification for the instance sizes in this region. Each instance size has a default storage and memory capacity. The instance size you select applies to all the data-bearing hosts of the node type. * @enum {string} */ - instanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M100" - | "M140" - | "M200" - | "M300" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R700" - | "M40_NVME" - | "M50_NVME" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M400_NVME"; + instanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M100" | "M140" | "M200" | "M300" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R700" | "M40_NVME" | "M50_NVME" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M400_NVME"; /** * Format: int32 * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. @@ -584,32 +501,7 @@ export interface components { * @description Hardware specification for the instance sizes in this region in this shard. Each instance size has a default storage and memory capacity. Electable nodes and read-only nodes (known as "base nodes") within a single shard must use the same instance size. Analytics nodes can scale independently from base nodes within a shard. Both base nodes and analytics nodes can scale independently from their equivalents in other shards. * @enum {string} */ - instanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M100" - | "M140" - | "M200" - | "M300" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R700" - | "M40_NVME" - | "M50_NVME" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M400_NVME"; + instanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M100" | "M140" | "M200" | "M300" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R700" | "M40_NVME" | "M50_NVME" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M400_NVME"; /** * Format: int32 * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. @@ -631,7 +523,13 @@ export interface components { * @enum {string} */ providerName: "AWS"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AWS"; + }; /** * AWS Regional Replication Specifications * @description Details that explain how MongoDB Cloud replicates data in one region on the specified MongoDB database. @@ -647,7 +545,13 @@ export interface components { * @enum {string} */ providerName: "AWS"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AWS"; + }; /** * Automatic Scaling Settings * @description Options that determine how this cluster handles resource scaling. @@ -681,10 +585,7 @@ export interface components { /** @description Group of settings that configures a subset of the advanced configuration details. */ ApiAtlasClusterAdvancedConfigurationView: { /** @description The custom OpenSSL cipher suite list for TLS 1.2. This field is only valid when `tlsCipherConfigMode` is set to `CUSTOM`. */ - customOpensslCipherConfigTls12?: ( - | "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" - | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - )[]; + customOpensslCipherConfigTls12?: ("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" | "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")[]; /** * @description Minimum Transport Layer Security (TLS) version that the cluster accepts for incoming connections. Clusters using TLS 1.0 or 1.1 should consider setting TLS 1.2 as the minimum TLS protocol version. * @enum {string} @@ -702,12 +603,7 @@ export interface components { */ ApiAtlasFTSAnalyzersViewManual: { /** @description Filters that examine text one character at a time and perform filtering operations. */ - charFilters?: ( - | components["schemas"]["charFilterhtmlStrip"] - | components["schemas"]["charFiltericuNormalize"] - | components["schemas"]["charFiltermapping"] - | components["schemas"]["charFilterpersian"] - )[]; + charFilters?: (components["schemas"]["charFilterhtmlStrip"] | components["schemas"]["charFiltericuNormalize"] | components["schemas"]["charFiltermapping"] | components["schemas"]["charFilterpersian"])[]; /** @description Human-readable name that identifies the custom analyzer. Names must be unique within an index, and must not start with any of the following strings: * - `lucene.` * - `builtin.` @@ -718,39 +614,9 @@ export interface components { * - Stemming, which reduces related words, such as "talking", "talked", and "talks" to their root word "talk". * * - Redaction, the removal of sensitive information from public documents. */ - tokenFilters?: ( - | components["schemas"]["tokenFilterasciiFolding"] - | components["schemas"]["tokenFilterdaitchMokotoffSoundex"] - | components["schemas"]["tokenFilteredgeGram"] - | components["schemas"]["TokenFilterEnglishPossessive"] - | components["schemas"]["TokenFilterFlattenGraph"] - | components["schemas"]["tokenFiltericuFolding"] - | components["schemas"]["tokenFiltericuNormalizer"] - | components["schemas"]["TokenFilterkStemming"] - | components["schemas"]["tokenFilterlength"] - | components["schemas"]["tokenFilterlowercase"] - | components["schemas"]["tokenFilternGram"] - | components["schemas"]["TokenFilterPorterStemming"] - | components["schemas"]["tokenFilterregex"] - | components["schemas"]["tokenFilterreverse"] - | components["schemas"]["tokenFiltershingle"] - | components["schemas"]["tokenFiltersnowballStemming"] - | components["schemas"]["TokenFilterSpanishPluralStemming"] - | components["schemas"]["TokenFilterStempel"] - | components["schemas"]["tokenFilterstopword"] - | components["schemas"]["tokenFiltertrim"] - | components["schemas"]["TokenFilterWordDelimiterGraph"] - )[]; + tokenFilters?: (components["schemas"]["tokenFilterasciiFolding"] | components["schemas"]["tokenFilterdaitchMokotoffSoundex"] | components["schemas"]["tokenFilteredgeGram"] | components["schemas"]["TokenFilterEnglishPossessive"] | components["schemas"]["TokenFilterFlattenGraph"] | components["schemas"]["tokenFiltericuFolding"] | components["schemas"]["tokenFiltericuNormalizer"] | components["schemas"]["TokenFilterkStemming"] | components["schemas"]["tokenFilterlength"] | components["schemas"]["tokenFilterlowercase"] | components["schemas"]["tokenFilternGram"] | components["schemas"]["TokenFilterPorterStemming"] | components["schemas"]["tokenFilterregex"] | components["schemas"]["tokenFilterreverse"] | components["schemas"]["tokenFiltershingle"] | components["schemas"]["tokenFiltersnowballStemming"] | components["schemas"]["TokenFilterSpanishPluralStemming"] | components["schemas"]["TokenFilterStempel"] | components["schemas"]["tokenFilterstopword"] | components["schemas"]["tokenFiltertrim"] | components["schemas"]["TokenFilterWordDelimiterGraph"])[]; /** @description Tokenizer that you want to use to create tokens. Tokens determine how Atlas Search splits up text into discrete chunks for indexing. */ - tokenizer: - | components["schemas"]["tokenizeredgeGram"] - | components["schemas"]["tokenizerkeyword"] - | components["schemas"]["tokenizernGram"] - | components["schemas"]["tokenizerregexCaptureGroup"] - | components["schemas"]["tokenizerregexSplit"] - | components["schemas"]["tokenizerstandard"] - | components["schemas"]["tokenizeruaxUrlEmail"] - | components["schemas"]["tokenizerwhitespace"]; + tokenizer: components["schemas"]["tokenizeredgeGram"] | components["schemas"]["tokenizerkeyword"] | components["schemas"]["tokenizernGram"] | components["schemas"]["tokenizerregexCaptureGroup"] | components["schemas"]["tokenizerregexSplit"] | components["schemas"]["tokenizerstandard"] | components["schemas"]["tokenizeruaxUrlEmail"] | components["schemas"]["tokenizerwhitespace"]; }; /** * mappings @@ -783,6 +649,25 @@ export interface components { /** @description Application error message returned with this error. */ readonly reason?: string; }; + /** @description Details that describe the organization. */ + AtlasOrganization: { + /** + * @description Unique 24-hexadecimal digit string that identifies the organization. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id?: string; + /** @description Flag that indicates whether this organization has been deleted. */ + readonly isDeleted?: boolean; + /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ + readonly links?: components["schemas"]["Link"][]; + /** @description Human-readable label that identifies the organization. */ + name: string; + /** + * @description Disables automatic alert creation. When set to true, no organization level alerts will be created automatically. + * @default false + */ + skipDefaultAlertsSettings: boolean; + }; /** Atlas Search Analyzer */ AtlasSearchAnalyzer: { /** @description Filters that examine text one character at a time and perform filtering operations. */ @@ -830,63 +715,7 @@ export interface components { * @description Azure region to which MongoDB Cloud deployed this network peering container. * @enum {string} */ - region: - | "US_CENTRAL" - | "US_EAST" - | "US_EAST_2" - | "US_EAST_2_EUAP" - | "US_NORTH_CENTRAL" - | "US_WEST" - | "US_SOUTH_CENTRAL" - | "EUROPE_NORTH" - | "EUROPE_WEST" - | "US_WEST_CENTRAL" - | "US_WEST_2" - | "US_WEST_3" - | "CANADA_EAST" - | "CANADA_CENTRAL" - | "BRAZIL_SOUTH" - | "BRAZIL_SOUTHEAST" - | "AUSTRALIA_EAST" - | "AUSTRALIA_SOUTH_EAST" - | "AUSTRALIA_CENTRAL" - | "AUSTRALIA_CENTRAL_2" - | "UAE_NORTH" - | "GERMANY_CENTRAL" - | "GERMANY_NORTH_EAST" - | "GERMANY_WEST_CENTRAL" - | "GERMANY_NORTH" - | "SWITZERLAND_NORTH" - | "SWITZERLAND_WEST" - | "SWEDEN_CENTRAL" - | "SWEDEN_SOUTH" - | "UK_SOUTH" - | "UK_WEST" - | "INDIA_CENTRAL" - | "INDIA_WEST" - | "INDIA_SOUTH" - | "CHINA_EAST" - | "CHINA_NORTH" - | "ASIA_EAST" - | "JAPAN_EAST" - | "JAPAN_WEST" - | "ASIA_SOUTH_EAST" - | "KOREA_CENTRAL" - | "KOREA_SOUTH" - | "FRANCE_CENTRAL" - | "FRANCE_SOUTH" - | "SOUTH_AFRICA_NORTH" - | "SOUTH_AFRICA_WEST" - | "NORWAY_EAST" - | "NORWAY_WEST" - | "UAE_CENTRAL" - | "QATAR_CENTRAL" - | "POLAND_CENTRAL" - | "ISRAEL_CENTRAL" - | "ITALY_NORTH" - | "SPAIN_CENTRAL" - | "MEXICO_CENTRAL" - | "NEW_ZEALAND_NORTH"; + region: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_EAST_2_EUAP" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "UAE_NORTH" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "UK_SOUTH" | "UK_WEST" | "INDIA_CENTRAL" | "INDIA_WEST" | "INDIA_SOUTH" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "UAE_CENTRAL" | "QATAR_CENTRAL" | "POLAND_CENTRAL" | "ISRAEL_CENTRAL" | "ITALY_NORTH" | "SPAIN_CENTRAL" | "MEXICO_CENTRAL" | "NEW_ZEALAND_NORTH"; /** @description Unique string that identifies the Azure VNet in which MongoDB Cloud clusters in this network peering container exist. The response returns **null** if no clusters exist in this network peering container. */ readonly vnetName?: string; } & { @@ -895,7 +724,13 @@ export interface components { * @enum {string} */ providerName: "AZURE"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AZURE"; + }; AzureCloudProviderSettings: Omit & { autoScaling?: components["schemas"]["CloudProviderAzureAutoScaling"]; /** @@ -908,91 +743,26 @@ export interface components { * @description Cluster tier, with a default storage and memory capacity, that applies to all the data-bearing hosts in your cluster. * @enum {string} */ - instanceSizeName?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M90" - | "M200" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M300_NVME" - | "M400_NVME" - | "M600_NVME"; + instanceSizeName?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M90" | "M200" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M300_NVME" | "M400_NVME" | "M600_NVME"; /** * Azure Regions * @description Microsoft Azure Regions. * @enum {string} */ - regionName?: - | "US_CENTRAL" - | "US_EAST" - | "US_EAST_2" - | "US_NORTH_CENTRAL" - | "US_WEST" - | "US_SOUTH_CENTRAL" - | "EUROPE_NORTH" - | "EUROPE_WEST" - | "US_WEST_CENTRAL" - | "US_WEST_2" - | "US_WEST_3" - | "CANADA_EAST" - | "CANADA_CENTRAL" - | "BRAZIL_SOUTH" - | "BRAZIL_SOUTHEAST" - | "AUSTRALIA_CENTRAL" - | "AUSTRALIA_CENTRAL_2" - | "AUSTRALIA_EAST" - | "AUSTRALIA_SOUTH_EAST" - | "GERMANY_CENTRAL" - | "GERMANY_NORTH_EAST" - | "GERMANY_WEST_CENTRAL" - | "GERMANY_NORTH" - | "SWEDEN_CENTRAL" - | "SWEDEN_SOUTH" - | "SWITZERLAND_NORTH" - | "SWITZERLAND_WEST" - | "UK_SOUTH" - | "UK_WEST" - | "NORWAY_EAST" - | "NORWAY_WEST" - | "INDIA_CENTRAL" - | "INDIA_SOUTH" - | "INDIA_WEST" - | "CHINA_EAST" - | "CHINA_NORTH" - | "ASIA_EAST" - | "JAPAN_EAST" - | "JAPAN_WEST" - | "ASIA_SOUTH_EAST" - | "KOREA_CENTRAL" - | "KOREA_SOUTH" - | "FRANCE_CENTRAL" - | "FRANCE_SOUTH" - | "SOUTH_AFRICA_NORTH" - | "SOUTH_AFRICA_WEST" - | "UAE_CENTRAL" - | "UAE_NORTH" - | "QATAR_CENTRAL"; + regionName?: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL"; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AZURE"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ providerName: "AZURE"; - } ; + }; /** * Azure * @description Collection of settings that configures how a cluster might scale its cluster tier and whether the cluster can scale down. Cluster tier auto-scaling is unavailable for clusters using Low CPU or NVME storage classes. @@ -1003,62 +773,15 @@ export interface components { * @description Maximum instance size to which your cluster can automatically scale. * @enum {string} */ - maxInstanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M90" - | "M200" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M300_NVME" - | "M400_NVME" - | "M600_NVME"; + maxInstanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M90" | "M200" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M300_NVME" | "M400_NVME" | "M600_NVME"; /** * Azure Instance Sizes * @description Minimum instance size to which your cluster can automatically scale. * @enum {string} */ - minInstanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M90" - | "M200" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M300_NVME" - | "M400_NVME" - | "M600_NVME"; - }; - AzureCreateDataProcessRegionView: Omit< - components["schemas"]["CreateDataProcessRegionView"], - "cloudProvider" - > & { + minInstanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M90" | "M200" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M300_NVME" | "M400_NVME" | "M600_NVME"; + }; + AzureCreateDataProcessRegionView: Omit & { /** * @description Human-readable label that identifies the geographic location of the region where you wish to store your archived data. * @enum {string} @@ -1102,29 +825,7 @@ export interface components { * @description Hardware specification for the instance sizes in this region. Each instance size has a default storage and memory capacity. The instance size you select applies to all the data-bearing hosts of the node type. * @enum {string} */ - instanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M90" - | "M200" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M300_NVME" - | "M400_NVME" - | "M600_NVME"; + instanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M90" | "M200" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M300_NVME" | "M400_NVME" | "M600_NVME"; /** * Format: int32 * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. @@ -1166,29 +867,7 @@ export interface components { * @description Hardware specification for the instance sizes in this region in this shard. Each instance size has a default storage and memory capacity. Electable nodes and read-only nodes (known as "base nodes") within a single shard must use the same instance size. Analytics nodes can scale independently from base nodes within a shard. Both base nodes and analytics nodes can scale independently from their equivalents in other shards. * @enum {string} */ - instanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M90" - | "M200" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M300_NVME" - | "M400_NVME" - | "M600_NVME"; + instanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M90" | "M200" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M300_NVME" | "M400_NVME" | "M600_NVME"; /** * Format: int32 * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. @@ -1210,7 +889,13 @@ export interface components { * @enum {string} */ providerName: "AZURE"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AZURE"; + }; /** * Azure Regional Replication Specifications * @description Details that explain how MongoDB Cloud replicates data in one region on the specified MongoDB database. @@ -1226,87 +911,20 @@ export interface components { * @enum {string} */ providerName: "AZURE"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "AZURE"; + }; /** @description Bad request detail. */ BadRequestDetail: { /** @description Describes all violations in a client request. */ fields?: components["schemas"]["FieldViolation"][]; }; /** @description Instance size boundary to which your cluster can automatically scale. */ - BaseCloudProviderInstanceSize: - | ( - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M100" - | "M140" - | "M200" - | "M300" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R700" - | "M40_NVME" - | "M50_NVME" - | "M60_NVME" - | "M80_NVME" - | "M200_NVME" - | "M400_NVME" - ) - | ( - - - - - - - - | "M90" - - - - - - - - - - - - | "M300_NVME" - - | "M600_NVME" - ) - | ( - - - - - - - - - - | "M250" - - | "M400" - - - - - - - - | "R600" - ); + BaseCloudProviderInstanceSize: ("M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M100" | "M140" | "M200" | "M300" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R700" | "M40_NVME" | "M50_NVME" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M400_NVME") | ("M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M90" | "M200" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "M60_NVME" | "M80_NVME" | "M200_NVME" | "M300_NVME" | "M400_NVME" | "M600_NVME") | ("M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M140" | "M200" | "M250" | "M300" | "M400" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R600"); BasicDBObject: { [key: string]: Record; }; @@ -1535,18 +1153,7 @@ export interface components { * - `PARTIAL_PAID`: Customer paid for part of this line item. * @enum {string} */ - statusName?: - | "NEW" - | "FORGIVEN" - | "FAILED" - | "PAID" - | "PARTIAL_PAID" - | "CANCELLED" - | "INVOICED" - | "FAILED_AUTHENTICATION" - | "PROCESSING" - | "PENDING_REVERSAL" - | "REFUNDED"; + statusName?: "NEW" | "FORGIVEN" | "FAILED" | "PAID" | "PARTIAL_PAID" | "CANCELLED" | "INVOICED" | "FAILED_AUTHENTICATION" | "PROCESSING" | "PENDING_REVERSAL" | "REFUNDED"; /** * Format: int64 * @description Sum of all positive invoice line items contained in this invoice. This parameter expresses its value in cents (100ths of one US Dollar). @@ -1701,99 +1308,32 @@ export interface components { * @description Cluster tier, with a default storage and memory capacity, that applies to all the data-bearing hosts in your cluster. * @enum {string} */ - instanceSizeName?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M140" - | "M200" - | "M250" - | "M300" - | "M400" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R600"; + instanceSizeName?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M140" | "M200" | "M250" | "M300" | "M400" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R600"; /** * GCP Regions * @description Google Compute Regions. * @enum {string} */ - regionName?: - | "EASTERN_US" - | "EASTERN_US_AW" - | "US_EAST_4" - | "US_EAST_4_AW" - | "US_EAST_5" - | "US_EAST_5_AW" - | "US_WEST_2" - | "US_WEST_2_AW" - | "US_WEST_3" - | "US_WEST_3_AW" - | "US_WEST_4" - | "US_WEST_4_AW" - | "US_SOUTH_1" - | "US_SOUTH_1_AW" - | "CENTRAL_US" - | "CENTRAL_US_AW" - | "WESTERN_US" - | "WESTERN_US_AW" - | "NORTH_AMERICA_NORTHEAST_1" - | "NORTH_AMERICA_NORTHEAST_2" - | "NORTH_AMERICA_SOUTH_1" - | "SOUTH_AMERICA_EAST_1" - | "SOUTH_AMERICA_WEST_1" - | "WESTERN_EUROPE" - | "EUROPE_NORTH_1" - | "EUROPE_WEST_2" - | "EUROPE_WEST_3" - | "EUROPE_WEST_4" - | "EUROPE_WEST_6" - | "EUROPE_WEST_8" - | "EUROPE_WEST_9" - | "EUROPE_WEST_10" - | "EUROPE_WEST_12" - | "EUROPE_SOUTHWEST_1" - | "EUROPE_CENTRAL_2" - | "MIDDLE_EAST_CENTRAL_1" - | "MIDDLE_EAST_CENTRAL_2" - | "MIDDLE_EAST_WEST_1" - | "AUSTRALIA_SOUTHEAST_1" - | "AUSTRALIA_SOUTHEAST_2" - | "AFRICA_SOUTH_1" - | "EASTERN_ASIA_PACIFIC" - | "NORTHEASTERN_ASIA_PACIFIC" - | "SOUTHEASTERN_ASIA_PACIFIC" - | "ASIA_EAST_2" - | "ASIA_NORTHEAST_2" - | "ASIA_NORTHEAST_3" - | "ASIA_SOUTH_1" - | "ASIA_SOUTH_2" - | "ASIA_SOUTHEAST_2"; + regionName?: "EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "GCP"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ providerName: "GCP"; - } ; + }; /** @description Range of instance sizes to which your cluster can scale. */ CloudProviderAWSAutoScaling: { compute?: components["schemas"]["AWSComputeAutoScaling"]; }; /** @description Details that describe the features linked to the Amazon Web Services (AWS) Identity and Access Management (IAM) role. */ - CloudProviderAccessAWSIAMRole: Omit< - WithRequired, - "providerName" - > & { + CloudProviderAccessAWSIAMRole: Omit, "providerName"> & { /** * @description Amazon Resource Name that identifies the Amazon Web Services (AWS) user account that MongoDB Cloud uses when it assumes the Identity and Access Management (IAM) role. * @example arn:aws:iam::772401394250:role/my-test-aws-role @@ -1834,10 +1374,7 @@ export interface components { providerName: "AWS"; }; /** @description Details that describe the features linked to the Amazon Web Services (AWS) Identity and Access Management (IAM) role. */ - CloudProviderAccessAWSIAMRoleRequestUpdate: Omit< - WithRequired, - "providerName" - > & { + CloudProviderAccessAWSIAMRoleRequestUpdate: Omit, "providerName"> & { /** * @description Amazon Resource Name that identifies the Amazon Web Services (AWS) user account that MongoDB Cloud uses when it assumes the Identity and Access Management (IAM) role. * @example arn:aws:iam::772401394250:role/my-test-aws-role @@ -1878,10 +1415,7 @@ export interface components { providerName: "AWS"; }; /** @description Details that describe the features linked to the Azure Service Principal. */ - CloudProviderAccessAzureServicePrincipal: Omit< - WithRequired, - "providerName" - > & { + CloudProviderAccessAzureServicePrincipal: Omit, "providerName"> & { /** * @description Unique 24-hexadecimal digit string that identifies the role. * @example 32b6e34b3d91647abb20e7b8 @@ -1922,10 +1456,7 @@ export interface components { providerName: "AZURE"; }; /** @description Details that describe the features linked to the Azure Service Principal. */ - CloudProviderAccessAzureServicePrincipalRequestUpdate: Omit< - WithRequired, - "providerName" - > & { + CloudProviderAccessAzureServicePrincipalRequestUpdate: Omit, "providerName"> & { /** * @description Unique 24-hexadecimal digit string that identifies the role. * @example 32b6e34b3d91647abb20e7b8 @@ -1966,10 +1497,7 @@ export interface components { providerName: "AZURE"; }; /** @description Details that describe the Atlas Data Lakes linked to this Amazon Web Services (AWS) Identity and Access Management (IAM) role. */ - CloudProviderAccessDataLakeFeatureUsage: Omit< - components["schemas"]["CloudProviderAccessFeatureUsage"], - "featureType" - > & { + CloudProviderAccessDataLakeFeatureUsage: Omit & { featureId?: components["schemas"]["CloudProviderAccessFeatureUsageDataLakeFeatureId"]; } & { /** @@ -1979,10 +1507,7 @@ export interface components { featureType: "ATLAS_DATA_LAKE"; }; /** @description Details that describe the Key Management Service (KMS) linked to this Amazon Web Services (AWS) Identity and Access Management (IAM) role. */ - CloudProviderAccessEncryptionAtRestFeatureUsage: Omit< - components["schemas"]["CloudProviderAccessFeatureUsage"], - "featureType" - > & { + CloudProviderAccessEncryptionAtRestFeatureUsage: Omit & { featureId?: components["schemas"]["ApiAtlasCloudProviderAccessFeatureUsageFeatureIdView"]; } & { /** @@ -1992,10 +1517,7 @@ export interface components { featureType: "ENCRYPTION_AT_REST"; }; /** @description Details that describe the Amazon Web Services (AWS) Simple Storage Service (S3) export buckets linked to this AWS Identity and Access Management (IAM) role. */ - CloudProviderAccessExportSnapshotFeatureUsage: Omit< - components["schemas"]["CloudProviderAccessFeatureUsage"], - "featureType" - > & { + CloudProviderAccessExportSnapshotFeatureUsage: Omit & { featureId?: components["schemas"]["CloudProviderAccessFeatureUsageExportSnapshotFeatureId"]; } & { /** @@ -2010,11 +1532,7 @@ export interface components { * @description Human-readable label that describes one MongoDB Cloud feature linked to this Amazon Web Services (AWS) Identity and Access Management (IAM) role. * @enum {string} */ - readonly featureType?: - | "ATLAS_DATA_LAKE" - | "ENCRYPTION_AT_REST" - | "EXPORT_SNAPSHOT" - | "PUSH_BASED_LOG_EXPORT"; + readonly featureType?: "ATLAS_DATA_LAKE" | "ENCRYPTION_AT_REST" | "EXPORT_SNAPSHOT" | "PUSH_BASED_LOG_EXPORT"; }; /** @description Identifying characteristics about the data lake linked to this Amazon Web Services (AWS) Identity and Access Management (IAM) role. */ CloudProviderAccessFeatureUsageDataLakeFeatureId: { @@ -2050,10 +1568,7 @@ export interface components { readonly groupId?: string; }; /** @description Details that describe the features linked to the GCP Service Account. */ - CloudProviderAccessGCPServiceAccount: Omit< - WithRequired, - "providerName" - > & { + CloudProviderAccessGCPServiceAccount: Omit, "providerName"> & { /** * Format: date-time * @description Date and time when this Google Service Account was created. This parameter expresses its value in the ISO 8601 timestamp format in UTC. @@ -2076,10 +1591,7 @@ export interface components { providerName: "GCP"; }; /** @description Details that describe the features linked to the GCP Service Account. */ - CloudProviderAccessGCPServiceAccountRequestUpdate: Omit< - WithRequired, - "providerName" - > & { + CloudProviderAccessGCPServiceAccountRequestUpdate: Omit, "providerName"> & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} @@ -2087,10 +1599,7 @@ export interface components { providerName: "GCP"; }; /** @description Details that describe the Amazon Web Services (AWS) Simple Storage Service (S3) export buckets linked to this AWS Identity and Access Management (IAM) role. */ - CloudProviderAccessPushBasedLogExportFeatureUsage: Omit< - components["schemas"]["CloudProviderAccessFeatureUsage"], - "featureType" - > & { + CloudProviderAccessPushBasedLogExportFeatureUsage: Omit & { featureId?: components["schemas"]["CloudProviderAccessFeatureUsagePushBasedLogExportFeatureId"]; } & { /** @@ -2133,11 +1642,7 @@ export interface components { providerName?: "AWS" | "GCP" | "AZURE" | "TENANT" | "SERVERLESS"; /** @description Flag that indicates whether MongoDB Cloud clusters exist in the specified network peering container. */ readonly provisioned?: boolean; - } & ( - | components["schemas"]["AzureCloudProviderContainer"] - | components["schemas"]["GCPCloudProviderContainer"] - | components["schemas"]["AWSCloudProviderContainer"] - ); + } & (components["schemas"]["AzureCloudProviderContainer"] | components["schemas"]["GCPCloudProviderContainer"] | components["schemas"]["AWSCloudProviderContainer"]); /** @description Range of instance sizes to which your cluster can scale. */ CloudProviderGCPAutoScaling: { compute?: components["schemas"]["GCPComputeAutoScaling"]; @@ -2161,155 +1666,8 @@ export interface components { */ providerName?: "AWS" | "AZURE" | "GCP" | "TENANT"; /** @description Physical location of your MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. The region name is only returned in the response for single-region clusters. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. It assigns the VPC a Classless Inter-Domain Routing (CIDR) block. To limit a new VPC peering connection to one Classless Inter-Domain Routing (CIDR) block and region, create the connection first. Deploy the cluster after the connection starts. GCP Clusters and Multi-region clusters require one VPC peering connection for each region. MongoDB nodes can use only the peering connection that resides in the same region as the nodes to communicate with the peered VPC. */ - regionName?: - | ( - | "US_GOV_WEST_1" - | "US_GOV_EAST_1" - | "US_EAST_1" - | "US_EAST_2" - | "US_WEST_1" - | "US_WEST_2" - | "CA_CENTRAL_1" - | "EU_NORTH_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_WEST_3" - | "EU_CENTRAL_1" - | "EU_CENTRAL_2" - | "AP_EAST_1" - | "AP_NORTHEAST_1" - | "AP_NORTHEAST_2" - | "AP_NORTHEAST_3" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2" - | "AP_SOUTHEAST_3" - | "AP_SOUTHEAST_4" - | "AP_SOUTH_1" - | "AP_SOUTH_2" - | "SA_EAST_1" - | "CN_NORTH_1" - | "CN_NORTHWEST_1" - | "ME_SOUTH_1" - | "ME_CENTRAL_1" - | "AF_SOUTH_1" - | "EU_SOUTH_1" - | "EU_SOUTH_2" - | "IL_CENTRAL_1" - | "CA_WEST_1" - | "AP_SOUTHEAST_5" - | "AP_SOUTHEAST_7" - | "MX_CENTRAL_1" - | "GLOBAL" - ) - | ( - | "US_CENTRAL" - | "US_EAST" - - | "US_NORTH_CENTRAL" - | "US_WEST" - | "US_SOUTH_CENTRAL" - | "EUROPE_NORTH" - | "EUROPE_WEST" - | "US_WEST_CENTRAL" - - | "US_WEST_3" - | "CANADA_EAST" - | "CANADA_CENTRAL" - | "BRAZIL_SOUTH" - | "BRAZIL_SOUTHEAST" - | "AUSTRALIA_CENTRAL" - | "AUSTRALIA_CENTRAL_2" - | "AUSTRALIA_EAST" - | "AUSTRALIA_SOUTH_EAST" - | "GERMANY_CENTRAL" - | "GERMANY_NORTH_EAST" - | "GERMANY_WEST_CENTRAL" - | "GERMANY_NORTH" - | "SWEDEN_CENTRAL" - | "SWEDEN_SOUTH" - | "SWITZERLAND_NORTH" - | "SWITZERLAND_WEST" - | "UK_SOUTH" - | "UK_WEST" - | "NORWAY_EAST" - | "NORWAY_WEST" - | "INDIA_CENTRAL" - | "INDIA_SOUTH" - | "INDIA_WEST" - | "CHINA_EAST" - | "CHINA_NORTH" - | "ASIA_EAST" - | "JAPAN_EAST" - | "JAPAN_WEST" - | "ASIA_SOUTH_EAST" - | "KOREA_CENTRAL" - | "KOREA_SOUTH" - | "FRANCE_CENTRAL" - | "FRANCE_SOUTH" - | "SOUTH_AFRICA_NORTH" - | "SOUTH_AFRICA_WEST" - | "UAE_CENTRAL" - | "UAE_NORTH" - | "QATAR_CENTRAL" - ) - | ( - | "EASTERN_US" - | "EASTERN_US_AW" - | "US_EAST_4" - | "US_EAST_4_AW" - | "US_EAST_5" - | "US_EAST_5_AW" - - | "US_WEST_2_AW" - - | "US_WEST_3_AW" - | "US_WEST_4" - | "US_WEST_4_AW" - | "US_SOUTH_1" - | "US_SOUTH_1_AW" - | "CENTRAL_US" - | "CENTRAL_US_AW" - | "WESTERN_US" - | "WESTERN_US_AW" - | "NORTH_AMERICA_NORTHEAST_1" - | "NORTH_AMERICA_NORTHEAST_2" - | "NORTH_AMERICA_SOUTH_1" - | "SOUTH_AMERICA_EAST_1" - | "SOUTH_AMERICA_WEST_1" - | "WESTERN_EUROPE" - | "EUROPE_NORTH_1" - | "EUROPE_WEST_2" - | "EUROPE_WEST_3" - | "EUROPE_WEST_4" - | "EUROPE_WEST_6" - | "EUROPE_WEST_8" - | "EUROPE_WEST_9" - | "EUROPE_WEST_10" - | "EUROPE_WEST_12" - | "EUROPE_SOUTHWEST_1" - | "EUROPE_CENTRAL_2" - | "MIDDLE_EAST_CENTRAL_1" - | "MIDDLE_EAST_CENTRAL_2" - | "MIDDLE_EAST_WEST_1" - | "AUSTRALIA_SOUTHEAST_1" - | "AUSTRALIA_SOUTHEAST_2" - | "AFRICA_SOUTH_1" - | "EASTERN_ASIA_PACIFIC" - | "NORTHEASTERN_ASIA_PACIFIC" - | "SOUTHEASTERN_ASIA_PACIFIC" - | "ASIA_EAST_2" - | "ASIA_NORTHEAST_2" - | "ASIA_NORTHEAST_3" - | "ASIA_SOUTH_1" - | "ASIA_SOUTH_2" - | "ASIA_SOUTHEAST_2" - ); - } & ( - | components["schemas"]["AWSRegionConfig"] - | components["schemas"]["AzureRegionConfig"] - | components["schemas"]["GCPRegionConfig"] - | components["schemas"]["TenantRegionConfig"] - ); + regionName?: ("US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL") | ("US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL") | ("EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"); + } & (components["schemas"]["AWSRegionConfig"] | components["schemas"]["AzureRegionConfig"] | components["schemas"]["GCPRegionConfig"] | components["schemas"]["TenantRegionConfig"]); /** * Cloud Service Provider Settings * @description Cloud service provider on which MongoDB Cloud provisions the hosts. @@ -2329,155 +1687,8 @@ export interface components { */ providerName?: "AWS" | "AZURE" | "GCP" | "TENANT"; /** @description Physical location of your MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. The region name is only returned in the response for single-region clusters. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. It assigns the VPC a Classless Inter-Domain Routing (CIDR) block. To limit a new VPC peering connection to one Classless Inter-Domain Routing (CIDR) block and region, create the connection first. Deploy the cluster after the connection starts. GCP Clusters and Multi-region clusters require one VPC peering connection for each region. MongoDB nodes can use only the peering connection that resides in the same region as the nodes to communicate with the peered VPC. */ - regionName?: - | ( - | "US_GOV_WEST_1" - | "US_GOV_EAST_1" - | "US_EAST_1" - | "US_EAST_2" - | "US_WEST_1" - | "US_WEST_2" - | "CA_CENTRAL_1" - | "EU_NORTH_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_WEST_3" - | "EU_CENTRAL_1" - | "EU_CENTRAL_2" - | "AP_EAST_1" - | "AP_NORTHEAST_1" - | "AP_NORTHEAST_2" - | "AP_NORTHEAST_3" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2" - | "AP_SOUTHEAST_3" - | "AP_SOUTHEAST_4" - | "AP_SOUTH_1" - | "AP_SOUTH_2" - | "SA_EAST_1" - | "CN_NORTH_1" - | "CN_NORTHWEST_1" - | "ME_SOUTH_1" - | "ME_CENTRAL_1" - | "AF_SOUTH_1" - | "EU_SOUTH_1" - | "EU_SOUTH_2" - | "IL_CENTRAL_1" - | "CA_WEST_1" - | "AP_SOUTHEAST_5" - | "AP_SOUTHEAST_7" - | "MX_CENTRAL_1" - | "GLOBAL" - ) - | ( - | "US_CENTRAL" - | "US_EAST" - - | "US_NORTH_CENTRAL" - | "US_WEST" - | "US_SOUTH_CENTRAL" - | "EUROPE_NORTH" - | "EUROPE_WEST" - | "US_WEST_CENTRAL" - - | "US_WEST_3" - | "CANADA_EAST" - | "CANADA_CENTRAL" - | "BRAZIL_SOUTH" - | "BRAZIL_SOUTHEAST" - | "AUSTRALIA_CENTRAL" - | "AUSTRALIA_CENTRAL_2" - | "AUSTRALIA_EAST" - | "AUSTRALIA_SOUTH_EAST" - | "GERMANY_CENTRAL" - | "GERMANY_NORTH_EAST" - | "GERMANY_WEST_CENTRAL" - | "GERMANY_NORTH" - | "SWEDEN_CENTRAL" - | "SWEDEN_SOUTH" - | "SWITZERLAND_NORTH" - | "SWITZERLAND_WEST" - | "UK_SOUTH" - | "UK_WEST" - | "NORWAY_EAST" - | "NORWAY_WEST" - | "INDIA_CENTRAL" - | "INDIA_SOUTH" - | "INDIA_WEST" - | "CHINA_EAST" - | "CHINA_NORTH" - | "ASIA_EAST" - | "JAPAN_EAST" - | "JAPAN_WEST" - | "ASIA_SOUTH_EAST" - | "KOREA_CENTRAL" - | "KOREA_SOUTH" - | "FRANCE_CENTRAL" - | "FRANCE_SOUTH" - | "SOUTH_AFRICA_NORTH" - | "SOUTH_AFRICA_WEST" - | "UAE_CENTRAL" - | "UAE_NORTH" - | "QATAR_CENTRAL" - ) - | ( - | "EASTERN_US" - | "EASTERN_US_AW" - | "US_EAST_4" - | "US_EAST_4_AW" - | "US_EAST_5" - | "US_EAST_5_AW" - - | "US_WEST_2_AW" - - | "US_WEST_3_AW" - | "US_WEST_4" - | "US_WEST_4_AW" - | "US_SOUTH_1" - | "US_SOUTH_1_AW" - | "CENTRAL_US" - | "CENTRAL_US_AW" - | "WESTERN_US" - | "WESTERN_US_AW" - | "NORTH_AMERICA_NORTHEAST_1" - | "NORTH_AMERICA_NORTHEAST_2" - | "NORTH_AMERICA_SOUTH_1" - | "SOUTH_AMERICA_EAST_1" - | "SOUTH_AMERICA_WEST_1" - | "WESTERN_EUROPE" - | "EUROPE_NORTH_1" - | "EUROPE_WEST_2" - | "EUROPE_WEST_3" - | "EUROPE_WEST_4" - | "EUROPE_WEST_6" - | "EUROPE_WEST_8" - | "EUROPE_WEST_9" - | "EUROPE_WEST_10" - | "EUROPE_WEST_12" - | "EUROPE_SOUTHWEST_1" - | "EUROPE_CENTRAL_2" - | "MIDDLE_EAST_CENTRAL_1" - | "MIDDLE_EAST_CENTRAL_2" - | "MIDDLE_EAST_WEST_1" - | "AUSTRALIA_SOUTHEAST_1" - | "AUSTRALIA_SOUTHEAST_2" - | "AFRICA_SOUTH_1" - | "EASTERN_ASIA_PACIFIC" - | "NORTHEASTERN_ASIA_PACIFIC" - | "SOUTHEASTERN_ASIA_PACIFIC" - | "ASIA_EAST_2" - | "ASIA_NORTHEAST_2" - | "ASIA_NORTHEAST_3" - | "ASIA_SOUTH_1" - | "ASIA_SOUTH_2" - | "ASIA_SOUTHEAST_2" - ); - } & ( - | components["schemas"]["AWSRegionConfig20240805"] - | components["schemas"]["AzureRegionConfig20240805"] - | components["schemas"]["GCPRegionConfig20240805"] - | components["schemas"]["TenantRegionConfig20240805"] - ); + regionName?: ("US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "AP_SOUTHEAST_5" | "AP_SOUTHEAST_7" | "MX_CENTRAL_1" | "GLOBAL") | ("US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL") | ("EASTERN_US" | "EASTERN_US_AW" | "US_EAST_4" | "US_EAST_4_AW" | "US_EAST_5" | "US_EAST_5_AW" | "US_WEST_2" | "US_WEST_2_AW" | "US_WEST_3" | "US_WEST_3_AW" | "US_WEST_4" | "US_WEST_4_AW" | "US_SOUTH_1" | "US_SOUTH_1_AW" | "CENTRAL_US" | "CENTRAL_US_AW" | "WESTERN_US" | "WESTERN_US_AW" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "WESTERN_EUROPE" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_8" | "EUROPE_WEST_9" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "EUROPE_SOUTHWEST_1" | "EUROPE_CENTRAL_2" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "AFRICA_SOUTH_1" | "EASTERN_ASIA_PACIFIC" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTHEASTERN_ASIA_PACIFIC" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2"); + } & (components["schemas"]["AWSRegionConfig20240805"] | components["schemas"]["AzureRegionConfig20240805"] | components["schemas"]["GCPRegionConfig20240805"] | components["schemas"]["TenantRegionConfig20240805"]); /** * Cluster Connection Strings * @description Collection of Uniform Resource Locators that point to the MongoDB database. @@ -2702,7 +1913,13 @@ export interface components { * @enum {string} */ providerName: "FLEX"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "FLEX"; + }; /** @description Range of instance sizes to which your cluster can scale. */ ClusterFreeAutoScaling: { compute?: components["schemas"]["FreeComputeAutoScalingRules"]; @@ -2735,20 +1952,20 @@ export interface components { * @enum {string} */ providerName: "TENANT"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "TENANT"; + }; /** * Cloud Service Provider Settings for a Cluster * @description Group of cloud provider settings that configure the provisioned MongoDB hosts. */ ClusterProviderSettings: { providerName: string; - } & ( - | components["schemas"]["AWSCloudProviderSettings"] - | components["schemas"]["AzureCloudProviderSettings"] - | components["schemas"]["CloudGCPProviderSettings"] - | components["schemas"]["ClusterFreeProviderSettings"] - | components["schemas"]["ClusterFlexProviderSettings"] - ); + } & (components["schemas"]["AWSCloudProviderSettings"] | components["schemas"]["AzureCloudProviderSettings"] | components["schemas"]["CloudGCPProviderSettings"] | components["schemas"]["ClusterFreeProviderSettings"] | components["schemas"]["ClusterFlexProviderSettings"]); ClusterSearchIndex: { /** @description Human-readable label that identifies the collection that contains one or more Atlas Search indexes. */ collectionName: string; @@ -2826,10 +2043,7 @@ export interface components { */ cloudProvider?: "AWS" | "AZURE" | "GCP"; }; - CreateEndpointRequest: - | components["schemas"]["CreateAWSEndpointRequest"] - | components["schemas"]["CreateAzureEndpointRequest"] - | components["schemas"]["CreateGCPEndpointGroupRequest"]; + CreateEndpointRequest: components["schemas"]["CreateAWSEndpointRequest"] | components["schemas"]["CreateAzureEndpointRequest"] | components["schemas"]["CreateGCPEndpointGroupRequest"]; /** * GCP * @description Group of Private Endpoint settings. @@ -2941,7 +2155,13 @@ export interface components { * @enum {string} */ type: "DAILY"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "DAILY"; + }; DataLakeAtlasStoreInstance: Omit & { /** @description Human-readable label of the MongoDB Cloud cluster on which the store is based. */ clusterName?: string; @@ -2955,7 +2175,13 @@ export interface components { * @enum {string} */ provider: "atlas"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "atlas"; + }; /** @description MongoDB Cloud cluster read concern, which determines the consistency and isolation properties of the data read from an Atlas cluster. */ DataLakeAtlasStoreReadConcern: { /** @@ -3002,56 +2228,7 @@ export interface components { * @description Microsoft Azure Regions. * @enum {string} */ - region?: - | "US_CENTRAL" - | "US_EAST" - | "US_EAST_2" - | "US_NORTH_CENTRAL" - | "US_WEST" - | "US_SOUTH_CENTRAL" - | "EUROPE_NORTH" - | "EUROPE_WEST" - | "US_WEST_CENTRAL" - | "US_WEST_2" - | "US_WEST_3" - | "CANADA_EAST" - | "CANADA_CENTRAL" - | "BRAZIL_SOUTH" - | "BRAZIL_SOUTHEAST" - | "AUSTRALIA_CENTRAL" - | "AUSTRALIA_CENTRAL_2" - | "AUSTRALIA_EAST" - | "AUSTRALIA_SOUTH_EAST" - | "GERMANY_CENTRAL" - | "GERMANY_NORTH_EAST" - | "GERMANY_WEST_CENTRAL" - | "GERMANY_NORTH" - | "SWEDEN_CENTRAL" - | "SWEDEN_SOUTH" - | "SWITZERLAND_NORTH" - | "SWITZERLAND_WEST" - | "UK_SOUTH" - | "UK_WEST" - | "NORWAY_EAST" - | "NORWAY_WEST" - | "INDIA_CENTRAL" - | "INDIA_SOUTH" - | "INDIA_WEST" - | "CHINA_EAST" - | "CHINA_NORTH" - | "ASIA_EAST" - | "JAPAN_EAST" - | "JAPAN_WEST" - | "ASIA_SOUTH_EAST" - | "KOREA_CENTRAL" - | "KOREA_SOUTH" - | "FRANCE_CENTRAL" - | "FRANCE_SOUTH" - | "SOUTH_AFRICA_NORTH" - | "SOUTH_AFRICA_WEST" - | "UAE_CENTRAL" - | "UAE_NORTH" - | "QATAR_CENTRAL"; + region?: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL"; /** @description Replacement Delimiter. */ replacementDelimiter?: string; /** @description Service URL. */ @@ -3062,168 +2239,73 @@ export interface components { * @enum {string} */ provider: "azure"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "azure"; + }; DataLakeDLSAWSStore: Omit & { /** * AWS Regions * @description Physical location where MongoDB Cloud deploys your AWS-hosted MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. MongoDB Cloud assigns the VPC a CIDR block. To limit a new VPC peering connection to one CIDR block and region, create the connection first. Deploy the cluster after the connection starts. * @enum {string} */ - region?: - | "US_GOV_WEST_1" - | "US_GOV_EAST_1" - | "US_EAST_1" - | "US_EAST_2" - | "US_WEST_1" - | "US_WEST_2" - | "CA_CENTRAL_1" - | "EU_NORTH_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_WEST_3" - | "EU_CENTRAL_1" - | "EU_CENTRAL_2" - | "AP_EAST_1" - | "AP_NORTHEAST_1" - | "AP_NORTHEAST_2" - | "AP_NORTHEAST_3" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2" - | "AP_SOUTHEAST_3" - | "AP_SOUTHEAST_4" - | "AP_SOUTH_1" - | "AP_SOUTH_2" - | "SA_EAST_1" - | "CN_NORTH_1" - | "CN_NORTHWEST_1" - | "ME_SOUTH_1" - | "ME_CENTRAL_1" - | "AF_SOUTH_1" - | "EU_SOUTH_1" - | "EU_SOUTH_2" - | "IL_CENTRAL_1" - | "CA_WEST_1" - | "GLOBAL"; + region?: "US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "GLOBAL"; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "dls:aws"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ provider: "dls:aws"; - } ; + }; DataLakeDLSAzureStore: Omit & { /** * Azure Regions * @description Microsoft Azure Regions. * @enum {string} */ - region?: - | "US_CENTRAL" - | "US_EAST" - | "US_EAST_2" - | "US_NORTH_CENTRAL" - | "US_WEST" - | "US_SOUTH_CENTRAL" - | "EUROPE_NORTH" - | "EUROPE_WEST" - | "US_WEST_CENTRAL" - | "US_WEST_2" - | "US_WEST_3" - | "CANADA_EAST" - | "CANADA_CENTRAL" - | "BRAZIL_SOUTH" - | "BRAZIL_SOUTHEAST" - | "AUSTRALIA_CENTRAL" - | "AUSTRALIA_CENTRAL_2" - | "AUSTRALIA_EAST" - | "AUSTRALIA_SOUTH_EAST" - | "GERMANY_CENTRAL" - | "GERMANY_NORTH_EAST" - | "GERMANY_WEST_CENTRAL" - | "GERMANY_NORTH" - | "SWEDEN_CENTRAL" - | "SWEDEN_SOUTH" - | "SWITZERLAND_NORTH" - | "SWITZERLAND_WEST" - | "UK_SOUTH" - | "UK_WEST" - | "NORWAY_EAST" - | "NORWAY_WEST" - | "INDIA_CENTRAL" - | "INDIA_SOUTH" - | "INDIA_WEST" - | "CHINA_EAST" - | "CHINA_NORTH" - | "ASIA_EAST" - | "JAPAN_EAST" - | "JAPAN_WEST" - | "ASIA_SOUTH_EAST" - | "KOREA_CENTRAL" - | "KOREA_SOUTH" - | "FRANCE_CENTRAL" - | "FRANCE_SOUTH" - | "SOUTH_AFRICA_NORTH" - | "SOUTH_AFRICA_WEST" - | "UAE_CENTRAL" - | "UAE_NORTH" - | "QATAR_CENTRAL"; + region?: "US_CENTRAL" | "US_EAST" | "US_EAST_2" | "US_NORTH_CENTRAL" | "US_WEST" | "US_SOUTH_CENTRAL" | "EUROPE_NORTH" | "EUROPE_WEST" | "US_WEST_CENTRAL" | "US_WEST_2" | "US_WEST_3" | "CANADA_EAST" | "CANADA_CENTRAL" | "BRAZIL_SOUTH" | "BRAZIL_SOUTHEAST" | "AUSTRALIA_CENTRAL" | "AUSTRALIA_CENTRAL_2" | "AUSTRALIA_EAST" | "AUSTRALIA_SOUTH_EAST" | "GERMANY_CENTRAL" | "GERMANY_NORTH_EAST" | "GERMANY_WEST_CENTRAL" | "GERMANY_NORTH" | "SWEDEN_CENTRAL" | "SWEDEN_SOUTH" | "SWITZERLAND_NORTH" | "SWITZERLAND_WEST" | "UK_SOUTH" | "UK_WEST" | "NORWAY_EAST" | "NORWAY_WEST" | "INDIA_CENTRAL" | "INDIA_SOUTH" | "INDIA_WEST" | "CHINA_EAST" | "CHINA_NORTH" | "ASIA_EAST" | "JAPAN_EAST" | "JAPAN_WEST" | "ASIA_SOUTH_EAST" | "KOREA_CENTRAL" | "KOREA_SOUTH" | "FRANCE_CENTRAL" | "FRANCE_SOUTH" | "SOUTH_AFRICA_NORTH" | "SOUTH_AFRICA_WEST" | "UAE_CENTRAL" | "UAE_NORTH" | "QATAR_CENTRAL"; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "dls:azure"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ provider: "dls:azure"; - } ; + }; DataLakeDLSGCPStore: Omit & { /** * GCP Regions * @description Google Cloud Platform Regions. * @enum {string} */ - region?: - | "ASIA_EAST_2" - | "ASIA_NORTHEAST_2" - | "ASIA_NORTHEAST_3" - | "ASIA_SOUTH_1" - | "ASIA_SOUTH_2" - | "ASIA_SOUTHEAST_2" - | "AUSTRALIA_SOUTHEAST_1" - | "AUSTRALIA_SOUTHEAST_2" - | "CENTRAL_US" - | "EASTERN_ASIA_PACIFIC" - | "EASTERN_US" - | "EUROPE_CENTRAL_2" - | "EUROPE_NORTH_1" - | "EUROPE_WEST_2" - | "EUROPE_WEST_3" - | "EUROPE_WEST_4" - | "EUROPE_WEST_6" - | "EUROPE_WEST_10" - | "EUROPE_WEST_12" - | "MIDDLE_EAST_CENTRAL_1" - | "MIDDLE_EAST_CENTRAL_2" - | "MIDDLE_EAST_WEST_1" - | "NORTH_AMERICA_NORTHEAST_1" - | "NORTH_AMERICA_NORTHEAST_2" - | "NORTHEASTERN_ASIA_PACIFIC" - | "SOUTH_AMERICA_EAST_1" - | "SOUTH_AMERICA_WEST_1" - | "SOUTHEASTERN_ASIA_PACIFIC" - | "US_EAST_4" - | "US_EAST_5" - | "US_WEST_2" - | "US_WEST_3" - | "US_WEST_4" - | "US_SOUTH_1" - | "WESTERN_EUROPE" - | "WESTERN_US"; + region?: "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "CENTRAL_US" | "EASTERN_ASIA_PACIFIC" | "EASTERN_US" | "EUROPE_CENTRAL_2" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "SOUTHEASTERN_ASIA_PACIFIC" | "US_EAST_4" | "US_EAST_5" | "US_WEST_2" | "US_WEST_3" | "US_WEST_4" | "US_SOUTH_1" | "WESTERN_EUROPE" | "WESTERN_US"; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "dls:gcp"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ provider: "dls:gcp"; - } ; + }; DataLakeGoogleCloudStorageStore: Omit & { /** @description Human-readable label that identifies the Google Cloud Storage bucket. */ bucket?: string; @@ -3241,43 +2323,7 @@ export interface components { * @description Google Cloud Platform Regions. * @enum {string} */ - region?: - | "ASIA_EAST_2" - | "ASIA_NORTHEAST_2" - | "ASIA_NORTHEAST_3" - | "ASIA_SOUTH_1" - | "ASIA_SOUTH_2" - | "ASIA_SOUTHEAST_2" - | "AUSTRALIA_SOUTHEAST_1" - | "AUSTRALIA_SOUTHEAST_2" - | "CENTRAL_US" - | "EASTERN_ASIA_PACIFIC" - | "EASTERN_US" - | "EUROPE_CENTRAL_2" - | "EUROPE_NORTH_1" - | "EUROPE_WEST_2" - | "EUROPE_WEST_3" - | "EUROPE_WEST_4" - | "EUROPE_WEST_6" - | "EUROPE_WEST_10" - | "EUROPE_WEST_12" - | "MIDDLE_EAST_CENTRAL_1" - | "MIDDLE_EAST_CENTRAL_2" - | "MIDDLE_EAST_WEST_1" - | "NORTH_AMERICA_NORTHEAST_1" - | "NORTH_AMERICA_NORTHEAST_2" - | "NORTHEASTERN_ASIA_PACIFIC" - | "SOUTH_AMERICA_EAST_1" - | "SOUTH_AMERICA_WEST_1" - | "SOUTHEASTERN_ASIA_PACIFIC" - | "US_EAST_4" - | "US_EAST_5" - | "US_WEST_2" - | "US_WEST_3" - | "US_WEST_4" - | "US_SOUTH_1" - | "WESTERN_EUROPE" - | "WESTERN_US"; + region?: "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "CENTRAL_US" | "EASTERN_ASIA_PACIFIC" | "EASTERN_US" | "EUROPE_CENTRAL_2" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "SOUTHEASTERN_ASIA_PACIFIC" | "US_EAST_4" | "US_EAST_5" | "US_WEST_2" | "US_WEST_3" | "US_WEST_4" | "US_SOUTH_1" | "WESTERN_EUROPE" | "WESTERN_US"; /** @description Replacement Delimiter. */ replacementDelimiter?: string; } & { @@ -3286,7 +2332,13 @@ export interface components { * @enum {string} */ provider: "gcs"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "gcs"; + }; DataLakeHTTPStore: Omit & { /** * @description Flag that validates the scheme in the specified URLs. If `true`, allows insecure `HTTP` scheme, doesn't verify the server's certificate chain and hostname, and accepts any certificate with any hostname presented by the server. If `false`, allows secure `HTTPS` scheme only. @@ -3303,7 +2355,13 @@ export interface components { * @enum {string} */ provider: "http"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "http"; + }; /** * Partition Field * @description Partition Field in the Data Lake Storage provider for a Data Lake Pipeline. @@ -3342,63 +2400,26 @@ export interface components { * @description Physical location where MongoDB Cloud deploys your AWS-hosted MongoDB cluster nodes. The region you choose can affect network latency for clients accessing your databases. When MongoDB Cloud deploys a dedicated cluster, it checks if a VPC or VPC connection exists for that provider and region. If not, MongoDB Cloud creates them as part of the deployment. MongoDB Cloud assigns the VPC a CIDR block. To limit a new VPC peering connection to one CIDR block and region, create the connection first. Deploy the cluster after the connection starts. * @enum {string} */ - region?: - | "US_GOV_WEST_1" - | "US_GOV_EAST_1" - | "US_EAST_1" - | "US_EAST_2" - | "US_WEST_1" - | "US_WEST_2" - | "CA_CENTRAL_1" - | "EU_NORTH_1" - | "EU_WEST_1" - | "EU_WEST_2" - | "EU_WEST_3" - | "EU_CENTRAL_1" - | "EU_CENTRAL_2" - | "AP_EAST_1" - | "AP_NORTHEAST_1" - | "AP_NORTHEAST_2" - | "AP_NORTHEAST_3" - | "AP_SOUTHEAST_1" - | "AP_SOUTHEAST_2" - | "AP_SOUTHEAST_3" - | "AP_SOUTHEAST_4" - | "AP_SOUTH_1" - | "AP_SOUTH_2" - | "SA_EAST_1" - | "CN_NORTH_1" - | "CN_NORTHWEST_1" - | "ME_SOUTH_1" - | "ME_CENTRAL_1" - | "AF_SOUTH_1" - | "EU_SOUTH_1" - | "EU_SOUTH_2" - | "IL_CENTRAL_1" - | "CA_WEST_1" - | "GLOBAL"; + region?: "US_GOV_WEST_1" | "US_GOV_EAST_1" | "US_EAST_1" | "US_EAST_2" | "US_WEST_1" | "US_WEST_2" | "CA_CENTRAL_1" | "EU_NORTH_1" | "EU_WEST_1" | "EU_WEST_2" | "EU_WEST_3" | "EU_CENTRAL_1" | "EU_CENTRAL_2" | "AP_EAST_1" | "AP_NORTHEAST_1" | "AP_NORTHEAST_2" | "AP_NORTHEAST_3" | "AP_SOUTHEAST_1" | "AP_SOUTHEAST_2" | "AP_SOUTHEAST_3" | "AP_SOUTHEAST_4" | "AP_SOUTH_1" | "AP_SOUTH_2" | "SA_EAST_1" | "CN_NORTH_1" | "CN_NORTHWEST_1" | "ME_SOUTH_1" | "ME_CENTRAL_1" | "AF_SOUTH_1" | "EU_SOUTH_1" | "EU_SOUTH_2" | "IL_CENTRAL_1" | "CA_WEST_1" | "GLOBAL"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ provider: "s3"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + provider: "s3"; + }; /** @description Group of settings that define where the data is stored. */ DataLakeStoreSettings: { /** @description Human-readable label that identifies the data store. The **databases.[n].collections.[n].dataSources.[n].storeName** field references this values as part of the mapping configuration. To use MongoDB Cloud as a data store, the data lake requires a serverless instance or an `M10` or higher cluster. */ name?: string; provider: string; - } & ( - | components["schemas"]["DataLakeS3StoreSettings"] - | components["schemas"]["DataLakeDLSAWSStore"] - | components["schemas"]["DataLakeDLSAzureStore"] - | components["schemas"]["DataLakeDLSGCPStore"] - | components["schemas"]["DataLakeAtlasStoreInstance"] - | components["schemas"]["DataLakeHTTPStore"] - | components["schemas"]["DataLakeAzureBlobStore"] - | components["schemas"]["DataLakeGoogleCloudStorageStore"] - ); + } & (components["schemas"]["DataLakeS3StoreSettings"] | components["schemas"]["DataLakeDLSAWSStore"] | components["schemas"]["DataLakeDLSAzureStore"] | components["schemas"]["DataLakeDLSGCPStore"] | components["schemas"]["DataLakeAtlasStoreInstance"] | components["schemas"]["DataLakeHTTPStore"] | components["schemas"]["DataLakeAzureBlobStore"] | components["schemas"]["DataLakeGoogleCloudStorageStore"]); /** @description Settings to configure the region where you wish to store your archived data. */ DataProcessRegionView: { /** @@ -3420,18 +2441,7 @@ export interface components { * @description Human-readable label that identifies a group of privileges assigned to a database user. This value can either be a built-in role or a custom role. * @enum {string} */ - roleName: - | "atlasAdmin" - | "backup" - | "clusterMonitor" - | "dbAdmin" - | "dbAdminAnyDatabase" - | "enableSharding" - | "read" - | "readAnyDatabase" - | "readWrite" - | "readWriteAnyDatabase" - | ""; + roleName: "atlasAdmin" | "backup" | "clusterMonitor" | "dbAdmin" | "dbAdminAnyDatabase" | "enableSharding" | "read" | "readAnyDatabase" | "readWrite" | "readWriteAnyDatabase" | ""; }; /** * Archival Criteria @@ -3466,11 +2476,7 @@ export interface components { * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. */ nodeCount?: number; - } & ( - | components["schemas"]["AWSHardwareSpec"] - | components["schemas"]["AzureHardwareSpec"] - | components["schemas"]["GCPHardwareSpec"] - ); + } & (components["schemas"]["AWSHardwareSpec"] | components["schemas"]["AzureHardwareSpec"] | components["schemas"]["GCPHardwareSpec"]); /** @description Hardware specifications for read-only nodes in the region. Read-only nodes can never become the primary member, but can enable local reads. If you don't specify this parameter, no read-only nodes are deployed to the region. */ DedicatedHardwareSpec20240805: { /** @@ -3495,22 +2501,21 @@ export interface components { * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. */ nodeCount?: number; - } & ( - | components["schemas"]["AWSHardwareSpec20240805"] - | components["schemas"]["AzureHardwareSpec20240805"] - | components["schemas"]["GCPHardwareSpec20240805"] - ); + } & (components["schemas"]["AWSHardwareSpec20240805"] | components["schemas"]["AzureHardwareSpec20240805"] | components["schemas"]["GCPHardwareSpec20240805"]); DefaultScheduleView: Omit, "type"> & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ type: "DEFAULT"; - } ; - DiskBackupSnapshotAWSExportBucketRequest: Omit< - WithRequired, - "cloudProvider" - > & { + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "DEFAULT"; + }; + DiskBackupSnapshotAWSExportBucketRequest: Omit, "cloudProvider"> & { /** * @description Human-readable label that identifies the AWS S3 Bucket that the role is authorized to export to. * @example export-bucket @@ -3552,10 +2557,7 @@ export interface components { /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ readonly links?: components["schemas"]["Link"][]; }; - DiskBackupSnapshotAzureExportBucketRequest: Omit< - WithRequired, - "cloudProvider" - > & { + DiskBackupSnapshotAzureExportBucketRequest: Omit, "cloudProvider"> & { /** * @description The name of the Azure Storage Container to export to. This can be omitted and computed from the serviceUrl if the serviceUrl includes a Azure Storage Container name. For example a serviceUrl of "https://examplestorageaccount.blob.core.windows.net/exportcontainer" will yield a computed bucketName of "exportcontainer". If the serviceUrl does not include a Container name, this field is required. * @example exportcontainer @@ -3584,13 +2586,7 @@ export interface components { */ cloudProvider: "AZURE"; }; - DiskBackupSnapshotAzureExportBucketResponse: Omit< - WithRequired< - components["schemas"]["DiskBackupSnapshotExportBucketResponse"], - "_id" | "bucketName" | "cloudProvider" - >, - "cloudProvider" - > & { + DiskBackupSnapshotAzureExportBucketResponse: Omit, "cloudProvider"> & { /** * @description Unique 24-hexadecimal digit string that identifies the Azure Cloud Provider Access Role that MongoDB Cloud uses to access the Azure Blob Storage Container. * @example 32b6e34b3d91647abb20e7b8 @@ -3659,10 +2655,7 @@ export interface components { * @description Level of access to grant to MongoDB Employees. * @enum {string} */ - grantType: - | "CLUSTER_DATABASE_LOGS" - | "CLUSTER_INFRASTRUCTURE" - | "CLUSTER_INFRASTRUCTURE_AND_APP_SERVICES_SYNC_DATA"; + grantType: "CLUSTER_DATABASE_LOGS" | "CLUSTER_INFRASTRUCTURE" | "CLUSTER_INFRASTRUCTURE_AND_APP_SERVICES_SYNC_DATA"; /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ readonly links?: components["schemas"]["Link"][]; }; @@ -3714,53 +2707,20 @@ export interface components { /** @description Human-readable label that identifies the network in which MongoDB Cloud clusters in this network peering container exist. MongoDB Cloud returns **null** if no clusters exist in this network peering container. */ readonly networkName?: string; /** @description List of GCP regions to which you want to deploy this MongoDB Cloud network peering container. In this MongoDB Cloud project, you can deploy clusters only to the GCP regions in this list. To deploy MongoDB Cloud clusters to other GCP regions, create additional projects. */ - regions?: ( - | "AFRICA_SOUTH_1" - | "ASIA_EAST_2" - | "ASIA_NORTHEAST_2" - | "ASIA_NORTHEAST_3" - | "ASIA_SOUTH_1" - | "ASIA_SOUTH_2" - | "ASIA_SOUTHEAST_2" - | "AUSTRALIA_SOUTHEAST_1" - | "AUSTRALIA_SOUTHEAST_2" - | "CENTRAL_US" - | "EASTERN_ASIA_PACIFIC" - | "EASTERN_US" - | "EUROPE_CENTRAL_2" - | "EUROPE_NORTH_1" - | "EUROPE_WEST_2" - | "EUROPE_WEST_3" - | "EUROPE_WEST_4" - | "EUROPE_WEST_6" - | "EUROPE_WEST_10" - | "EUROPE_WEST_12" - | "MIDDLE_EAST_CENTRAL_1" - | "MIDDLE_EAST_CENTRAL_2" - | "MIDDLE_EAST_WEST_1" - | "NORTH_AMERICA_NORTHEAST_1" - | "NORTH_AMERICA_NORTHEAST_2" - | "NORTH_AMERICA_SOUTH_1" - | "NORTHEASTERN_ASIA_PACIFIC" - | "SOUTH_AMERICA_EAST_1" - | "SOUTH_AMERICA_WEST_1" - | "SOUTHEASTERN_ASIA_PACIFIC" - | "US_EAST_4" - | "US_EAST_5" - | "US_WEST_2" - | "US_WEST_3" - | "US_WEST_4" - | "US_SOUTH_1" - | "WESTERN_EUROPE" - | "WESTERN_US" - )[]; + regions?: ("AFRICA_SOUTH_1" | "ASIA_EAST_2" | "ASIA_NORTHEAST_2" | "ASIA_NORTHEAST_3" | "ASIA_SOUTH_1" | "ASIA_SOUTH_2" | "ASIA_SOUTHEAST_2" | "AUSTRALIA_SOUTHEAST_1" | "AUSTRALIA_SOUTHEAST_2" | "CENTRAL_US" | "EASTERN_ASIA_PACIFIC" | "EASTERN_US" | "EUROPE_CENTRAL_2" | "EUROPE_NORTH_1" | "EUROPE_WEST_2" | "EUROPE_WEST_3" | "EUROPE_WEST_4" | "EUROPE_WEST_6" | "EUROPE_WEST_10" | "EUROPE_WEST_12" | "MIDDLE_EAST_CENTRAL_1" | "MIDDLE_EAST_CENTRAL_2" | "MIDDLE_EAST_WEST_1" | "NORTH_AMERICA_NORTHEAST_1" | "NORTH_AMERICA_NORTHEAST_2" | "NORTH_AMERICA_SOUTH_1" | "NORTHEASTERN_ASIA_PACIFIC" | "SOUTH_AMERICA_EAST_1" | "SOUTH_AMERICA_WEST_1" | "SOUTHEASTERN_ASIA_PACIFIC" | "US_EAST_4" | "US_EAST_5" | "US_WEST_2" | "US_WEST_3" | "US_WEST_4" | "US_SOUTH_1" | "WESTERN_EUROPE" | "WESTERN_US")[]; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "GCP"; } & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ providerName: "GCP"; - } ; + }; /** * GCP * @description Collection of settings that configures how a cluster might scale its cluster tier and whether the cluster can scale down. Cluster tier auto-scaling is unavailable for clusters using Low CPU or NVME storage classes. @@ -3771,53 +2731,13 @@ export interface components { * @description Maximum instance size to which your cluster can automatically scale. * @enum {string} */ - maxInstanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M140" - | "M200" - | "M250" - | "M300" - | "M400" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R600"; + maxInstanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M140" | "M200" | "M250" | "M300" | "M400" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R600"; /** * GCP Instance Sizes * @description Minimum instance size to which your cluster can automatically scale. * @enum {string} */ - minInstanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M140" - | "M200" - | "M250" - | "M300" - | "M400" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R600"; + minInstanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M140" | "M200" | "M250" | "M300" | "M400" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R600"; }; GCPCreateDataProcessRegionView: Omit & { /** @@ -3851,27 +2771,7 @@ export interface components { * @description Hardware specification for the instance sizes in this region. Each instance size has a default storage and memory capacity. The instance size you select applies to all the data-bearing hosts of the node type. * @enum {string} */ - instanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M140" - | "M200" - | "M250" - | "M300" - | "M400" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R600"; + instanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M140" | "M200" | "M250" | "M300" | "M400" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R600"; /** * Format: int32 * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. @@ -3901,27 +2801,7 @@ export interface components { * @description Hardware specification for the instance sizes in this region in this shard. Each instance size has a default storage and memory capacity. Electable nodes and read-only nodes (known as "base nodes") within a single shard must use the same instance size. Analytics nodes can scale independently from base nodes within a shard. Both base nodes and analytics nodes can scale independently from their equivalents in other shards. * @enum {string} */ - instanceSize?: - | "M10" - | "M20" - | "M30" - | "M40" - | "M50" - | "M60" - | "M80" - | "M140" - | "M200" - | "M250" - | "M300" - | "M400" - | "R40" - | "R50" - | "R60" - | "R80" - | "R200" - | "R300" - | "R400" - | "R600"; + instanceSize?: "M10" | "M20" | "M30" | "M40" | "M50" | "M60" | "M80" | "M140" | "M200" | "M250" | "M300" | "M400" | "R40" | "R50" | "R60" | "R80" | "R200" | "R300" | "R400" | "R600"; /** * Format: int32 * @description Number of nodes of the given type for MongoDB Cloud to deploy to the region. @@ -3943,7 +2823,13 @@ export interface components { * @enum {string} */ providerName: "GCP"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "GCP"; + }; /** * GCP Regional Replication Specifications * @description Details that explain how MongoDB Cloud replicates data in one region on the specified MongoDB database. @@ -3959,7 +2845,13 @@ export interface components { * @enum {string} */ providerName: "GCP"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "GCP"; + }; Group: { /** * Format: int64 @@ -4007,13 +2899,7 @@ export interface components { */ withDefaultAlertsSettings: boolean; }; - GroupActiveUserResponse: Omit< - WithRequired< - components["schemas"]["GroupUserResponse"], - "id" | "orgMembershipStatus" | "roles" | "username" - >, - "orgMembershipStatus" - > & { + GroupActiveUserResponse: Omit, "orgMembershipStatus"> & { /** * @description Two-character alphabetical string that identifies the MongoDB Cloud user's geographic location. This parameter uses the ISO 3166-1a2 code format. * @example US @@ -4047,17 +2933,17 @@ export interface components { * @enum {string} */ orgMembershipStatus: "ACTIVE"; - } ; - GroupPendingUserResponse: Omit< - WithRequired< - components["schemas"]["GroupUserResponse"], - "id" | "orgMembershipStatus" | "roles" | "username" - >, - "orgMembershipStatus" - > & { + } & { /** - * Format: date-time - * @description Date and time when MongoDB Cloud sent the invitation. MongoDB Cloud represents this timestamp in ISO 8601 format in UTC. + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + orgMembershipStatus: "ACTIVE"; + }; + GroupPendingUserResponse: Omit, "orgMembershipStatus"> & { + /** + * Format: date-time + * @description Date and time when MongoDB Cloud sent the invitation. MongoDB Cloud represents this timestamp in ISO 8601 format in UTC. */ readonly invitationCreatedAt: string; /** @@ -4076,7 +2962,13 @@ export interface components { * @enum {string} */ orgMembershipStatus: "PENDING"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + orgMembershipStatus: "PENDING"; + }; GroupRoleAssignment: { /** * @description Unique 24-hexadecimal digit string that identifies the project to which these roles belong. @@ -4084,19 +2976,7 @@ export interface components { */ groupId?: string; /** @description One or more project-level roles assigned to the MongoDB Cloud user. */ - groupRoles?: ( - | "GROUP_OWNER" - | "GROUP_CLUSTER_MANAGER" - | "GROUP_STREAM_PROCESSING_OWNER" - | "GROUP_DATA_ACCESS_ADMIN" - | "GROUP_DATA_ACCESS_READ_WRITE" - | "GROUP_DATA_ACCESS_READ_ONLY" - | "GROUP_READ_ONLY" - | "GROUP_SEARCH_INDEX_EDITOR" - | "GROUP_BACKUP_MANAGER" - | "GROUP_OBSERVABILITY_VIEWER" - | "GROUP_DATABASE_ACCESS_ADMIN" - )[]; + groupRoles?: ("GROUP_OWNER" | "GROUP_CLUSTER_MANAGER" | "GROUP_STREAM_PROCESSING_OWNER" | "GROUP_DATA_ACCESS_ADMIN" | "GROUP_DATA_ACCESS_READ_WRITE" | "GROUP_DATA_ACCESS_READ_ONLY" | "GROUP_READ_ONLY" | "GROUP_SEARCH_INDEX_EDITOR" | "GROUP_BACKUP_MANAGER" | "GROUP_OBSERVABILITY_VIEWER" | "GROUP_DATABASE_ACCESS_ADMIN")[]; }; GroupUserResponse: { /** @@ -4110,19 +2990,7 @@ export interface components { */ readonly orgMembershipStatus: "PENDING" | "ACTIVE"; /** @description One or more project-level roles assigned to the MongoDB Cloud user. */ - readonly roles: ( - | "GROUP_OWNER" - | "GROUP_CLUSTER_MANAGER" - | "GROUP_STREAM_PROCESSING_OWNER" - | "GROUP_DATA_ACCESS_ADMIN" - | "GROUP_DATA_ACCESS_READ_WRITE" - | "GROUP_DATA_ACCESS_READ_ONLY" - | "GROUP_READ_ONLY" - | "GROUP_SEARCH_INDEX_EDITOR" - | "GROUP_BACKUP_MANAGER" - | "GROUP_OBSERVABILITY_VIEWER" - | "GROUP_DATABASE_ACCESS_ADMIN" - )[]; + readonly roles: ("GROUP_OWNER" | "GROUP_CLUSTER_MANAGER" | "GROUP_STREAM_PROCESSING_OWNER" | "GROUP_DATA_ACCESS_ADMIN" | "GROUP_DATA_ACCESS_READ_WRITE" | "GROUP_DATA_ACCESS_READ_ONLY" | "GROUP_READ_ONLY" | "GROUP_SEARCH_INDEX_EDITOR" | "GROUP_BACKUP_MANAGER" | "GROUP_OBSERVABILITY_VIEWER" | "GROUP_DATABASE_ACCESS_ADMIN")[]; /** * Format: email * @description Email address that represents the username of the MongoDB Cloud user. @@ -4130,11 +2998,7 @@ export interface components { readonly username: string; } & (components["schemas"]["GroupPendingUserResponse"] | components["schemas"]["GroupActiveUserResponse"]); /** @description Hardware specifications for all electable nodes deployed in the region. Electable nodes can become the primary and can enable local reads. If you don't specify this option, MongoDB Cloud deploys no electable nodes to the region. */ - HardwareSpec: - | components["schemas"]["AWSHardwareSpec"] - | components["schemas"]["AzureHardwareSpec"] - | components["schemas"]["GCPHardwareSpec"] - | components["schemas"]["TenantHardwareSpec"]; + HardwareSpec: components["schemas"]["AWSHardwareSpec"] | components["schemas"]["AzureHardwareSpec"] | components["schemas"]["GCPHardwareSpec"] | components["schemas"]["TenantHardwareSpec"]; /** @description Hardware specifications for all electable nodes deployed in the region. Electable nodes can become the primary and can enable local reads. If you don't specify this option, MongoDB Cloud deploys no electable nodes to the region. */ HardwareSpec20240805: { /** @@ -4154,12 +3018,7 @@ export interface components { * The maximum value for disk storage cannot exceed 50 times the maximum RAM for the selected cluster. If you require more storage space, consider upgrading your cluster to a higher tier. */ diskSizeGB?: number; - } & ( - | components["schemas"]["AWSHardwareSpec20240805"] - | components["schemas"]["AzureHardwareSpec20240805"] - | components["schemas"]["GCPHardwareSpec20240805"] - | components["schemas"]["TenantHardwareSpec20240805"] - ); + } & (components["schemas"]["AWSHardwareSpec20240805"] | components["schemas"]["AzureHardwareSpec20240805"] | components["schemas"]["GCPHardwareSpec20240805"] | components["schemas"]["TenantHardwareSpec20240805"]); /** * Ingestion Destination * @description Ingestion destination of a Data Lake Pipeline. @@ -4227,412 +3086,7 @@ export interface components { * @description Human-readable description of the service that this line item provided. This Stock Keeping Unit (SKU) could be the instance type, a support charge, advanced security, or another service. * @enum {string} */ - readonly sku?: - | "CLASSIC_BACKUP_OPLOG" - | "CLASSIC_BACKUP_STORAGE" - | "CLASSIC_BACKUP_SNAPSHOT_CREATE" - | "CLASSIC_BACKUP_DAILY_MINIMUM" - | "CLASSIC_BACKUP_FREE_TIER" - | "CLASSIC_COUPON" - | "BACKUP_STORAGE_FREE_TIER" - | "BACKUP_STORAGE" - | "FLEX_CONSULTING" - | "CLOUD_MANAGER_CLASSIC" - | "CLOUD_MANAGER_BASIC_FREE_TIER" - | "CLOUD_MANAGER_BASIC" - | "CLOUD_MANAGER_PREMIUM" - | "CLOUD_MANAGER_FREE_TIER" - | "CLOUD_MANAGER_STANDARD_FREE_TIER" - | "CLOUD_MANAGER_STANDARD_ANNUAL" - | "CLOUD_MANAGER_STANDARD" - | "CLOUD_MANAGER_FREE_TRIAL" - | "ATLAS_INSTANCE_M0" - | "ATLAS_INSTANCE_M2" - | "ATLAS_INSTANCE_M5" - | "ATLAS_AWS_INSTANCE_M10" - | "ATLAS_AWS_INSTANCE_M20" - | "ATLAS_AWS_INSTANCE_M30" - | "ATLAS_AWS_INSTANCE_M40" - | "ATLAS_AWS_INSTANCE_M50" - | "ATLAS_AWS_INSTANCE_M60" - | "ATLAS_AWS_INSTANCE_M80" - | "ATLAS_AWS_INSTANCE_M100" - | "ATLAS_AWS_INSTANCE_M140" - | "ATLAS_AWS_INSTANCE_M200" - | "ATLAS_AWS_INSTANCE_M300" - | "ATLAS_AWS_INSTANCE_M40_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M50_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M60_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M80_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M200_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M300_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M400_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M700_LOW_CPU" - | "ATLAS_AWS_INSTANCE_M40_NVME" - | "ATLAS_AWS_INSTANCE_M50_NVME" - | "ATLAS_AWS_INSTANCE_M60_NVME" - | "ATLAS_AWS_INSTANCE_M80_NVME" - | "ATLAS_AWS_INSTANCE_M200_NVME" - | "ATLAS_AWS_INSTANCE_M400_NVME" - | "ATLAS_AWS_INSTANCE_M10_PAUSED" - | "ATLAS_AWS_INSTANCE_M20_PAUSED" - | "ATLAS_AWS_INSTANCE_M30_PAUSED" - | "ATLAS_AWS_INSTANCE_M40_PAUSED" - | "ATLAS_AWS_INSTANCE_M50_PAUSED" - | "ATLAS_AWS_INSTANCE_M60_PAUSED" - | "ATLAS_AWS_INSTANCE_M80_PAUSED" - | "ATLAS_AWS_INSTANCE_M100_PAUSED" - | "ATLAS_AWS_INSTANCE_M140_PAUSED" - | "ATLAS_AWS_INSTANCE_M200_PAUSED" - | "ATLAS_AWS_INSTANCE_M300_PAUSED" - | "ATLAS_AWS_INSTANCE_M40_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M50_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M60_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M80_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M200_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M300_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M400_LOW_CPU_PAUSED" - | "ATLAS_AWS_INSTANCE_M700_LOW_CPU_PAUSED" - | "ATLAS_AWS_SEARCH_INSTANCE_S20_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S30_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S40_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S50_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S60_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S70_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S80_COMPUTE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S30_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S40_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S50_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S60_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S80_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S90_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S100_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S110_MEMORY_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S40_STORAGE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S50_STORAGE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S60_STORAGE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S80_STORAGE_NVME" - | "ATLAS_AWS_SEARCH_INSTANCE_S90_STORAGE_NVME" - | "ATLAS_AWS_STORAGE_PROVISIONED" - | "ATLAS_AWS_STORAGE_STANDARD" - | "ATLAS_AWS_STORAGE_STANDARD_GP3" - | "ATLAS_AWS_STORAGE_IOPS" - | "ATLAS_AWS_DATA_TRANSFER_SAME_REGION" - | "ATLAS_AWS_DATA_TRANSFER_DIFFERENT_REGION" - | "ATLAS_AWS_DATA_TRANSFER_INTERNET" - | "ATLAS_AWS_BACKUP_SNAPSHOT_STORAGE" - | "ATLAS_AWS_BACKUP_DOWNLOAD_VM" - | "ATLAS_AWS_BACKUP_DOWNLOAD_VM_STORAGE" - | "ATLAS_AWS_BACKUP_DOWNLOAD_VM_STORAGE_IOPS" - | "ATLAS_AWS_PRIVATE_ENDPOINT" - | "ATLAS_AWS_PRIVATE_ENDPOINT_CAPACITY_UNITS" - | "ATLAS_GCP_SEARCH_INSTANCE_S20_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S30_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S40_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S50_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S60_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S70_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S80_COMPUTE_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S30_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S40_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S50_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S60_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S70_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S80_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S90_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S100_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S110_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S120_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S130_MEMORY_LOCALSSD" - | "ATLAS_GCP_SEARCH_INSTANCE_S140_MEMORY_LOCALSSD" - | "ATLAS_GCP_INSTANCE_M10" - | "ATLAS_GCP_INSTANCE_M20" - | "ATLAS_GCP_INSTANCE_M30" - | "ATLAS_GCP_INSTANCE_M40" - | "ATLAS_GCP_INSTANCE_M50" - | "ATLAS_GCP_INSTANCE_M60" - | "ATLAS_GCP_INSTANCE_M80" - | "ATLAS_GCP_INSTANCE_M140" - | "ATLAS_GCP_INSTANCE_M200" - | "ATLAS_GCP_INSTANCE_M250" - | "ATLAS_GCP_INSTANCE_M300" - | "ATLAS_GCP_INSTANCE_M400" - | "ATLAS_GCP_INSTANCE_M40_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M50_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M60_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M80_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M200_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M300_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M400_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M600_LOW_CPU" - | "ATLAS_GCP_INSTANCE_M10_PAUSED" - | "ATLAS_GCP_INSTANCE_M20_PAUSED" - | "ATLAS_GCP_INSTANCE_M30_PAUSED" - | "ATLAS_GCP_INSTANCE_M40_PAUSED" - | "ATLAS_GCP_INSTANCE_M50_PAUSED" - | "ATLAS_GCP_INSTANCE_M60_PAUSED" - | "ATLAS_GCP_INSTANCE_M80_PAUSED" - | "ATLAS_GCP_INSTANCE_M140_PAUSED" - | "ATLAS_GCP_INSTANCE_M200_PAUSED" - | "ATLAS_GCP_INSTANCE_M250_PAUSED" - | "ATLAS_GCP_INSTANCE_M300_PAUSED" - | "ATLAS_GCP_INSTANCE_M400_PAUSED" - | "ATLAS_GCP_INSTANCE_M40_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M50_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M60_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M80_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M200_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M300_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M400_LOW_CPU_PAUSED" - | "ATLAS_GCP_INSTANCE_M600_LOW_CPU_PAUSED" - | "ATLAS_GCP_DATA_TRANSFER_INTERNET" - | "ATLAS_GCP_STORAGE_SSD" - | "ATLAS_GCP_DATA_TRANSFER_INTER_CONNECT" - | "ATLAS_GCP_DATA_TRANSFER_INTER_ZONE" - | "ATLAS_GCP_DATA_TRANSFER_INTER_REGION" - | "ATLAS_GCP_DATA_TRANSFER_GOOGLE" - | "ATLAS_GCP_BACKUP_SNAPSHOT_STORAGE" - | "ATLAS_GCP_BACKUP_DOWNLOAD_VM" - | "ATLAS_GCP_BACKUP_DOWNLOAD_VM_STORAGE" - | "ATLAS_GCP_PRIVATE_ENDPOINT" - | "ATLAS_GCP_PRIVATE_ENDPOINT_CAPACITY_UNITS" - | "ATLAS_GCP_SNAPSHOT_COPY_DATA_TRANSFER" - | "ATLAS_AZURE_INSTANCE_M10" - | "ATLAS_AZURE_INSTANCE_M20" - | "ATLAS_AZURE_INSTANCE_M30" - | "ATLAS_AZURE_INSTANCE_M40" - | "ATLAS_AZURE_INSTANCE_M50" - | "ATLAS_AZURE_INSTANCE_M60" - | "ATLAS_AZURE_INSTANCE_M80" - | "ATLAS_AZURE_INSTANCE_M90" - | "ATLAS_AZURE_INSTANCE_M200" - | "ATLAS_AZURE_INSTANCE_R40" - | "ATLAS_AZURE_INSTANCE_R50" - | "ATLAS_AZURE_INSTANCE_R60" - | "ATLAS_AZURE_INSTANCE_R80" - | "ATLAS_AZURE_INSTANCE_R200" - | "ATLAS_AZURE_INSTANCE_R300" - | "ATLAS_AZURE_INSTANCE_R400" - | "ATLAS_AZURE_INSTANCE_M60_NVME" - | "ATLAS_AZURE_INSTANCE_M80_NVME" - | "ATLAS_AZURE_INSTANCE_M200_NVME" - | "ATLAS_AZURE_INSTANCE_M300_NVME" - | "ATLAS_AZURE_INSTANCE_M400_NVME" - | "ATLAS_AZURE_INSTANCE_M600_NVME" - | "ATLAS_AZURE_INSTANCE_M10_PAUSED" - | "ATLAS_AZURE_INSTANCE_M20_PAUSED" - | "ATLAS_AZURE_INSTANCE_M30_PAUSED" - | "ATLAS_AZURE_INSTANCE_M40_PAUSED" - | "ATLAS_AZURE_INSTANCE_M50_PAUSED" - | "ATLAS_AZURE_INSTANCE_M60_PAUSED" - | "ATLAS_AZURE_INSTANCE_M80_PAUSED" - | "ATLAS_AZURE_INSTANCE_M90_PAUSED" - | "ATLAS_AZURE_INSTANCE_M200_PAUSED" - | "ATLAS_AZURE_INSTANCE_R40_PAUSED" - | "ATLAS_AZURE_INSTANCE_R50_PAUSED" - | "ATLAS_AZURE_INSTANCE_R60_PAUSED" - | "ATLAS_AZURE_INSTANCE_R80_PAUSED" - | "ATLAS_AZURE_INSTANCE_R200_PAUSED" - | "ATLAS_AZURE_INSTANCE_R300_PAUSED" - | "ATLAS_AZURE_INSTANCE_R400_PAUSED" - | "ATLAS_AZURE_SEARCH_INSTANCE_S20_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S30_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S40_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S50_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S60_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S70_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S80_COMPUTE_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S40_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S50_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S60_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S80_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S90_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S100_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S110_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S130_MEMORY_LOCALSSD" - | "ATLAS_AZURE_SEARCH_INSTANCE_S135_MEMORY_LOCALSSD" - | "ATLAS_AZURE_STORAGE_P2" - | "ATLAS_AZURE_STORAGE_P3" - | "ATLAS_AZURE_STORAGE_P4" - | "ATLAS_AZURE_STORAGE_P6" - | "ATLAS_AZURE_STORAGE_P10" - | "ATLAS_AZURE_STORAGE_P15" - | "ATLAS_AZURE_STORAGE_P20" - | "ATLAS_AZURE_STORAGE_P30" - | "ATLAS_AZURE_STORAGE_P40" - | "ATLAS_AZURE_STORAGE_P50" - | "ATLAS_AZURE_DATA_TRANSFER" - | "ATLAS_AZURE_DATA_TRANSFER_REGIONAL_VNET_IN" - | "ATLAS_AZURE_DATA_TRANSFER_REGIONAL_VNET_OUT" - | "ATLAS_AZURE_DATA_TRANSFER_GLOBAL_VNET_IN" - | "ATLAS_AZURE_DATA_TRANSFER_GLOBAL_VNET_OUT" - | "ATLAS_AZURE_DATA_TRANSFER_AVAILABILITY_ZONE_IN" - | "ATLAS_AZURE_DATA_TRANSFER_AVAILABILITY_ZONE_OUT" - | "ATLAS_AZURE_DATA_TRANSFER_INTER_REGION_INTRA_CONTINENT" - | "ATLAS_AZURE_DATA_TRANSFER_INTER_REGION_INTER_CONTINENT" - | "ATLAS_AZURE_BACKUP_SNAPSHOT_STORAGE" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P2" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P3" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P4" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P6" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P10" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P15" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P20" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P30" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P40" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P50" - | "ATLAS_AZURE_STANDARD_STORAGE" - | "ATLAS_AZURE_EXTENDED_STANDARD_IOPS" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE" - | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_EXTENDED_IOPS" - | "ATLAS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE" - | "ATLAS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_EXTENDED_IOPS" - | "ATLAS_BI_CONNECTOR" - | "ATLAS_ADVANCED_SECURITY" - | "ATLAS_ENTERPRISE_AUDITING" - | "ATLAS_FREE_SUPPORT" - | "ATLAS_SUPPORT" - | "ATLAS_NDS_BACKFILL_SUPPORT" - | "STITCH_DATA_DOWNLOADED_FREE_TIER" - | "STITCH_DATA_DOWNLOADED" - | "STITCH_COMPUTE_FREE_TIER" - | "STITCH_COMPUTE" - | "CREDIT" - | "MINIMUM_CHARGE" - | "CHARTS_DATA_DOWNLOADED_FREE_TIER" - | "CHARTS_DATA_DOWNLOADED" - | "ATLAS_DATA_LAKE_AWS_DATA_RETURNED_SAME_REGION" - | "ATLAS_DATA_LAKE_AWS_DATA_RETURNED_DIFFERENT_REGION" - | "ATLAS_DATA_LAKE_AWS_DATA_RETURNED_INTERNET" - | "ATLAS_DATA_LAKE_AWS_DATA_SCANNED" - | "ATLAS_DATA_LAKE_AWS_DATA_TRANSFERRED_FROM_DIFFERENT_REGION" - | "ATLAS_NDS_AWS_DATA_LAKE_STORAGE_ACCESS" - | "ATLAS_NDS_AWS_DATA_LAKE_STORAGE" - | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_SAME_REGION" - | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_SAME_CONTINENT" - | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_DIFFERENT_CONTINENT" - | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_INTERNET" - | "ATLAS_DATA_FEDERATION_GCP_DATA_RETURNED_SAME_REGION" - | "ATLAS_DATA_FEDERATION_GCP_DATA_RETURNED_DIFFERENT_REGION" - | "ATLAS_DATA_FEDERATION_GCP_DATA_RETURNED_INTERNET" - | "ATLAS_DATA_FEDERATION_AZURE_DATA_SCANNED" - | "ATLAS_NDS_AZURE_DATA_LAKE_STORAGE_ACCESS" - | "ATLAS_NDS_AZURE_DATA_LAKE_STORAGE" - | "ATLAS_DATA_FEDERATION_GCP_DATA_SCANNED" - | "ATLAS_NDS_GCP_DATA_LAKE_STORAGE_ACCESS" - | "ATLAS_NDS_GCP_DATA_LAKE_STORAGE" - | "ATLAS_NDS_AWS_OBJECT_STORAGE_ACCESS" - | "ATLAS_NDS_AWS_COMPRESSED_OBJECT_STORAGE" - | "ATLAS_NDS_AZURE_OBJECT_STORAGE_ACCESS" - | "ATLAS_NDS_AZURE_OBJECT_STORAGE" - | "ATLAS_NDS_AZURE_COMPRESSED_OBJECT_STORAGE" - | "ATLAS_NDS_GCP_OBJECT_STORAGE_ACCESS" - | "ATLAS_NDS_GCP_OBJECT_STORAGE" - | "ATLAS_NDS_GCP_COMPRESSED_OBJECT_STORAGE" - | "ATLAS_ARCHIVE_ACCESS_PARTITION_LOCATE" - | "ATLAS_NDS_AWS_PIT_RESTORE_STORAGE_FREE_TIER" - | "ATLAS_NDS_AWS_PIT_RESTORE_STORAGE" - | "ATLAS_NDS_GCP_PIT_RESTORE_STORAGE_FREE_TIER" - | "ATLAS_NDS_GCP_PIT_RESTORE_STORAGE" - | "ATLAS_NDS_AZURE_PIT_RESTORE_STORAGE_FREE_TIER" - | "ATLAS_NDS_AZURE_PIT_RESTORE_STORAGE" - | "ATLAS_NDS_AZURE_PRIVATE_ENDPOINT_CAPACITY_UNITS" - | "ATLAS_NDS_AZURE_CMK_PRIVATE_NETWORKING" - | "ATLAS_NDS_AWS_CMK_PRIVATE_NETWORKING" - | "ATLAS_NDS_AWS_OBJECT_STORAGE" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_UPLOAD" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_UPLOAD" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_M40" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_M50" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_M60" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P2" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P3" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P4" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P6" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P10" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P15" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P20" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P30" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P40" - | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P50" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_M40" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_M50" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_M60" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_STORAGE" - | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_STORAGE_IOPS" - | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM" - | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_M40" - | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_M50" - | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_M60" - | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_STORAGE" - | "ATLAS_NDS_AWS_SERVERLESS_RPU" - | "ATLAS_NDS_AWS_SERVERLESS_WPU" - | "ATLAS_NDS_AWS_SERVERLESS_STORAGE" - | "ATLAS_NDS_AWS_SERVERLESS_CONTINUOUS_BACKUP" - | "ATLAS_NDS_AWS_SERVERLESS_BACKUP_RESTORE_VM" - | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_PREVIEW" - | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER" - | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_REGIONAL" - | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_CROSS_REGION" - | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_INTERNET" - | "ATLAS_NDS_GCP_SERVERLESS_RPU" - | "ATLAS_NDS_GCP_SERVERLESS_WPU" - | "ATLAS_NDS_GCP_SERVERLESS_STORAGE" - | "ATLAS_NDS_GCP_SERVERLESS_CONTINUOUS_BACKUP" - | "ATLAS_NDS_GCP_SERVERLESS_BACKUP_RESTORE_VM" - | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_PREVIEW" - | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER" - | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_REGIONAL" - | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_CROSS_REGION" - | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_INTERNET" - | "ATLAS_NDS_AZURE_SERVERLESS_RPU" - | "ATLAS_NDS_AZURE_SERVERLESS_WPU" - | "ATLAS_NDS_AZURE_SERVERLESS_STORAGE" - | "ATLAS_NDS_AZURE_SERVERLESS_CONTINUOUS_BACKUP" - | "ATLAS_NDS_AZURE_SERVERLESS_BACKUP_RESTORE_VM" - | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_PREVIEW" - | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER" - | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_REGIONAL" - | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_CROSS_REGION" - | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_INTERNET" - | "REALM_APP_REQUESTS_FREE_TIER" - | "REALM_APP_REQUESTS" - | "REALM_APP_COMPUTE_FREE_TIER" - | "REALM_APP_COMPUTE" - | "REALM_APP_SYNC_FREE_TIER" - | "REALM_APP_SYNC" - | "REALM_APP_DATA_TRANSFER_FREE_TIER" - | "REALM_APP_DATA_TRANSFER" - | "GCP_SNAPSHOT_COPY_DISK" - | "ATLAS_AWS_STREAM_PROCESSING_INSTANCE_SP10" - | "ATLAS_AWS_STREAM_PROCESSING_INSTANCE_SP30" - | "ATLAS_AWS_STREAM_PROCESSING_INSTANCE_SP50" - | "ATLAS_AZURE_STREAM_PROCESSING_INSTANCE_SP10" - | "ATLAS_AZURE_STREAM_PROCESSING_INSTANCE_SP30" - | "ATLAS_AZURE_STREAM_PROCESSING_INSTANCE_SP50" - | "ATLAS_AWS_STREAM_PROCESSING_DATA_TRANSFER" - | "ATLAS_AZURE_STREAM_PROCESSING_DATA_TRANSFER" - | "ATLAS_AWS_STREAM_PROCESSING_VPC_PEERING" - | "ATLAS_AZURE_STREAM_PROCESSING_PRIVATELINK" - | "ATLAS_AWS_STREAM_PROCESSING_PRIVATELINK" - | "ATLAS_FLEX_AWS_100_USAGE_HOURS" - | "ATLAS_FLEX_AWS_200_USAGE_HOURS" - | "ATLAS_FLEX_AWS_300_USAGE_HOURS" - | "ATLAS_FLEX_AWS_400_USAGE_HOURS" - | "ATLAS_FLEX_AWS_500_USAGE_HOURS" - | "ATLAS_FLEX_AZURE_100_USAGE_HOURS" - | "ATLAS_FLEX_AZURE_200_USAGE_HOURS" - | "ATLAS_FLEX_AZURE_300_USAGE_HOURS" - | "ATLAS_FLEX_AZURE_400_USAGE_HOURS" - | "ATLAS_FLEX_AZURE_500_USAGE_HOURS" - | "ATLAS_FLEX_GCP_100_USAGE_HOURS" - | "ATLAS_FLEX_GCP_200_USAGE_HOURS" - | "ATLAS_FLEX_GCP_300_USAGE_HOURS" - | "ATLAS_FLEX_GCP_400_USAGE_HOURS" - | "ATLAS_FLEX_GCP_500_USAGE_HOURS"; + readonly sku?: "CLASSIC_BACKUP_OPLOG" | "CLASSIC_BACKUP_STORAGE" | "CLASSIC_BACKUP_SNAPSHOT_CREATE" | "CLASSIC_BACKUP_DAILY_MINIMUM" | "CLASSIC_BACKUP_FREE_TIER" | "CLASSIC_COUPON" | "BACKUP_STORAGE_FREE_TIER" | "BACKUP_STORAGE" | "FLEX_CONSULTING" | "CLOUD_MANAGER_CLASSIC" | "CLOUD_MANAGER_BASIC_FREE_TIER" | "CLOUD_MANAGER_BASIC" | "CLOUD_MANAGER_PREMIUM" | "CLOUD_MANAGER_FREE_TIER" | "CLOUD_MANAGER_STANDARD_FREE_TIER" | "CLOUD_MANAGER_STANDARD_ANNUAL" | "CLOUD_MANAGER_STANDARD" | "CLOUD_MANAGER_FREE_TRIAL" | "ATLAS_INSTANCE_M0" | "ATLAS_INSTANCE_M2" | "ATLAS_INSTANCE_M5" | "ATLAS_AWS_INSTANCE_M10" | "ATLAS_AWS_INSTANCE_M20" | "ATLAS_AWS_INSTANCE_M30" | "ATLAS_AWS_INSTANCE_M40" | "ATLAS_AWS_INSTANCE_M50" | "ATLAS_AWS_INSTANCE_M60" | "ATLAS_AWS_INSTANCE_M80" | "ATLAS_AWS_INSTANCE_M100" | "ATLAS_AWS_INSTANCE_M140" | "ATLAS_AWS_INSTANCE_M200" | "ATLAS_AWS_INSTANCE_M300" | "ATLAS_AWS_INSTANCE_M40_LOW_CPU" | "ATLAS_AWS_INSTANCE_M50_LOW_CPU" | "ATLAS_AWS_INSTANCE_M60_LOW_CPU" | "ATLAS_AWS_INSTANCE_M80_LOW_CPU" | "ATLAS_AWS_INSTANCE_M200_LOW_CPU" | "ATLAS_AWS_INSTANCE_M300_LOW_CPU" | "ATLAS_AWS_INSTANCE_M400_LOW_CPU" | "ATLAS_AWS_INSTANCE_M700_LOW_CPU" | "ATLAS_AWS_INSTANCE_M40_NVME" | "ATLAS_AWS_INSTANCE_M50_NVME" | "ATLAS_AWS_INSTANCE_M60_NVME" | "ATLAS_AWS_INSTANCE_M80_NVME" | "ATLAS_AWS_INSTANCE_M200_NVME" | "ATLAS_AWS_INSTANCE_M400_NVME" | "ATLAS_AWS_INSTANCE_M10_PAUSED" | "ATLAS_AWS_INSTANCE_M20_PAUSED" | "ATLAS_AWS_INSTANCE_M30_PAUSED" | "ATLAS_AWS_INSTANCE_M40_PAUSED" | "ATLAS_AWS_INSTANCE_M50_PAUSED" | "ATLAS_AWS_INSTANCE_M60_PAUSED" | "ATLAS_AWS_INSTANCE_M80_PAUSED" | "ATLAS_AWS_INSTANCE_M100_PAUSED" | "ATLAS_AWS_INSTANCE_M140_PAUSED" | "ATLAS_AWS_INSTANCE_M200_PAUSED" | "ATLAS_AWS_INSTANCE_M300_PAUSED" | "ATLAS_AWS_INSTANCE_M40_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M50_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M60_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M80_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M200_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M300_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M400_LOW_CPU_PAUSED" | "ATLAS_AWS_INSTANCE_M700_LOW_CPU_PAUSED" | "ATLAS_AWS_SEARCH_INSTANCE_S20_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S30_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S40_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S50_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S60_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S70_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S80_COMPUTE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S30_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S40_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S50_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S60_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S80_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S90_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S100_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S110_MEMORY_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S40_STORAGE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S50_STORAGE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S60_STORAGE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S80_STORAGE_NVME" | "ATLAS_AWS_SEARCH_INSTANCE_S90_STORAGE_NVME" | "ATLAS_AWS_STORAGE_PROVISIONED" | "ATLAS_AWS_STORAGE_STANDARD" | "ATLAS_AWS_STORAGE_STANDARD_GP3" | "ATLAS_AWS_STORAGE_IOPS" | "ATLAS_AWS_DATA_TRANSFER_SAME_REGION" | "ATLAS_AWS_DATA_TRANSFER_DIFFERENT_REGION" | "ATLAS_AWS_DATA_TRANSFER_INTERNET" | "ATLAS_AWS_BACKUP_SNAPSHOT_STORAGE" | "ATLAS_AWS_BACKUP_DOWNLOAD_VM" | "ATLAS_AWS_BACKUP_DOWNLOAD_VM_STORAGE" | "ATLAS_AWS_BACKUP_DOWNLOAD_VM_STORAGE_IOPS" | "ATLAS_AWS_PRIVATE_ENDPOINT" | "ATLAS_AWS_PRIVATE_ENDPOINT_CAPACITY_UNITS" | "ATLAS_GCP_SEARCH_INSTANCE_S20_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S30_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S40_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S50_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S60_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S70_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S80_COMPUTE_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S30_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S40_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S50_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S60_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S70_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S80_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S90_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S100_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S110_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S120_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S130_MEMORY_LOCALSSD" | "ATLAS_GCP_SEARCH_INSTANCE_S140_MEMORY_LOCALSSD" | "ATLAS_GCP_INSTANCE_M10" | "ATLAS_GCP_INSTANCE_M20" | "ATLAS_GCP_INSTANCE_M30" | "ATLAS_GCP_INSTANCE_M40" | "ATLAS_GCP_INSTANCE_M50" | "ATLAS_GCP_INSTANCE_M60" | "ATLAS_GCP_INSTANCE_M80" | "ATLAS_GCP_INSTANCE_M140" | "ATLAS_GCP_INSTANCE_M200" | "ATLAS_GCP_INSTANCE_M250" | "ATLAS_GCP_INSTANCE_M300" | "ATLAS_GCP_INSTANCE_M400" | "ATLAS_GCP_INSTANCE_M40_LOW_CPU" | "ATLAS_GCP_INSTANCE_M50_LOW_CPU" | "ATLAS_GCP_INSTANCE_M60_LOW_CPU" | "ATLAS_GCP_INSTANCE_M80_LOW_CPU" | "ATLAS_GCP_INSTANCE_M200_LOW_CPU" | "ATLAS_GCP_INSTANCE_M300_LOW_CPU" | "ATLAS_GCP_INSTANCE_M400_LOW_CPU" | "ATLAS_GCP_INSTANCE_M600_LOW_CPU" | "ATLAS_GCP_INSTANCE_M10_PAUSED" | "ATLAS_GCP_INSTANCE_M20_PAUSED" | "ATLAS_GCP_INSTANCE_M30_PAUSED" | "ATLAS_GCP_INSTANCE_M40_PAUSED" | "ATLAS_GCP_INSTANCE_M50_PAUSED" | "ATLAS_GCP_INSTANCE_M60_PAUSED" | "ATLAS_GCP_INSTANCE_M80_PAUSED" | "ATLAS_GCP_INSTANCE_M140_PAUSED" | "ATLAS_GCP_INSTANCE_M200_PAUSED" | "ATLAS_GCP_INSTANCE_M250_PAUSED" | "ATLAS_GCP_INSTANCE_M300_PAUSED" | "ATLAS_GCP_INSTANCE_M400_PAUSED" | "ATLAS_GCP_INSTANCE_M40_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M50_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M60_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M80_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M200_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M300_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M400_LOW_CPU_PAUSED" | "ATLAS_GCP_INSTANCE_M600_LOW_CPU_PAUSED" | "ATLAS_GCP_DATA_TRANSFER_INTERNET" | "ATLAS_GCP_STORAGE_SSD" | "ATLAS_GCP_DATA_TRANSFER_INTER_CONNECT" | "ATLAS_GCP_DATA_TRANSFER_INTER_ZONE" | "ATLAS_GCP_DATA_TRANSFER_INTER_REGION" | "ATLAS_GCP_DATA_TRANSFER_GOOGLE" | "ATLAS_GCP_BACKUP_SNAPSHOT_STORAGE" | "ATLAS_GCP_BACKUP_DOWNLOAD_VM" | "ATLAS_GCP_BACKUP_DOWNLOAD_VM_STORAGE" | "ATLAS_GCP_PRIVATE_ENDPOINT" | "ATLAS_GCP_PRIVATE_ENDPOINT_CAPACITY_UNITS" | "ATLAS_GCP_SNAPSHOT_COPY_DATA_TRANSFER" | "ATLAS_AZURE_INSTANCE_M10" | "ATLAS_AZURE_INSTANCE_M20" | "ATLAS_AZURE_INSTANCE_M30" | "ATLAS_AZURE_INSTANCE_M40" | "ATLAS_AZURE_INSTANCE_M50" | "ATLAS_AZURE_INSTANCE_M60" | "ATLAS_AZURE_INSTANCE_M80" | "ATLAS_AZURE_INSTANCE_M90" | "ATLAS_AZURE_INSTANCE_M200" | "ATLAS_AZURE_INSTANCE_R40" | "ATLAS_AZURE_INSTANCE_R50" | "ATLAS_AZURE_INSTANCE_R60" | "ATLAS_AZURE_INSTANCE_R80" | "ATLAS_AZURE_INSTANCE_R200" | "ATLAS_AZURE_INSTANCE_R300" | "ATLAS_AZURE_INSTANCE_R400" | "ATLAS_AZURE_INSTANCE_M60_NVME" | "ATLAS_AZURE_INSTANCE_M80_NVME" | "ATLAS_AZURE_INSTANCE_M200_NVME" | "ATLAS_AZURE_INSTANCE_M300_NVME" | "ATLAS_AZURE_INSTANCE_M400_NVME" | "ATLAS_AZURE_INSTANCE_M600_NVME" | "ATLAS_AZURE_INSTANCE_M10_PAUSED" | "ATLAS_AZURE_INSTANCE_M20_PAUSED" | "ATLAS_AZURE_INSTANCE_M30_PAUSED" | "ATLAS_AZURE_INSTANCE_M40_PAUSED" | "ATLAS_AZURE_INSTANCE_M50_PAUSED" | "ATLAS_AZURE_INSTANCE_M60_PAUSED" | "ATLAS_AZURE_INSTANCE_M80_PAUSED" | "ATLAS_AZURE_INSTANCE_M90_PAUSED" | "ATLAS_AZURE_INSTANCE_M200_PAUSED" | "ATLAS_AZURE_INSTANCE_R40_PAUSED" | "ATLAS_AZURE_INSTANCE_R50_PAUSED" | "ATLAS_AZURE_INSTANCE_R60_PAUSED" | "ATLAS_AZURE_INSTANCE_R80_PAUSED" | "ATLAS_AZURE_INSTANCE_R200_PAUSED" | "ATLAS_AZURE_INSTANCE_R300_PAUSED" | "ATLAS_AZURE_INSTANCE_R400_PAUSED" | "ATLAS_AZURE_SEARCH_INSTANCE_S20_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S30_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S40_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S50_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S60_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S70_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S80_COMPUTE_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S40_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S50_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S60_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S80_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S90_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S100_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S110_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S130_MEMORY_LOCALSSD" | "ATLAS_AZURE_SEARCH_INSTANCE_S135_MEMORY_LOCALSSD" | "ATLAS_AZURE_STORAGE_P2" | "ATLAS_AZURE_STORAGE_P3" | "ATLAS_AZURE_STORAGE_P4" | "ATLAS_AZURE_STORAGE_P6" | "ATLAS_AZURE_STORAGE_P10" | "ATLAS_AZURE_STORAGE_P15" | "ATLAS_AZURE_STORAGE_P20" | "ATLAS_AZURE_STORAGE_P30" | "ATLAS_AZURE_STORAGE_P40" | "ATLAS_AZURE_STORAGE_P50" | "ATLAS_AZURE_DATA_TRANSFER" | "ATLAS_AZURE_DATA_TRANSFER_REGIONAL_VNET_IN" | "ATLAS_AZURE_DATA_TRANSFER_REGIONAL_VNET_OUT" | "ATLAS_AZURE_DATA_TRANSFER_GLOBAL_VNET_IN" | "ATLAS_AZURE_DATA_TRANSFER_GLOBAL_VNET_OUT" | "ATLAS_AZURE_DATA_TRANSFER_AVAILABILITY_ZONE_IN" | "ATLAS_AZURE_DATA_TRANSFER_AVAILABILITY_ZONE_OUT" | "ATLAS_AZURE_DATA_TRANSFER_INTER_REGION_INTRA_CONTINENT" | "ATLAS_AZURE_DATA_TRANSFER_INTER_REGION_INTER_CONTINENT" | "ATLAS_AZURE_BACKUP_SNAPSHOT_STORAGE" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P2" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P3" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P4" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P6" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P10" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P15" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P20" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P30" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P40" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_P50" | "ATLAS_AZURE_STANDARD_STORAGE" | "ATLAS_AZURE_EXTENDED_STANDARD_IOPS" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE" | "ATLAS_AZURE_BACKUP_DOWNLOAD_VM_STORAGE_EXTENDED_IOPS" | "ATLAS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE" | "ATLAS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_EXTENDED_IOPS" | "ATLAS_BI_CONNECTOR" | "ATLAS_ADVANCED_SECURITY" | "ATLAS_ENTERPRISE_AUDITING" | "ATLAS_FREE_SUPPORT" | "ATLAS_SUPPORT" | "ATLAS_NDS_BACKFILL_SUPPORT" | "STITCH_DATA_DOWNLOADED_FREE_TIER" | "STITCH_DATA_DOWNLOADED" | "STITCH_COMPUTE_FREE_TIER" | "STITCH_COMPUTE" | "CREDIT" | "MINIMUM_CHARGE" | "CHARTS_DATA_DOWNLOADED_FREE_TIER" | "CHARTS_DATA_DOWNLOADED" | "ATLAS_DATA_LAKE_AWS_DATA_RETURNED_SAME_REGION" | "ATLAS_DATA_LAKE_AWS_DATA_RETURNED_DIFFERENT_REGION" | "ATLAS_DATA_LAKE_AWS_DATA_RETURNED_INTERNET" | "ATLAS_DATA_LAKE_AWS_DATA_SCANNED" | "ATLAS_DATA_LAKE_AWS_DATA_TRANSFERRED_FROM_DIFFERENT_REGION" | "ATLAS_NDS_AWS_DATA_LAKE_STORAGE_ACCESS" | "ATLAS_NDS_AWS_DATA_LAKE_STORAGE" | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_SAME_REGION" | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_SAME_CONTINENT" | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_DIFFERENT_CONTINENT" | "ATLAS_DATA_FEDERATION_AZURE_DATA_RETURNED_INTERNET" | "ATLAS_DATA_FEDERATION_GCP_DATA_RETURNED_SAME_REGION" | "ATLAS_DATA_FEDERATION_GCP_DATA_RETURNED_DIFFERENT_REGION" | "ATLAS_DATA_FEDERATION_GCP_DATA_RETURNED_INTERNET" | "ATLAS_DATA_FEDERATION_AZURE_DATA_SCANNED" | "ATLAS_NDS_AZURE_DATA_LAKE_STORAGE_ACCESS" | "ATLAS_NDS_AZURE_DATA_LAKE_STORAGE" | "ATLAS_DATA_FEDERATION_GCP_DATA_SCANNED" | "ATLAS_NDS_GCP_DATA_LAKE_STORAGE_ACCESS" | "ATLAS_NDS_GCP_DATA_LAKE_STORAGE" | "ATLAS_NDS_AWS_OBJECT_STORAGE_ACCESS" | "ATLAS_NDS_AWS_COMPRESSED_OBJECT_STORAGE" | "ATLAS_NDS_AZURE_OBJECT_STORAGE_ACCESS" | "ATLAS_NDS_AZURE_OBJECT_STORAGE" | "ATLAS_NDS_AZURE_COMPRESSED_OBJECT_STORAGE" | "ATLAS_NDS_GCP_OBJECT_STORAGE_ACCESS" | "ATLAS_NDS_GCP_OBJECT_STORAGE" | "ATLAS_NDS_GCP_COMPRESSED_OBJECT_STORAGE" | "ATLAS_ARCHIVE_ACCESS_PARTITION_LOCATE" | "ATLAS_NDS_AWS_PIT_RESTORE_STORAGE_FREE_TIER" | "ATLAS_NDS_AWS_PIT_RESTORE_STORAGE" | "ATLAS_NDS_GCP_PIT_RESTORE_STORAGE_FREE_TIER" | "ATLAS_NDS_GCP_PIT_RESTORE_STORAGE" | "ATLAS_NDS_AZURE_PIT_RESTORE_STORAGE_FREE_TIER" | "ATLAS_NDS_AZURE_PIT_RESTORE_STORAGE" | "ATLAS_NDS_AZURE_PRIVATE_ENDPOINT_CAPACITY_UNITS" | "ATLAS_NDS_AZURE_CMK_PRIVATE_NETWORKING" | "ATLAS_NDS_AWS_CMK_PRIVATE_NETWORKING" | "ATLAS_NDS_AWS_OBJECT_STORAGE" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_UPLOAD" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_UPLOAD" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_M40" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_M50" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_M60" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P2" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P3" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P4" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P6" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P10" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P15" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P20" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P30" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P40" | "ATLAS_NDS_AZURE_SNAPSHOT_EXPORT_VM_STORAGE_P50" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_M40" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_M50" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_M60" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_STORAGE" | "ATLAS_NDS_AWS_SNAPSHOT_EXPORT_VM_STORAGE_IOPS" | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM" | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_M40" | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_M50" | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_M60" | "ATLAS_NDS_GCP_SNAPSHOT_EXPORT_VM_STORAGE" | "ATLAS_NDS_AWS_SERVERLESS_RPU" | "ATLAS_NDS_AWS_SERVERLESS_WPU" | "ATLAS_NDS_AWS_SERVERLESS_STORAGE" | "ATLAS_NDS_AWS_SERVERLESS_CONTINUOUS_BACKUP" | "ATLAS_NDS_AWS_SERVERLESS_BACKUP_RESTORE_VM" | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_PREVIEW" | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER" | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_REGIONAL" | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_CROSS_REGION" | "ATLAS_NDS_AWS_SERVERLESS_DATA_TRANSFER_INTERNET" | "ATLAS_NDS_GCP_SERVERLESS_RPU" | "ATLAS_NDS_GCP_SERVERLESS_WPU" | "ATLAS_NDS_GCP_SERVERLESS_STORAGE" | "ATLAS_NDS_GCP_SERVERLESS_CONTINUOUS_BACKUP" | "ATLAS_NDS_GCP_SERVERLESS_BACKUP_RESTORE_VM" | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_PREVIEW" | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER" | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_REGIONAL" | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_CROSS_REGION" | "ATLAS_NDS_GCP_SERVERLESS_DATA_TRANSFER_INTERNET" | "ATLAS_NDS_AZURE_SERVERLESS_RPU" | "ATLAS_NDS_AZURE_SERVERLESS_WPU" | "ATLAS_NDS_AZURE_SERVERLESS_STORAGE" | "ATLAS_NDS_AZURE_SERVERLESS_CONTINUOUS_BACKUP" | "ATLAS_NDS_AZURE_SERVERLESS_BACKUP_RESTORE_VM" | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_PREVIEW" | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER" | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_REGIONAL" | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_CROSS_REGION" | "ATLAS_NDS_AZURE_SERVERLESS_DATA_TRANSFER_INTERNET" | "REALM_APP_REQUESTS_FREE_TIER" | "REALM_APP_REQUESTS" | "REALM_APP_COMPUTE_FREE_TIER" | "REALM_APP_COMPUTE" | "REALM_APP_SYNC_FREE_TIER" | "REALM_APP_SYNC" | "REALM_APP_DATA_TRANSFER_FREE_TIER" | "REALM_APP_DATA_TRANSFER" | "GCP_SNAPSHOT_COPY_DISK" | "ATLAS_AWS_STREAM_PROCESSING_INSTANCE_SP10" | "ATLAS_AWS_STREAM_PROCESSING_INSTANCE_SP30" | "ATLAS_AWS_STREAM_PROCESSING_INSTANCE_SP50" | "ATLAS_AZURE_STREAM_PROCESSING_INSTANCE_SP10" | "ATLAS_AZURE_STREAM_PROCESSING_INSTANCE_SP30" | "ATLAS_AZURE_STREAM_PROCESSING_INSTANCE_SP50" | "ATLAS_AWS_STREAM_PROCESSING_DATA_TRANSFER" | "ATLAS_AZURE_STREAM_PROCESSING_DATA_TRANSFER" | "ATLAS_AWS_STREAM_PROCESSING_VPC_PEERING" | "ATLAS_AZURE_STREAM_PROCESSING_PRIVATELINK" | "ATLAS_AWS_STREAM_PROCESSING_PRIVATELINK" | "ATLAS_FLEX_AWS_100_USAGE_HOURS" | "ATLAS_FLEX_AWS_200_USAGE_HOURS" | "ATLAS_FLEX_AWS_300_USAGE_HOURS" | "ATLAS_FLEX_AWS_400_USAGE_HOURS" | "ATLAS_FLEX_AWS_500_USAGE_HOURS" | "ATLAS_FLEX_AZURE_100_USAGE_HOURS" | "ATLAS_FLEX_AZURE_200_USAGE_HOURS" | "ATLAS_FLEX_AZURE_300_USAGE_HOURS" | "ATLAS_FLEX_AZURE_400_USAGE_HOURS" | "ATLAS_FLEX_AZURE_500_USAGE_HOURS" | "ATLAS_FLEX_GCP_100_USAGE_HOURS" | "ATLAS_FLEX_GCP_200_USAGE_HOURS" | "ATLAS_FLEX_GCP_300_USAGE_HOURS" | "ATLAS_FLEX_GCP_400_USAGE_HOURS" | "ATLAS_FLEX_GCP_500_USAGE_HOURS"; /** * Format: date-time * @description Date and time when MongoDB Cloud began charging for this line item. This parameter expresses its value in the ISO 8601 timestamp format in UTC. @@ -4715,7 +3169,13 @@ export interface components { * @enum {string} */ type: "MONTHLY"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "MONTHLY"; + }; NetworkPermissionEntry: { /** @description Unique string of the Amazon Web Services (AWS) security group that you want to add to the project's IP access list. Your IP access list entry can be one **awsSecurityGroup**, one **cidrBlock**, or one **ipAddress**. You must configure Virtual Private Connection (VPC) peering for your project before you can add an AWS security group to an IP access list. You cannot set AWS security groups as temporary access list entries. Don't set this parameter if you set **cidrBlock** or **ipAddress**. */ awsSecurityGroup?: string; @@ -4771,16 +3231,8 @@ export interface components { * @enum {string} */ type: "DEFAULT" | "DAILY" | "WEEKLY" | "MONTHLY"; - } & ( - | components["schemas"]["DefaultScheduleView"] - | components["schemas"]["DailyScheduleView"] - | components["schemas"]["WeeklyScheduleView"] - | components["schemas"]["MonthlyScheduleView"] - ); - OrgActiveUserResponse: Omit< - WithRequired, - "orgMembershipStatus" - > & { + } & (components["schemas"]["DefaultScheduleView"] | components["schemas"]["DailyScheduleView"] | components["schemas"]["WeeklyScheduleView"] | components["schemas"]["MonthlyScheduleView"]); + OrgActiveUserResponse: Omit, "orgMembershipStatus"> & { /** * @description Two-character alphabetical string that identifies the MongoDB Cloud user's geographic location. This parameter uses the ISO 3166-1a2 code format. * @example US @@ -4814,7 +3266,13 @@ export interface components { * @enum {string} */ orgMembershipStatus: "ACTIVE"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + orgMembershipStatus: "ACTIVE"; + }; OrgGroup: { /** @description Settings that describe the clusters in each project that the API key is authorized to view. */ readonly clusters?: components["schemas"]["CloudCluster"][]; @@ -4831,10 +3289,7 @@ export interface components { /** @description List of human-readable labels that categorize the specified project. MongoDB Cloud returns an empty array. */ readonly tags?: string[]; }; - OrgPendingUserResponse: Omit< - WithRequired, - "orgMembershipStatus" - > & { + OrgPendingUserResponse: Omit, "orgMembershipStatus"> & { /** * Format: date-time * @description Date and time when MongoDB Cloud sent the invitation. MongoDB Cloud represents this timestamp in ISO 8601 format in UTC. @@ -4856,7 +3311,13 @@ export interface components { * @enum {string} */ orgMembershipStatus: "PENDING"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + orgMembershipStatus: "PENDING"; + }; OrgUserResponse: { /** * @description Unique 24-hexadecimal digit string that identifies the MongoDB Cloud user. @@ -4882,14 +3343,7 @@ export interface components { /** @description List of project-level role assignments assigned to the MongoDB Cloud user. */ groupRoleAssignments?: components["schemas"]["GroupRoleAssignment"][]; /** @description One or more organization-level roles assigned to the MongoDB Cloud user. */ - orgRoles?: ( - | "ORG_OWNER" - | "ORG_GROUP_CREATOR" - | "ORG_BILLING_ADMIN" - | "ORG_BILLING_READ_ONLY" - | "ORG_READ_ONLY" - | "ORG_MEMBER" - )[]; + orgRoles?: ("ORG_OWNER" | "ORG_GROUP_CREATOR" | "ORG_BILLING_ADMIN" | "ORG_BILLING_READ_ONLY" | "ORG_READ_ONLY" | "ORG_MEMBER")[]; }; /** @description List of MongoDB Database users granted access to databases in the specified project. */ PaginatedApiAtlasDatabaseUserView: { @@ -4947,6 +3401,17 @@ export interface components { */ readonly totalCount?: number; }; + PaginatedOrganizationView: { + /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ + readonly links?: components["schemas"]["Link"][]; + /** @description List of returned documents that MongoDB Cloud provides when completing this request. */ + readonly results?: components["schemas"]["AtlasOrganization"][]; + /** + * Format: int32 + * @description Total number of documents available. MongoDB Cloud omits this value if `includeCount` is set to `false`. The total number is an estimate and may not be exact. + */ + readonly totalCount?: number; + }; /** * Periodic Cloud Provider Snapshot Source * @description Scheduled Cloud Provider Snapshot as Source for a Data Lake Pipeline. @@ -5030,10 +3495,7 @@ export interface components { */ status?: "DELETING" | "FAILED" | "STALE" | "PENDING" | "BUILDING" | "READY" | "DOES_NOT_EXIST"; }; - SearchIndex: Omit< - WithRequired, - "type" - > & { + SearchIndex: Omit, "type"> & { /** * @description Specific pre-defined method chosen to convert database field text into searchable words. This conversion reduces the text of fields into the smallest units of text. These units are called a **term** or **token**. This process, known as tokenization, involves a variety of changes made to the text in fields: * @@ -5048,53 +3510,7 @@ export interface components { * @default lucene.standard * @enum {string} */ - analyzer: - | "lucene.standard" - | "lucene.simple" - | "lucene.whitespace" - | "lucene.keyword" - | "lucene.arabic" - | "lucene.armenian" - | "lucene.basque" - | "lucene.bengali" - | "lucene.brazilian" - | "lucene.bulgarian" - | "lucene.catalan" - | "lucene.chinese" - | "lucene.cjk" - | "lucene.czech" - | "lucene.danish" - | "lucene.dutch" - | "lucene.english" - | "lucene.finnish" - | "lucene.french" - | "lucene.galician" - | "lucene.german" - | "lucene.greek" - | "lucene.hindi" - | "lucene.hungarian" - | "lucene.indonesian" - | "lucene.irish" - | "lucene.italian" - | "lucene.japanese" - | "lucene.korean" - | "lucene.kuromoji" - | "lucene.latvian" - | "lucene.lithuanian" - | "lucene.morfologik" - | "lucene.nori" - | "lucene.norwegian" - | "lucene.persian" - | "lucene.portuguese" - | "lucene.romanian" - | "lucene.russian" - | "lucene.smartcn" - | "lucene.sorani" - | "lucene.spanish" - | "lucene.swedish" - | "lucene.thai" - | "lucene.turkish" - | "lucene.ukrainian"; + analyzer: "lucene.standard" | "lucene.simple" | "lucene.whitespace" | "lucene.keyword" | "lucene.arabic" | "lucene.armenian" | "lucene.basque" | "lucene.bengali" | "lucene.brazilian" | "lucene.bulgarian" | "lucene.catalan" | "lucene.chinese" | "lucene.cjk" | "lucene.czech" | "lucene.danish" | "lucene.dutch" | "lucene.english" | "lucene.finnish" | "lucene.french" | "lucene.galician" | "lucene.german" | "lucene.greek" | "lucene.hindi" | "lucene.hungarian" | "lucene.indonesian" | "lucene.irish" | "lucene.italian" | "lucene.japanese" | "lucene.korean" | "lucene.kuromoji" | "lucene.latvian" | "lucene.lithuanian" | "lucene.morfologik" | "lucene.nori" | "lucene.norwegian" | "lucene.persian" | "lucene.portuguese" | "lucene.romanian" | "lucene.russian" | "lucene.smartcn" | "lucene.sorani" | "lucene.spanish" | "lucene.swedish" | "lucene.thai" | "lucene.turkish" | "lucene.ukrainian"; /** @description List of user-defined methods to convert database field text into searchable words. */ analyzers?: components["schemas"]["ApiAtlasFTSAnalyzersViewManual"][]; mappings?: components["schemas"]["ApiAtlasFTSMappingsViewManual"]; @@ -5103,53 +3519,7 @@ export interface components { * @default lucene.standard * @enum {string} */ - searchAnalyzer: - | "lucene.standard" - | "lucene.simple" - | "lucene.whitespace" - | "lucene.keyword" - | "lucene.arabic" - | "lucene.armenian" - | "lucene.basque" - | "lucene.bengali" - | "lucene.brazilian" - | "lucene.bulgarian" - | "lucene.catalan" - | "lucene.chinese" - | "lucene.cjk" - | "lucene.czech" - | "lucene.danish" - | "lucene.dutch" - | "lucene.english" - | "lucene.finnish" - | "lucene.french" - | "lucene.galician" - | "lucene.german" - | "lucene.greek" - | "lucene.hindi" - | "lucene.hungarian" - | "lucene.indonesian" - | "lucene.irish" - | "lucene.italian" - | "lucene.japanese" - | "lucene.korean" - | "lucene.kuromoji" - | "lucene.latvian" - | "lucene.lithuanian" - | "lucene.morfologik" - | "lucene.nori" - | "lucene.norwegian" - | "lucene.persian" - | "lucene.portuguese" - | "lucene.romanian" - | "lucene.russian" - | "lucene.smartcn" - | "lucene.sorani" - | "lucene.spanish" - | "lucene.swedish" - | "lucene.thai" - | "lucene.turkish" - | "lucene.ukrainian"; + searchAnalyzer: "lucene.standard" | "lucene.simple" | "lucene.whitespace" | "lucene.keyword" | "lucene.arabic" | "lucene.armenian" | "lucene.basque" | "lucene.bengali" | "lucene.brazilian" | "lucene.bulgarian" | "lucene.catalan" | "lucene.chinese" | "lucene.cjk" | "lucene.czech" | "lucene.danish" | "lucene.dutch" | "lucene.english" | "lucene.finnish" | "lucene.french" | "lucene.galician" | "lucene.german" | "lucene.greek" | "lucene.hindi" | "lucene.hungarian" | "lucene.indonesian" | "lucene.irish" | "lucene.italian" | "lucene.japanese" | "lucene.korean" | "lucene.kuromoji" | "lucene.latvian" | "lucene.lithuanian" | "lucene.morfologik" | "lucene.nori" | "lucene.norwegian" | "lucene.persian" | "lucene.portuguese" | "lucene.romanian" | "lucene.russian" | "lucene.smartcn" | "lucene.sorani" | "lucene.spanish" | "lucene.swedish" | "lucene.thai" | "lucene.turkish" | "lucene.ukrainian"; /** * @description Flag that indicates whether to store all fields (true) on Atlas Search. By default, Atlas doesn't store (false) the fields on Atlas Search. Alternatively, you can specify an object that only contains the list of fields to store (include) or not store (exclude) on Atlas Search. To learn more, see documentation. * @example { @@ -5316,53 +3686,7 @@ export interface components { * @description Specific pre-defined method chosen to apply to the synonyms to be searched. * @enum {string} */ - analyzer: - | "lucene.standard" - | "lucene.simple" - | "lucene.whitespace" - | "lucene.keyword" - | "lucene.arabic" - | "lucene.armenian" - | "lucene.basque" - | "lucene.bengali" - | "lucene.brazilian" - | "lucene.bulgarian" - | "lucene.catalan" - | "lucene.chinese" - | "lucene.cjk" - | "lucene.czech" - | "lucene.danish" - | "lucene.dutch" - | "lucene.english" - | "lucene.finnish" - | "lucene.french" - | "lucene.galician" - | "lucene.german" - | "lucene.greek" - | "lucene.hindi" - | "lucene.hungarian" - | "lucene.indonesian" - | "lucene.irish" - | "lucene.italian" - | "lucene.japanese" - | "lucene.korean" - | "lucene.kuromoji" - | "lucene.latvian" - | "lucene.lithuanian" - | "lucene.morfologik" - | "lucene.nori" - | "lucene.norwegian" - | "lucene.persian" - | "lucene.portuguese" - | "lucene.romanian" - | "lucene.russian" - | "lucene.smartcn" - | "lucene.sorani" - | "lucene.spanish" - | "lucene.swedish" - | "lucene.thai" - | "lucene.turkish" - | "lucene.ukrainian"; + analyzer: "lucene.standard" | "lucene.simple" | "lucene.whitespace" | "lucene.keyword" | "lucene.arabic" | "lucene.armenian" | "lucene.basque" | "lucene.bengali" | "lucene.brazilian" | "lucene.bulgarian" | "lucene.catalan" | "lucene.chinese" | "lucene.cjk" | "lucene.czech" | "lucene.danish" | "lucene.dutch" | "lucene.english" | "lucene.finnish" | "lucene.french" | "lucene.galician" | "lucene.german" | "lucene.greek" | "lucene.hindi" | "lucene.hungarian" | "lucene.indonesian" | "lucene.irish" | "lucene.italian" | "lucene.japanese" | "lucene.korean" | "lucene.kuromoji" | "lucene.latvian" | "lucene.lithuanian" | "lucene.morfologik" | "lucene.nori" | "lucene.norwegian" | "lucene.persian" | "lucene.portuguese" | "lucene.romanian" | "lucene.russian" | "lucene.smartcn" | "lucene.sorani" | "lucene.spanish" | "lucene.swedish" | "lucene.thai" | "lucene.turkish" | "lucene.ukrainian"; /** @description Label that identifies the synonym definition. Each **synonym.name** must be unique within the same index definition. */ name: string; source: components["schemas"]["SynonymSource"]; @@ -5371,10 +3695,7 @@ export interface components { * AWS * @description Updates to a serverless AWS tenant endpoint. */ - ServerlessAWSTenantEndpointUpdate: Omit< - WithRequired, - "providerName" - > & { + ServerlessAWSTenantEndpointUpdate: Omit, "providerName"> & { /** @description Unique string that identifies the private endpoint's network interface. */ cloudProviderEndpointId?: string; } & { @@ -5388,10 +3709,7 @@ export interface components { * AZURE * @description Updates to a serverless Azure tenant endpoint. */ - ServerlessAzureTenantEndpointUpdate: Omit< - WithRequired, - "providerName" - > & { + ServerlessAzureTenantEndpointUpdate: Omit, "providerName"> & { /** @description Unique string that identifies the Azure private endpoint's network interface for this private endpoint service. */ cloudProviderEndpointId?: string; /** @description IPv4 address of the private endpoint in your Azure VNet that someone added to this private endpoint service. */ @@ -5431,7 +3749,13 @@ export interface components { * @enum {string} */ type: "AWSLambda"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "AWSLambda"; + }; StreamsClusterConnection: Omit & { /** @description Name of the cluster configured for this connection. */ clusterName?: string; @@ -5442,7 +3766,13 @@ export interface components { * @enum {string} */ type: "Cluster"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "Cluster"; + }; /** @description Settings that define a connection to an external data store. */ StreamsConnection: { /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ @@ -5454,14 +3784,7 @@ export interface components { * @enum {string} */ type?: "Kafka" | "Cluster" | "Sample" | "Https" | "AWSLambda"; - } & ( - | components["schemas"]["StreamsSampleConnection"] - | components["schemas"]["StreamsClusterConnection"] - | components["schemas"]["StreamsKafkaConnection"] - | components["schemas"]["StreamsHttpsConnection"] - | components["schemas"]["StreamsAWSLambdaConnection"] - | components["schemas"]["StreamsS3Connection"] - ); + } & (components["schemas"]["StreamsSampleConnection"] | components["schemas"]["StreamsClusterConnection"] | components["schemas"]["StreamsKafkaConnection"] | components["schemas"]["StreamsHttpsConnection"] | components["schemas"]["StreamsAWSLambdaConnection"] | components["schemas"]["StreamsS3Connection"]); StreamsHttpsConnection: Omit & { /** @description A map of key-value pairs that will be passed as headers for the request. */ headers?: { @@ -5475,7 +3798,13 @@ export interface components { * @enum {string} */ type: "Https"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "Https"; + }; /** @description User credentials required to connect to a Kafka Cluster. Includes the authentication type, as well as the parameters for that authentication mode. */ StreamsKafkaAuthentication: { /** @description List of one or more Uniform Resource Locators (URLs) that point to API sub-resources, related API resources, or both. RFC 5988 outlines these relationships. */ @@ -5518,7 +3847,13 @@ export interface components { * @enum {string} */ type: "Kafka"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "Kafka"; + }; /** @description Networking Access Type can either be 'PUBLIC' (default) or VPC. VPC type is in public preview, please file a support ticket to enable VPC Network Access. */ StreamsKafkaNetworking: { access?: components["schemas"]["StreamsKafkaNetworkingAccess"]; @@ -5561,14 +3896,26 @@ export interface components { * @enum {string} */ type: "S3"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "S3"; + }; StreamsSampleConnection: Omit & { /** * @description discriminator enum property added by openapi-typescript * @enum {string} */ type: "Sample"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "Sample"; + }; /** * Synonym Mapping Status Detail * @description Contains the status of the index's synonym mappings on each search host. This field (and its subfields) only appear if the index has synonyms defined. @@ -5653,7 +4000,13 @@ export interface components { * @enum {string} */ providerName: "TENANT"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "TENANT"; + }; /** * Tenant Regional Replication Specifications * @description Details that explain how MongoDB Cloud replicates data in one region on the specified MongoDB database. @@ -5672,7 +4025,13 @@ export interface components { * @enum {string} */ providerName: "TENANT"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + providerName: "TENANT"; + }; /** Text Search Host Status Detail */ TextSearchHostStatusDetail: { /** @description Hostname that corresponds to the status detail. */ @@ -5695,10 +4054,7 @@ export interface components { status?: "DELETING" | "FAILED" | "STALE" | "PENDING" | "BUILDING" | "READY" | "DOES_NOT_EXIST"; }; /** @description Text Search Index Create Request */ - TextSearchIndexCreateRequest: Omit< - WithRequired, - "type" - > & { + TextSearchIndexCreateRequest: Omit, "type"> & { definition: components["schemas"]["TextSearchIndexDefinition"]; } & { /** @@ -5726,53 +4082,7 @@ export interface components { * @default lucene.standard * @enum {string} */ - analyzer: - | "lucene.standard" - | "lucene.simple" - | "lucene.whitespace" - | "lucene.keyword" - | "lucene.arabic" - | "lucene.armenian" - | "lucene.basque" - | "lucene.bengali" - | "lucene.brazilian" - | "lucene.bulgarian" - | "lucene.catalan" - | "lucene.chinese" - | "lucene.cjk" - | "lucene.czech" - | "lucene.danish" - | "lucene.dutch" - | "lucene.english" - | "lucene.finnish" - | "lucene.french" - | "lucene.galician" - | "lucene.german" - | "lucene.greek" - | "lucene.hindi" - | "lucene.hungarian" - | "lucene.indonesian" - | "lucene.irish" - | "lucene.italian" - | "lucene.japanese" - | "lucene.korean" - | "lucene.kuromoji" - | "lucene.latvian" - | "lucene.lithuanian" - | "lucene.morfologik" - | "lucene.nori" - | "lucene.norwegian" - | "lucene.persian" - | "lucene.portuguese" - | "lucene.romanian" - | "lucene.russian" - | "lucene.smartcn" - | "lucene.sorani" - | "lucene.spanish" - | "lucene.swedish" - | "lucene.thai" - | "lucene.turkish" - | "lucene.ukrainian"; + analyzer: "lucene.standard" | "lucene.simple" | "lucene.whitespace" | "lucene.keyword" | "lucene.arabic" | "lucene.armenian" | "lucene.basque" | "lucene.bengali" | "lucene.brazilian" | "lucene.bulgarian" | "lucene.catalan" | "lucene.chinese" | "lucene.cjk" | "lucene.czech" | "lucene.danish" | "lucene.dutch" | "lucene.english" | "lucene.finnish" | "lucene.french" | "lucene.galician" | "lucene.german" | "lucene.greek" | "lucene.hindi" | "lucene.hungarian" | "lucene.indonesian" | "lucene.irish" | "lucene.italian" | "lucene.japanese" | "lucene.korean" | "lucene.kuromoji" | "lucene.latvian" | "lucene.lithuanian" | "lucene.morfologik" | "lucene.nori" | "lucene.norwegian" | "lucene.persian" | "lucene.portuguese" | "lucene.romanian" | "lucene.russian" | "lucene.smartcn" | "lucene.sorani" | "lucene.spanish" | "lucene.swedish" | "lucene.thai" | "lucene.turkish" | "lucene.ukrainian"; /** @description List of user-defined methods to convert database field text into searchable words. */ analyzers?: components["schemas"]["AtlasSearchAnalyzer"][]; mappings: components["schemas"]["SearchMappings"]; @@ -5787,53 +4097,7 @@ export interface components { * @default lucene.standard * @enum {string} */ - searchAnalyzer: - | "lucene.standard" - | "lucene.simple" - | "lucene.whitespace" - | "lucene.keyword" - | "lucene.arabic" - | "lucene.armenian" - | "lucene.basque" - | "lucene.bengali" - | "lucene.brazilian" - | "lucene.bulgarian" - | "lucene.catalan" - | "lucene.chinese" - | "lucene.cjk" - | "lucene.czech" - | "lucene.danish" - | "lucene.dutch" - | "lucene.english" - | "lucene.finnish" - | "lucene.french" - | "lucene.galician" - | "lucene.german" - | "lucene.greek" - | "lucene.hindi" - | "lucene.hungarian" - | "lucene.indonesian" - | "lucene.irish" - | "lucene.italian" - | "lucene.japanese" - | "lucene.korean" - | "lucene.kuromoji" - | "lucene.latvian" - | "lucene.lithuanian" - | "lucene.morfologik" - | "lucene.nori" - | "lucene.norwegian" - | "lucene.persian" - | "lucene.portuguese" - | "lucene.romanian" - | "lucene.russian" - | "lucene.smartcn" - | "lucene.sorani" - | "lucene.spanish" - | "lucene.swedish" - | "lucene.thai" - | "lucene.turkish" - | "lucene.ukrainian"; + searchAnalyzer: "lucene.standard" | "lucene.simple" | "lucene.whitespace" | "lucene.keyword" | "lucene.arabic" | "lucene.armenian" | "lucene.basque" | "lucene.bengali" | "lucene.brazilian" | "lucene.bulgarian" | "lucene.catalan" | "lucene.chinese" | "lucene.cjk" | "lucene.czech" | "lucene.danish" | "lucene.dutch" | "lucene.english" | "lucene.finnish" | "lucene.french" | "lucene.galician" | "lucene.german" | "lucene.greek" | "lucene.hindi" | "lucene.hungarian" | "lucene.indonesian" | "lucene.irish" | "lucene.italian" | "lucene.japanese" | "lucene.korean" | "lucene.kuromoji" | "lucene.latvian" | "lucene.lithuanian" | "lucene.morfologik" | "lucene.nori" | "lucene.norwegian" | "lucene.persian" | "lucene.portuguese" | "lucene.romanian" | "lucene.russian" | "lucene.smartcn" | "lucene.sorani" | "lucene.spanish" | "lucene.swedish" | "lucene.thai" | "lucene.turkish" | "lucene.ukrainian"; /** * @description Flag that indicates whether to store all fields (true) on Atlas Search. By default, Atlas doesn't store (false) the fields on Atlas Search. Alternatively, you can specify an object that only contains the list of fields to store (include) or not store (exclude) on Atlas Search. To learn more, see Stored Source Fields. * @example { @@ -6073,10 +4337,7 @@ export interface components { */ status?: "DELETING" | "FAILED" | "STALE" | "PENDING" | "BUILDING" | "READY" | "DOES_NOT_EXIST"; }; - VectorSearchIndex: Omit< - WithRequired, - "type" - > & { + VectorSearchIndex: Omit, "type"> & { /** @description Settings that configure the fields, one per object, to index. You must define at least one "vector" type field. You can optionally define "filter" type fields also. */ fields?: components["schemas"]["BasicDBObject"][]; } & { @@ -6087,10 +4348,7 @@ export interface components { type: "vectorSearch"; }; /** @description Vector Search Index Create Request */ - VectorSearchIndexCreateRequest: Omit< - WithRequired, - "type" - > & { + VectorSearchIndexCreateRequest: Omit, "type"> & { definition: components["schemas"]["VectorSearchIndexDefinition"]; } & { /** @@ -6181,7 +4439,13 @@ export interface components { * @enum {string} */ type: "WEEKLY"; - } ; + } & { + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + type: "WEEKLY"; + }; /** * htmlStrip * @description Filter that strips out HTML constructs. @@ -6438,32 +4702,7 @@ export interface components { * @description Snowball-generated stemmer to use. * @enum {string} */ - stemmerName: - | "arabic" - | "armenian" - | "basque" - | "catalan" - | "danish" - | "dutch" - | "english" - | "finnish" - | "french" - | "german" - | "german2" - | "hungarian" - | "irish" - | "italian" - | "kp" - | "lithuanian" - | "lovins" - | "norwegian" - | "porter" - | "portuguese" - | "romanian" - | "russian" - | "spanish" - | "swedish" - | "turkish"; + stemmerName: "arabic" | "armenian" | "basque" | "catalan" | "danish" | "dutch" | "english" | "finnish" | "french" | "german" | "german2" | "hungarian" | "irish" | "italian" | "kp" | "lithuanian" | "lovins" | "norwegian" | "porter" | "portuguese" | "romanian" | "russian" | "spanish" | "swedish" | "turkish"; /** * @description Human-readable label that identifies this token filter type. * @enum {string} @@ -6693,6 +4932,8 @@ export interface components { includeCount: boolean; /** @description Number of items that the response returns per page. */ itemsPerPage: number; + /** @description Unique 24-hexadecimal digit string that identifies the organization that contains your projects. Use the [/orgs](#tag/Organizations/operation/listOrganizations) endpoint to retrieve all organizations to which the authenticated user has access. */ + orgId: string; /** @description Number of the page that displays the current set of the total objects that the response returns. */ pageNum: number; /** @description Flag that indicates whether the response body should be in the prettyprint format. */ @@ -6702,261 +4943,246 @@ export interface components { headers: never; pathItems: never; } -export type AwsCloudProviderContainer = components["schemas"]["AWSCloudProviderContainer"]; -export type AwsCloudProviderSettings = components["schemas"]["AWSCloudProviderSettings"]; -export type AwsComputeAutoScaling = components["schemas"]["AWSComputeAutoScaling"]; -export type AwsCreateDataProcessRegionView = components["schemas"]["AWSCreateDataProcessRegionView"]; -export type AwsDataProcessRegionView = components["schemas"]["AWSDataProcessRegionView"]; -export type AwsHardwareSpec = components["schemas"]["AWSHardwareSpec"]; -export type AwsHardwareSpec20240805 = components["schemas"]["AWSHardwareSpec20240805"]; -export type AwsRegionConfig = components["schemas"]["AWSRegionConfig"]; -export type AwsRegionConfig20240805 = components["schemas"]["AWSRegionConfig20240805"]; -export type AdvancedAutoScalingSettings = components["schemas"]["AdvancedAutoScalingSettings"]; -export type AdvancedComputeAutoScaling = components["schemas"]["AdvancedComputeAutoScaling"]; -export type ApiAtlasCloudProviderAccessFeatureUsageFeatureIdView = - components["schemas"]["ApiAtlasCloudProviderAccessFeatureUsageFeatureIdView"]; -export type ApiAtlasClusterAdvancedConfigurationView = - components["schemas"]["ApiAtlasClusterAdvancedConfigurationView"]; -export type ApiAtlasFtsAnalyzersViewManual = components["schemas"]["ApiAtlasFTSAnalyzersViewManual"]; -export type ApiAtlasFtsMappingsViewManual = components["schemas"]["ApiAtlasFTSMappingsViewManual"]; -export type ApiError = components["schemas"]["ApiError"]; -export type AtlasSearchAnalyzer = components["schemas"]["AtlasSearchAnalyzer"]; -export type AzureCloudProviderContainer = components["schemas"]["AzureCloudProviderContainer"]; -export type AzureCloudProviderSettings = components["schemas"]["AzureCloudProviderSettings"]; -export type AzureComputeAutoScalingRules = components["schemas"]["AzureComputeAutoScalingRules"]; -export type AzureCreateDataProcessRegionView = components["schemas"]["AzureCreateDataProcessRegionView"]; -export type AzureDataProcessRegionView = components["schemas"]["AzureDataProcessRegionView"]; -export type AzureHardwareSpec = components["schemas"]["AzureHardwareSpec"]; -export type AzureHardwareSpec20240805 = components["schemas"]["AzureHardwareSpec20240805"]; -export type AzureRegionConfig = components["schemas"]["AzureRegionConfig"]; -export type AzureRegionConfig20240805 = components["schemas"]["AzureRegionConfig20240805"]; -export type BadRequestDetail = components["schemas"]["BadRequestDetail"]; -export type BaseCloudProviderInstanceSize = components["schemas"]["BaseCloudProviderInstanceSize"]; -export type BasicDbObject = components["schemas"]["BasicDBObject"]; -export type BiConnector = components["schemas"]["BiConnector"]; -export type BillingInvoice = components["schemas"]["BillingInvoice"]; -export type BillingInvoiceMetadata = components["schemas"]["BillingInvoiceMetadata"]; -export type BillingPayment = components["schemas"]["BillingPayment"]; -export type BillingRefund = components["schemas"]["BillingRefund"]; -export type CloudCluster = components["schemas"]["CloudCluster"]; -export type CloudDatabaseUser = components["schemas"]["CloudDatabaseUser"]; -export type CloudGcpProviderSettings = components["schemas"]["CloudGCPProviderSettings"]; -export type CloudProviderAwsAutoScaling = components["schemas"]["CloudProviderAWSAutoScaling"]; -export type CloudProviderAccessAwsiamRole = components["schemas"]["CloudProviderAccessAWSIAMRole"]; -export type CloudProviderAccessAwsiamRoleRequestUpdate = - components["schemas"]["CloudProviderAccessAWSIAMRoleRequestUpdate"]; -export type CloudProviderAccessAzureServicePrincipal = - components["schemas"]["CloudProviderAccessAzureServicePrincipal"]; -export type CloudProviderAccessAzureServicePrincipalRequestUpdate = - components["schemas"]["CloudProviderAccessAzureServicePrincipalRequestUpdate"]; -export type CloudProviderAccessDataLakeFeatureUsage = components["schemas"]["CloudProviderAccessDataLakeFeatureUsage"]; -export type CloudProviderAccessEncryptionAtRestFeatureUsage = - components["schemas"]["CloudProviderAccessEncryptionAtRestFeatureUsage"]; -export type CloudProviderAccessExportSnapshotFeatureUsage = - components["schemas"]["CloudProviderAccessExportSnapshotFeatureUsage"]; -export type CloudProviderAccessFeatureUsage = components["schemas"]["CloudProviderAccessFeatureUsage"]; -export type CloudProviderAccessFeatureUsageDataLakeFeatureId = - components["schemas"]["CloudProviderAccessFeatureUsageDataLakeFeatureId"]; -export type CloudProviderAccessFeatureUsageExportSnapshotFeatureId = - components["schemas"]["CloudProviderAccessFeatureUsageExportSnapshotFeatureId"]; -export type CloudProviderAccessFeatureUsagePushBasedLogExportFeatureId = - components["schemas"]["CloudProviderAccessFeatureUsagePushBasedLogExportFeatureId"]; -export type CloudProviderAccessGcpServiceAccount = components["schemas"]["CloudProviderAccessGCPServiceAccount"]; -export type CloudProviderAccessGcpServiceAccountRequestUpdate = - components["schemas"]["CloudProviderAccessGCPServiceAccountRequestUpdate"]; -export type CloudProviderAccessPushBasedLogExportFeatureUsage = - components["schemas"]["CloudProviderAccessPushBasedLogExportFeatureUsage"]; -export type CloudProviderAccessRole = components["schemas"]["CloudProviderAccessRole"]; -export type CloudProviderAccessRoleRequestUpdate = components["schemas"]["CloudProviderAccessRoleRequestUpdate"]; -export type CloudProviderAzureAutoScaling = components["schemas"]["CloudProviderAzureAutoScaling"]; -export type CloudProviderContainer = components["schemas"]["CloudProviderContainer"]; -export type CloudProviderGcpAutoScaling = components["schemas"]["CloudProviderGCPAutoScaling"]; -export type CloudRegionConfig = components["schemas"]["CloudRegionConfig"]; -export type CloudRegionConfig20240805 = components["schemas"]["CloudRegionConfig20240805"]; -export type ClusterConnectionStrings = components["schemas"]["ClusterConnectionStrings"]; -export type ClusterDescription20240805 = components["schemas"]["ClusterDescription20240805"]; -export type ClusterDescriptionConnectionStringsPrivateEndpoint = - components["schemas"]["ClusterDescriptionConnectionStringsPrivateEndpoint"]; -export type ClusterDescriptionConnectionStringsPrivateEndpointEndpoint = - components["schemas"]["ClusterDescriptionConnectionStringsPrivateEndpointEndpoint"]; -export type ClusterFlexProviderSettings = components["schemas"]["ClusterFlexProviderSettings"]; -export type ClusterFreeAutoScaling = components["schemas"]["ClusterFreeAutoScaling"]; -export type ClusterFreeProviderSettings = components["schemas"]["ClusterFreeProviderSettings"]; -export type ClusterProviderSettings = components["schemas"]["ClusterProviderSettings"]; -export type ClusterSearchIndex = components["schemas"]["ClusterSearchIndex"]; -export type ComponentLabel = components["schemas"]["ComponentLabel"]; -export type CreateAwsEndpointRequest = components["schemas"]["CreateAWSEndpointRequest"]; -export type CreateAzureEndpointRequest = components["schemas"]["CreateAzureEndpointRequest"]; -export type CreateDataProcessRegionView = components["schemas"]["CreateDataProcessRegionView"]; -export type CreateEndpointRequest = components["schemas"]["CreateEndpointRequest"]; -export type CreateGcpEndpointGroupRequest = components["schemas"]["CreateGCPEndpointGroupRequest"]; -export type CreateGcpForwardingRuleRequest = components["schemas"]["CreateGCPForwardingRuleRequest"]; -export type CriteriaView = components["schemas"]["CriteriaView"]; -export type CustomCriteriaView = components["schemas"]["CustomCriteriaView"]; -export type DbRoleToExecute = components["schemas"]["DBRoleToExecute"]; -export type DlsIngestionSink = components["schemas"]["DLSIngestionSink"]; -export type DailyScheduleView = components["schemas"]["DailyScheduleView"]; -export type DataLakeAtlasStoreInstance = components["schemas"]["DataLakeAtlasStoreInstance"]; -export type DataLakeAtlasStoreReadConcern = components["schemas"]["DataLakeAtlasStoreReadConcern"]; -export type DataLakeAtlasStoreReadPreference = components["schemas"]["DataLakeAtlasStoreReadPreference"]; -export type DataLakeAtlasStoreReadPreferenceTag = components["schemas"]["DataLakeAtlasStoreReadPreferenceTag"]; -export type DataLakeAzureBlobStore = components["schemas"]["DataLakeAzureBlobStore"]; -export type DataLakeDlsawsStore = components["schemas"]["DataLakeDLSAWSStore"]; -export type DataLakeDlsAzureStore = components["schemas"]["DataLakeDLSAzureStore"]; -export type DataLakeDlsgcpStore = components["schemas"]["DataLakeDLSGCPStore"]; -export type DataLakeGoogleCloudStorageStore = components["schemas"]["DataLakeGoogleCloudStorageStore"]; -export type DataLakeHttpStore = components["schemas"]["DataLakeHTTPStore"]; -export type DataLakePipelinesPartitionField = components["schemas"]["DataLakePipelinesPartitionField"]; -export type DataLakeS3StoreSettings = components["schemas"]["DataLakeS3StoreSettings"]; -export type DataLakeStoreSettings = components["schemas"]["DataLakeStoreSettings"]; -export type DataProcessRegionView = components["schemas"]["DataProcessRegionView"]; -export type DatabaseUserRole = components["schemas"]["DatabaseUserRole"]; -export type DateCriteriaView = components["schemas"]["DateCriteriaView"]; -export type DedicatedHardwareSpec = components["schemas"]["DedicatedHardwareSpec"]; -export type DedicatedHardwareSpec20240805 = components["schemas"]["DedicatedHardwareSpec20240805"]; -export type DefaultScheduleView = components["schemas"]["DefaultScheduleView"]; -export type DiskBackupSnapshotAwsExportBucketRequest = - components["schemas"]["DiskBackupSnapshotAWSExportBucketRequest"]; -export type DiskBackupSnapshotAwsExportBucketResponse = - components["schemas"]["DiskBackupSnapshotAWSExportBucketResponse"]; -export type DiskBackupSnapshotAzureExportBucketRequest = - components["schemas"]["DiskBackupSnapshotAzureExportBucketRequest"]; -export type DiskBackupSnapshotAzureExportBucketResponse = - components["schemas"]["DiskBackupSnapshotAzureExportBucketResponse"]; -export type DiskBackupSnapshotExportBucketRequest = components["schemas"]["DiskBackupSnapshotExportBucketRequest"]; -export type DiskBackupSnapshotExportBucketResponse = components["schemas"]["DiskBackupSnapshotExportBucketResponse"]; -export type DiskGbAutoScaling = components["schemas"]["DiskGBAutoScaling"]; -export type EmployeeAccessGrantView = components["schemas"]["EmployeeAccessGrantView"]; -export type FieldViolation = components["schemas"]["FieldViolation"]; -export type Fields = components["schemas"]["Fields"]; -export type FreeComputeAutoScalingRules = components["schemas"]["FreeComputeAutoScalingRules"]; -export type GcpCloudProviderContainer = components["schemas"]["GCPCloudProviderContainer"]; -export type GcpComputeAutoScaling = components["schemas"]["GCPComputeAutoScaling"]; -export type GcpCreateDataProcessRegionView = components["schemas"]["GCPCreateDataProcessRegionView"]; -export type GcpDataProcessRegionView = components["schemas"]["GCPDataProcessRegionView"]; -export type GcpHardwareSpec = components["schemas"]["GCPHardwareSpec"]; -export type GcpHardwareSpec20240805 = components["schemas"]["GCPHardwareSpec20240805"]; -export type GcpRegionConfig = components["schemas"]["GCPRegionConfig"]; -export type GcpRegionConfig20240805 = components["schemas"]["GCPRegionConfig20240805"]; -export type Group = components["schemas"]["Group"]; -export type GroupActiveUserResponse = components["schemas"]["GroupActiveUserResponse"]; -export type GroupPendingUserResponse = components["schemas"]["GroupPendingUserResponse"]; -export type GroupRoleAssignment = components["schemas"]["GroupRoleAssignment"]; -export type GroupUserResponse = components["schemas"]["GroupUserResponse"]; -export type HardwareSpec = components["schemas"]["HardwareSpec"]; -export type HardwareSpec20240805 = components["schemas"]["HardwareSpec20240805"]; -export type IngestionSink = components["schemas"]["IngestionSink"]; -export type IngestionSource = components["schemas"]["IngestionSource"]; -export type InvoiceLineItem = components["schemas"]["InvoiceLineItem"]; -export type Link = components["schemas"]["Link"]; -export type MonthlyScheduleView = components["schemas"]["MonthlyScheduleView"]; -export type NetworkPermissionEntry = components["schemas"]["NetworkPermissionEntry"]; -export type OnDemandCpsSnapshotSource = components["schemas"]["OnDemandCpsSnapshotSource"]; -export type OnlineArchiveSchedule = components["schemas"]["OnlineArchiveSchedule"]; -export type OrgActiveUserResponse = components["schemas"]["OrgActiveUserResponse"]; -export type OrgGroup = components["schemas"]["OrgGroup"]; -export type OrgPendingUserResponse = components["schemas"]["OrgPendingUserResponse"]; -export type OrgUserResponse = components["schemas"]["OrgUserResponse"]; -export type OrgUserRolesResponse = components["schemas"]["OrgUserRolesResponse"]; -export type PaginatedApiAtlasDatabaseUserView = components["schemas"]["PaginatedApiAtlasDatabaseUserView"]; -export type PaginatedAtlasGroupView = components["schemas"]["PaginatedAtlasGroupView"]; -export type PaginatedClusterDescription20240805 = components["schemas"]["PaginatedClusterDescription20240805"]; -export type PaginatedNetworkAccessView = components["schemas"]["PaginatedNetworkAccessView"]; -export type PaginatedOrgGroupView = components["schemas"]["PaginatedOrgGroupView"]; -export type PeriodicCpsSnapshotSource = components["schemas"]["PeriodicCpsSnapshotSource"]; -export type ReplicationSpec20240805 = components["schemas"]["ReplicationSpec20240805"]; -export type ResourceTag = components["schemas"]["ResourceTag"]; -export type SearchHostStatusDetail = components["schemas"]["SearchHostStatusDetail"]; -export type SearchIndex = components["schemas"]["SearchIndex"]; -export type SearchIndexCreateRequest = components["schemas"]["SearchIndexCreateRequest"]; -export type SearchIndexDefinition = components["schemas"]["SearchIndexDefinition"]; -export type SearchIndexDefinitionVersion = components["schemas"]["SearchIndexDefinitionVersion"]; -export type SearchIndexResponse = components["schemas"]["SearchIndexResponse"]; -export type SearchMainIndexStatusDetail = components["schemas"]["SearchMainIndexStatusDetail"]; -export type SearchMappings = components["schemas"]["SearchMappings"]; -export type SearchStagedIndexStatusDetail = components["schemas"]["SearchStagedIndexStatusDetail"]; -export type SearchSynonymMappingDefinition = components["schemas"]["SearchSynonymMappingDefinition"]; -export type ServerlessAwsTenantEndpointUpdate = components["schemas"]["ServerlessAWSTenantEndpointUpdate"]; -export type ServerlessAzureTenantEndpointUpdate = components["schemas"]["ServerlessAzureTenantEndpointUpdate"]; -export type ServerlessTenantEndpointUpdate = components["schemas"]["ServerlessTenantEndpointUpdate"]; -export type StreamsAwsConnectionConfig = components["schemas"]["StreamsAWSConnectionConfig"]; -export type StreamsAwsLambdaConnection = components["schemas"]["StreamsAWSLambdaConnection"]; -export type StreamsClusterConnection = components["schemas"]["StreamsClusterConnection"]; -export type StreamsConnection = components["schemas"]["StreamsConnection"]; -export type StreamsHttpsConnection = components["schemas"]["StreamsHttpsConnection"]; -export type StreamsKafkaAuthentication = components["schemas"]["StreamsKafkaAuthentication"]; -export type StreamsKafkaConnection = components["schemas"]["StreamsKafkaConnection"]; -export type StreamsKafkaNetworking = components["schemas"]["StreamsKafkaNetworking"]; -export type StreamsKafkaNetworkingAccess = components["schemas"]["StreamsKafkaNetworkingAccess"]; -export type StreamsKafkaSecurity = components["schemas"]["StreamsKafkaSecurity"]; -export type StreamsS3Connection = components["schemas"]["StreamsS3Connection"]; -export type StreamsSampleConnection = components["schemas"]["StreamsSampleConnection"]; -export type SynonymMappingStatusDetail = components["schemas"]["SynonymMappingStatusDetail"]; -export type SynonymMappingStatusDetailMap = components["schemas"]["SynonymMappingStatusDetailMap"]; -export type SynonymSource = components["schemas"]["SynonymSource"]; -export type TenantHardwareSpec = components["schemas"]["TenantHardwareSpec"]; -export type TenantHardwareSpec20240805 = components["schemas"]["TenantHardwareSpec20240805"]; -export type TenantRegionConfig = components["schemas"]["TenantRegionConfig"]; -export type TenantRegionConfig20240805 = components["schemas"]["TenantRegionConfig20240805"]; -export type TextSearchHostStatusDetail = components["schemas"]["TextSearchHostStatusDetail"]; -export type TextSearchIndexCreateRequest = components["schemas"]["TextSearchIndexCreateRequest"]; -export type TextSearchIndexDefinition = components["schemas"]["TextSearchIndexDefinition"]; -export type TextSearchIndexResponse = components["schemas"]["TextSearchIndexResponse"]; -export type TextSearchIndexStatusDetail = components["schemas"]["TextSearchIndexStatusDetail"]; -export type TokenFilterEnglishPossessive = components["schemas"]["TokenFilterEnglishPossessive"]; -export type TokenFilterFlattenGraph = components["schemas"]["TokenFilterFlattenGraph"]; -export type TokenFilterPorterStemming = components["schemas"]["TokenFilterPorterStemming"]; -export type TokenFilterSpanishPluralStemming = components["schemas"]["TokenFilterSpanishPluralStemming"]; -export type TokenFilterStempel = components["schemas"]["TokenFilterStempel"]; -export type TokenFilterWordDelimiterGraph = components["schemas"]["TokenFilterWordDelimiterGraph"]; -export type TokenFilterkStemming = components["schemas"]["TokenFilterkStemming"]; -export type UserScope = components["schemas"]["UserScope"]; -export type VectorSearchHostStatusDetail = components["schemas"]["VectorSearchHostStatusDetail"]; -export type VectorSearchIndex = components["schemas"]["VectorSearchIndex"]; -export type VectorSearchIndexCreateRequest = components["schemas"]["VectorSearchIndexCreateRequest"]; -export type VectorSearchIndexDefinition = components["schemas"]["VectorSearchIndexDefinition"]; -export type VectorSearchIndexResponse = components["schemas"]["VectorSearchIndexResponse"]; -export type VectorSearchIndexStatusDetail = components["schemas"]["VectorSearchIndexStatusDetail"]; -export type WeeklyScheduleView = components["schemas"]["WeeklyScheduleView"]; -export type CharFilterhtmlStrip = components["schemas"]["charFilterhtmlStrip"]; -export type CharFiltericuNormalize = components["schemas"]["charFiltericuNormalize"]; -export type CharFiltermapping = components["schemas"]["charFiltermapping"]; -export type CharFilterpersian = components["schemas"]["charFilterpersian"]; -export type TokenFilterasciiFolding = components["schemas"]["tokenFilterasciiFolding"]; -export type TokenFilterdaitchMokotoffSoundex = components["schemas"]["tokenFilterdaitchMokotoffSoundex"]; -export type TokenFilteredgeGram = components["schemas"]["tokenFilteredgeGram"]; -export type TokenFiltericuFolding = components["schemas"]["tokenFiltericuFolding"]; -export type TokenFiltericuNormalizer = components["schemas"]["tokenFiltericuNormalizer"]; -export type TokenFilterlength = components["schemas"]["tokenFilterlength"]; -export type TokenFilterlowercase = components["schemas"]["tokenFilterlowercase"]; -export type TokenFilternGram = components["schemas"]["tokenFilternGram"]; -export type TokenFilterregex = components["schemas"]["tokenFilterregex"]; -export type TokenFilterreverse = components["schemas"]["tokenFilterreverse"]; -export type TokenFiltershingle = components["schemas"]["tokenFiltershingle"]; -export type TokenFiltersnowballStemming = components["schemas"]["tokenFiltersnowballStemming"]; -export type TokenFilterstopword = components["schemas"]["tokenFilterstopword"]; -export type TokenFiltertrim = components["schemas"]["tokenFiltertrim"]; -export type TokenizeredgeGram = components["schemas"]["tokenizeredgeGram"]; -export type Tokenizerkeyword = components["schemas"]["tokenizerkeyword"]; -export type TokenizernGram = components["schemas"]["tokenizernGram"]; -export type TokenizerregexCaptureGroup = components["schemas"]["tokenizerregexCaptureGroup"]; -export type TokenizerregexSplit = components["schemas"]["tokenizerregexSplit"]; -export type Tokenizerstandard = components["schemas"]["tokenizerstandard"]; -export type TokenizeruaxUrlEmail = components["schemas"]["tokenizeruaxUrlEmail"]; -export type Tokenizerwhitespace = components["schemas"]["tokenizerwhitespace"]; -export type ResponseBadRequest = components["responses"]["badRequest"]; -export type ResponseConflict = components["responses"]["conflict"]; -export type ResponseForbidden = components["responses"]["forbidden"]; -export type ResponseInternalServerError = components["responses"]["internalServerError"]; -export type ResponseNotFound = components["responses"]["notFound"]; -export type ResponsePaymentRequired = components["responses"]["paymentRequired"]; -export type ResponseUnauthorized = components["responses"]["unauthorized"]; -export type ParameterEnvelope = components["parameters"]["envelope"]; -export type ParameterGroupId = components["parameters"]["groupId"]; -export type ParameterIncludeCount = components["parameters"]["includeCount"]; -export type ParameterItemsPerPage = components["parameters"]["itemsPerPage"]; -export type ParameterPageNum = components["parameters"]["pageNum"]; -export type ParameterPretty = components["parameters"]["pretty"]; +export type AwsCloudProviderContainer = components['schemas']['AWSCloudProviderContainer']; +export type AwsCloudProviderSettings = components['schemas']['AWSCloudProviderSettings']; +export type AwsComputeAutoScaling = components['schemas']['AWSComputeAutoScaling']; +export type AwsCreateDataProcessRegionView = components['schemas']['AWSCreateDataProcessRegionView']; +export type AwsDataProcessRegionView = components['schemas']['AWSDataProcessRegionView']; +export type AwsHardwareSpec = components['schemas']['AWSHardwareSpec']; +export type AwsHardwareSpec20240805 = components['schemas']['AWSHardwareSpec20240805']; +export type AwsRegionConfig = components['schemas']['AWSRegionConfig']; +export type AwsRegionConfig20240805 = components['schemas']['AWSRegionConfig20240805']; +export type AdvancedAutoScalingSettings = components['schemas']['AdvancedAutoScalingSettings']; +export type AdvancedComputeAutoScaling = components['schemas']['AdvancedComputeAutoScaling']; +export type ApiAtlasCloudProviderAccessFeatureUsageFeatureIdView = components['schemas']['ApiAtlasCloudProviderAccessFeatureUsageFeatureIdView']; +export type ApiAtlasClusterAdvancedConfigurationView = components['schemas']['ApiAtlasClusterAdvancedConfigurationView']; +export type ApiAtlasFtsAnalyzersViewManual = components['schemas']['ApiAtlasFTSAnalyzersViewManual']; +export type ApiAtlasFtsMappingsViewManual = components['schemas']['ApiAtlasFTSMappingsViewManual']; +export type ApiError = components['schemas']['ApiError']; +export type AtlasOrganization = components['schemas']['AtlasOrganization']; +export type AtlasSearchAnalyzer = components['schemas']['AtlasSearchAnalyzer']; +export type AzureCloudProviderContainer = components['schemas']['AzureCloudProviderContainer']; +export type AzureCloudProviderSettings = components['schemas']['AzureCloudProviderSettings']; +export type AzureComputeAutoScalingRules = components['schemas']['AzureComputeAutoScalingRules']; +export type AzureCreateDataProcessRegionView = components['schemas']['AzureCreateDataProcessRegionView']; +export type AzureDataProcessRegionView = components['schemas']['AzureDataProcessRegionView']; +export type AzureHardwareSpec = components['schemas']['AzureHardwareSpec']; +export type AzureHardwareSpec20240805 = components['schemas']['AzureHardwareSpec20240805']; +export type AzureRegionConfig = components['schemas']['AzureRegionConfig']; +export type AzureRegionConfig20240805 = components['schemas']['AzureRegionConfig20240805']; +export type BadRequestDetail = components['schemas']['BadRequestDetail']; +export type BaseCloudProviderInstanceSize = components['schemas']['BaseCloudProviderInstanceSize']; +export type BasicDbObject = components['schemas']['BasicDBObject']; +export type BiConnector = components['schemas']['BiConnector']; +export type BillingInvoice = components['schemas']['BillingInvoice']; +export type BillingInvoiceMetadata = components['schemas']['BillingInvoiceMetadata']; +export type BillingPayment = components['schemas']['BillingPayment']; +export type BillingRefund = components['schemas']['BillingRefund']; +export type CloudCluster = components['schemas']['CloudCluster']; +export type CloudDatabaseUser = components['schemas']['CloudDatabaseUser']; +export type CloudGcpProviderSettings = components['schemas']['CloudGCPProviderSettings']; +export type CloudProviderAwsAutoScaling = components['schemas']['CloudProviderAWSAutoScaling']; +export type CloudProviderAccessAwsiamRole = components['schemas']['CloudProviderAccessAWSIAMRole']; +export type CloudProviderAccessAwsiamRoleRequestUpdate = components['schemas']['CloudProviderAccessAWSIAMRoleRequestUpdate']; +export type CloudProviderAccessAzureServicePrincipal = components['schemas']['CloudProviderAccessAzureServicePrincipal']; +export type CloudProviderAccessAzureServicePrincipalRequestUpdate = components['schemas']['CloudProviderAccessAzureServicePrincipalRequestUpdate']; +export type CloudProviderAccessDataLakeFeatureUsage = components['schemas']['CloudProviderAccessDataLakeFeatureUsage']; +export type CloudProviderAccessEncryptionAtRestFeatureUsage = components['schemas']['CloudProviderAccessEncryptionAtRestFeatureUsage']; +export type CloudProviderAccessExportSnapshotFeatureUsage = components['schemas']['CloudProviderAccessExportSnapshotFeatureUsage']; +export type CloudProviderAccessFeatureUsage = components['schemas']['CloudProviderAccessFeatureUsage']; +export type CloudProviderAccessFeatureUsageDataLakeFeatureId = components['schemas']['CloudProviderAccessFeatureUsageDataLakeFeatureId']; +export type CloudProviderAccessFeatureUsageExportSnapshotFeatureId = components['schemas']['CloudProviderAccessFeatureUsageExportSnapshotFeatureId']; +export type CloudProviderAccessFeatureUsagePushBasedLogExportFeatureId = components['schemas']['CloudProviderAccessFeatureUsagePushBasedLogExportFeatureId']; +export type CloudProviderAccessGcpServiceAccount = components['schemas']['CloudProviderAccessGCPServiceAccount']; +export type CloudProviderAccessGcpServiceAccountRequestUpdate = components['schemas']['CloudProviderAccessGCPServiceAccountRequestUpdate']; +export type CloudProviderAccessPushBasedLogExportFeatureUsage = components['schemas']['CloudProviderAccessPushBasedLogExportFeatureUsage']; +export type CloudProviderAccessRole = components['schemas']['CloudProviderAccessRole']; +export type CloudProviderAccessRoleRequestUpdate = components['schemas']['CloudProviderAccessRoleRequestUpdate']; +export type CloudProviderAzureAutoScaling = components['schemas']['CloudProviderAzureAutoScaling']; +export type CloudProviderContainer = components['schemas']['CloudProviderContainer']; +export type CloudProviderGcpAutoScaling = components['schemas']['CloudProviderGCPAutoScaling']; +export type CloudRegionConfig = components['schemas']['CloudRegionConfig']; +export type CloudRegionConfig20240805 = components['schemas']['CloudRegionConfig20240805']; +export type ClusterConnectionStrings = components['schemas']['ClusterConnectionStrings']; +export type ClusterDescription20240805 = components['schemas']['ClusterDescription20240805']; +export type ClusterDescriptionConnectionStringsPrivateEndpoint = components['schemas']['ClusterDescriptionConnectionStringsPrivateEndpoint']; +export type ClusterDescriptionConnectionStringsPrivateEndpointEndpoint = components['schemas']['ClusterDescriptionConnectionStringsPrivateEndpointEndpoint']; +export type ClusterFlexProviderSettings = components['schemas']['ClusterFlexProviderSettings']; +export type ClusterFreeAutoScaling = components['schemas']['ClusterFreeAutoScaling']; +export type ClusterFreeProviderSettings = components['schemas']['ClusterFreeProviderSettings']; +export type ClusterProviderSettings = components['schemas']['ClusterProviderSettings']; +export type ClusterSearchIndex = components['schemas']['ClusterSearchIndex']; +export type ComponentLabel = components['schemas']['ComponentLabel']; +export type CreateAwsEndpointRequest = components['schemas']['CreateAWSEndpointRequest']; +export type CreateAzureEndpointRequest = components['schemas']['CreateAzureEndpointRequest']; +export type CreateDataProcessRegionView = components['schemas']['CreateDataProcessRegionView']; +export type CreateEndpointRequest = components['schemas']['CreateEndpointRequest']; +export type CreateGcpEndpointGroupRequest = components['schemas']['CreateGCPEndpointGroupRequest']; +export type CreateGcpForwardingRuleRequest = components['schemas']['CreateGCPForwardingRuleRequest']; +export type CriteriaView = components['schemas']['CriteriaView']; +export type CustomCriteriaView = components['schemas']['CustomCriteriaView']; +export type DbRoleToExecute = components['schemas']['DBRoleToExecute']; +export type DlsIngestionSink = components['schemas']['DLSIngestionSink']; +export type DailyScheduleView = components['schemas']['DailyScheduleView']; +export type DataLakeAtlasStoreInstance = components['schemas']['DataLakeAtlasStoreInstance']; +export type DataLakeAtlasStoreReadConcern = components['schemas']['DataLakeAtlasStoreReadConcern']; +export type DataLakeAtlasStoreReadPreference = components['schemas']['DataLakeAtlasStoreReadPreference']; +export type DataLakeAtlasStoreReadPreferenceTag = components['schemas']['DataLakeAtlasStoreReadPreferenceTag']; +export type DataLakeAzureBlobStore = components['schemas']['DataLakeAzureBlobStore']; +export type DataLakeDlsawsStore = components['schemas']['DataLakeDLSAWSStore']; +export type DataLakeDlsAzureStore = components['schemas']['DataLakeDLSAzureStore']; +export type DataLakeDlsgcpStore = components['schemas']['DataLakeDLSGCPStore']; +export type DataLakeGoogleCloudStorageStore = components['schemas']['DataLakeGoogleCloudStorageStore']; +export type DataLakeHttpStore = components['schemas']['DataLakeHTTPStore']; +export type DataLakePipelinesPartitionField = components['schemas']['DataLakePipelinesPartitionField']; +export type DataLakeS3StoreSettings = components['schemas']['DataLakeS3StoreSettings']; +export type DataLakeStoreSettings = components['schemas']['DataLakeStoreSettings']; +export type DataProcessRegionView = components['schemas']['DataProcessRegionView']; +export type DatabaseUserRole = components['schemas']['DatabaseUserRole']; +export type DateCriteriaView = components['schemas']['DateCriteriaView']; +export type DedicatedHardwareSpec = components['schemas']['DedicatedHardwareSpec']; +export type DedicatedHardwareSpec20240805 = components['schemas']['DedicatedHardwareSpec20240805']; +export type DefaultScheduleView = components['schemas']['DefaultScheduleView']; +export type DiskBackupSnapshotAwsExportBucketRequest = components['schemas']['DiskBackupSnapshotAWSExportBucketRequest']; +export type DiskBackupSnapshotAwsExportBucketResponse = components['schemas']['DiskBackupSnapshotAWSExportBucketResponse']; +export type DiskBackupSnapshotAzureExportBucketRequest = components['schemas']['DiskBackupSnapshotAzureExportBucketRequest']; +export type DiskBackupSnapshotAzureExportBucketResponse = components['schemas']['DiskBackupSnapshotAzureExportBucketResponse']; +export type DiskBackupSnapshotExportBucketRequest = components['schemas']['DiskBackupSnapshotExportBucketRequest']; +export type DiskBackupSnapshotExportBucketResponse = components['schemas']['DiskBackupSnapshotExportBucketResponse']; +export type DiskGbAutoScaling = components['schemas']['DiskGBAutoScaling']; +export type EmployeeAccessGrantView = components['schemas']['EmployeeAccessGrantView']; +export type FieldViolation = components['schemas']['FieldViolation']; +export type Fields = components['schemas']['Fields']; +export type FreeComputeAutoScalingRules = components['schemas']['FreeComputeAutoScalingRules']; +export type GcpCloudProviderContainer = components['schemas']['GCPCloudProviderContainer']; +export type GcpComputeAutoScaling = components['schemas']['GCPComputeAutoScaling']; +export type GcpCreateDataProcessRegionView = components['schemas']['GCPCreateDataProcessRegionView']; +export type GcpDataProcessRegionView = components['schemas']['GCPDataProcessRegionView']; +export type GcpHardwareSpec = components['schemas']['GCPHardwareSpec']; +export type GcpHardwareSpec20240805 = components['schemas']['GCPHardwareSpec20240805']; +export type GcpRegionConfig = components['schemas']['GCPRegionConfig']; +export type GcpRegionConfig20240805 = components['schemas']['GCPRegionConfig20240805']; +export type Group = components['schemas']['Group']; +export type GroupActiveUserResponse = components['schemas']['GroupActiveUserResponse']; +export type GroupPendingUserResponse = components['schemas']['GroupPendingUserResponse']; +export type GroupRoleAssignment = components['schemas']['GroupRoleAssignment']; +export type GroupUserResponse = components['schemas']['GroupUserResponse']; +export type HardwareSpec = components['schemas']['HardwareSpec']; +export type HardwareSpec20240805 = components['schemas']['HardwareSpec20240805']; +export type IngestionSink = components['schemas']['IngestionSink']; +export type IngestionSource = components['schemas']['IngestionSource']; +export type InvoiceLineItem = components['schemas']['InvoiceLineItem']; +export type Link = components['schemas']['Link']; +export type MonthlyScheduleView = components['schemas']['MonthlyScheduleView']; +export type NetworkPermissionEntry = components['schemas']['NetworkPermissionEntry']; +export type OnDemandCpsSnapshotSource = components['schemas']['OnDemandCpsSnapshotSource']; +export type OnlineArchiveSchedule = components['schemas']['OnlineArchiveSchedule']; +export type OrgActiveUserResponse = components['schemas']['OrgActiveUserResponse']; +export type OrgGroup = components['schemas']['OrgGroup']; +export type OrgPendingUserResponse = components['schemas']['OrgPendingUserResponse']; +export type OrgUserResponse = components['schemas']['OrgUserResponse']; +export type OrgUserRolesResponse = components['schemas']['OrgUserRolesResponse']; +export type PaginatedApiAtlasDatabaseUserView = components['schemas']['PaginatedApiAtlasDatabaseUserView']; +export type PaginatedAtlasGroupView = components['schemas']['PaginatedAtlasGroupView']; +export type PaginatedClusterDescription20240805 = components['schemas']['PaginatedClusterDescription20240805']; +export type PaginatedNetworkAccessView = components['schemas']['PaginatedNetworkAccessView']; +export type PaginatedOrgGroupView = components['schemas']['PaginatedOrgGroupView']; +export type PaginatedOrganizationView = components['schemas']['PaginatedOrganizationView']; +export type PeriodicCpsSnapshotSource = components['schemas']['PeriodicCpsSnapshotSource']; +export type ReplicationSpec20240805 = components['schemas']['ReplicationSpec20240805']; +export type ResourceTag = components['schemas']['ResourceTag']; +export type SearchHostStatusDetail = components['schemas']['SearchHostStatusDetail']; +export type SearchIndex = components['schemas']['SearchIndex']; +export type SearchIndexCreateRequest = components['schemas']['SearchIndexCreateRequest']; +export type SearchIndexDefinition = components['schemas']['SearchIndexDefinition']; +export type SearchIndexDefinitionVersion = components['schemas']['SearchIndexDefinitionVersion']; +export type SearchIndexResponse = components['schemas']['SearchIndexResponse']; +export type SearchMainIndexStatusDetail = components['schemas']['SearchMainIndexStatusDetail']; +export type SearchMappings = components['schemas']['SearchMappings']; +export type SearchStagedIndexStatusDetail = components['schemas']['SearchStagedIndexStatusDetail']; +export type SearchSynonymMappingDefinition = components['schemas']['SearchSynonymMappingDefinition']; +export type ServerlessAwsTenantEndpointUpdate = components['schemas']['ServerlessAWSTenantEndpointUpdate']; +export type ServerlessAzureTenantEndpointUpdate = components['schemas']['ServerlessAzureTenantEndpointUpdate']; +export type ServerlessTenantEndpointUpdate = components['schemas']['ServerlessTenantEndpointUpdate']; +export type StreamsAwsConnectionConfig = components['schemas']['StreamsAWSConnectionConfig']; +export type StreamsAwsLambdaConnection = components['schemas']['StreamsAWSLambdaConnection']; +export type StreamsClusterConnection = components['schemas']['StreamsClusterConnection']; +export type StreamsConnection = components['schemas']['StreamsConnection']; +export type StreamsHttpsConnection = components['schemas']['StreamsHttpsConnection']; +export type StreamsKafkaAuthentication = components['schemas']['StreamsKafkaAuthentication']; +export type StreamsKafkaConnection = components['schemas']['StreamsKafkaConnection']; +export type StreamsKafkaNetworking = components['schemas']['StreamsKafkaNetworking']; +export type StreamsKafkaNetworkingAccess = components['schemas']['StreamsKafkaNetworkingAccess']; +export type StreamsKafkaSecurity = components['schemas']['StreamsKafkaSecurity']; +export type StreamsS3Connection = components['schemas']['StreamsS3Connection']; +export type StreamsSampleConnection = components['schemas']['StreamsSampleConnection']; +export type SynonymMappingStatusDetail = components['schemas']['SynonymMappingStatusDetail']; +export type SynonymMappingStatusDetailMap = components['schemas']['SynonymMappingStatusDetailMap']; +export type SynonymSource = components['schemas']['SynonymSource']; +export type TenantHardwareSpec = components['schemas']['TenantHardwareSpec']; +export type TenantHardwareSpec20240805 = components['schemas']['TenantHardwareSpec20240805']; +export type TenantRegionConfig = components['schemas']['TenantRegionConfig']; +export type TenantRegionConfig20240805 = components['schemas']['TenantRegionConfig20240805']; +export type TextSearchHostStatusDetail = components['schemas']['TextSearchHostStatusDetail']; +export type TextSearchIndexCreateRequest = components['schemas']['TextSearchIndexCreateRequest']; +export type TextSearchIndexDefinition = components['schemas']['TextSearchIndexDefinition']; +export type TextSearchIndexResponse = components['schemas']['TextSearchIndexResponse']; +export type TextSearchIndexStatusDetail = components['schemas']['TextSearchIndexStatusDetail']; +export type TokenFilterEnglishPossessive = components['schemas']['TokenFilterEnglishPossessive']; +export type TokenFilterFlattenGraph = components['schemas']['TokenFilterFlattenGraph']; +export type TokenFilterPorterStemming = components['schemas']['TokenFilterPorterStemming']; +export type TokenFilterSpanishPluralStemming = components['schemas']['TokenFilterSpanishPluralStemming']; +export type TokenFilterStempel = components['schemas']['TokenFilterStempel']; +export type TokenFilterWordDelimiterGraph = components['schemas']['TokenFilterWordDelimiterGraph']; +export type TokenFilterkStemming = components['schemas']['TokenFilterkStemming']; +export type UserScope = components['schemas']['UserScope']; +export type VectorSearchHostStatusDetail = components['schemas']['VectorSearchHostStatusDetail']; +export type VectorSearchIndex = components['schemas']['VectorSearchIndex']; +export type VectorSearchIndexCreateRequest = components['schemas']['VectorSearchIndexCreateRequest']; +export type VectorSearchIndexDefinition = components['schemas']['VectorSearchIndexDefinition']; +export type VectorSearchIndexResponse = components['schemas']['VectorSearchIndexResponse']; +export type VectorSearchIndexStatusDetail = components['schemas']['VectorSearchIndexStatusDetail']; +export type WeeklyScheduleView = components['schemas']['WeeklyScheduleView']; +export type CharFilterhtmlStrip = components['schemas']['charFilterhtmlStrip']; +export type CharFiltericuNormalize = components['schemas']['charFiltericuNormalize']; +export type CharFiltermapping = components['schemas']['charFiltermapping']; +export type CharFilterpersian = components['schemas']['charFilterpersian']; +export type TokenFilterasciiFolding = components['schemas']['tokenFilterasciiFolding']; +export type TokenFilterdaitchMokotoffSoundex = components['schemas']['tokenFilterdaitchMokotoffSoundex']; +export type TokenFilteredgeGram = components['schemas']['tokenFilteredgeGram']; +export type TokenFiltericuFolding = components['schemas']['tokenFiltericuFolding']; +export type TokenFiltericuNormalizer = components['schemas']['tokenFiltericuNormalizer']; +export type TokenFilterlength = components['schemas']['tokenFilterlength']; +export type TokenFilterlowercase = components['schemas']['tokenFilterlowercase']; +export type TokenFilternGram = components['schemas']['tokenFilternGram']; +export type TokenFilterregex = components['schemas']['tokenFilterregex']; +export type TokenFilterreverse = components['schemas']['tokenFilterreverse']; +export type TokenFiltershingle = components['schemas']['tokenFiltershingle']; +export type TokenFiltersnowballStemming = components['schemas']['tokenFiltersnowballStemming']; +export type TokenFilterstopword = components['schemas']['tokenFilterstopword']; +export type TokenFiltertrim = components['schemas']['tokenFiltertrim']; +export type TokenizeredgeGram = components['schemas']['tokenizeredgeGram']; +export type Tokenizerkeyword = components['schemas']['tokenizerkeyword']; +export type TokenizernGram = components['schemas']['tokenizernGram']; +export type TokenizerregexCaptureGroup = components['schemas']['tokenizerregexCaptureGroup']; +export type TokenizerregexSplit = components['schemas']['tokenizerregexSplit']; +export type Tokenizerstandard = components['schemas']['tokenizerstandard']; +export type TokenizeruaxUrlEmail = components['schemas']['tokenizeruaxUrlEmail']; +export type Tokenizerwhitespace = components['schemas']['tokenizerwhitespace']; +export type ResponseBadRequest = components['responses']['badRequest']; +export type ResponseConflict = components['responses']['conflict']; +export type ResponseForbidden = components['responses']['forbidden']; +export type ResponseInternalServerError = components['responses']['internalServerError']; +export type ResponseNotFound = components['responses']['notFound']; +export type ResponsePaymentRequired = components['responses']['paymentRequired']; +export type ResponseUnauthorized = components['responses']['unauthorized']; +export type ParameterEnvelope = components['parameters']['envelope']; +export type ParameterGroupId = components['parameters']['groupId']; +export type ParameterIncludeCount = components['parameters']['includeCount']; +export type ParameterItemsPerPage = components['parameters']['itemsPerPage']; +export type ParameterOrgId = components['parameters']['orgId']; +export type ParameterPageNum = components['parameters']['pageNum']; +export type ParameterPretty = components['parameters']['pretty']; export type $defs = Record; export interface operations { listClustersForAllProjects: { @@ -7097,6 +5323,40 @@ export interface operations { 500: components["responses"]["internalServerError"]; }; }; + deleteProject: { + parameters: { + query?: { + /** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */ + envelope?: components["parameters"]["envelope"]; + /** @description Flag that indicates whether the response body should be in the prettyprint format. */ + pretty?: components["parameters"]["pretty"]; + }; + header?: never; + path: { + /** @description Unique 24-hexadecimal digit string that identifies your project. Use the [/groups](#tag/Projects/operation/listProjects) endpoint to retrieve all projects to which the authenticated user has access. + * + * **NOTE**: Groups and projects are synonymous terms. Your group id is the same as your project id. For existing groups, your group/project id remains the same. The resource and corresponding endpoints use the term groups. */ + groupId: components["parameters"]["groupId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description This endpoint does not return a response body. */ + 204: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-01-01+json": unknown; + }; + }; + 400: components["responses"]["badRequest"]; + 404: components["responses"]["notFound"]; + 409: components["responses"]["conflict"]; + 500: components["responses"]["internalServerError"]; + }; + }; listProjectIpAccessLists: { parameters: { query?: { @@ -7180,6 +5440,45 @@ export interface operations { 500: components["responses"]["internalServerError"]; }; }; + deleteProjectIpAccessList: { + parameters: { + query?: { + /** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */ + envelope?: components["parameters"]["envelope"]; + /** @description Flag that indicates whether the response body should be in the prettyprint format. */ + pretty?: components["parameters"]["pretty"]; + }; + header?: never; + path: { + /** @description Unique 24-hexadecimal digit string that identifies your project. Use the [/groups](#tag/Projects/operation/listProjects) endpoint to retrieve all projects to which the authenticated user has access. + * + * **NOTE**: Groups and projects are synonymous terms. Your group id is the same as your project id. For existing groups, your group/project id remains the same. The resource and corresponding endpoints use the term groups. */ + groupId: components["parameters"]["groupId"]; + /** @description Access list entry that you want to remove from the project's IP access list. This value can use one of the following: one AWS security group ID, one IP address, or one CIDR block of addresses. For CIDR blocks that use a subnet mask, replace the forward slash (`/`) with its URL-encoded value (`%2F`). When you remove an entry from the IP access list, existing connections from the removed address or addresses may remain open for a variable amount of time. The amount of time it takes MongoDB Cloud to close the connection depends upon several factors, including: + * + * - how your application established the connection, + * - how MongoDB Cloud or the driver using the address behaves, and + * - which protocol (like TCP or UDP) the connection uses. */ + entryValue: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description This endpoint does not return a response body. */ + 204: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-01-01+json": unknown; + }; + }; + 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; + 500: components["responses"]["internalServerError"]; + }; + }; listClusters: { parameters: { query?: { @@ -7297,6 +5596,45 @@ export interface operations { 500: components["responses"]["internalServerError"]; }; }; + deleteCluster: { + parameters: { + query?: { + /** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */ + envelope?: components["parameters"]["envelope"]; + /** @description Flag that indicates whether the response body should be in the prettyprint format. */ + pretty?: components["parameters"]["pretty"]; + /** @description Flag that indicates whether to retain backup snapshots for the deleted dedicated cluster. */ + retainBackups?: boolean; + }; + header?: never; + path: { + /** @description Unique 24-hexadecimal digit string that identifies your project. Use the [/groups](#tag/Projects/operation/listProjects) endpoint to retrieve all projects to which the authenticated user has access. + * + * **NOTE**: Groups and projects are synonymous terms. Your group id is the same as your project id. For existing groups, your group/project id remains the same. The resource and corresponding endpoints use the term groups. */ + groupId: components["parameters"]["groupId"]; + /** @description Human-readable label that identifies the cluster. */ + clusterName: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Accepted */ + 202: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-02-01+json": unknown; + }; + }; + 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 404: components["responses"]["notFound"]; + 409: components["responses"]["conflict"]; + 500: components["responses"]["internalServerError"]; + }; + }; listDatabaseUsers: { parameters: { query?: { @@ -7376,6 +5714,135 @@ export interface operations { 500: components["responses"]["internalServerError"]; }; }; + deleteDatabaseUser: { + parameters: { + query?: { + /** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */ + envelope?: components["parameters"]["envelope"]; + /** @description Flag that indicates whether the response body should be in the prettyprint format. */ + pretty?: components["parameters"]["pretty"]; + }; + header?: never; + path: { + /** @description Unique 24-hexadecimal digit string that identifies your project. Use the [/groups](#tag/Projects/operation/listProjects) endpoint to retrieve all projects to which the authenticated user has access. + * + * **NOTE**: Groups and projects are synonymous terms. Your group id is the same as your project id. For existing groups, your group/project id remains the same. The resource and corresponding endpoints use the term groups. */ + groupId: components["parameters"]["groupId"]; + /** @description The database against which the database user authenticates. Database users must provide both a username and authentication database to log into MongoDB. If the user authenticates with AWS IAM, x.509, LDAP, or OIDC Workload this value should be `$external`. If the user authenticates with SCRAM-SHA or OIDC Workforce, this value should be `admin`. */ + databaseName: string; + /** @description Human-readable label that represents the user that authenticates to MongoDB. The format of this label depends on the method of authentication: + * + * | Authentication Method | Parameter Needed | Parameter Value | username Format | + * |---|---|---|---| + * | AWS IAM | awsIAMType | ROLE | ARN | + * | AWS IAM | awsIAMType | USER | ARN | + * | x.509 | x509Type | CUSTOMER | [RFC 2253](https://tools.ietf.org/html/2253) Distinguished Name | + * | x.509 | x509Type | MANAGED | [RFC 2253](https://tools.ietf.org/html/2253) Distinguished Name | + * | LDAP | ldapAuthType | USER | [RFC 2253](https://tools.ietf.org/html/2253) Distinguished Name | + * | LDAP | ldapAuthType | GROUP | [RFC 2253](https://tools.ietf.org/html/2253) Distinguished Name | + * | OIDC Workforce | oidcAuthType | IDP_GROUP | Atlas OIDC IdP ID (found in federation settings), followed by a '/', followed by the IdP group name | + * | OIDC Workload | oidcAuthType | USER | Atlas OIDC IdP ID (found in federation settings), followed by a '/', followed by the IdP user name | + * | SCRAM-SHA | awsIAMType, x509Type, ldapAuthType, oidcAuthType | NONE | Alphanumeric string | + * */ + username: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description This endpoint does not return a response body. */ + 204: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-01-01+json": unknown; + }; + }; + 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; + 500: components["responses"]["internalServerError"]; + }; + }; + listOrganizations: { + parameters: { + query?: { + /** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */ + envelope?: components["parameters"]["envelope"]; + /** @description Flag that indicates whether the response returns the total number of items (**totalCount**) in the response. */ + includeCount?: components["parameters"]["includeCount"]; + /** @description Number of items that the response returns per page. */ + itemsPerPage?: components["parameters"]["itemsPerPage"]; + /** @description Number of the page that displays the current set of the total objects that the response returns. */ + pageNum?: components["parameters"]["pageNum"]; + /** @description Flag that indicates whether the response body should be in the prettyprint format. */ + pretty?: components["parameters"]["pretty"]; + /** @description Human-readable label of the organization to use to filter the returned list. Performs a case-insensitive search for an organization that starts with the specified name. */ + name?: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-01-01+json": components["schemas"]["PaginatedOrganizationView"]; + }; + }; + 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 404: components["responses"]["notFound"]; + 409: components["responses"]["conflict"]; + 500: components["responses"]["internalServerError"]; + }; + }; + listOrganizationProjects: { + parameters: { + query?: { + /** @description Flag that indicates whether Application wraps the response in an `envelope` JSON object. Some API clients cannot access the HTTP response headers or status code. To remediate this, set envelope=true in the query. Endpoints that return a list of results use the results object as an envelope. Application adds the status parameter to the response body. */ + envelope?: components["parameters"]["envelope"]; + /** @description Flag that indicates whether the response returns the total number of items (**totalCount**) in the response. */ + includeCount?: components["parameters"]["includeCount"]; + /** @description Number of items that the response returns per page. */ + itemsPerPage?: components["parameters"]["itemsPerPage"]; + /** @description Number of the page that displays the current set of the total objects that the response returns. */ + pageNum?: components["parameters"]["pageNum"]; + /** @description Flag that indicates whether the response body should be in the prettyprint format. */ + pretty?: components["parameters"]["pretty"]; + /** @description Human-readable label of the project to use to filter the returned list. Performs a case-insensitive search for a project within the organization which is prefixed by the specified name. */ + name?: string; + }; + header?: never; + path: { + /** @description Unique 24-hexadecimal digit string that identifies the organization that contains your projects. Use the [/orgs](#tag/Organizations/operation/listOrganizations) endpoint to retrieve all organizations to which the authenticated user has access. */ + orgId: components["parameters"]["orgId"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-01-01+json": components["schemas"]["PaginatedAtlasGroupView"]; + }; + }; + 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 404: components["responses"]["notFound"]; + 500: components["responses"]["internalServerError"]; + }; + }; } type WithRequired = T & { [P in K]-?: T[P]; diff --git a/src/config.ts b/src/config.ts index cce25722..cea589ba 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,15 +2,15 @@ import path from "path"; import os from "os"; import argv from "yargs-parser"; -import packageJson from "../package.json" with { type: "json" }; import { ReadConcernLevel, ReadPreferenceMode, W } from "mongodb"; // If we decide to support non-string config options, we'll need to extend the mechanism for parsing // env variables. -interface UserConfig { +export interface UserConfig { apiBaseUrl?: string; apiClientId?: string; apiClientSecret?: string; + telemetry?: "enabled" | "disabled"; logPath: string; connectionString?: string; connectOptions: { @@ -19,6 +19,7 @@ interface UserConfig { writeConcern: W; timeoutMS: number; }; + disabledTools: Array; } const defaults: UserConfig = { @@ -29,21 +30,15 @@ const defaults: UserConfig = { writeConcern: "majority", timeoutMS: 30_000, }, + disabledTools: [], }; -const mergedUserConfig = { +export const config = { ...defaults, ...getEnvConfig(), ...getCliConfig(), }; -const config = { - ...mergedUserConfig, - version: packageJson.version, -}; - -export default config; - function getLogPath(): string { const localDataPath = process.platform === "win32" @@ -77,6 +72,12 @@ function getEnvConfig(): Partial { return; } + // Try to parse an array of values + if (value.indexOf(",") !== -1) { + obj[currentField] = value.split(",").map((v) => v.trim()); + return; + } + obj[currentField] = value; return; } @@ -110,5 +111,7 @@ function SNAKE_CASE_toCamelCase(str: string): string { // Reads the cli args and parses them into a UserConfig object. function getCliConfig() { - return argv(process.argv.slice(2)) as unknown as Partial; + return argv(process.argv.slice(2), { + array: ["disabledTools"], + }) as unknown as Partial; } diff --git a/src/index.ts b/src/index.ts index 944ee92a..268c4803 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,20 +4,25 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js" import logger from "./logger.js"; import { mongoLogId } from "mongodb-log-writer"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; -import config from "./config.js"; +import { config } from "./config.js"; import { Session } from "./session.js"; import { Server } from "./server.js"; +import { packageInfo } from "./packageInfo.js"; try { - const session = new Session(); + const session = new Session({ + apiBaseUrl: config.apiBaseUrl, + apiClientId: config.apiClientId, + apiClientSecret: config.apiClientSecret, + }); const mcpServer = new McpServer({ - name: "MongoDB Atlas", - version: config.version, + name: packageInfo.mcpServerName, + version: packageInfo.version, }); - const server = new Server({ mcpServer, session, + userConfig: config, }); const transport = new StdioServerTransport(); @@ -25,6 +30,5 @@ try { await server.connect(transport); } catch (error: unknown) { logger.emergency(mongoLogId(1_000_004), "server", `Fatal error running server: ${error as string}`); - process.exit(1); } diff --git a/src/logger.ts b/src/logger.ts index 6682566a..425f56b9 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,6 +1,5 @@ import fs from "fs/promises"; import { MongoLogId, MongoLogManager, MongoLogWriter } from "mongodb-log-writer"; -import config from "./config.js"; import redact from "mongodb-redact"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { LoggingMessageNotification } from "@modelcontextprotocol/sdk/types.js"; @@ -98,11 +97,11 @@ class ProxyingLogger extends LoggerBase { const logger = new ProxyingLogger(); export default logger; -export async function initializeLogger(server: McpServer): Promise { - await fs.mkdir(config.logPath, { recursive: true }); +export async function initializeLogger(server: McpServer, logPath: string): Promise { + await fs.mkdir(logPath, { recursive: true }); const manager = new MongoLogManager({ - directory: config.logPath, + directory: logPath, retentionDays: 30, onwarn: console.warn, onerror: console.error, diff --git a/src/packageInfo.ts b/src/packageInfo.ts new file mode 100644 index 00000000..dea9214b --- /dev/null +++ b/src/packageInfo.ts @@ -0,0 +1,6 @@ +import packageJson from "../package.json" with { type: "json" }; + +export const packageInfo = { + version: packageJson.version, + mcpServerName: "MongoDB MCP Server", +}; diff --git a/src/server.ts b/src/server.ts index 72d9c4f9..fd16c75d 100644 --- a/src/server.ts +++ b/src/server.ts @@ -5,26 +5,48 @@ import { AtlasTools } from "./tools/atlas/tools.js"; import { MongoDbTools } from "./tools/mongodb/tools.js"; import logger, { initializeLogger } from "./logger.js"; import { mongoLogId } from "mongodb-log-writer"; +import { ObjectId } from "mongodb"; +import { Telemetry } from "./telemetry/telemetry.js"; +import { UserConfig } from "./config.js"; + +export interface ServerOptions { + session: Session; + userConfig: UserConfig; + mcpServer: McpServer; +} export class Server { public readonly session: Session; private readonly mcpServer: McpServer; + private readonly telemetry: Telemetry; + private readonly userConfig: UserConfig; - constructor({ mcpServer, session }: { mcpServer: McpServer; session: Session }) { - this.mcpServer = mcpServer; + constructor({ session, mcpServer, userConfig }: ServerOptions) { this.session = session; + this.telemetry = new Telemetry(session); + this.mcpServer = mcpServer; + this.userConfig = userConfig; } async connect(transport: Transport) { this.mcpServer.server.registerCapabilities({ logging: {} }); - this.registerTools(); + this.registerResources(); - await initializeLogger(this.mcpServer); + await initializeLogger(this.mcpServer, this.userConfig.logPath); await this.mcpServer.connect(transport); - logger.info(mongoLogId(1_000_004), "server", `Server started with transport ${transport.constructor.name}`); + this.mcpServer.server.oninitialized = () => { + this.session.setAgentRunner(this.mcpServer.server.getClientVersion()); + this.session.sessionId = new ObjectId().toString(); + + logger.info( + mongoLogId(1_000_004), + "server", + `Server started with transport ${transport.constructor.name} and agent runner ${this.session.agentRunner?.name}` + ); + }; } async close(): Promise { @@ -34,7 +56,29 @@ export class Server { private registerTools() { for (const tool of [...AtlasTools, ...MongoDbTools]) { - new tool(this.session).register(this.mcpServer); + new tool(this.session, this.userConfig, this.telemetry).register(this.mcpServer); + } + } + + private registerResources() { + if (this.userConfig.connectionString) { + this.mcpServer.resource( + "connection-string", + "config://connection-string", + { + description: "Preconfigured connection string that will be used as a default in the `connect` tool", + }, + (uri) => { + return { + contents: [ + { + text: `Preconfigured connection string: ${this.userConfig.connectionString}`, + uri: uri.href, + }, + ], + }; + } + ); } } } diff --git a/src/session.ts b/src/session.ts index 0d5ac951..2c5267ce 100644 --- a/src/session.ts +++ b/src/session.ts @@ -1,26 +1,43 @@ import { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver"; -import { ApiClient } from "./common/atlas/apiClient.js"; -import config from "./config.js"; +import { ApiClient, ApiClientCredentials } from "./common/atlas/apiClient.js"; +import { Implementation } from "@modelcontextprotocol/sdk/types.js"; + +export interface SessionOptions { + apiBaseUrl?: string; + apiClientId?: string; + apiClientSecret?: string; +} export class Session { + sessionId?: string; serviceProvider?: NodeDriverServiceProvider; - apiClient?: ApiClient; + apiClient: ApiClient; + agentRunner?: { + name: string; + version: string; + }; - ensureAuthenticated(): asserts this is { apiClient: ApiClient } { - if (!this.apiClient) { - if (!config.apiClientId || !config.apiClientSecret) { - throw new Error( - "Not authenticated make sure to configure MCP server with MDB_MCP_API_CLIENT_ID and MDB_MCP_API_CLIENT_SECRET environment variables." - ); - } + constructor({ apiBaseUrl, apiClientId, apiClientSecret }: SessionOptions = {}) { + const credentials: ApiClientCredentials | undefined = + apiClientId && apiClientSecret + ? { + clientId: apiClientId, + clientSecret: apiClientSecret, + } + : undefined; + + this.apiClient = new ApiClient({ + baseUrl: apiBaseUrl, + credentials, + }); + } - this.apiClient = new ApiClient({ - baseUrl: config.apiBaseUrl, - credentials: { - clientId: config.apiClientId, - clientSecret: config.apiClientSecret, - }, - }); + setAgentRunner(agentRunner: Implementation | undefined) { + if (agentRunner?.name && agentRunner?.version) { + this.agentRunner = { + name: agentRunner.name, + version: agentRunner.version, + }; } } diff --git a/src/telemetry/constants.ts b/src/telemetry/constants.ts new file mode 100644 index 00000000..dfccbe75 --- /dev/null +++ b/src/telemetry/constants.ts @@ -0,0 +1,15 @@ +import { getMachineIdSync } from "native-machine-id"; +import { packageInfo } from "../packageInfo.js"; + +/** + * Machine-specific metadata formatted for telemetry + */ +export const MACHINE_METADATA = { + device_id: getMachineIdSync(), + mcp_server_version: packageInfo.version, + mcp_server_name: packageInfo.mcpServerName, + platform: process.platform, + arch: process.arch, + os_type: process.platform, + os_version: process.version, +} as const; diff --git a/src/telemetry/eventCache.ts b/src/telemetry/eventCache.ts new file mode 100644 index 00000000..49025227 --- /dev/null +++ b/src/telemetry/eventCache.ts @@ -0,0 +1,62 @@ +import { BaseEvent } from "./types.js"; +import { LRUCache } from "lru-cache"; + +/** + * Singleton class for in-memory telemetry event caching + * Provides a central storage for telemetry events that couldn't be sent + * Uses LRU cache to automatically drop oldest events when limit is exceeded + */ +export class EventCache { + private static instance: EventCache; + private static readonly MAX_EVENTS = 1000; + + private cache: LRUCache; + private nextId = 0; + + private constructor() { + this.cache = new LRUCache({ + max: EventCache.MAX_EVENTS, + // Using FIFO eviction strategy for events + allowStale: false, + updateAgeOnGet: false, + }); + } + + /** + * Gets the singleton instance of EventCache + * @returns The EventCache instance + */ + public static getInstance(): EventCache { + if (!EventCache.instance) { + EventCache.instance = new EventCache(); + } + return EventCache.instance; + } + + /** + * Gets a copy of the currently cached events + * @returns Array of cached BaseEvent objects + */ + public getEvents(): BaseEvent[] { + return Array.from(this.cache.values()); + } + + /** + * Appends new events to the cached events + * LRU cache automatically handles dropping oldest events when limit is exceeded + * @param events - The events to append + */ + public appendEvents(events: BaseEvent[]): void { + for (const event of events) { + this.cache.set(this.nextId++, event); + } + } + + /** + * Clears all cached events + */ + public clearEvents(): void { + this.cache.clear(); + this.nextId = 0; + } +} diff --git a/src/telemetry/telemetry.ts b/src/telemetry/telemetry.ts new file mode 100644 index 00000000..a43b11c9 --- /dev/null +++ b/src/telemetry/telemetry.ts @@ -0,0 +1,138 @@ +import { Session } from "../session.js"; +import { BaseEvent } from "./types.js"; +import { config } from "../config.js"; +import logger from "../logger.js"; +import { mongoLogId } from "mongodb-log-writer"; +import { ApiClient } from "../common/atlas/apiClient.js"; +import { MACHINE_METADATA } from "./constants.js"; +import { EventCache } from "./eventCache.js"; + +type EventResult = { + success: boolean; + error?: Error; +}; + +type CommonProperties = { + device_id: string; + mcp_server_version: string; + mcp_server_name: string; + mcp_client_version?: string; + mcp_client_name?: string; + platform: string; + arch: string; + os_type: string; + os_version?: string; + session_id?: string; +}; + +export class Telemetry { + private readonly commonProperties: CommonProperties; + + constructor( + private readonly session: Session, + private readonly eventCache: EventCache = EventCache.getInstance() + ) { + this.commonProperties = { + ...MACHINE_METADATA, + }; + } + + /** + * Checks if telemetry is currently enabled + * This is a method rather than a constant to capture runtime config changes + * + * Follows the Console Do Not Track standard (https://consoledonottrack.com/) + * by respecting the DO_NOT_TRACK environment variable + */ + private static isTelemetryEnabled(): boolean { + // Check if telemetry is explicitly disabled in config + if (config.telemetry === "disabled") { + return false; + } + + const doNotTrack = process.env.DO_NOT_TRACK; + if (doNotTrack) { + const value = doNotTrack.toLowerCase(); + // Telemetry should be disabled if DO_NOT_TRACK is "1", "true", or "yes" + if (value === "1" || value === "true" || value === "yes") { + return false; + } + } + + return true; + } + + /** + * Emits events through the telemetry pipeline + * @param events - The events to emit + */ + public async emitEvents(events: BaseEvent[]): Promise { + try { + if (!Telemetry.isTelemetryEnabled()) { + logger.debug(mongoLogId(1_000_000), "telemetry", "Telemetry is disabled, skipping events."); + return; + } + + await this.emit(events); + } catch { + logger.debug(mongoLogId(1_000_002), "telemetry", `Error emitting telemetry events.`); + } + } + + /** + * Gets the common properties for events + * @returns Object containing common properties for all events + */ + public getCommonProperties(): CommonProperties { + return { + ...this.commonProperties, + mcp_client_version: this.session.agentRunner?.version, + mcp_client_name: this.session.agentRunner?.name, + session_id: this.session.sessionId, + }; + } + + /** + * Attempts to emit events through authenticated and unauthenticated clients + * Falls back to caching if both attempts fail + */ + private async emit(events: BaseEvent[]): Promise { + const cachedEvents = this.eventCache.getEvents(); + const allEvents = [...cachedEvents, ...events]; + + logger.debug( + mongoLogId(1_000_003), + "telemetry", + `Attempting to send ${allEvents.length} events (${cachedEvents.length} cached)` + ); + + const result = await this.sendEvents(this.session.apiClient, allEvents); + if (result.success) { + this.eventCache.clearEvents(); + logger.debug(mongoLogId(1_000_004), "telemetry", `Sent ${allEvents.length} events successfully`); + return; + } + + logger.warning( + mongoLogId(1_000_005), + "telemetry", + `Error sending event to client: ${result.error instanceof Error ? result.error.message : String(result.error)}` + ); + this.eventCache.appendEvents(events); + } + + /** + * Attempts to send events through the provided API client + */ + private async sendEvents(client: ApiClient, events: BaseEvent[]): Promise { + try { + await client.sendEvents(events); + return { success: true }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error : new Error(String(error)), + }; + } + } +} diff --git a/src/telemetry/types.ts b/src/telemetry/types.ts new file mode 100644 index 00000000..4f24e545 --- /dev/null +++ b/src/telemetry/types.ts @@ -0,0 +1,47 @@ +/** + * Result type constants for telemetry events + */ +export type TelemetryResult = "success" | "failure"; + +/** + * Base interface for all events + */ +export interface Event { + timestamp: string; + source: "mdbmcp"; + properties: Record; +} + +export interface BaseEvent extends Event { + properties: { + device_id: string; + mcp_server_version: string; + mcp_server_name: string; + mcp_client_version?: string; + mcp_client_name?: string; + platform: string; + arch: string; + os_type: string; + component: string; + duration_ms: number; + result: TelemetryResult; + category: string; + os_version?: string; + session_id?: string; + } & Event["properties"]; +} + +/** + * Interface for tool events + */ +export interface ToolEvent extends BaseEvent { + properties: { + command: string; + error_code?: string; + error_type?: string; + project_id?: string; + org_id?: string; + cluster_name?: string; + is_atlas?: boolean; + } & BaseEvent["properties"]; +} diff --git a/src/tools/atlas/atlasTool.ts b/src/tools/atlas/atlasTool.ts index 7a1c00fe..6ca5282d 100644 --- a/src/tools/atlas/atlasTool.ts +++ b/src/tools/atlas/atlasTool.ts @@ -1,8 +1,12 @@ -import { ToolBase } from "../tool.js"; -import { Session } from "../../session.js"; +import { ToolBase, ToolCategory } from "../tool.js"; export abstract class AtlasToolBase extends ToolBase { - constructor(protected readonly session: Session) { - super(session); + protected category: ToolCategory = "atlas"; + + protected verifyAllowed(): boolean { + if (!this.config.apiClientId || !this.config.apiClientSecret) { + return false; + } + return super.verifyAllowed(); } } diff --git a/src/tools/atlas/createAccessList.ts b/src/tools/atlas/createAccessList.ts index 3ba12046..46eb9af6 100644 --- a/src/tools/atlas/createAccessList.ts +++ b/src/tools/atlas/createAccessList.ts @@ -1,13 +1,14 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; const DEFAULT_COMMENT = "Added by Atlas MCP"; export class CreateAccessListTool extends AtlasToolBase { protected name = "atlas-create-access-list"; protected description = "Allow Ip/CIDR ranges to access your MongoDB Atlas clusters."; + protected operationType: OperationType = "create"; protected argsShape = { projectId: z.string().describe("Atlas project ID"), ipAddresses: z @@ -26,8 +27,6 @@ export class CreateAccessListTool extends AtlasToolBase { comment, currentIpAddress, }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - if (!ipAddresses?.length && !cidrBlocks?.length && !currentIpAddress) { throw new Error("One of ipAddresses, cidrBlocks, currentIpAddress must be provided."); } diff --git a/src/tools/atlas/createDBUser.ts b/src/tools/atlas/createDBUser.ts index a388ef9a..0b0122c9 100644 --- a/src/tools/atlas/createDBUser.ts +++ b/src/tools/atlas/createDBUser.ts @@ -1,12 +1,13 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; import { CloudDatabaseUser, DatabaseUserRole } from "../../common/atlas/openapi.js"; export class CreateDBUserTool extends AtlasToolBase { protected name = "atlas-create-db-user"; protected description = "Create an MongoDB Atlas database user"; + protected operationType: OperationType = "create"; protected argsShape = { projectId: z.string().describe("Atlas project ID"), username: z.string().describe("Username for the new user"), @@ -33,8 +34,6 @@ export class CreateDBUserTool extends AtlasToolBase { roles, clusters, }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - const input = { groupId: projectId, awsIAMType: "NONE", diff --git a/src/tools/atlas/createFreeCluster.ts b/src/tools/atlas/createFreeCluster.ts index 675d48cd..ccf13856 100644 --- a/src/tools/atlas/createFreeCluster.ts +++ b/src/tools/atlas/createFreeCluster.ts @@ -1,12 +1,13 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; import { ClusterDescription20240805 } from "../../common/atlas/openapi.js"; export class CreateFreeClusterTool extends AtlasToolBase { protected name = "atlas-create-free-cluster"; protected description = "Create a free MongoDB Atlas cluster"; + protected operationType: OperationType = "create"; protected argsShape = { projectId: z.string().describe("Atlas project ID to create the cluster in"), name: z.string().describe("Name of the cluster"), @@ -14,8 +15,6 @@ export class CreateFreeClusterTool extends AtlasToolBase { }; protected async execute({ projectId, name, region }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - const input = { groupId: projectId, name, diff --git a/src/tools/atlas/createProject.ts b/src/tools/atlas/createProject.ts new file mode 100644 index 00000000..f1c4da31 --- /dev/null +++ b/src/tools/atlas/createProject.ts @@ -0,0 +1,62 @@ +import { z } from "zod"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { AtlasToolBase } from "./atlasTool.js"; +import { ToolArgs, OperationType } from "../tool.js"; +import { Group } from "../../common/atlas/openapi.js"; + +export class CreateProjectTool extends AtlasToolBase { + protected name = "atlas-create-project"; + protected description = "Create a MongoDB Atlas project"; + protected operationType: OperationType = "create"; + protected argsShape = { + projectName: z.string().optional().describe("Name for the new project"), + organizationId: z.string().optional().describe("Organization ID for the new project"), + }; + + protected async execute({ projectName, organizationId }: ToolArgs): Promise { + let assumedOrg = false; + + if (!projectName) { + projectName = "Atlas Project"; + } + + if (!organizationId) { + try { + const organizations = await this.session.apiClient.listOrganizations(); + if (!organizations?.results?.length) { + throw new Error( + "No organizations were found in your MongoDB Atlas account. Please create an organization first." + ); + } + organizationId = organizations.results[0].id; + assumedOrg = true; + } catch { + throw new Error( + "Could not search for organizations in your MongoDB Atlas account, please provide an organization ID or create one first." + ); + } + } + + const input = { + name: projectName, + orgId: organizationId, + } as Group; + + const group = await this.session.apiClient.createProject({ + body: input, + }); + + if (!group?.id) { + throw new Error("Failed to create project"); + } + + return { + content: [ + { + type: "text", + text: `Project "${projectName}" created successfully${assumedOrg ? ` (using organizationId ${organizationId}).` : ""}.`, + }, + ], + }; + } +} diff --git a/src/tools/atlas/inspectAccessList.ts b/src/tools/atlas/inspectAccessList.ts index 8c25367b..755da768 100644 --- a/src/tools/atlas/inspectAccessList.ts +++ b/src/tools/atlas/inspectAccessList.ts @@ -1,18 +1,17 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; export class InspectAccessListTool extends AtlasToolBase { protected name = "atlas-inspect-access-list"; protected description = "Inspect Ip/CIDR ranges with access to your MongoDB Atlas clusters."; + protected operationType: OperationType = "read"; protected argsShape = { projectId: z.string().describe("Atlas project ID"), }; protected async execute({ projectId }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - const accessList = await this.session.apiClient.listProjectIpAccessLists({ params: { path: { diff --git a/src/tools/atlas/inspectCluster.ts b/src/tools/atlas/inspectCluster.ts index c8aa3185..c435beaf 100644 --- a/src/tools/atlas/inspectCluster.ts +++ b/src/tools/atlas/inspectCluster.ts @@ -1,20 +1,19 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; import { ClusterDescription20240805 } from "../../common/atlas/openapi.js"; export class InspectClusterTool extends AtlasToolBase { protected name = "atlas-inspect-cluster"; protected description = "Inspect MongoDB Atlas cluster"; + protected operationType: OperationType = "read"; protected argsShape = { projectId: z.string().describe("Atlas project ID"), clusterName: z.string().describe("Atlas cluster name"), }; protected async execute({ projectId, clusterName }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - const cluster = await this.session.apiClient.getCluster({ params: { path: { diff --git a/src/tools/atlas/listClusters.ts b/src/tools/atlas/listClusters.ts index 8a6a1b08..82a59fd4 100644 --- a/src/tools/atlas/listClusters.ts +++ b/src/tools/atlas/listClusters.ts @@ -1,19 +1,18 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; import { PaginatedClusterDescription20240805, PaginatedOrgGroupView, Group } from "../../common/atlas/openapi.js"; export class ListClustersTool extends AtlasToolBase { protected name = "atlas-list-clusters"; protected description = "List MongoDB Atlas clusters"; + protected operationType: OperationType = "read"; protected argsShape = { projectId: z.string().describe("Atlas project ID to filter clusters").optional(), }; protected async execute({ projectId }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - if (!projectId) { const data = await this.session.apiClient.listClustersForAllProjects(); @@ -47,20 +46,23 @@ export class ListClustersTool extends AtlasToolBase { if (!clusters?.results?.length) { throw new Error("No clusters found."); } - const rows = clusters.results + const formattedClusters = clusters.results .map((result) => { return (result.clusters || []).map((cluster) => { return { ...result, ...cluster, clusters: undefined }; }); }) - .flat() + .flat(); + if (!formattedClusters.length) { + throw new Error("No clusters found."); + } + const rows = formattedClusters .map((cluster) => { return `${cluster.groupName} (${cluster.groupId}) | ${cluster.name}`; }) .join("\n"); return { content: [ - { type: "text", text: `Here are your MongoDB Atlas clusters:` }, { type: "text", text: `Project | Cluster Name diff --git a/src/tools/atlas/listDBUsers.ts b/src/tools/atlas/listDBUsers.ts index 5e7a73a9..c3013162 100644 --- a/src/tools/atlas/listDBUsers.ts +++ b/src/tools/atlas/listDBUsers.ts @@ -1,19 +1,18 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; -import { ToolArgs } from "../tool.js"; +import { ToolArgs, OperationType } from "../tool.js"; import { DatabaseUserRole, UserScope } from "../../common/atlas/openapi.js"; export class ListDBUsersTool extends AtlasToolBase { protected name = "atlas-list-db-users"; protected description = "List MongoDB Atlas database users"; + protected operationType: OperationType = "read"; protected argsShape = { projectId: z.string().describe("Atlas project ID to filter DB users"), }; protected async execute({ projectId }: ToolArgs): Promise { - this.session.ensureAuthenticated(); - const data = await this.session.apiClient.listDatabaseUsers({ params: { path: { diff --git a/src/tools/atlas/listOrgs.ts b/src/tools/atlas/listOrgs.ts new file mode 100644 index 00000000..2bfa95c2 --- /dev/null +++ b/src/tools/atlas/listOrgs.ts @@ -0,0 +1,32 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { AtlasToolBase } from "./atlasTool.js"; +import { OperationType } from "../tool.js"; + +export class ListOrganizationsTool extends AtlasToolBase { + protected name = "atlas-list-orgs"; + protected description = "List MongoDB Atlas organizations"; + protected operationType: OperationType = "read"; + protected argsShape = {}; + + protected async execute(): Promise { + const data = await this.session.apiClient.listOrganizations(); + + if (!data?.results?.length) { + throw new Error("No projects found in your MongoDB Atlas account."); + } + + // Format projects as a table + const output = + `Organization Name | Organization ID +----------------| ---------------- +` + + data.results + .map((org) => { + return `${org.name} | ${org.id}`; + }) + .join("\n"); + return { + content: [{ type: "text", text: output }], + }; + } +} diff --git a/src/tools/atlas/listProjects.ts b/src/tools/atlas/listProjects.ts index bb9e0865..be127b29 100644 --- a/src/tools/atlas/listProjects.ts +++ b/src/tools/atlas/listProjects.ts @@ -1,15 +1,27 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { AtlasToolBase } from "./atlasTool.js"; +import { OperationType } from "../tool.js"; +import { z } from "zod"; +import { ToolArgs } from "../tool.js"; export class ListProjectsTool extends AtlasToolBase { protected name = "atlas-list-projects"; protected description = "List MongoDB Atlas projects"; - protected argsShape = {}; + protected operationType: OperationType = "read"; + protected argsShape = { + orgId: z.string().describe("Atlas organization ID to filter projects").optional(), + }; - protected async execute(): Promise { - this.session.ensureAuthenticated(); - - const data = await this.session.apiClient.listProjects(); + protected async execute({ orgId }: ToolArgs): Promise { + const data = orgId + ? await this.session.apiClient.listOrganizationProjects({ + params: { + path: { + orgId, + }, + }, + }) + : await this.session.apiClient.listProjects(); if (!data?.results?.length) { throw new Error("No projects found in your MongoDB Atlas account."); diff --git a/src/tools/atlas/tools.ts b/src/tools/atlas/tools.ts index 4e7bd200..4a3772ef 100644 --- a/src/tools/atlas/tools.ts +++ b/src/tools/atlas/tools.ts @@ -6,6 +6,8 @@ import { CreateAccessListTool } from "./createAccessList.js"; import { InspectAccessListTool } from "./inspectAccessList.js"; import { ListDBUsersTool } from "./listDBUsers.js"; import { CreateDBUserTool } from "./createDBUser.js"; +import { CreateProjectTool } from "./createProject.js"; +import { ListOrganizationsTool } from "./listOrgs.js"; export const AtlasTools = [ ListClustersTool, @@ -16,4 +18,6 @@ export const AtlasTools = [ InspectAccessListTool, ListDBUsersTool, CreateDBUserTool, + CreateProjectTool, + ListOrganizationsTool, ]; diff --git a/src/tools/mongodb/collectionIndexes.ts b/src/tools/mongodb/collectionIndexes.ts deleted file mode 100644 index 4d8cae90..00000000 --- a/src/tools/mongodb/collectionIndexes.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "./mongodbTool.js"; -import { ToolArgs } from "../tool.js"; - -export class CollectionIndexesTool extends MongoDBToolBase { - protected name = "collection-indexes"; - protected description = "Describe the indexes for a collection"; - protected argsShape = DbOperationArgs; - protected operationType: DbOperationType = "read"; - - protected async execute({ database, collection }: ToolArgs): Promise { - const provider = await this.ensureConnected(); - const indexes = await provider.getIndexes(database, collection); - - return { - content: indexes.map((indexDefinition) => { - return { - text: `Field: ${indexDefinition.name}: ${JSON.stringify(indexDefinition.key)}`, - type: "text", - }; - }), - }; - } -} diff --git a/src/tools/mongodb/connect.ts b/src/tools/mongodb/connect.ts deleted file mode 100644 index 66df62e3..00000000 --- a/src/tools/mongodb/connect.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { z } from "zod"; -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "./mongodbTool.js"; -import { ToolArgs } from "../tool.js"; -import { ErrorCodes, MongoDBError } from "../../errors.js"; -import config from "../../config.js"; - -export class ConnectTool extends MongoDBToolBase { - protected name = "connect"; - protected description = "Connect to a MongoDB instance"; - protected argsShape = { - connectionStringOrClusterName: z - .string() - .optional() - .describe("MongoDB connection string (in the mongodb:// or mongodb+srv:// format) or cluster name"), - }; - - protected operationType: DbOperationType = "metadata"; - - protected async execute({ - connectionStringOrClusterName, - }: ToolArgs): Promise { - connectionStringOrClusterName ??= config.connectionString; - if (!connectionStringOrClusterName) { - return { - content: [ - { type: "text", text: "No connection details provided." }, - { type: "text", text: "Please provide either a connection string or a cluster name" }, - { - type: "text", - text: "Alternatively, you can use the default deployment at mongodb://localhost:27017", - }, - ], - }; - } - - let connectionString: string; - - if (typeof connectionStringOrClusterName === "string") { - if ( - connectionStringOrClusterName.startsWith("mongodb://") || - connectionStringOrClusterName.startsWith("mongodb+srv://") - ) { - connectionString = connectionStringOrClusterName; - } else { - // TODO: - return { - content: [ - { - type: "text", - text: `Connecting via cluster name not supported yet. Please provide a connection string.`, - }, - ], - }; - } - } else { - throw new MongoDBError(ErrorCodes.InvalidParams, "Invalid connection options"); - } - - await this.connectToMongoDB(connectionString); - - return { - content: [{ type: "text", text: `Successfully connected to ${connectionString}.` }], - }; - } -} diff --git a/src/tools/mongodb/create/createCollection.ts b/src/tools/mongodb/create/createCollection.ts new file mode 100644 index 00000000..27eaa9f5 --- /dev/null +++ b/src/tools/mongodb/create/createCollection.ts @@ -0,0 +1,26 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { OperationType, ToolArgs } from "../../tool.js"; + +export class CreateCollectionTool extends MongoDBToolBase { + protected name = "create-collection"; + protected description = + "Creates a new collection in a database. If the database doesn't exist, it will be created automatically."; + protected argsShape = DbOperationArgs; + + protected operationType: OperationType = "create"; + + protected async execute({ collection, database }: ToolArgs): Promise { + const provider = await this.ensureConnected(); + await provider.createCollection(database, collection); + + return { + content: [ + { + type: "text", + text: `Collection "${collection}" created in database "${database}".`, + }, + ], + }; + } +} diff --git a/src/tools/mongodb/createIndex.ts b/src/tools/mongodb/create/createIndex.ts similarity index 58% rename from src/tools/mongodb/createIndex.ts rename to src/tools/mongodb/create/createIndex.ts index 30bc17af..beffaf86 100644 --- a/src/tools/mongodb/createIndex.ts +++ b/src/tools/mongodb/create/createIndex.ts @@ -1,7 +1,7 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "./mongodbTool.js"; -import { ToolArgs } from "../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; import { IndexDirection } from "mongodb"; export class CreateIndexTool extends MongoDBToolBase { @@ -10,22 +10,29 @@ export class CreateIndexTool extends MongoDBToolBase { protected argsShape = { ...DbOperationArgs, keys: z.record(z.string(), z.custom()).describe("The index definition"), + name: z.string().optional().describe("The name of the index"), }; - protected operationType: DbOperationType = "create"; + protected operationType: OperationType = "create"; - protected async execute({ database, collection, keys }: ToolArgs): Promise { + protected async execute({ + database, + collection, + keys, + name, + }: ToolArgs): Promise { const provider = await this.ensureConnected(); const indexes = await provider.createIndexes(database, collection, [ { key: keys, + name, }, ]); return { content: [ { - text: `Created the index \`${indexes[0]}\``, + text: `Created the index "${indexes[0]}" on collection "${collection}" in database "${database}"`, type: "text", }, ], diff --git a/src/tools/mongodb/create/insertMany.ts b/src/tools/mongodb/create/insertMany.ts index fdf1dcbc..eb624275 100644 --- a/src/tools/mongodb/create/insertMany.ts +++ b/src/tools/mongodb/create/insertMany.ts @@ -1,7 +1,7 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class InsertManyTool extends MongoDBToolBase { protected name = "insert-many"; @@ -14,7 +14,7 @@ export class InsertManyTool extends MongoDBToolBase { "The array of documents to insert, matching the syntax of the document argument of db.collection.insertMany()" ), }; - protected operationType: DbOperationType = "create"; + protected operationType: OperationType = "create"; protected async execute({ database, @@ -27,7 +27,7 @@ export class InsertManyTool extends MongoDBToolBase { return { content: [ { - text: `Inserted \`${result.insertedCount}\` documents into collection \`${collection}\``, + text: `Inserted \`${result.insertedCount}\` document(s) into collection "${collection}"`, type: "text", }, { diff --git a/src/tools/mongodb/create/insertOne.ts b/src/tools/mongodb/create/insertOne.ts deleted file mode 100644 index 795c603e..00000000 --- a/src/tools/mongodb/create/insertOne.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { z } from "zod"; -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; - -export class InsertOneTool extends MongoDBToolBase { - protected name = "insert-one"; - protected description = "Insert a document into a MongoDB collection"; - protected argsShape = { - ...DbOperationArgs, - document: z - .object({}) - .passthrough() - .describe( - "The document to insert, matching the syntax of the document argument of db.collection.insertOne()" - ), - }; - - protected operationType: DbOperationType = "create"; - - protected async execute({ - database, - collection, - document, - }: ToolArgs): Promise { - const provider = await this.ensureConnected(); - const result = await provider.insertOne(database, collection, document); - - return { - content: [ - { - text: `Inserted document with ID \`${result.insertedId.toString()}\` into collection \`${collection}\``, - type: "text", - }, - ], - }; - } -} diff --git a/src/tools/mongodb/delete/deleteMany.ts b/src/tools/mongodb/delete/deleteMany.ts index 5702b54a..9e6e9fde 100644 --- a/src/tools/mongodb/delete/deleteMany.ts +++ b/src/tools/mongodb/delete/deleteMany.ts @@ -1,7 +1,7 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class DeleteManyTool extends MongoDBToolBase { protected name = "delete-many"; @@ -16,7 +16,7 @@ export class DeleteManyTool extends MongoDBToolBase { "The query filter, specifying the deletion criteria. Matches the syntax of the filter argument of db.collection.deleteMany()" ), }; - protected operationType: DbOperationType = "delete"; + protected operationType: OperationType = "delete"; protected async execute({ database, @@ -29,7 +29,7 @@ export class DeleteManyTool extends MongoDBToolBase { return { content: [ { - text: `Deleted \`${result.deletedCount}\` documents from collection \`${collection}\``, + text: `Deleted \`${result.deletedCount}\` document(s) from collection "${collection}"`, type: "text", }, ], diff --git a/src/tools/mongodb/delete/deleteOne.ts b/src/tools/mongodb/delete/deleteOne.ts deleted file mode 100644 index 3c9a2e57..00000000 --- a/src/tools/mongodb/delete/deleteOne.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { z } from "zod"; -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; - -export class DeleteOneTool extends MongoDBToolBase { - protected name = "delete-one"; - protected description = "Removes a single document that match the filter from a MongoDB collection"; - protected argsShape = { - ...DbOperationArgs, - filter: z - .object({}) - .passthrough() - .optional() - .describe( - "The query filter, specifying the deletion criteria. Matches the syntax of the filter argument of db.collection.deleteMany()" - ), - }; - protected operationType: DbOperationType = "delete"; - - protected async execute({ - database, - collection, - filter, - }: ToolArgs): Promise { - const provider = await this.ensureConnected(); - const result = await provider.deleteOne(database, collection, filter); - - return { - content: [ - { - text: `Deleted \`${result.deletedCount}\` documents from collection \`${collection}\``, - type: "text", - }, - ], - }; - } -} diff --git a/src/tools/mongodb/delete/dropCollection.ts b/src/tools/mongodb/delete/dropCollection.ts index b6444da6..ac914f75 100644 --- a/src/tools/mongodb/delete/dropCollection.ts +++ b/src/tools/mongodb/delete/dropCollection.ts @@ -1,6 +1,6 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class DropCollectionTool extends MongoDBToolBase { protected name = "drop-collection"; @@ -9,7 +9,7 @@ export class DropCollectionTool extends MongoDBToolBase { protected argsShape = { ...DbOperationArgs, }; - protected operationType: DbOperationType = "delete"; + protected operationType: OperationType = "delete"; protected async execute({ database, collection }: ToolArgs): Promise { const provider = await this.ensureConnected(); @@ -18,7 +18,7 @@ export class DropCollectionTool extends MongoDBToolBase { return { content: [ { - text: `${result ? "Successfully dropped" : "Failed to drop"} collection \`${collection}\` from database \`${database}\``, + text: `${result ? "Successfully dropped" : "Failed to drop"} collection "${collection}" from database "${database}"`, type: "text", }, ], diff --git a/src/tools/mongodb/delete/dropDatabase.ts b/src/tools/mongodb/delete/dropDatabase.ts index 4b126b2c..b10862b2 100644 --- a/src/tools/mongodb/delete/dropDatabase.ts +++ b/src/tools/mongodb/delete/dropDatabase.ts @@ -1,6 +1,6 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class DropDatabaseTool extends MongoDBToolBase { protected name = "drop-database"; @@ -8,7 +8,7 @@ export class DropDatabaseTool extends MongoDBToolBase { protected argsShape = { database: DbOperationArgs.database, }; - protected operationType: DbOperationType = "delete"; + protected operationType: OperationType = "delete"; protected async execute({ database }: ToolArgs): Promise { const provider = await this.ensureConnected(); @@ -17,7 +17,7 @@ export class DropDatabaseTool extends MongoDBToolBase { return { content: [ { - text: `${result.ok ? "Successfully dropped" : "Failed to drop"} database \`${database}\``, + text: `${result.ok ? "Successfully dropped" : "Failed to drop"} database "${database}"`, type: "text", }, ], diff --git a/src/tools/mongodb/metadata/collectionSchema.ts b/src/tools/mongodb/metadata/collectionSchema.ts index dfa45a6c..f0145323 100644 --- a/src/tools/mongodb/metadata/collectionSchema.ts +++ b/src/tools/mongodb/metadata/collectionSchema.ts @@ -1,41 +1,43 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; -import { parseSchema, SchemaField } from "mongodb-schema"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; +import { getSimplifiedSchema } from "mongodb-schema"; export class CollectionSchemaTool extends MongoDBToolBase { protected name = "collection-schema"; protected description = "Describe the schema for a collection"; protected argsShape = DbOperationArgs; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "metadata"; protected async execute({ database, collection }: ToolArgs): Promise { const provider = await this.ensureConnected(); const documents = await provider.find(database, collection, {}, { limit: 5 }).toArray(); - const schema = await parseSchema(documents); + const schema = await getSimplifiedSchema(documents); + + const fieldsCount = Object.entries(schema).length; + if (fieldsCount === 0) { + return { + content: [ + { + text: `Could not deduce the schema for "${database}.${collection}". This may be because it doesn't exist or is empty.`, + type: "text", + }, + ], + }; + } return { content: [ { - text: `Found ${schema.fields.length} fields in the schema for \`${database}.${collection}\``, + text: `Found ${fieldsCount} fields in the schema for "${database}.${collection}"`, type: "text", }, { - text: this.formatFieldOutput(schema.fields), + text: JSON.stringify(schema), type: "text", }, ], }; } - - private formatFieldOutput(fields: SchemaField[]): string { - let result = "| Field | Type | Confidence |\n"; - result += "|-------|------|-------------|\n"; - for (const field of fields) { - const fieldType = Array.isArray(field.type) ? field.type.join(", ") : field.type; - result += `| ${field.name} | \`${fieldType}\` | ${(field.probability * 100).toFixed(0)}% |\n`; - } - return result; - } } diff --git a/src/tools/mongodb/metadata/collectionStorageSize.ts b/src/tools/mongodb/metadata/collectionStorageSize.ts index 09b7e6d3..127e7172 100644 --- a/src/tools/mongodb/metadata/collectionStorageSize.ts +++ b/src/tools/mongodb/metadata/collectionStorageSize.ts @@ -1,30 +1,68 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class CollectionStorageSizeTool extends MongoDBToolBase { protected name = "collection-storage-size"; - protected description = "Gets the size of the collection in MB"; + protected description = "Gets the size of the collection"; protected argsShape = DbOperationArgs; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "metadata"; protected async execute({ database, collection }: ToolArgs): Promise { const provider = await this.ensureConnected(); const [{ value }] = (await provider .aggregate(database, collection, [ { $collStats: { storageStats: {} } }, - { $group: { _id: null, value: { $sum: "$storageStats.storageSize" } } }, + { $group: { _id: null, value: { $sum: "$storageStats.size" } } }, ]) .toArray()) as [{ value: number }]; + const { units, value: scaledValue } = CollectionStorageSizeTool.getStats(value); + return { content: [ { - text: `The size of \`${database}.${collection}\` is \`${(value / 1024 / 1024).toFixed(2)} MB\``, + text: `The size of "${database}.${collection}" is \`${scaledValue.toFixed(2)} ${units}\``, type: "text", }, ], }; } + + protected handleError( + error: unknown, + args: ToolArgs + ): Promise | CallToolResult { + if (error instanceof Error && "codeName" in error && error.codeName === "NamespaceNotFound") { + return { + content: [ + { + text: `The size of "${args.database}.${args.collection}" cannot be determined because the collection does not exist.`, + type: "text", + }, + ], + }; + } + + return super.handleError(error, args); + } + + private static getStats(value: number): { value: number; units: string } { + const kb = 1024; + const mb = kb * 1024; + const gb = mb * 1024; + + if (value > gb) { + return { value: value / gb, units: "GB" }; + } + + if (value > mb) { + return { value: value / mb, units: "MB" }; + } + if (value > kb) { + return { value: value / kb, units: "KB" }; + } + return { value, units: "bytes" }; + } } diff --git a/src/tools/mongodb/metadata/connect.ts b/src/tools/mongodb/metadata/connect.ts new file mode 100644 index 00000000..746da9b3 --- /dev/null +++ b/src/tools/mongodb/metadata/connect.ts @@ -0,0 +1,93 @@ +import { z } from "zod"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; +import { MongoError as DriverError } from "mongodb"; + +export class ConnectTool extends MongoDBToolBase { + protected name = "connect"; + protected description = "Connect to a MongoDB instance"; + protected argsShape = { + options: z + .array( + z + .union([ + z.object({ + connectionString: z + .string() + .describe("MongoDB connection string (in the mongodb:// or mongodb+srv:// format)"), + }), + z.object({ + clusterName: z.string().describe("MongoDB cluster name"), + }), + ]) + .optional() + ) + .optional() + .describe( + "Options for connecting to MongoDB. If not provided, the connection string from the config://connection-string resource will be used. If the user hasn't specified Atlas cluster name or a connection string explicitly and the `config://connection-string` resource is present, always invoke this with no arguments." + ), + }; + + protected operationType: OperationType = "metadata"; + + protected async execute({ options: optionsArr }: ToolArgs): Promise { + const options = optionsArr?.[0]; + let connectionString: string; + if (!options && !this.config.connectionString) { + return { + content: [ + { type: "text", text: "No connection details provided." }, + { type: "text", text: "Please provide either a connection string or a cluster name" }, + ], + }; + } + + if (!options) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + connectionString = this.config.connectionString!; + } else if ("connectionString" in options) { + connectionString = options.connectionString; + } else { + // TODO: https://github.com/mongodb-js/mongodb-mcp-server/issues/19 + // We don't support connecting via cluster name since we'd need to obtain the user credentials + // and fill in the connection string. + return { + content: [ + { + type: "text", + text: `Connecting via cluster name not supported yet. Please provide a connection string.`, + }, + ], + }; + } + + try { + await this.connectToMongoDB(connectionString); + return { + content: [{ type: "text", text: `Successfully connected to ${connectionString}.` }], + }; + } catch (error) { + // Sometimes the model will supply an incorrect connection string. If the user has configured + // a different one as environment variable or a cli argument, suggest using that one instead. + if ( + this.config.connectionString && + error instanceof DriverError && + this.config.connectionString !== connectionString + ) { + return { + content: [ + { + type: "text", + text: + `Failed to connect to MongoDB at '${connectionString}' due to error: '${error.message}.` + + `Your config lists a different connection string: '${this.config.connectionString}' - do you want to try connecting to it instead?`, + }, + ], + }; + } + + throw error; + } + } +} diff --git a/src/tools/mongodb/metadata/dbStats.ts b/src/tools/mongodb/metadata/dbStats.ts index 1223b25b..a8c0ea0d 100644 --- a/src/tools/mongodb/metadata/dbStats.ts +++ b/src/tools/mongodb/metadata/dbStats.ts @@ -1,6 +1,7 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; +import { EJSON } from "bson"; export class DbStatsTool extends MongoDBToolBase { protected name = "db-stats"; @@ -9,7 +10,7 @@ export class DbStatsTool extends MongoDBToolBase { database: DbOperationArgs.database, }; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "metadata"; protected async execute({ database }: ToolArgs): Promise { const provider = await this.ensureConnected(); @@ -21,7 +22,11 @@ export class DbStatsTool extends MongoDBToolBase { return { content: [ { - text: `Statistics for database ${database}: ${JSON.stringify(result)}`, + text: `Statistics for database ${database}`, + type: "text", + }, + { + text: EJSON.stringify(result), type: "text", }, ], diff --git a/src/tools/mongodb/metadata/explain.ts b/src/tools/mongodb/metadata/explain.ts index 4a750a1f..e529e899 100644 --- a/src/tools/mongodb/metadata/explain.ts +++ b/src/tools/mongodb/metadata/explain.ts @@ -1,6 +1,6 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; import { z } from "zod"; import { ExplainVerbosity, Document } from "mongodb"; import { AggregateArgs } from "../read/aggregate.js"; @@ -34,7 +34,7 @@ export class ExplainTool extends MongoDBToolBase { .describe("The method and its arguments to run"), }; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "metadata"; static readonly defaultVerbosity = ExplainVerbosity.queryPlanner; @@ -47,14 +47,24 @@ export class ExplainTool extends MongoDBToolBase { const method = methods[0]; if (!method) { - throw new Error("No method provided"); + throw new Error("No method provided. Expected one of the following: `aggregate`, `find`, or `count`"); } let result: Document; switch (method.name) { case "aggregate": { const { pipeline } = method.arguments; - result = await provider.aggregate(database, collection, pipeline).explain(ExplainTool.defaultVerbosity); + result = await provider + .aggregate( + database, + collection, + pipeline, + {}, + { + writeConcern: undefined, + } + ) + .explain(ExplainTool.defaultVerbosity); break; } case "find": { @@ -66,10 +76,13 @@ export class ExplainTool extends MongoDBToolBase { } case "count": { const { query } = method.arguments; - // This helper doesn't have explain() command but does have the argument explain - result = (await provider.count(database, collection, query, { - explain: ExplainTool.defaultVerbosity, - })) as unknown as Document; + result = await provider.mongoClient.db(database).command({ + explain: { + count: collection, + query, + }, + verbosity: ExplainTool.defaultVerbosity, + }); break; } } @@ -77,7 +90,7 @@ export class ExplainTool extends MongoDBToolBase { return { content: [ { - text: `Here is some information about the winning plan chosen by the query optimizer for running the given \`${method.name}\` operation in \`${database}.${collection}\`. This information can be used to understand how the query was executed and to optimize the query performance.`, + text: `Here is some information about the winning plan chosen by the query optimizer for running the given \`${method.name}\` operation in "${database}.${collection}". This information can be used to understand how the query was executed and to optimize the query performance.`, type: "text", }, { diff --git a/src/tools/mongodb/metadata/listCollections.ts b/src/tools/mongodb/metadata/listCollections.ts index 2fc95d3d..193d0465 100644 --- a/src/tools/mongodb/metadata/listCollections.ts +++ b/src/tools/mongodb/metadata/listCollections.ts @@ -1,6 +1,6 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class ListCollectionsTool extends MongoDBToolBase { protected name = "list-collections"; @@ -9,16 +9,27 @@ export class ListCollectionsTool extends MongoDBToolBase { database: DbOperationArgs.database, }; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "metadata"; protected async execute({ database }: ToolArgs): Promise { const provider = await this.ensureConnected(); const collections = await provider.listCollections(database); + if (collections.length === 0) { + return { + content: [ + { + type: "text", + text: `No collections found for database "${database}". To create a collection, use the "create-collection" tool.`, + }, + ], + }; + } + return { content: collections.map((collection) => { return { - text: `Name: ${collection.name}`, + text: `Name: "${collection.name}"`, type: "text", }; }), diff --git a/src/tools/mongodb/metadata/listDatabases.ts b/src/tools/mongodb/metadata/listDatabases.ts index bdbdd19a..ce943a69 100644 --- a/src/tools/mongodb/metadata/listDatabases.ts +++ b/src/tools/mongodb/metadata/listDatabases.ts @@ -1,13 +1,14 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; +import { MongoDBToolBase } from "../mongodbTool.js"; import * as bson from "bson"; +import { OperationType } from "../../tool.js"; export class ListDatabasesTool extends MongoDBToolBase { protected name = "list-databases"; protected description = "List all databases for a MongoDB connection"; protected argsShape = {}; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "metadata"; protected async execute(): Promise { const provider = await this.ensureConnected(); diff --git a/src/tools/mongodb/mongodbTool.ts b/src/tools/mongodb/mongodbTool.ts index fb1a0a32..d818c7ab 100644 --- a/src/tools/mongodb/mongodbTool.ts +++ b/src/tools/mongodb/mongodbTool.ts @@ -1,39 +1,33 @@ import { z } from "zod"; -import { ToolBase } from "../tool.js"; -import { Session } from "../../session.js"; +import { ToolArgs, ToolBase, ToolCategory } from "../tool.js"; import { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { ErrorCodes, MongoDBError } from "../../errors.js"; -import config from "../../config.js"; export const DbOperationArgs = { database: z.string().describe("Database name"), collection: z.string().describe("Collection name"), }; -export type DbOperationType = "metadata" | "read" | "create" | "update" | "delete"; - export abstract class MongoDBToolBase extends ToolBase { - constructor(session: Session) { - super(session); - } - - protected abstract operationType: DbOperationType; + protected category: ToolCategory = "mongodb"; protected async ensureConnected(): Promise { - const provider = this.session.serviceProvider; - if (!provider && config.connectionString) { - await this.connectToMongoDB(config.connectionString); + if (!this.session.serviceProvider && this.config.connectionString) { + await this.connectToMongoDB(this.config.connectionString); } - if (!provider) { + if (!this.session.serviceProvider) { throw new MongoDBError(ErrorCodes.NotConnectedToMongoDB, "Not connected to MongoDB"); } - return provider; + return this.session.serviceProvider; } - protected handleError(error: unknown): Promise | CallToolResult { + protected handleError( + error: unknown, + args: ToolArgs + ): Promise | CallToolResult { if (error instanceof MongoDBError && error.code === ErrorCodes.NotConnectedToMongoDB) { return { content: [ @@ -50,7 +44,7 @@ export abstract class MongoDBToolBase extends ToolBase { }; } - return super.handleError(error); + return super.handleError(error, args); } protected async connectToMongoDB(connectionString: string): Promise { @@ -58,13 +52,13 @@ export abstract class MongoDBToolBase extends ToolBase { productDocsLink: "https://docs.mongodb.com/todo-mcp", productName: "MongoDB MCP", readConcern: { - level: config.connectOptions.readConcern, + level: this.config.connectOptions.readConcern, }, - readPreference: config.connectOptions.readPreference, + readPreference: this.config.connectOptions.readPreference, writeConcern: { - w: config.connectOptions.writeConcern, + w: this.config.connectOptions.writeConcern, }, - timeoutMS: config.connectOptions.timeoutMS, + timeoutMS: this.config.connectOptions.timeoutMS, }); this.session.serviceProvider = provider; diff --git a/src/tools/mongodb/read/aggregate.ts b/src/tools/mongodb/read/aggregate.ts index abdbf70e..c5824785 100644 --- a/src/tools/mongodb/read/aggregate.ts +++ b/src/tools/mongodb/read/aggregate.ts @@ -1,11 +1,11 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; +import { EJSON } from "bson"; export const AggregateArgs = { pipeline: z.array(z.object({}).passthrough()).describe("An array of aggregation stages to execute"), - limit: z.number().optional().default(10).describe("The maximum number of documents to return"), }; export class AggregateTool extends MongoDBToolBase { @@ -15,7 +15,7 @@ export class AggregateTool extends MongoDBToolBase { ...DbOperationArgs, ...AggregateArgs, }; - protected operationType: DbOperationType = "read"; + protected operationType: OperationType = "read"; protected async execute({ database, @@ -27,12 +27,12 @@ export class AggregateTool extends MongoDBToolBase { const content: Array<{ text: string; type: "text" }> = [ { - text: `Found ${documents.length} documents in the collection \`${collection}\`:`, + text: `Found ${documents.length} documents in the collection "${collection}":`, type: "text", }, ...documents.map((doc) => { return { - text: JSON.stringify(doc), + text: EJSON.stringify(doc), type: "text", } as { text: string; type: "text" }; }), diff --git a/src/tools/mongodb/read/collectionIndexes.ts b/src/tools/mongodb/read/collectionIndexes.ts new file mode 100644 index 00000000..cc0a141b --- /dev/null +++ b/src/tools/mongodb/read/collectionIndexes.ts @@ -0,0 +1,48 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; + +export class CollectionIndexesTool extends MongoDBToolBase { + protected name = "collection-indexes"; + protected description = "Describe the indexes for a collection"; + protected argsShape = DbOperationArgs; + protected operationType: OperationType = "read"; + + protected async execute({ database, collection }: ToolArgs): Promise { + const provider = await this.ensureConnected(); + const indexes = await provider.getIndexes(database, collection); + + return { + content: [ + { + text: `Found ${indexes.length} indexes in the collection "${collection}":`, + type: "text", + }, + ...(indexes.map((indexDefinition) => { + return { + text: `Name "${indexDefinition.name}", definition: ${JSON.stringify(indexDefinition.key)}`, + type: "text", + }; + }) as { text: string; type: "text" }[]), + ], + }; + } + + protected handleError( + error: unknown, + args: ToolArgs + ): Promise | CallToolResult { + if (error instanceof Error && "codeName" in error && error.codeName === "NamespaceNotFound") { + return { + content: [ + { + text: `The indexes for "${args.database}.${args.collection}" cannot be determined because the collection does not exist.`, + type: "text", + }, + ], + }; + } + + return super.handleError(error, args); + } +} diff --git a/src/tools/mongodb/read/count.ts b/src/tools/mongodb/read/count.ts index 63d052bb..188648d5 100644 --- a/src/tools/mongodb/read/count.ts +++ b/src/tools/mongodb/read/count.ts @@ -1,6 +1,6 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; import { z } from "zod"; export const CountArgs = { @@ -21,7 +21,7 @@ export class CountTool extends MongoDBToolBase { ...CountArgs, }; - protected operationType: DbOperationType = "metadata"; + protected operationType: OperationType = "read"; protected async execute({ database, collection, query }: ToolArgs): Promise { const provider = await this.ensureConnected(); @@ -30,7 +30,7 @@ export class CountTool extends MongoDBToolBase { return { content: [ { - text: `Found ${count} documents in the collection \`${collection}\``, + text: `Found ${count} documents in the collection "${collection}"`, type: "text", }, ], diff --git a/src/tools/mongodb/read/find.ts b/src/tools/mongodb/read/find.ts index 9893891a..e0f806b0 100644 --- a/src/tools/mongodb/read/find.ts +++ b/src/tools/mongodb/read/find.ts @@ -1,8 +1,9 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationArgs, DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; import { SortDirection } from "mongodb"; +import { EJSON } from "bson"; export const FindArgs = { filter: z @@ -29,7 +30,7 @@ export class FindTool extends MongoDBToolBase { ...DbOperationArgs, ...FindArgs, }; - protected operationType: DbOperationType = "read"; + protected operationType: OperationType = "read"; protected async execute({ database, @@ -44,12 +45,12 @@ export class FindTool extends MongoDBToolBase { const content: Array<{ text: string; type: "text" }> = [ { - text: `Found ${documents.length} documents in the collection \`${collection}\`:`, + text: `Found ${documents.length} documents in the collection "${collection}":`, type: "text", }, ...documents.map((doc) => { return { - text: JSON.stringify(doc), + text: EJSON.stringify(doc), type: "text", } as { text: string; type: "text" }; }), diff --git a/src/tools/mongodb/tools.ts b/src/tools/mongodb/tools.ts index ac22e095..eddbd26b 100644 --- a/src/tools/mongodb/tools.ts +++ b/src/tools/mongodb/tools.ts @@ -1,24 +1,22 @@ -import { ConnectTool } from "./connect.js"; +import { ConnectTool } from "./metadata/connect.js"; import { ListCollectionsTool } from "./metadata/listCollections.js"; -import { CollectionIndexesTool } from "./collectionIndexes.js"; +import { CollectionIndexesTool } from "./read/collectionIndexes.js"; import { ListDatabasesTool } from "./metadata/listDatabases.js"; -import { CreateIndexTool } from "./createIndex.js"; +import { CreateIndexTool } from "./create/createIndex.js"; import { CollectionSchemaTool } from "./metadata/collectionSchema.js"; -import { InsertOneTool } from "./create/insertOne.js"; import { FindTool } from "./read/find.js"; import { InsertManyTool } from "./create/insertMany.js"; import { DeleteManyTool } from "./delete/deleteMany.js"; -import { DeleteOneTool } from "./delete/deleteOne.js"; import { CollectionStorageSizeTool } from "./metadata/collectionStorageSize.js"; import { CountTool } from "./read/count.js"; import { DbStatsTool } from "./metadata/dbStats.js"; import { AggregateTool } from "./read/aggregate.js"; -import { UpdateOneTool } from "./update/updateOne.js"; import { UpdateManyTool } from "./update/updateMany.js"; import { RenameCollectionTool } from "./update/renameCollection.js"; import { DropDatabaseTool } from "./delete/dropDatabase.js"; import { DropCollectionTool } from "./delete/dropCollection.js"; import { ExplainTool } from "./metadata/explain.js"; +import { CreateCollectionTool } from "./create/createCollection.js"; export const MongoDbTools = [ ConnectTool, @@ -27,19 +25,17 @@ export const MongoDbTools = [ CollectionIndexesTool, CreateIndexTool, CollectionSchemaTool, - InsertOneTool, FindTool, InsertManyTool, DeleteManyTool, - DeleteOneTool, CollectionStorageSizeTool, CountTool, DbStatsTool, AggregateTool, - UpdateOneTool, UpdateManyTool, RenameCollectionTool, DropDatabaseTool, DropCollectionTool, ExplainTool, + CreateCollectionTool, ]; diff --git a/src/tools/mongodb/update/renameCollection.ts b/src/tools/mongodb/update/renameCollection.ts index e0c83875..d3b07c15 100644 --- a/src/tools/mongodb/update/renameCollection.ts +++ b/src/tools/mongodb/update/renameCollection.ts @@ -1,18 +1,17 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class RenameCollectionTool extends MongoDBToolBase { protected name = "rename-collection"; protected description = "Renames a collection in a MongoDB database"; protected argsShape = { - collection: z.string().describe("Collection name"), - database: z.string().describe("Database name"), + ...DbOperationArgs, newName: z.string().describe("The new name for the collection"), dropTarget: z.boolean().optional().default(false).describe("If true, drops the target collection if it exists"), }; - protected operationType: DbOperationType = "update"; + protected operationType: OperationType = "update"; protected async execute({ database, @@ -28,10 +27,40 @@ export class RenameCollectionTool extends MongoDBToolBase { return { content: [ { - text: `Collection \`${collection}\` renamed to \`${result.collectionName}\` in database \`${database}\`.`, + text: `Collection "${collection}" renamed to "${result.collectionName}" in database "${database}".`, type: "text", }, ], }; } + + protected handleError( + error: unknown, + args: ToolArgs + ): Promise | CallToolResult { + if (error instanceof Error && "codeName" in error) { + switch (error.codeName) { + case "NamespaceNotFound": + return { + content: [ + { + text: `Cannot rename "${args.database}.${args.collection}" because it doesn't exist.`, + type: "text", + }, + ], + }; + case "NamespaceExists": + return { + content: [ + { + text: `Cannot rename "${args.database}.${args.collection}" to "${args.newName}" because the target collection already exists. If you want to overwrite it, set the "dropTarget" argument to true.`, + type: "text", + }, + ], + }; + } + } + + return super.handleError(error, args); + } } diff --git a/src/tools/mongodb/update/updateMany.ts b/src/tools/mongodb/update/updateMany.ts index f02e2a62..c11d8a49 100644 --- a/src/tools/mongodb/update/updateMany.ts +++ b/src/tools/mongodb/update/updateMany.ts @@ -1,14 +1,13 @@ import { z } from "zod"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; +import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; export class UpdateManyTool extends MongoDBToolBase { protected name = "update-many"; protected description = "Updates all documents that match the specified filter for a collection"; protected argsShape = { - collection: z.string().describe("Collection name"), - database: z.string().describe("Database name"), + ...DbOperationArgs, filter: z .object({}) .passthrough() @@ -19,14 +18,13 @@ export class UpdateManyTool extends MongoDBToolBase { update: z .object({}) .passthrough() - .optional() .describe("An update document describing the modifications to apply using update operator expressions"), upsert: z .boolean() .optional() .describe("Controls whether to insert a new document if no documents match the filter"), }; - protected operationType: DbOperationType = "update"; + protected operationType: OperationType = "update"; protected async execute({ database, @@ -41,15 +39,15 @@ export class UpdateManyTool extends MongoDBToolBase { }); let message = ""; - if (result.matchedCount === 0) { - message = `No documents matched the filter.`; + if (result.matchedCount === 0 && result.modifiedCount === 0 && result.upsertedCount === 0) { + message = "No documents matched the filter."; } else { message = `Matched ${result.matchedCount} document(s).`; if (result.modifiedCount > 0) { message += ` Modified ${result.modifiedCount} document(s).`; } if (result.upsertedCount > 0) { - message += ` Upserted ${result.upsertedCount} document(s) (with id: ${result.upsertedId?.toString()}).`; + message += ` Upserted ${result.upsertedCount} document with id: ${result.upsertedId?.toString()}.`; } } diff --git a/src/tools/mongodb/update/updateOne.ts b/src/tools/mongodb/update/updateOne.ts deleted file mode 100644 index 9d117b7b..00000000 --- a/src/tools/mongodb/update/updateOne.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { z } from "zod"; -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; -import { DbOperationType, MongoDBToolBase } from "../mongodbTool.js"; -import { ToolArgs } from "../../tool.js"; - -export class UpdateOneTool extends MongoDBToolBase { - protected name = "update-one"; - protected description = "Updates a single document within the collection based on the filter"; - protected argsShape = { - collection: z.string().describe("Collection name"), - database: z.string().describe("Database name"), - filter: z - .object({}) - .passthrough() - .optional() - .describe( - "The selection criteria for the update, matching the syntax of the filter argument of db.collection.updateOne()" - ), - update: z - .object({}) - .passthrough() - .optional() - .describe("An update document describing the modifications to apply using update operator expressions"), - upsert: z - .boolean() - .optional() - .describe("Controls whether to insert a new document if no documents match the filter"), - }; - protected operationType: DbOperationType = "update"; - - protected async execute({ - database, - collection, - filter, - update, - upsert, - }: ToolArgs): Promise { - const provider = await this.ensureConnected(); - const result = await provider.updateOne(database, collection, filter, update, { - upsert, - }); - - let message = ""; - if (result.matchedCount === 0) { - message = `No documents matched the filter.`; - } else { - message = `Matched ${result.matchedCount} document(s).`; - if (result.modifiedCount > 0) { - message += ` Modified ${result.modifiedCount} document(s).`; - } - if (result.upsertedCount > 0) { - message += ` Upserted ${result.upsertedCount} document(s) (with id: ${result.upsertedId?.toString()}).`; - } - } - - return { - content: [ - { - text: message, - type: "text", - }, - ], - }; - } -} diff --git a/src/tools/tool.ts b/src/tools/tool.ts index 1f5dd8c4..a37c7224 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -1,54 +1,126 @@ -import { McpServer, ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js"; -import { z, ZodNever, ZodRawShape } from "zod"; -import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { z, type ZodRawShape, type ZodNever } from "zod"; +import type { McpServer, ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js"; +import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; import { Session } from "../session.js"; import logger from "../logger.js"; import { mongoLogId } from "mongodb-log-writer"; +import { Telemetry } from "../telemetry/telemetry.js"; +import { type ToolEvent } from "../telemetry/types.js"; +import { UserConfig } from "../config.js"; export type ToolArgs = z.objectOutputType; +export type OperationType = "metadata" | "read" | "create" | "delete" | "update" | "cluster"; +export type ToolCategory = "mongodb" | "atlas"; + export abstract class ToolBase { protected abstract name: string; + protected abstract category: ToolCategory; + + protected abstract operationType: OperationType; + protected abstract description: string; protected abstract argsShape: ZodRawShape; protected abstract execute(...args: Parameters>): Promise; - protected constructor(protected session: Session) {} + constructor( + protected readonly session: Session, + protected readonly config: UserConfig, + protected readonly telemetry: Telemetry + ) {} + + /** + * Creates and emits a tool telemetry event + * @param startTime - Start time in milliseconds + * @param result - Whether the command succeeded or failed + * @param error - Optional error if the command failed + */ + private async emitToolEvent(startTime: number, result: CallToolResult): Promise { + const duration = Date.now() - startTime; + const event: ToolEvent = { + timestamp: new Date().toISOString(), + source: "mdbmcp", + properties: { + ...this.telemetry.getCommonProperties(), + command: this.name, + category: this.category, + component: "tool", + duration_ms: duration, + result: result.isError ? "failure" : "success", + }, + }; + await this.telemetry.emitEvents([event]); + } public register(server: McpServer): void { + if (!this.verifyAllowed()) { + return; + } + const callback: ToolCallback = async (...args) => { + const startTime = Date.now(); try { - // TODO: add telemetry here logger.debug( mongoLogId(1_000_006), "tool", `Executing ${this.name} with args: ${JSON.stringify(args)}` ); - return await this.execute(...args); + const result = await this.execute(...args); + await this.emitToolEvent(startTime, result); + return result; } catch (error: unknown) { logger.error(mongoLogId(1_000_000), "tool", `Error executing ${this.name}: ${error as string}`); - - return await this.handleError(error); + const toolResult = await this.handleError(error, args[0] as ToolArgs); + await this.emitToolEvent(startTime, toolResult).catch(() => {}); + return toolResult; } }; server.tool(this.name, this.description, this.argsShape, callback); } + // Checks if a tool is allowed to run based on the config + protected verifyAllowed(): boolean { + let errorClarification: string | undefined; + if (this.config.disabledTools.includes(this.category)) { + errorClarification = `its category, \`${this.category}\`,`; + } else if (this.config.disabledTools.includes(this.operationType)) { + errorClarification = `its operation type, \`${this.operationType}\`,`; + } else if (this.config.disabledTools.includes(this.name)) { + errorClarification = `it`; + } + + if (errorClarification) { + logger.debug( + mongoLogId(1_000_010), + "tool", + `Prevented registration of ${this.name} because ${errorClarification} is disabled in the config` + ); + + return false; + } + + return true; + } + // This method is intended to be overridden by subclasses to handle errors - protected handleError(error: unknown): Promise | CallToolResult { + protected handleError( + error: unknown, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + args: ToolArgs + ): Promise | CallToolResult { return { content: [ { type: "text", text: `Error running ${this.name}: ${error instanceof Error ? error.message : String(error)}`, + isError: true, }, ], - isError: true, }; } } diff --git a/src/types/native-machine-id.d.ts b/src/types/native-machine-id.d.ts new file mode 100644 index 00000000..153dbf38 --- /dev/null +++ b/src/types/native-machine-id.d.ts @@ -0,0 +1,34 @@ +/** + * Type definitions for native-machine-id + * Provides functionality to retrieve the machine ID of the current device. + */ + +declare module "native-machine-id" { + /** + * Gets the machine ID synchronously. + * @returns A string containing the machine ID. + */ + export function getMachineIdSync(): string; + + /** + * Gets the machine ID asynchronously. + * @returns A Promise that resolves to a string containing the machine ID. + */ + export function getMachineId(): Promise; + + /** + * Gets a machine ID that is based on the original ID but is "hashed" for privacy. + * @param {string} [original] - The original ID to hash. If not provided, gets the machine ID first. + * @param {string} [type='md5'] - The hashing algorithm to use. + * @returns A Promise that resolves to a string containing the hashed machine ID. + */ + export function machineIdSync(original?: string, type?: string): string; + + /** + * Gets a machine ID that is based on the original ID but is "hashed" for privacy. + * @param {string} [original] - The original ID to hash. If not provided, gets the machine ID first. + * @param {string} [type='md5'] - The hashing algorithm to use. + * @returns A Promise that resolves to a string containing the hashed machine ID. + */ + export function machineId(original?: string, type?: string): Promise; +} diff --git a/tests/integration/helpers.ts b/tests/integration/helpers.ts index 207492da..5b7ebe1c 100644 --- a/tests/integration/helpers.ts +++ b/tests/integration/helpers.ts @@ -1,82 +1,212 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { InMemoryTransport } from "./inMemoryTransport.js"; import { Server } from "../../src/server.js"; -import runner, { MongoCluster } from "mongodb-runner"; -import path from "path"; -import fs from "fs/promises"; -import { Session } from "../../src/session.js"; +import { ObjectId } from "mongodb"; +import { config, UserConfig } from "../../src/config.js"; +import { McpError } from "@modelcontextprotocol/sdk/types.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { Session } from "../../src/session.js"; +import { toIncludeAllMembers } from "jest-extended"; -export async function setupIntegrationTest(): Promise<{ - client: Client; - server: Server; - teardown: () => Promise; -}> { - const clientTransport = new InMemoryTransport(); - const serverTransport = new InMemoryTransport(); - - await serverTransport.start(); - await clientTransport.start(); - - clientTransport.output.pipeTo(serverTransport.input); - serverTransport.output.pipeTo(clientTransport.input); - - const client = new Client( - { - name: "test-client", - version: "1.2.3", - }, - { - capabilities: {}, - } - ); - - const server = new Server({ - mcpServer: new McpServer({ - name: "test-server", - version: "1.2.3", - }), - session: new Session(), - }); - await server.connect(serverTransport); - await client.connect(clientTransport); +interface ParameterInfo { + name: string; + type: string; + description: string; + required: boolean; +} - return { - client, - server, - teardown: async () => { - await client.close(); - await server.close(); - }, - }; +type ToolInfo = Awaited>["tools"][number]; + +export interface IntegrationTest { + mcpClient: () => Client; + mcpServer: () => Server; } -export async function runMongoDB(): Promise { - const tmpDir = path.join(__dirname, "..", "tmp"); - await fs.mkdir(tmpDir, { recursive: true }); +export function setupIntegrationTest(userConfig: UserConfig = config): IntegrationTest { + let mcpClient: Client | undefined; + let mcpServer: Server | undefined; + + let randomDbName: string; + + beforeAll(async () => { + const clientTransport = new InMemoryTransport(); + const serverTransport = new InMemoryTransport(); + + await serverTransport.start(); + await clientTransport.start(); - try { - const cluster = await MongoCluster.start({ - tmpDir: path.join(tmpDir, "mongodb-runner", "dbs"), - logDir: path.join(tmpDir, "mongodb-runner", "logs"), - topology: "standalone", + clientTransport.output.pipeTo(serverTransport.input); + serverTransport.output.pipeTo(clientTransport.input); + + mcpClient = new Client( + { + name: "test-client", + version: "1.2.3", + }, + { + capabilities: {}, + } + ); + + const session = new Session({ + apiBaseUrl: userConfig.apiBaseUrl, + apiClientId: userConfig.apiClientId, + apiClientSecret: userConfig.apiClientSecret, }); - return cluster; - } catch (err) { - throw err; - } + mcpServer = new Server({ + session, + userConfig, + mcpServer: new McpServer({ + name: "test-server", + version: "1.2.3", + }), + }); + await mcpServer.connect(serverTransport); + await mcpClient.connect(clientTransport); + }); + + beforeEach(async () => { + config.telemetry = "disabled"; + randomDbName = new ObjectId().toString(); + }); + + afterAll(async () => { + await mcpClient?.close(); + mcpClient = undefined; + + await mcpServer?.close(); + mcpServer = undefined; + }); + + const getMcpClient = () => { + if (!mcpClient) { + throw new Error("beforeEach() hook not ran yet"); + } + + return mcpClient; + }; + + const getMcpServer = () => { + if (!mcpServer) { + throw new Error("beforeEach() hook not ran yet"); + } + + return mcpServer; + }; + + return { + mcpClient: getMcpClient, + mcpServer: getMcpServer, + }; +} + +export function getResponseContent(content: unknown): string { + return getResponseElements(content) + .map((item) => item.text) + .join("\n"); } -export function validateToolResponse(content: unknown): string { +export function getResponseElements(content: unknown): { type: string; text: string }[] { expect(Array.isArray(content)).toBe(true); - const response = content as Array<{ type: string; text: string }>; + const response = content as { type: string; text: string }[]; for (const item of response) { expect(item).toHaveProperty("type"); expect(item).toHaveProperty("text"); expect(item.type).toBe("text"); } - return response.map((item) => item.text).join("\n"); + return response; +} + +export async function connect(client: Client, connectionString: string): Promise { + await client.callTool({ + name: "connect", + arguments: { connectionStringOrClusterName: connectionString }, + }); +} + +export function getParameters(tool: ToolInfo): ParameterInfo[] { + expect(tool.inputSchema.type).toBe("object"); + expect(tool.inputSchema.properties).toBeDefined(); + + return Object.entries(tool.inputSchema.properties!) + .sort((a, b) => a[0].localeCompare(b[0])) + .map(([key, value]) => { + expect(value).toHaveProperty("type"); + expect(value).toHaveProperty("description"); + + const typedValue = value as { type: string; description: string }; + expect(typeof typedValue.type).toBe("string"); + expect(typeof typedValue.description).toBe("string"); + return { + name: key, + type: typedValue.type, + description: typedValue.description, + required: (tool.inputSchema.required as string[])?.includes(key) ?? false, + }; + }); +} + +export const databaseParameters: ParameterInfo[] = [ + { name: "database", type: "string", description: "Database name", required: true }, +]; + +export const databaseCollectionParameters: ParameterInfo[] = [ + ...databaseParameters, + { name: "collection", type: "string", description: "Collection name", required: true }, +]; + +export const databaseCollectionInvalidArgs = [ + {}, + { database: "test" }, + { collection: "foo" }, + { database: 123, collection: "foo" }, + { database: "test", collection: "foo", extra: "bar" }, + { database: "test", collection: 123 }, + { database: [], collection: "foo" }, + { database: "test", collection: [] }, +]; + +export const databaseInvalidArgs = [{}, { database: 123 }, { database: [] }, { database: "test", extra: "bar" }]; + +export function validateToolMetadata( + integration: IntegrationTest, + name: string, + description: string, + parameters: ParameterInfo[] +): void { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const tool = tools.find((tool) => tool.name === name)!; + expect(tool).toBeDefined(); + expect(tool.description).toBe(description); + + const toolParameters = getParameters(tool); + expect(toolParameters).toHaveLength(parameters.length); + expect(toolParameters).toIncludeAllMembers(parameters); + }); +} + +export function validateThrowsForInvalidArguments( + integration: IntegrationTest, + name: string, + args: { [x: string]: unknown }[] +): void { + describe("with invalid arguments", () => { + for (const arg of args) { + it(`throws a schema error for: ${JSON.stringify(arg)}`, async () => { + try { + await integration.mcpClient().callTool({ name, arguments: arg }); + expect.fail("Expected an error to be thrown"); + } catch (error) { + expect(error).toBeInstanceOf(McpError); + const mcpError = error as McpError; + expect(mcpError.code).toEqual(-32602); + expect(mcpError.message).toContain(`Invalid arguments for tool ${name}`); + } + }); + } + }); } diff --git a/tests/integration/server.test.ts b/tests/integration/server.test.ts index 1d804943..5130b4b6 100644 --- a/tests/integration/server.test.ts +++ b/tests/integration/server.test.ts @@ -1,45 +1,61 @@ -import { Client } from "@modelcontextprotocol/sdk/client/index.js"; -import { setupIntegrationTest } from "./helpers.js"; +import { setupIntegrationTest } from "./helpers"; +import { config } from "../../src/config.js"; describe("Server integration test", () => { - let client: Client; - let teardown: () => Promise; - - beforeEach(async () => { - ({ client, teardown } = await setupIntegrationTest()); - }); - - afterEach(async () => { - await teardown(); - }); + describe("without atlas", () => { + const integration = setupIntegrationTest({ + ...config, + apiClientId: undefined, + apiClientSecret: undefined, + }); - describe("list capabilities", () => { - it("should return positive number of tools", async () => { - const tools = await client.listTools(); + it("should return positive number of tools and have no atlas tools", async () => { + const tools = await integration.mcpClient().listTools(); expect(tools).toBeDefined(); expect(tools.tools.length).toBeGreaterThan(0); + + const atlasTools = tools.tools.filter((tool) => tool.name.startsWith("atlas-")); + expect(atlasTools.length).toBeLessThanOrEqual(0); + }); + }); + describe("with atlas", () => { + const integration = setupIntegrationTest({ + ...config, + apiClientId: "test", + apiClientSecret: "test", }); - it("should return no resources", async () => { - await expect(() => client.listResources()).rejects.toMatchObject({ - message: "MCP error -32601: Method not found", + describe("list capabilities", () => { + it("should return positive number of tools and have some atlas tools", async () => { + const tools = await integration.mcpClient().listTools(); + expect(tools).toBeDefined(); + expect(tools.tools.length).toBeGreaterThan(0); + + const atlasTools = tools.tools.filter((tool) => tool.name.startsWith("atlas-")); + expect(atlasTools.length).toBeGreaterThan(0); }); - }); - it("should return no prompts", async () => { - await expect(() => client.listPrompts()).rejects.toMatchObject({ - message: "MCP error -32601: Method not found", + it("should return no resources", async () => { + await expect(() => integration.mcpClient().listResources()).rejects.toMatchObject({ + message: "MCP error -32601: Method not found", + }); }); - }); - it("should return capabilities", async () => { - const capabilities = client.getServerCapabilities(); - expect(capabilities).toBeDefined(); - expect(capabilities?.completions).toBeUndefined(); - expect(capabilities?.experimental).toBeUndefined(); - expect(capabilities?.tools).toBeDefined(); - expect(capabilities?.logging).toBeDefined(); - expect(capabilities?.prompts).toBeUndefined(); + it("should return no prompts", async () => { + await expect(() => integration.mcpClient().listPrompts()).rejects.toMatchObject({ + message: "MCP error -32601: Method not found", + }); + }); + + it("should return capabilities", async () => { + const capabilities = integration.mcpClient().getServerCapabilities(); + expect(capabilities).toBeDefined(); + expect(capabilities?.completions).toBeUndefined(); + expect(capabilities?.experimental).toBeUndefined(); + expect(capabilities?.tools).toBeDefined(); + expect(capabilities?.logging).toBeDefined(); + expect(capabilities?.prompts).toBeUndefined(); + }); }); }); }); diff --git a/tests/integration/tools/atlas/accessLists.test.ts b/tests/integration/tools/atlas/accessLists.test.ts new file mode 100644 index 00000000..43e5742d --- /dev/null +++ b/tests/integration/tools/atlas/accessLists.test.ts @@ -0,0 +1,97 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { describeWithAtlas, withProject } from "./atlasHelpers.js"; + +function generateRandomIp() { + const randomIp: number[] = [192]; + for (let i = 0; i < 3; i++) { + randomIp.push(Math.floor(Math.random() * 256)); + } + return randomIp.join("."); +} + +describeWithAtlas("ip access lists", (integration) => { + withProject(integration, ({ getProjectId }) => { + const ips = [generateRandomIp(), generateRandomIp()]; + const cidrBlocks = [generateRandomIp() + "/16", generateRandomIp() + "/24"]; + const values = [...ips, ...cidrBlocks]; + + beforeAll(async () => { + const apiClient = integration.mcpServer().session.apiClient; + const ipInfo = await apiClient.getIpInfo(); + values.push(ipInfo.currentIpv4Address); + }); + + afterAll(async () => { + const apiClient = integration.mcpServer().session.apiClient; + + const projectId = getProjectId(); + + for (const value of values) { + await apiClient.deleteProjectIpAccessList({ + params: { + path: { + groupId: projectId, + entryValue: value, + }, + }, + }); + } + }); + + describe("atlas-create-access-list", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const createAccessList = tools.find((tool) => tool.name === "atlas-create-access-list")!; + expect(createAccessList).toBeDefined(); + expect(createAccessList.inputSchema.type).toBe("object"); + expect(createAccessList.inputSchema.properties).toBeDefined(); + expect(createAccessList.inputSchema.properties).toHaveProperty("projectId"); + expect(createAccessList.inputSchema.properties).toHaveProperty("ipAddresses"); + expect(createAccessList.inputSchema.properties).toHaveProperty("cidrBlocks"); + expect(createAccessList.inputSchema.properties).toHaveProperty("currentIpAddress"); + expect(createAccessList.inputSchema.properties).toHaveProperty("comment"); + }); + + it("should create an access list", async () => { + const projectId = getProjectId(); + + const response = (await integration.mcpClient().callTool({ + name: "atlas-create-access-list", + arguments: { + projectId, + ipAddresses: ips, + cidrBlocks: cidrBlocks, + currentIpAddress: true, + }, + })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain("IP/CIDR ranges added to access list"); + }); + }); + + describe("atlas-inspect-access-list", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const inspectAccessList = tools.find((tool) => tool.name === "atlas-inspect-access-list")!; + expect(inspectAccessList).toBeDefined(); + expect(inspectAccessList.inputSchema.type).toBe("object"); + expect(inspectAccessList.inputSchema.properties).toBeDefined(); + expect(inspectAccessList.inputSchema.properties).toHaveProperty("projectId"); + }); + + it("returns access list data", async () => { + const projectId = getProjectId(); + + const response = (await integration + .mcpClient() + .callTool({ name: "atlas-inspect-access-list", arguments: { projectId } })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + for (const value of values) { + expect(response.content[0].text).toContain(value); + } + }); + }); + }); +}); diff --git a/tests/integration/tools/atlas/atlasHelpers.ts b/tests/integration/tools/atlas/atlasHelpers.ts new file mode 100644 index 00000000..36b88c1e --- /dev/null +++ b/tests/integration/tools/atlas/atlasHelpers.ts @@ -0,0 +1,105 @@ +import { ObjectId } from "mongodb"; +import { Group } from "../../../../src/common/atlas/openapi.js"; +import { ApiClient } from "../../../../src/common/atlas/apiClient.js"; +import { setupIntegrationTest, IntegrationTest } from "../../helpers.js"; + +export type IntegrationTestFunction = (integration: IntegrationTest) => void; + +export function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export function describeWithAtlas(name: number | string | Function | jest.FunctionLike, fn: IntegrationTestFunction) { + const testDefinition = () => { + const integration = setupIntegrationTest(); + describe(name, () => { + fn(integration); + }); + }; + + if (!process.env.MDB_MCP_API_CLIENT_ID?.length || !process.env.MDB_MCP_API_CLIENT_SECRET?.length) { + return describe.skip("atlas", testDefinition); + } + return describe("atlas", testDefinition); +} + +interface ProjectTestArgs { + getProjectId: () => string; +} + +type ProjectTestFunction = (args: ProjectTestArgs) => void; + +export function withProject(integration: IntegrationTest, fn: ProjectTestFunction) { + return describe("project", () => { + let projectId: string = ""; + + beforeAll(async () => { + const apiClient = integration.mcpServer().session.apiClient; + + const group = await createProject(apiClient); + projectId = group.id || ""; + }); + + afterAll(async () => { + const apiClient = integration.mcpServer().session.apiClient; + + await apiClient.deleteProject({ + params: { + path: { + groupId: projectId, + }, + }, + }); + }); + + const args = { + getProjectId: () => projectId, + }; + + describe("with project", () => { + fn(args); + }); + }); +} + +export function parseTable(text: string): Record[] { + const data = text + .split("\n") + .filter((line) => line.trim() !== "") + .map((line) => line.split("|").map((cell) => cell.trim())); + + const headers = data[0]; + return data + .filter((_, index) => index >= 2) + .map((cells) => { + const row = {}; + cells.forEach((cell, index) => { + row[headers[index]] = cell; + }); + return row; + }); +} + +export const randomId = new ObjectId().toString(); + +async function createProject(apiClient: ApiClient): Promise { + const projectName: string = `testProj-` + randomId; + + const orgs = await apiClient.listOrganizations(); + if (!orgs?.results?.length || !orgs.results[0].id) { + throw new Error("No orgs found"); + } + + const group = await apiClient.createProject({ + body: { + name: projectName, + orgId: orgs.results[0].id, + } as Group, + }); + + if (!group?.id) { + throw new Error("Failed to create project"); + } + + return group; +} diff --git a/tests/integration/tools/atlas/clusters.test.ts b/tests/integration/tools/atlas/clusters.test.ts new file mode 100644 index 00000000..72f41df0 --- /dev/null +++ b/tests/integration/tools/atlas/clusters.test.ts @@ -0,0 +1,120 @@ +import { Session } from "../../../../src/session.js"; +import { describeWithAtlas, withProject, sleep, randomId } from "./atlasHelpers.js"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; + +async function deleteAndWaitCluster(session: Session, projectId: string, clusterName: string) { + await session.apiClient.deleteCluster({ + params: { + path: { + groupId: projectId, + clusterName: clusterName, + }, + }, + }); + while (true) { + try { + await session.apiClient.getCluster({ + params: { + path: { + groupId: projectId, + clusterName: clusterName, + }, + }, + }); + await sleep(1000); + } catch { + break; + } + } +} + +describeWithAtlas("clusters", (integration) => { + withProject(integration, ({ getProjectId }) => { + const clusterName = "ClusterTest-" + randomId; + + afterAll(async () => { + const projectId = getProjectId(); + + const session: Session = integration.mcpServer().session; + + await deleteAndWaitCluster(session, projectId, clusterName); + }); + + describe("atlas-create-free-cluster", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const createFreeCluster = tools.find((tool) => tool.name === "atlas-create-free-cluster")!; + + expect(createFreeCluster).toBeDefined(); + expect(createFreeCluster.inputSchema.type).toBe("object"); + expect(createFreeCluster.inputSchema.properties).toBeDefined(); + expect(createFreeCluster.inputSchema.properties).toHaveProperty("projectId"); + expect(createFreeCluster.inputSchema.properties).toHaveProperty("name"); + expect(createFreeCluster.inputSchema.properties).toHaveProperty("region"); + }); + + it("should create a free cluster", async () => { + const projectId = getProjectId(); + + const response = (await integration.mcpClient().callTool({ + name: "atlas-create-free-cluster", + arguments: { + projectId, + name: clusterName, + region: "US_EAST_1", + }, + })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain("has been created"); + }); + }); + + describe("atlas-inspect-cluster", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const inspectCluster = tools.find((tool) => tool.name === "atlas-inspect-cluster")!; + + expect(inspectCluster).toBeDefined(); + expect(inspectCluster.inputSchema.type).toBe("object"); + expect(inspectCluster.inputSchema.properties).toBeDefined(); + expect(inspectCluster.inputSchema.properties).toHaveProperty("projectId"); + expect(inspectCluster.inputSchema.properties).toHaveProperty("clusterName"); + }); + + it("returns cluster data", async () => { + const projectId = getProjectId(); + + const response = (await integration.mcpClient().callTool({ + name: "atlas-inspect-cluster", + arguments: { projectId, clusterName: clusterName }, + })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain(`${clusterName} | `); + }); + }); + + describe("atlas-list-clusters", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const listClusters = tools.find((tool) => tool.name === "atlas-list-clusters")!; + expect(listClusters).toBeDefined(); + expect(listClusters.inputSchema.type).toBe("object"); + expect(listClusters.inputSchema.properties).toBeDefined(); + expect(listClusters.inputSchema.properties).toHaveProperty("projectId"); + }); + + it("returns clusters by project", async () => { + const projectId = getProjectId(); + + const response = (await integration + .mcpClient() + .callTool({ name: "atlas-list-clusters", arguments: { projectId } })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(2); + expect(response.content[1].text).toContain(`${clusterName} | `); + }); + }); + }); +}); diff --git a/tests/integration/tools/atlas/dbUsers.test.ts b/tests/integration/tools/atlas/dbUsers.test.ts new file mode 100644 index 00000000..2a5eb02a --- /dev/null +++ b/tests/integration/tools/atlas/dbUsers.test.ts @@ -0,0 +1,79 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { Session } from "../../../../src/session.js"; +import { describeWithAtlas, withProject, randomId } from "./atlasHelpers.js"; + +describeWithAtlas("db users", (integration) => { + const userName = "testuser-" + randomId; + withProject(integration, ({ getProjectId }) => { + afterAll(async () => { + const projectId = getProjectId(); + + const session: Session = integration.mcpServer().session; + await session.apiClient.deleteDatabaseUser({ + params: { + path: { + groupId: projectId, + username: userName, + databaseName: "admin", + }, + }, + }); + }); + + describe("atlas-create-db-user", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const createDbUser = tools.find((tool) => tool.name === "atlas-create-db-user")!; + expect(createDbUser).toBeDefined(); + expect(createDbUser.inputSchema.type).toBe("object"); + expect(createDbUser.inputSchema.properties).toBeDefined(); + expect(createDbUser.inputSchema.properties).toHaveProperty("projectId"); + expect(createDbUser.inputSchema.properties).toHaveProperty("username"); + expect(createDbUser.inputSchema.properties).toHaveProperty("password"); + expect(createDbUser.inputSchema.properties).toHaveProperty("roles"); + expect(createDbUser.inputSchema.properties).toHaveProperty("clusters"); + }); + it("should create a database user", async () => { + const projectId = getProjectId(); + + const response = (await integration.mcpClient().callTool({ + name: "atlas-create-db-user", + arguments: { + projectId, + username: userName, + password: "testpassword", + roles: [ + { + roleName: "readWrite", + databaseName: "admin", + }, + ], + }, + })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain("created sucessfully"); + }); + }); + describe("atlas-list-db-users", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const listDbUsers = tools.find((tool) => tool.name === "atlas-list-db-users")!; + expect(listDbUsers).toBeDefined(); + expect(listDbUsers.inputSchema.type).toBe("object"); + expect(listDbUsers.inputSchema.properties).toBeDefined(); + expect(listDbUsers.inputSchema.properties).toHaveProperty("projectId"); + }); + it("returns database users by project", async () => { + const projectId = getProjectId(); + + const response = (await integration + .mcpClient() + .callTool({ name: "atlas-list-db-users", arguments: { projectId } })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain(userName); + }); + }); + }); +}); diff --git a/tests/integration/tools/atlas/orgs.test.ts b/tests/integration/tools/atlas/orgs.test.ts new file mode 100644 index 00000000..ca86e4b9 --- /dev/null +++ b/tests/integration/tools/atlas/orgs.test.ts @@ -0,0 +1,24 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { setupIntegrationTest } from "../../helpers.js"; +import { parseTable, describeWithAtlas } from "./atlasHelpers.js"; + +describeWithAtlas("orgs", (integration) => { + describe("atlas-list-orgs", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const listOrgs = tools.find((tool) => tool.name === "atlas-list-orgs"); + expect(listOrgs).toBeDefined(); + }); + + it("returns org names", async () => { + const response = (await integration + .mcpClient() + .callTool({ name: "atlas-list-orgs", arguments: {} })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + const data = parseTable(response.content[0].text as string); + expect(data).toHaveLength(1); + expect(data[0]["Organization Name"]).toEqual("MongoDB MCP Test"); + }); + }); +}); diff --git a/tests/integration/tools/atlas/projects.test.ts b/tests/integration/tools/atlas/projects.test.ts new file mode 100644 index 00000000..3f570183 --- /dev/null +++ b/tests/integration/tools/atlas/projects.test.ts @@ -0,0 +1,77 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { ObjectId } from "mongodb"; +import { parseTable, describeWithAtlas } from "./atlasHelpers.js"; + +const randomId = new ObjectId().toString(); + +describeWithAtlas("projects", (integration) => { + const projName = "testProj-" + randomId; + + afterAll(async () => { + const session = integration.mcpServer().session; + + const projects = await session.apiClient.listProjects(); + for (const project of projects?.results || []) { + if (project.name === projName) { + await session.apiClient.deleteProject({ + params: { + path: { + groupId: project.id || "", + }, + }, + }); + break; + } + } + }); + + describe("atlas-create-project", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const createProject = tools.find((tool) => tool.name === "atlas-create-project")!; + expect(createProject).toBeDefined(); + expect(createProject.inputSchema.type).toBe("object"); + expect(createProject.inputSchema.properties).toBeDefined(); + expect(createProject.inputSchema.properties).toHaveProperty("projectName"); + expect(createProject.inputSchema.properties).toHaveProperty("organizationId"); + }); + it("should create a project", async () => { + const response = (await integration.mcpClient().callTool({ + name: "atlas-create-project", + arguments: { projectName: projName }, + })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain(projName); + }); + }); + describe("atlas-list-projects", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const listProjects = tools.find((tool) => tool.name === "atlas-list-projects")!; + expect(listProjects).toBeDefined(); + expect(listProjects.inputSchema.type).toBe("object"); + expect(listProjects.inputSchema.properties).toBeDefined(); + expect(listProjects.inputSchema.properties).toHaveProperty("orgId"); + }); + + it("returns project names", async () => { + const response = (await integration + .mcpClient() + .callTool({ name: "atlas-list-projects", arguments: {} })) as CallToolResult; + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + expect(response.content[0].text).toContain(projName); + const data = parseTable(response.content[0].text as string); + expect(data).toBeArray(); + expect(data.length).toBeGreaterThan(0); + let found = false; + for (const project of data) { + if (project["Project Name"] === projName) { + found = true; + } + } + expect(found).toBe(true); + }); + }); +}); diff --git a/tests/integration/tools/mongodb/connect.test.ts b/tests/integration/tools/mongodb/connect.test.ts deleted file mode 100644 index 7e5dacec..00000000 --- a/tests/integration/tools/mongodb/connect.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Client } from "@modelcontextprotocol/sdk/client/index.js"; -import { runMongoDB, setupIntegrationTest, validateToolResponse } from "../../helpers.js"; -import runner from "mongodb-runner"; - -import config from "../../../../src/config.js"; - -describe("Connect tool", () => { - let client: Client; - let serverClientTeardown: () => Promise; - - let cluster: runner.MongoCluster; - - beforeAll(async () => { - cluster = await runMongoDB(); - }, 60_000); - - beforeEach(async () => { - ({ client, teardown: serverClientTeardown } = await setupIntegrationTest()); - }); - - afterEach(async () => { - await serverClientTeardown?.(); - }); - - afterAll(async () => { - await cluster.close(); - }); - - describe("with default config", () => { - it("should have correct metadata", async () => { - const tools = await client.listTools(); - const connectTool = tools.tools.find((tool) => tool.name === "connect"); - expect(connectTool).toBeDefined(); - expect(connectTool!.description).toBe("Connect to a MongoDB instance"); - expect(connectTool!.inputSchema.type).toBe("object"); - expect(connectTool!.inputSchema.properties).toBeDefined(); - - const propertyNames = Object.keys(connectTool!.inputSchema.properties!); - expect(propertyNames).toHaveLength(1); - expect(propertyNames[0]).toBe("connectionStringOrClusterName"); - - const connectionStringOrClusterNameProp = connectTool!.inputSchema.properties![propertyNames[0]] as { - type: string; - description: string; - }; - expect(connectionStringOrClusterNameProp.type).toBe("string"); - expect(connectionStringOrClusterNameProp.description).toContain("MongoDB connection string"); - expect(connectionStringOrClusterNameProp.description).toContain("cluster name"); - }); - - describe("without connection string", () => { - it("prompts for connection string", async () => { - const response = await client.callTool({ name: "connect", arguments: {} }); - const content = validateToolResponse(response.content); - expect(content).toContain("No connection details provided"); - expect(content).toContain("mongodb://localhost:27017"); - }); - }); - - describe("with connection string", () => { - it("connects to the database", async () => { - const response = await client.callTool({ - name: "connect", - arguments: { connectionStringOrClusterName: cluster.connectionString }, - }); - const content = validateToolResponse(response.content); - expect(content).toContain("Successfully connected"); - expect(content).toContain(cluster.connectionString); - }); - }); - - describe("with invalid connection string", () => { - it("returns error message", async () => { - const response = await client.callTool({ - name: "connect", - arguments: { connectionStringOrClusterName: "mongodb://localhost:12345" }, - }); - const content = validateToolResponse(response.content); - expect(content).toContain("Error running connect"); - }); - }); - }); - - describe("with connection string in config", () => { - beforeEach(async () => { - config.connectionString = cluster.connectionString; - }); - - it("uses the connection string from config", async () => { - const response = await client.callTool({ name: "connect", arguments: {} }); - const content = validateToolResponse(response.content); - expect(content).toContain("Successfully connected"); - expect(content).toContain(cluster.connectionString); - }); - - it("prefers connection string from arguments", async () => { - const newConnectionString = `${cluster.connectionString}?appName=foo-bar`; - const response = await client.callTool({ - name: "connect", - arguments: { connectionStringOrClusterName: newConnectionString }, - }); - const content = validateToolResponse(response.content); - expect(content).toContain("Successfully connected"); - expect(content).toContain(newConnectionString); - }); - }); -}); diff --git a/tests/integration/tools/mongodb/create/createCollection.test.ts b/tests/integration/tools/mongodb/create/createCollection.test.ts new file mode 100644 index 00000000..ef8da5f1 --- /dev/null +++ b/tests/integration/tools/mongodb/create/createCollection.test.ts @@ -0,0 +1,95 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + databaseCollectionInvalidArgs, +} from "../../../helpers.js"; + +describeWithMongoDB("createCollection tool", (integration) => { + validateToolMetadata( + integration, + "create-collection", + "Creates a new collection in a database. If the database doesn't exist, it will be created automatically.", + databaseCollectionParameters + ); + + validateThrowsForInvalidArguments(integration, "create-collection", databaseCollectionInvalidArgs); + + describe("with non-existent database", () => { + it("creates a new collection", async () => { + const mongoClient = integration.mongoClient(); + let collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(0); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "create-collection", + arguments: { database: integration.randomDbName(), collection: "bar" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual(`Collection "bar" created in database "${integration.randomDbName()}".`); + + collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(1); + expect(collections[0].name).toEqual("bar"); + }); + }); + + describe("with existing database", () => { + it("creates new collection", async () => { + const mongoClient = integration.mongoClient(); + await mongoClient.db(integration.randomDbName()).createCollection("collection1"); + let collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(1); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "create-collection", + arguments: { database: integration.randomDbName(), collection: "collection2" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual(`Collection "collection2" created in database "${integration.randomDbName()}".`); + collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(2); + expect(collections.map((c) => c.name)).toIncludeSameMembers(["collection1", "collection2"]); + }); + + it("does nothing if collection already exists", async () => { + const mongoClient = integration.mongoClient(); + await mongoClient.db(integration.randomDbName()).collection("collection1").insertOne({}); + let collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(1); + let documents = await mongoClient + .db(integration.randomDbName()) + .collection("collection1") + .find({}) + .toArray(); + expect(documents).toHaveLength(1); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "create-collection", + arguments: { database: integration.randomDbName(), collection: "collection1" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual(`Collection "collection1" created in database "${integration.randomDbName()}".`); + collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(1); + expect(collections[0].name).toEqual("collection1"); + + // Make sure we didn't drop the existing collection + documents = await mongoClient.db(integration.randomDbName()).collection("collection1").find({}).toArray(); + expect(documents).toHaveLength(1); + }); + }); + + validateAutoConnectBehavior(integration, "create-collection", () => { + return { + args: { database: integration.randomDbName(), collection: "new-collection" }, + expectedResponse: `Collection "new-collection" created in database "${integration.randomDbName()}".`, + }; + }); +}); diff --git a/tests/integration/tools/mongodb/create/createIndex.test.ts b/tests/integration/tools/mongodb/create/createIndex.test.ts new file mode 100644 index 00000000..fa921339 --- /dev/null +++ b/tests/integration/tools/mongodb/create/createIndex.test.ts @@ -0,0 +1,203 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, +} from "../../../helpers.js"; +import { IndexDirection } from "mongodb"; + +describeWithMongoDB("createIndex tool", (integration) => { + validateToolMetadata(integration, "create-index", "Create an index for a collection", [ + ...databaseCollectionParameters, + { + name: "keys", + type: "object", + description: "The index definition", + required: true, + }, + { + name: "name", + type: "string", + description: "The name of the index", + required: false, + }, + ]); + + validateThrowsForInvalidArguments(integration, "create-index", [ + {}, + { collection: "bar", database: 123, keys: { foo: 1 } }, + { collection: "bar", database: "test", keys: { foo: 5 } }, + { collection: [], database: "test", keys: { foo: 1 } }, + { collection: "bar", database: "test", keys: { foo: 1 }, name: 123 }, + { collection: "bar", database: "test", keys: "foo", name: "my-index" }, + ]); + + const validateIndex = async (collection: string, expected: { name: string; key: object }[]) => { + const mongoClient = integration.mongoClient(); + const collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(1); + expect(collections[0].name).toEqual("coll1"); + const indexes = await mongoClient.db(integration.randomDbName()).collection(collection).indexes(); + expect(indexes).toHaveLength(expected.length + 1); + expect(indexes[0].name).toEqual("_id_"); + for (const index of expected) { + const foundIndex = indexes.find((i) => i.name === index.name); + expect(foundIndex).toBeDefined(); + expect(foundIndex!.key).toEqual(index.key); + } + }; + + it("creates the namespace if necessary", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + keys: { prop1: 1 }, + name: "my-index", + }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual( + `Created the index "my-index" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + await validateIndex("coll1", [{ name: "my-index", key: { prop1: 1 } }]); + }); + + it("generates a name if not provided", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: 1 } }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual( + `Created the index "prop1_1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + await validateIndex("coll1", [{ name: "prop1_1", key: { prop1: 1 } }]); + }); + + it("can create multiple indexes in the same collection", async () => { + await integration.connectMcpClient(); + let response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: 1 } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop1_1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop2: -1 } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop2_-1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + await validateIndex("coll1", [ + { name: "prop1_1", key: { prop1: 1 } }, + { name: "prop2_-1", key: { prop2: -1 } }, + ]); + }); + + it("can create multiple indexes on the same property", async () => { + await integration.connectMcpClient(); + let response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: 1 } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop1_1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: -1 } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop1_-1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + await validateIndex("coll1", [ + { name: "prop1_1", key: { prop1: 1 } }, + { name: "prop1_-1", key: { prop1: -1 } }, + ]); + }); + + it("doesn't duplicate indexes", async () => { + await integration.connectMcpClient(); + let response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: 1 } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop1_1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: 1 } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop1_1" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + await validateIndex("coll1", [{ name: "prop1_1", key: { prop1: 1 } }]); + }); + + const testCases: { name: string; direction: IndexDirection }[] = [ + { name: "descending", direction: -1 }, + { name: "ascending", direction: 1 }, + { name: "hashed", direction: "hashed" }, + { name: "text", direction: "text" }, + { name: "geoHaystack", direction: "2dsphere" }, + { name: "geo2d", direction: "2d" }, + ]; + + for (const { name, direction } of testCases) { + it(`creates ${name} index`, async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "create-index", + arguments: { database: integration.randomDbName(), collection: "coll1", keys: { prop1: direction } }, + }); + + expect(getResponseContent(response.content)).toEqual( + `Created the index "prop1_${direction}" on collection "coll1" in database "${integration.randomDbName()}"` + ); + + let expectedKey: object = { prop1: direction }; + if (direction === "text") { + expectedKey = { + _fts: "text", + _ftsx: 1, + }; + } + await validateIndex("coll1", [{ name: `prop1_${direction}`, key: expectedKey }]); + }); + } + + validateAutoConnectBehavior(integration, "create-index", () => { + return { + args: { + database: integration.randomDbName(), + collection: "coll1", + keys: { prop1: 1 }, + }, + expectedResponse: `Created the index "prop1_1" on collection "coll1" in database "${integration.randomDbName()}"`, + }; + }); +}); diff --git a/tests/integration/tools/mongodb/create/insertMany.test.ts b/tests/integration/tools/mongodb/create/insertMany.test.ts new file mode 100644 index 00000000..b4042029 --- /dev/null +++ b/tests/integration/tools/mongodb/create/insertMany.test.ts @@ -0,0 +1,97 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, +} from "../../../helpers.js"; + +describeWithMongoDB("insertMany tool", (integration) => { + validateToolMetadata(integration, "insert-many", "Insert an array of documents into a MongoDB collection", [ + ...databaseCollectionParameters, + { + name: "documents", + type: "array", + description: + "The array of documents to insert, matching the syntax of the document argument of db.collection.insertMany()", + required: true, + }, + ]); + + validateThrowsForInvalidArguments(integration, "insert-many", [ + {}, + { collection: "bar", database: 123, documents: [] }, + { collection: [], database: "test", documents: [] }, + { collection: "bar", database: "test", documents: "my-document" }, + { collection: "bar", database: "test", documents: { name: "Peter" } }, + ]); + + const validateDocuments = async (collection: string, expectedDocuments: object[]) => { + const collections = await integration.mongoClient().db(integration.randomDbName()).listCollections().toArray(); + expect(collections.find((c) => c.name === collection)).toBeDefined(); + + const docs = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection(collection) + .find() + .toArray(); + + expect(docs).toHaveLength(expectedDocuments.length); + for (const expectedDocument of expectedDocuments) { + expect(docs).toContainEqual(expect.objectContaining(expectedDocument)); + } + }; + + it("creates the namespace if necessary", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "insert-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + documents: [{ prop1: "value1" }], + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain('Inserted `1` document(s) into collection "coll1"'); + + await validateDocuments("coll1", [{ prop1: "value1" }]); + }); + + it("returns an error when inserting duplicates", async () => { + const { insertedIds } = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .insertMany([{ prop1: "value1" }]); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "insert-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + documents: [{ prop1: "value1", _id: insertedIds[0] }], + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain("Error running insert-many"); + expect(content).toContain("duplicate key error"); + expect(content).toContain(insertedIds[0].toString()); + }); + + validateAutoConnectBehavior(integration, "insert-many", () => { + return { + args: { + database: integration.randomDbName(), + collection: "coll1", + documents: [{ prop1: "value1" }], + }, + expectedResponse: 'Inserted `1` document(s) into collection "coll1"', + }; + }); +}); diff --git a/tests/integration/tools/mongodb/delete/deleteMany.test.ts b/tests/integration/tools/mongodb/delete/deleteMany.test.ts new file mode 100644 index 00000000..9201d566 --- /dev/null +++ b/tests/integration/tools/mongodb/delete/deleteMany.test.ts @@ -0,0 +1,154 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, +} from "../../../helpers.js"; + +describeWithMongoDB("deleteMany tool", (integration) => { + validateToolMetadata( + integration, + "delete-many", + "Removes all documents that match the filter from a MongoDB collection", + [ + ...databaseCollectionParameters, + { + name: "filter", + type: "object", + description: + "The query filter, specifying the deletion criteria. Matches the syntax of the filter argument of db.collection.deleteMany()", + required: false, + }, + ] + ); + + describe("with invalid arguments", () => { + validateThrowsForInvalidArguments(integration, "delete-many", [ + {}, + { collection: "bar", database: 123, filter: {} }, + { collection: [], database: "test", filter: {} }, + { collection: "bar", database: "test", filter: "my-document" }, + { collection: "bar", database: "test", filter: [{ name: "Peter" }] }, + ]); + }); + + it("doesn't create the collection if it doesn't exist", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "delete-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + filter: {}, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain('Deleted `0` document(s) from collection "coll1"'); + + const collections = await integration.mongoClient().db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(0); + }); + + const insertDocuments = async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .insertMany([ + { age: 10, name: "Peter" }, + { age: 20, name: "John" }, + { age: 30, name: "Mary" }, + { age: 40, name: "Lucy" }, + ]); + }; + + const validateDocuments = async (expected: object[]) => { + const documents = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .find() + .toArray(); + + expect(documents).toHaveLength(expected.length); + for (const expectedDocument of expected) { + expect(documents).toContainEqual(expect.objectContaining(expectedDocument)); + } + }; + + it("deletes documents matching the filter", async () => { + await insertDocuments(); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "delete-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + filter: { age: { $gt: 20 } }, + }, + }); + const content = getResponseContent(response.content); + expect(content).toContain('Deleted `2` document(s) from collection "coll1"'); + + await validateDocuments([ + { age: 10, name: "Peter" }, + { age: 20, name: "John" }, + ]); + }); + + it("when filter doesn't match, deletes nothing", async () => { + await insertDocuments(); + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "delete-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + filter: { age: { $gt: 100 } }, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain('Deleted `0` document(s) from collection "coll1"'); + + await validateDocuments([ + { age: 10, name: "Peter" }, + { age: 20, name: "John" }, + { age: 30, name: "Mary" }, + { age: 40, name: "Lucy" }, + ]); + }); + + it("with empty filter, deletes all documents", async () => { + await insertDocuments(); + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "delete-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + filter: {}, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain('Deleted `4` document(s) from collection "coll1"'); + + await validateDocuments([]); + }); + + validateAutoConnectBehavior(integration, "delete-many", () => { + return { + args: { + database: integration.randomDbName(), + collection: "coll1", + filter: {}, + }, + expectedResponse: 'Deleted `0` document(s) from collection "coll1"', + }; + }); +}); diff --git a/tests/integration/tools/mongodb/delete/dropCollection.test.ts b/tests/integration/tools/mongodb/delete/dropCollection.test.ts new file mode 100644 index 00000000..1dcaa218 --- /dev/null +++ b/tests/integration/tools/mongodb/delete/dropCollection.test.ts @@ -0,0 +1,69 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + databaseCollectionInvalidArgs, +} from "../../../helpers.js"; + +describeWithMongoDB("dropCollection tool", (integration) => { + validateToolMetadata( + integration, + "drop-collection", + "Removes a collection or view from the database. The method also removes any indexes associated with the dropped collection.", + databaseCollectionParameters + ); + + validateThrowsForInvalidArguments(integration, "drop-collection", databaseCollectionInvalidArgs); + + it("can drop non-existing collection", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "drop-collection", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain( + `Successfully dropped collection "coll1" from database "${integration.randomDbName()}"` + ); + + const collections = await integration.mongoClient().db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(0); + }); + + it("removes the collection if it exists", async () => { + await integration.connectMcpClient(); + await integration.mongoClient().db(integration.randomDbName()).createCollection("coll1"); + await integration.mongoClient().db(integration.randomDbName()).createCollection("coll2"); + const response = await integration.mcpClient().callTool({ + name: "drop-collection", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + }, + }); + const content = getResponseContent(response.content); + expect(content).toContain( + `Successfully dropped collection "coll1" from database "${integration.randomDbName()}"` + ); + const collections = await integration.mongoClient().db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(1); + expect(collections[0].name).toBe("coll2"); + }); + + validateAutoConnectBehavior(integration, "drop-collection", () => { + return { + args: { + database: integration.randomDbName(), + collection: "coll1", + }, + expectedResponse: `Successfully dropped collection "coll1" from database "${integration.randomDbName()}"`, + }; + }); +}); diff --git a/tests/integration/tools/mongodb/delete/dropDatabase.test.ts b/tests/integration/tools/mongodb/delete/dropDatabase.test.ts new file mode 100644 index 00000000..29a79206 --- /dev/null +++ b/tests/integration/tools/mongodb/delete/dropDatabase.test.ts @@ -0,0 +1,80 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + validateToolMetadata, + validateThrowsForInvalidArguments, + databaseParameters, + databaseInvalidArgs, +} from "../../../helpers.js"; + +describeWithMongoDB("dropDatabase tool", (integration) => { + validateToolMetadata( + integration, + "drop-database", + "Removes the specified database, deleting the associated data files", + databaseParameters + ); + + validateThrowsForInvalidArguments(integration, "drop-database", databaseInvalidArgs); + + it("can drop non-existing database", async () => { + let { databases } = await integration.mongoClient().db("").admin().listDatabases(); + + const preDropLength = databases.length; + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "drop-database", + arguments: { + database: integration.randomDbName(), + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain(`Successfully dropped database "${integration.randomDbName()}"`); + + ({ databases } = await integration.mongoClient().db("").admin().listDatabases()); + + expect(databases).toHaveLength(preDropLength); + expect(databases.find((db) => db.name === integration.randomDbName())).toBeUndefined(); + }); + + it("removes the database along with its collections", async () => { + await integration.connectMcpClient(); + await integration.mongoClient().db(integration.randomDbName()).createCollection("coll1"); + await integration.mongoClient().db(integration.randomDbName()).createCollection("coll2"); + + let { databases } = await integration.mongoClient().db("").admin().listDatabases(); + expect(databases.find((db) => db.name === integration.randomDbName())).toBeDefined(); + + const response = await integration.mcpClient().callTool({ + name: "drop-database", + arguments: { + database: integration.randomDbName(), + }, + }); + const content = getResponseContent(response.content); + expect(content).toContain(`Successfully dropped database "${integration.randomDbName()}"`); + + ({ databases } = await integration.mongoClient().db("").admin().listDatabases()); + expect(databases.find((db) => db.name === integration.randomDbName())).toBeUndefined(); + + const collections = await integration.mongoClient().db(integration.randomDbName()).listCollections().toArray(); + expect(collections).toHaveLength(0); + }); + + validateAutoConnectBehavior( + integration, + "drop-database", + () => { + return { + args: { database: integration.randomDbName() }, + expectedResponse: `Successfully dropped database "${integration.randomDbName()}"`, + }; + }, + async () => { + await integration.mongoClient().db(integration.randomDbName()).createCollection("coll1"); + } + ); +}); diff --git a/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts b/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts new file mode 100644 index 00000000..ccfc988f --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts @@ -0,0 +1,151 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseElements, + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + databaseCollectionInvalidArgs, +} from "../../../helpers.js"; +import { Document } from "bson"; +import { OptionalId } from "mongodb"; +import { SimplifiedSchema } from "mongodb-schema"; + +describeWithMongoDB("collectionSchema tool", (integration) => { + validateToolMetadata( + integration, + "collection-schema", + "Describe the schema for a collection", + databaseCollectionParameters + ); + + validateThrowsForInvalidArguments(integration, "collection-schema", databaseCollectionInvalidArgs); + + describe("with non-existent database", () => { + it("returns empty schema", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-schema", + arguments: { database: "non-existent", collection: "foo" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + `Could not deduce the schema for "non-existent.foo". This may be because it doesn't exist or is empty.` + ); + }); + }); + + describe("with existing database", () => { + const testCases: Array<{ + insertionData: OptionalId[]; + name: string; + expectedSchema: SimplifiedSchema; + }> = [ + { + name: "homogenous schema", + insertionData: [ + { name: "Alice", age: 30 }, + { name: "Bob", age: 25 }, + ], + expectedSchema: { + _id: { + types: [{ bsonType: "ObjectId" }], + }, + name: { + types: [{ bsonType: "String" }], + }, + age: { + types: [{ bsonType: "Number" as any }], + }, + }, + }, + { + name: "heterogenous schema", + insertionData: [ + { name: "Alice", age: 30 }, + { name: "Bob", age: "25", country: "UK" }, + { name: "Charlie", country: "USA" }, + { name: "Mims", age: 25, country: false }, + ], + expectedSchema: { + _id: { + types: [{ bsonType: "ObjectId" }], + }, + name: { + types: [{ bsonType: "String" }], + }, + age: { + types: [{ bsonType: "Number" as any }, { bsonType: "String" }], + }, + country: { + types: [{ bsonType: "String" }, { bsonType: "Boolean" }], + }, + }, + }, + { + name: "schema with nested documents", + insertionData: [ + { name: "Alice", address: { city: "New York", zip: "10001" }, ageRange: [18, 30] }, + { name: "Bob", address: { city: "Los Angeles" }, ageRange: "25-30" }, + { name: "Charlie", address: { city: "Chicago", zip: "60601" }, ageRange: [20, 35] }, + ], + expectedSchema: { + _id: { + types: [{ bsonType: "ObjectId" }], + }, + name: { + types: [{ bsonType: "String" }], + }, + address: { + types: [ + { + bsonType: "Document", + fields: { + city: { types: [{ bsonType: "String" }] }, + zip: { types: [{ bsonType: "String" }] }, + }, + }, + ], + }, + ageRange: { + types: [{ bsonType: "Array", types: [{ bsonType: "Number" as any }] }, { bsonType: "String" }], + }, + }, + }, + ]; + + for (const testCase of testCases) { + it(`returns ${testCase.name}`, async () => { + const mongoClient = integration.mongoClient(); + await mongoClient.db(integration.randomDbName()).collection("foo").insertMany(testCase.insertionData); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-schema", + arguments: { database: integration.randomDbName(), collection: "foo" }, + }); + const items = getResponseElements(response.content); + expect(items).toHaveLength(2); + + // Expect to find _id, name, age + expect(items[0].text).toEqual( + `Found ${Object.entries(testCase.expectedSchema).length} fields in the schema for "${integration.randomDbName()}.foo"` + ); + + const schema = JSON.parse(items[1].text) as SimplifiedSchema; + expect(schema).toEqual(testCase.expectedSchema); + }); + } + }); + + validateAutoConnectBehavior(integration, "collection-schema", () => { + return { + args: { + database: integration.randomDbName(), + collection: "new-collection", + }, + expectedResponse: `Could not deduce the schema for "${integration.randomDbName()}.new-collection". This may be because it doesn't exist or is empty.`, + }; + }); +}); diff --git a/tests/integration/tools/mongodb/metadata/collectionStorageSize.test.ts b/tests/integration/tools/mongodb/metadata/collectionStorageSize.test.ts new file mode 100644 index 00000000..23e86cde --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/collectionStorageSize.test.ts @@ -0,0 +1,85 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + databaseCollectionInvalidArgs, + validateToolMetadata, + validateThrowsForInvalidArguments, +} from "../../../helpers.js"; +import * as crypto from "crypto"; + +describeWithMongoDB("collectionStorageSize tool", (integration) => { + validateToolMetadata( + integration, + "collection-storage-size", + "Gets the size of the collection", + databaseCollectionParameters + ); + + validateThrowsForInvalidArguments(integration, "collection-storage-size", databaseCollectionInvalidArgs); + + describe("with non-existent database", () => { + it("returns an error", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-storage-size", + arguments: { database: integration.randomDbName(), collection: "foo" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + `The size of "${integration.randomDbName()}.foo" cannot be determined because the collection does not exist.` + ); + }); + }); + + describe("with existing database", () => { + const testCases = [ + { + expectedScale: "bytes", + bytesToInsert: 1, + }, + { + expectedScale: "KB", + bytesToInsert: 1024, + }, + { + expectedScale: "MB", + bytesToInsert: 1024 * 1024, + }, + ]; + for (const test of testCases) { + it(`returns the size of the collection in ${test.expectedScale}`, async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("foo") + .insertOne({ data: crypto.randomBytes(test.bytesToInsert) }); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-storage-size", + arguments: { database: integration.randomDbName(), collection: "foo" }, + }); + const content = getResponseContent(response.content); + expect(content).toContain(`The size of "${integration.randomDbName()}.foo" is`); + const size = /is `(\d+\.\d+) ([a-zA-Z]*)`/.exec(content); + + expect(size?.[1]).toBeDefined(); + expect(size?.[2]).toBeDefined(); + expect(parseFloat(size?.[1] || "")).toBeGreaterThan(0); + expect(size?.[2]).toBe(test.expectedScale); + }); + } + }); + + validateAutoConnectBehavior(integration, "collection-storage-size", () => { + return { + args: { + database: integration.randomDbName(), + collection: "foo", + }, + expectedResponse: `The size of "${integration.randomDbName()}.foo" cannot be determined because the collection does not exist.`, + }; + }); +}); diff --git a/tests/integration/tools/mongodb/metadata/connect.test.ts b/tests/integration/tools/mongodb/metadata/connect.test.ts new file mode 100644 index 00000000..017c6779 --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/connect.test.ts @@ -0,0 +1,130 @@ +import { describeWithMongoDB } from "../mongodbHelpers.js"; + +import { getResponseContent, validateToolMetadata } from "../../../helpers.js"; + +import { config } from "../../../../../src/config.js"; + +describeWithMongoDB("Connect tool", (integration) => { + validateToolMetadata(integration, "connect", "Connect to a MongoDB instance", [ + { + name: "options", + description: + "Options for connecting to MongoDB. If not provided, the connection string from the config://connection-string resource will be used. If the user hasn't specified Atlas cluster name or a connection string explicitly and the `config://connection-string` resource is present, always invoke this with no arguments.", + type: "array", + required: false, + }, + ]); + + describe("with default config", () => { + describe("without connection string", () => { + it("prompts for connection string", async () => { + const response = await integration.mcpClient().callTool({ name: "connect", arguments: {} }); + const content = getResponseContent(response.content); + expect(content).toContain("No connection details provided"); + }); + }); + + describe("with connection string", () => { + it("connects to the database", async () => { + const response = await integration.mcpClient().callTool({ + name: "connect", + arguments: { + options: [ + { + connectionString: integration.connectionString(), + }, + ], + }, + }); + const content = getResponseContent(response.content); + expect(content).toContain("Successfully connected"); + expect(content).toContain(integration.connectionString()); + }); + }); + + describe("with invalid connection string", () => { + it("returns error message", async () => { + const response = await integration.mcpClient().callTool({ + name: "connect", + arguments: { options: [{ connectionString: "mongodb://localhost:12345" }] }, + }); + const content = getResponseContent(response.content); + expect(content).toContain("Error running connect"); + + // Should not suggest using the config connection string (because we don't have one) + expect(content).not.toContain("Your config lists a different connection string"); + }); + }); + }); + + describe("with connection string in config", () => { + beforeEach(async () => { + config.connectionString = integration.connectionString(); + }); + + it("uses the connection string from config", async () => { + const response = await integration.mcpClient().callTool({ name: "connect", arguments: {} }); + const content = getResponseContent(response.content); + expect(content).toContain("Successfully connected"); + expect(content).toContain(integration.connectionString()); + }); + + it("prefers connection string from arguments", async () => { + const newConnectionString = `${integration.connectionString()}?appName=foo-bar`; + const response = await integration.mcpClient().callTool({ + name: "connect", + arguments: { + options: [ + { + connectionString: newConnectionString, + }, + ], + }, + }); + const content = getResponseContent(response.content); + expect(content).toContain("Successfully connected"); + expect(content).toContain(newConnectionString); + }); + + describe("when the arugment connection string is invalid", () => { + it("suggests the config connection string if set", async () => { + const response = await integration.mcpClient().callTool({ + name: "connect", + arguments: { + options: [ + { + connectionString: "mongodb://localhost:12345", + }, + ], + }, + }); + const content = getResponseContent(response.content); + expect(content).toContain("Failed to connect to MongoDB at 'mongodb://localhost:12345'"); + expect(content).toContain( + `Your config lists a different connection string: '${config.connectionString}' - do you want to try connecting to it instead?` + ); + }); + + it("returns error message if the config connection string matches the argument", async () => { + config.connectionString = "mongodb://localhost:12345"; + const response = await integration.mcpClient().callTool({ + name: "connect", + arguments: { + options: [ + { + connectionString: "mongodb://localhost:12345", + }, + ], + }, + }); + + const content = getResponseContent(response.content); + + // Should be handled by default error handler and not suggest the config connection string + // because it matches the argument connection string + expect(content).toContain("Error running connect"); + expect(content).not.toContain("Your config lists a different connection string"); + }); + }); + }); +}); diff --git a/tests/integration/tools/mongodb/metadata/dbStats.test.ts b/tests/integration/tools/mongodb/metadata/dbStats.test.ts new file mode 100644 index 00000000..8e4a57c7 --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/dbStats.test.ts @@ -0,0 +1,96 @@ +import { ObjectId } from "bson"; +import { + databaseParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + databaseInvalidArgs, + getResponseElements, +} from "../../../helpers.js"; +import * as crypto from "crypto"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("dbStats tool", (integration) => { + validateToolMetadata( + integration, + "db-stats", + "Returns statistics that reflect the use state of a single database", + databaseParameters + ); + + validateThrowsForInvalidArguments(integration, "db-stats", databaseInvalidArgs); + + describe("with non-existent database", () => { + it("returns an error", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "db-stats", + arguments: { database: integration.randomDbName() }, + }); + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(2); + expect(elements[0].text).toBe(`Statistics for database ${integration.randomDbName()}`); + + const stats = JSON.parse(elements[1].text); + expect(stats.db).toBe(integration.randomDbName()); + expect(stats.collections).toBe(0); + expect(stats.storageSize).toBe(0); + }); + }); + + describe("with existing database", () => { + const testCases = [ + { + collections: { + foos: 3, + }, + name: "single collection", + }, + { + collections: { + foos: 2, + bars: 5, + }, + name: "multiple collections", + }, + ]; + for (const test of testCases) { + it(`returns correct stats for ${test.name}`, async () => { + for (const [name, count] of Object.entries(test.collections)) { + const objects = Array(count) + .fill(0) + .map(() => { + return { data: crypto.randomBytes(1024), _id: new ObjectId() }; + }); + await integration.mongoClient().db(integration.randomDbName()).collection(name).insertMany(objects); + } + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "db-stats", + arguments: { database: integration.randomDbName() }, + }); + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(2); + expect(elements[0].text).toBe(`Statistics for database ${integration.randomDbName()}`); + + const stats = JSON.parse(elements[1].text); + expect(stats.db).toBe(integration.randomDbName()); + expect(stats.collections).toBe(Object.entries(test.collections).length); + expect(stats.storageSize).toBeGreaterThan(1024); + expect(stats.objects).toBe(Object.values(test.collections).reduce((a, b) => a + b, 0)); + }); + } + }); + + describe("when not connected", () => { + validateAutoConnectBehavior(integration, "db-stats", () => { + return { + args: { + database: integration.randomDbName(), + collection: "foo", + }, + expectedResponse: `Statistics for database ${integration.randomDbName()}`, + }; + }); + }); +}); diff --git a/tests/integration/tools/mongodb/metadata/explain.test.ts b/tests/integration/tools/mongodb/metadata/explain.test.ts new file mode 100644 index 00000000..dafdd238 --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/explain.test.ts @@ -0,0 +1,172 @@ +import { + databaseCollectionParameters, + setupIntegrationTest, + validateToolMetadata, + validateThrowsForInvalidArguments, + getResponseElements, +} from "../../../helpers.js"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("explain tool", (integration) => { + validateToolMetadata( + integration, + "explain", + "Returns statistics describing the execution of the winning plan chosen by the query optimizer for the evaluated method", + [ + ...databaseCollectionParameters, + + { + name: "method", + description: "The method and its arguments to run", + type: "array", + required: true, + }, + ] + ); + + validateThrowsForInvalidArguments(integration, "explain", [ + {}, + { database: 123, collection: "bar", method: [{ name: "find", arguments: {} }] }, + { database: "test", collection: true, method: [{ name: "find", arguments: {} }] }, + { database: "test", collection: "bar", method: [{ name: "dnif", arguments: {} }] }, + { database: "test", collection: "bar", method: "find" }, + { database: "test", collection: "bar", method: { name: "find", arguments: {} } }, + ]); + + const testCases = [ + { + method: "aggregate", + arguments: { pipeline: [{ $match: { name: "Peter" } }] }, + }, + { + method: "find", + arguments: { filter: { name: "Peter" } }, + }, + { + method: "count", + arguments: { + query: { name: "Peter" }, + }, + }, + ]; + + for (const testType of ["database", "collection"] as const) { + describe(`with non-existing ${testType}`, () => { + for (const testCase of testCases) { + it(`should return the explain plan for ${testCase.method}`, async () => { + if (testType === "database") { + const { databases } = await integration.mongoClient().db("").admin().listDatabases(); + expect(databases.find((db) => db.name === integration.randomDbName())).toBeUndefined(); + } else if (testType === "collection") { + await integration + .mongoClient() + .db(integration.randomDbName()) + .createCollection("some-collection"); + + const collections = await integration + .mongoClient() + .db(integration.randomDbName()) + .listCollections() + .toArray(); + + expect(collections.find((collection) => collection.name === "coll1")).toBeUndefined(); + } + + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "explain", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + method: [ + { + name: testCase.method, + arguments: testCase.arguments, + }, + ], + }, + }); + + const content = getResponseElements(response.content); + expect(content).toHaveLength(2); + expect(content[0].text).toEqual( + `Here is some information about the winning plan chosen by the query optimizer for running the given \`${testCase.method}\` operation in "${integration.randomDbName()}.coll1". This information can be used to understand how the query was executed and to optimize the query performance.` + ); + + expect(content[1].text).toContain("queryPlanner"); + expect(content[1].text).toContain("winningPlan"); + }); + } + }); + } + + describe("with existing database and collection", () => { + for (const indexed of [true, false] as const) { + describe(`with ${indexed ? "an index" : "no index"}`, () => { + beforeEach(async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("people") + .insertMany([{ name: "Alice" }, { name: "Bob" }, { name: "Charlie" }]); + + if (indexed) { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("people") + .createIndex({ name: 1 }); + } + }); + + for (const testCase of testCases) { + it(`should return the explain plan for ${testCase.method}`, async () => { + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "explain", + arguments: { + database: integration.randomDbName(), + collection: "people", + method: [ + { + name: testCase.method, + arguments: testCase.arguments, + }, + ], + }, + }); + + const content = getResponseElements(response.content); + expect(content).toHaveLength(2); + expect(content[0].text).toEqual( + `Here is some information about the winning plan chosen by the query optimizer for running the given \`${testCase.method}\` operation in "${integration.randomDbName()}.people". This information can be used to understand how the query was executed and to optimize the query performance.` + ); + + expect(content[1].text).toContain("queryPlanner"); + expect(content[1].text).toContain("winningPlan"); + + if (indexed) { + if (testCase.method === "count") { + expect(content[1].text).toContain("COUNT_SCAN"); + } else { + expect(content[1].text).toContain("IXSCAN"); + } + expect(content[1].text).toContain("name_1"); + } else { + expect(content[1].text).toContain("COLLSCAN"); + } + }); + } + }); + } + }); + + validateAutoConnectBehavior(integration, "explain", () => { + return { + args: { database: integration.randomDbName(), collection: "coll1", method: [] }, + expectedResponse: "No method provided. Expected one of the following: `aggregate`, `find`, or `count`", + }; + }); +}); diff --git a/tests/integration/tools/mongodb/metadata/listCollections.test.ts b/tests/integration/tools/mongodb/metadata/listCollections.test.ts new file mode 100644 index 00000000..cef0a59d --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/listCollections.test.ts @@ -0,0 +1,76 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseElements, + getResponseContent, + validateToolMetadata, + validateThrowsForInvalidArguments, + databaseInvalidArgs, + databaseParameters, +} from "../../../helpers.js"; + +describeWithMongoDB("listCollections tool", (integration) => { + validateToolMetadata( + integration, + "list-collections", + "List all collections for a given database", + databaseParameters + ); + + validateThrowsForInvalidArguments(integration, "list-collections", databaseInvalidArgs); + + describe("with non-existent database", () => { + it("returns no collections", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "list-collections", + arguments: { database: "non-existent" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + 'No collections found for database "non-existent". To create a collection, use the "create-collection" tool.' + ); + }); + }); + + describe("with existing database", () => { + it("returns collections", async () => { + const mongoClient = integration.mongoClient(); + await mongoClient.db(integration.randomDbName()).createCollection("collection-1"); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "list-collections", + arguments: { database: integration.randomDbName() }, + }); + const items = getResponseElements(response.content); + expect(items).toHaveLength(1); + expect(items[0].text).toContain('Name: "collection-1"'); + + await mongoClient.db(integration.randomDbName()).createCollection("collection-2"); + + const response2 = await integration.mcpClient().callTool({ + name: "list-collections", + arguments: { database: integration.randomDbName() }, + }); + const items2 = getResponseElements(response2.content); + expect(items2).toHaveLength(2); + expect(items2.map((item) => item.text)).toIncludeSameMembers([ + 'Name: "collection-1"', + 'Name: "collection-2"', + ]); + }); + }); + + validateAutoConnectBehavior( + integration, + "list-collections", + + () => { + return { + args: { database: integration.randomDbName() }, + expectedResponse: `No collections found for database "${integration.randomDbName()}". To create a collection, use the "create-collection" tool.`, + }; + } + ); +}); diff --git a/tests/integration/tools/mongodb/metadata/listDatabases.test.ts b/tests/integration/tools/mongodb/metadata/listDatabases.test.ts new file mode 100644 index 00000000..3288cf30 --- /dev/null +++ b/tests/integration/tools/mongodb/metadata/listDatabases.test.ts @@ -0,0 +1,73 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; +import { getResponseElements, getParameters } from "../../../helpers.js"; + +describeWithMongoDB("listDatabases tool", (integration) => { + const defaultDatabases = ["admin", "config", "local"]; + + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const listDatabases = tools.find((tool) => tool.name === "list-databases")!; + expect(listDatabases).toBeDefined(); + expect(listDatabases.description).toBe("List all databases for a MongoDB connection"); + + const parameters = getParameters(listDatabases); + expect(parameters).toHaveLength(0); + }); + + describe("with no preexisting databases", () => { + it("returns only the system databases", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ name: "list-databases", arguments: {} }); + const dbNames = getDbNames(response.content); + + expect(defaultDatabases).toIncludeAllMembers(dbNames); + }); + }); + + describe("with preexisting databases", () => { + it("returns their names and sizes", async () => { + const mongoClient = integration.mongoClient(); + await mongoClient.db("foo").collection("bar").insertOne({ test: "test" }); + await mongoClient.db("baz").collection("qux").insertOne({ test: "test" }); + + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ name: "list-databases", arguments: {} }); + const dbNames = getDbNames(response.content); + expect(dbNames).toIncludeSameMembers([...defaultDatabases, "foo", "baz"]); + }); + }); + + validateAutoConnectBehavior( + integration, + "list-databases", + () => { + return { + args: {}, + validate: (content) => { + const dbNames = getDbNames(content); + + expect(defaultDatabases).toIncludeAllMembers(dbNames); + }, + }; + }, + async () => { + const mongoClient = integration.mongoClient(); + const { databases } = await mongoClient.db("admin").command({ listDatabases: 1, nameOnly: true }); + for (const db of databases) { + if (!defaultDatabases.includes(db.name)) { + await mongoClient.db(db.name).dropDatabase(); + } + } + } + ); +}); + +function getDbNames(content: unknown): (string | null)[] { + const responseItems = getResponseElements(content); + + return responseItems.map((item) => { + const match = item.text.match(/Name: (.*), Size: \d+ bytes/); + return match ? match[1] : null; + }); +} diff --git a/tests/integration/tools/mongodb/mongodbHelpers.ts b/tests/integration/tools/mongodb/mongodbHelpers.ts new file mode 100644 index 00000000..44584339 --- /dev/null +++ b/tests/integration/tools/mongodb/mongodbHelpers.ts @@ -0,0 +1,159 @@ +import runner, { MongoCluster } from "mongodb-runner"; +import path from "path"; +import fs from "fs/promises"; +import { MongoClient, ObjectId } from "mongodb"; +import { getResponseContent, IntegrationTest, setupIntegrationTest } from "../../helpers.js"; +import { UserConfig, config } from "../../../../src/config.js"; + +interface MongoDBIntegrationTest { + mongoClient: () => MongoClient; + connectionString: () => string; + connectMcpClient: () => Promise; + randomDbName: () => string; +} + +export function describeWithMongoDB( + name: number | string | Function | jest.FunctionLike, + fn: (integration: IntegrationTest & MongoDBIntegrationTest) => void +): void { + describe("mongodb", () => { + const integration = setupIntegrationTest(); + const mdbIntegration = setupMongoDBIntegrationTest(integration); + describe(name, () => { + fn({ ...integration, ...mdbIntegration }); + }); + }); +} + +export function setupMongoDBIntegrationTest( + integration: IntegrationTest, + userConfig: UserConfig = config +): MongoDBIntegrationTest { + let mongoCluster: runner.MongoCluster | undefined; + let mongoClient: MongoClient | undefined; + let randomDbName: string; + + beforeEach(async () => { + randomDbName = new ObjectId().toString(); + }); + + afterEach(async () => { + await integration.mcpServer().session.close(); + config.connectionString = undefined; + + await mongoClient?.close(); + mongoClient = undefined; + }); + + beforeAll(async function () { + // Downloading Windows executables in CI takes a long time because + // they include debug symbols... + const tmpDir = path.join(__dirname, "..", "..", "..", "tmp"); + await fs.mkdir(tmpDir, { recursive: true }); + + // On Windows, we may have a situation where mongod.exe is not fully released by the OS + // before we attempt to run it again, so we add a retry. + let dbsDir = path.join(tmpDir, "mongodb-runner", "dbs"); + for (let i = 0; i < 10; i++) { + try { + mongoCluster = await MongoCluster.start({ + tmpDir: dbsDir, + logDir: path.join(tmpDir, "mongodb-runner", "logs"), + topology: "standalone", + }); + + return; + } catch (err) { + if (i < 5) { + // Just wait a little bit and retry + console.error(`Failed to start cluster in ${dbsDir}, attempt ${i}: ${err}`); + await new Promise((resolve) => setTimeout(resolve, 1000)); + } else { + // If we still fail after 5 seconds, try another db dir + console.error( + `Failed to start cluster in ${dbsDir}, attempt ${i}: ${err}. Retrying with a new db dir.` + ); + dbsDir = path.join(tmpDir, "mongodb-runner", `dbs${i - 5}`); + } + } + } + + throw new Error("Failed to start cluster after 10 attempts"); + }, 120_000); + + afterAll(async function () { + await mongoCluster?.close(); + mongoCluster = undefined; + }); + + const getConnectionString = () => { + if (!mongoCluster) { + throw new Error("beforeAll() hook not ran yet"); + } + + return mongoCluster.connectionString; + }; + + return { + mongoClient: () => { + if (!mongoClient) { + mongoClient = new MongoClient(getConnectionString()); + } + return mongoClient; + }, + connectionString: getConnectionString, + connectMcpClient: async () => { + await integration.mcpClient().callTool({ + name: "connect", + arguments: { options: [{ connectionString: getConnectionString() }] }, + }); + }, + randomDbName: () => randomDbName, + }; +} + +export function validateAutoConnectBehavior( + integration: IntegrationTest & MongoDBIntegrationTest, + name: string, + validation: () => { + args: { [x: string]: unknown }; + expectedResponse?: string; + validate?: (content: unknown) => void; + }, + beforeEachImpl?: () => Promise +): void { + describe("when not connected", () => { + if (beforeEachImpl) { + beforeEach(() => beforeEachImpl()); + } + + it("connects automatically if connection string is configured", async () => { + config.connectionString = integration.connectionString(); + + const validationInfo = validation(); + + const response = await integration.mcpClient().callTool({ + name, + arguments: validationInfo.args, + }); + + if (validationInfo.expectedResponse) { + const content = getResponseContent(response.content); + expect(content).toContain(validationInfo.expectedResponse); + } + + if (validationInfo.validate) { + validationInfo.validate(response.content); + } + }); + + it("throws an error if connection string is not configured", async () => { + const response = await integration.mcpClient().callTool({ + name, + arguments: validation().args, + }); + const content = getResponseContent(response.content); + expect(content).toContain("You need to connect to a MongoDB instance before you can access its data."); + }); + }); +} diff --git a/tests/integration/tools/mongodb/read/aggregate.test.ts b/tests/integration/tools/mongodb/read/aggregate.test.ts new file mode 100644 index 00000000..148117e1 --- /dev/null +++ b/tests/integration/tools/mongodb/read/aggregate.test.ts @@ -0,0 +1,98 @@ +import { + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + getResponseElements, +} from "../../../helpers.js"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("aggregate tool", (integration) => { + validateToolMetadata(integration, "aggregate", "Run an aggregation against a MongoDB collection", [ + ...databaseCollectionParameters, + { + name: "pipeline", + description: "An array of aggregation stages to execute", + type: "array", + required: true, + }, + ]); + + validateThrowsForInvalidArguments(integration, "aggregate", [ + {}, + { database: "test", collection: "foo" }, + { database: test, pipeline: [] }, + { database: "test", collection: "foo", pipeline: {} }, + { database: "test", collection: "foo", pipeline: [], extra: "extra" }, + { database: "test", collection: [], pipeline: [] }, + { database: 123, collection: "foo", pipeline: [] }, + ]); + + it("can run aggragation on non-existent database", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "aggregate", + arguments: { database: "non-existent", collection: "people", pipeline: [{ $match: { name: "Peter" } }] }, + }); + + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(1); + expect(elements[0].text).toEqual('Found 0 documents in the collection "people":'); + }); + + it("can run aggragation on an empty collection", async () => { + await integration.mongoClient().db(integration.randomDbName()).createCollection("people"); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "aggregate", + arguments: { + database: integration.randomDbName(), + collection: "people", + pipeline: [{ $match: { name: "Peter" } }], + }, + }); + + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(1); + expect(elements[0].text).toEqual('Found 0 documents in the collection "people":'); + }); + + it("can run aggragation on an existing collection", async () => { + const mongoClient = integration.mongoClient(); + await mongoClient + .db(integration.randomDbName()) + .collection("people") + .insertMany([ + { name: "Peter", age: 5 }, + { name: "Laura", age: 10 }, + { name: "Søren", age: 15 }, + ]); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "aggregate", + arguments: { + database: integration.randomDbName(), + collection: "people", + pipeline: [{ $match: { age: { $gt: 8 } } }, { $sort: { name: -1 } }], + }, + }); + + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(3); + expect(elements[0].text).toEqual('Found 2 documents in the collection "people":'); + expect(JSON.parse(elements[1].text)).toEqual({ _id: expect.any(Object), name: "Søren", age: 15 }); + expect(JSON.parse(elements[2].text)).toEqual({ _id: expect.any(Object), name: "Laura", age: 10 }); + }); + + validateAutoConnectBehavior(integration, "aggregate", () => { + return { + args: { + database: integration.randomDbName(), + collection: "coll1", + pipeline: [{ $match: { name: "Liva" } }], + }, + expectedResponse: 'Found 0 documents in the collection "coll1"', + }; + }); +}); diff --git a/tests/integration/tools/mongodb/read/collectionIndexes.test.ts b/tests/integration/tools/mongodb/read/collectionIndexes.test.ts new file mode 100644 index 00000000..2e919080 --- /dev/null +++ b/tests/integration/tools/mongodb/read/collectionIndexes.test.ts @@ -0,0 +1,98 @@ +import { IndexDirection } from "mongodb"; +import { + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + getResponseElements, + databaseCollectionInvalidArgs, +} from "../../../helpers.js"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("collectionIndexes tool", (integration) => { + validateToolMetadata( + integration, + "collection-indexes", + "Describe the indexes for a collection", + databaseCollectionParameters + ); + + validateThrowsForInvalidArguments(integration, "collection-indexes", databaseCollectionInvalidArgs); + + it("can inspect indexes on non-existent database", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-indexes", + arguments: { database: "non-existent", collection: "people" }, + }); + + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(1); + expect(elements[0].text).toEqual( + 'The indexes for "non-existent.people" cannot be determined because the collection does not exist.' + ); + }); + + it("returns the _id index for a new collection", async () => { + await integration.mongoClient().db(integration.randomDbName()).createCollection("people"); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-indexes", + arguments: { + database: integration.randomDbName(), + collection: "people", + }, + }); + + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(2); + expect(elements[0].text).toEqual('Found 1 indexes in the collection "people":'); + expect(elements[1].text).toEqual('Name "_id_", definition: {"_id":1}'); + }); + + it("returns all indexes for a collection", async () => { + await integration.mongoClient().db(integration.randomDbName()).createCollection("people"); + + const indexTypes: IndexDirection[] = [-1, 1, "2d", "2dsphere", "text", "hashed"]; + for (const indexType of indexTypes) { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("people") + .createIndex({ [`prop_${indexType}`]: indexType }); + } + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "collection-indexes", + arguments: { + database: integration.randomDbName(), + collection: "people", + }, + }); + + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(indexTypes.length + 2); + expect(elements[0].text).toEqual(`Found ${indexTypes.length + 1} indexes in the collection "people":`); + expect(elements[1].text).toEqual('Name "_id_", definition: {"_id":1}'); + + for (const indexType of indexTypes) { + const index = elements.find((element) => element.text.includes(`prop_${indexType}`)); + expect(index).toBeDefined(); + + let expectedDefinition = JSON.stringify({ [`prop_${indexType}`]: indexType }); + if (indexType === "text") { + expectedDefinition = '{"_fts":"text"'; + } + + expect(index!.text).toContain(`definition: ${expectedDefinition}`); + } + }); + + validateAutoConnectBehavior(integration, "collection-indexes", () => { + return { + args: { database: integration.randomDbName(), collection: "coll1" }, + expectedResponse: `The indexes for "${integration.randomDbName()}.coll1" cannot be determined because the collection does not exist.`, + }; + }); +}); diff --git a/tests/integration/tools/mongodb/read/count.test.ts b/tests/integration/tools/mongodb/read/count.test.ts new file mode 100644 index 00000000..938285a8 --- /dev/null +++ b/tests/integration/tools/mongodb/read/count.test.ts @@ -0,0 +1,91 @@ +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +import { + getResponseContent, + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, +} from "../../../helpers.js"; + +describeWithMongoDB("count tool", (integration) => { + validateToolMetadata(integration, "count", "Gets the number of documents in a MongoDB collection", [ + { + name: "query", + description: + "The query filter to count documents. Matches the syntax of the filter argument of db.collection.count()", + type: "object", + required: false, + }, + ...databaseCollectionParameters, + ]); + + validateThrowsForInvalidArguments(integration, "count", [ + {}, + { database: 123, collection: "bar" }, + { foo: "bar", database: "test", collection: "bar" }, + { collection: [], database: "test" }, + { collection: "bar", database: "test", query: "{ $gt: { foo: 5 } }" }, + ]); + + it("returns 0 when database doesn't exist", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "count", + arguments: { database: "non-existent", collection: "foos" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual('Found 0 documents in the collection "foos"'); + }); + + it("returns 0 when collection doesn't exist", async () => { + await integration.connectMcpClient(); + const mongoClient = integration.mongoClient(); + await mongoClient.db(integration.randomDbName()).collection("bar").insertOne({}); + const response = await integration.mcpClient().callTool({ + name: "count", + arguments: { database: integration.randomDbName(), collection: "non-existent" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual('Found 0 documents in the collection "non-existent"'); + }); + + describe("with existing database", () => { + beforeEach(async () => { + const mongoClient = integration.mongoClient(); + await mongoClient + .db(integration.randomDbName()) + .collection("foo") + .insertMany([ + { name: "Peter", age: 5 }, + { name: "Parker", age: 10 }, + { name: "George", age: 15 }, + ]); + }); + + const testCases = [ + { filter: undefined, expectedCount: 3 }, + { filter: {}, expectedCount: 3 }, + { filter: { age: { $lt: 15 } }, expectedCount: 2 }, + { filter: { age: { $gt: 5 }, name: { $regex: "^P" } }, expectedCount: 1 }, + ]; + for (const testCase of testCases) { + it(`returns ${testCase.expectedCount} documents for filter ${JSON.stringify(testCase.filter)}`, async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "count", + arguments: { database: integration.randomDbName(), collection: "foo", query: testCase.filter }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual(`Found ${testCase.expectedCount} documents in the collection "foo"`); + }); + } + }); + + validateAutoConnectBehavior(integration, "count", () => { + return { + args: { database: integration.randomDbName(), collection: "coll1" }, + expectedResponse: 'Found 0 documents in the collection "coll1"', + }; + }); +}); diff --git a/tests/integration/tools/mongodb/read/find.test.ts b/tests/integration/tools/mongodb/read/find.test.ts new file mode 100644 index 00000000..f2a3cfc3 --- /dev/null +++ b/tests/integration/tools/mongodb/read/find.test.ts @@ -0,0 +1,182 @@ +import { + getResponseContent, + databaseCollectionParameters, + setupIntegrationTest, + validateToolMetadata, + validateThrowsForInvalidArguments, + getResponseElements, +} from "../../../helpers.js"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("find tool", (integration) => { + validateToolMetadata(integration, "find", "Run a find query against a MongoDB collection", [ + ...databaseCollectionParameters, + + { + name: "filter", + description: "The query filter, matching the syntax of the query argument of db.collection.find()", + type: "object", + required: false, + }, + { + name: "projection", + description: "The projection, matching the syntax of the projection argument of db.collection.find()", + type: "object", + required: false, + }, + { + name: "limit", + description: "The maximum number of documents to return", + type: "number", + required: false, + }, + { + name: "sort", + description: + "A document, describing the sort order, matching the syntax of the sort argument of cursor.sort()", + type: "object", + required: false, + }, + ]); + + validateThrowsForInvalidArguments(integration, "find", [ + {}, + { database: 123, collection: "bar" }, + { database: "test", collection: "bar", extra: "extra" }, + { database: "test", collection: [] }, + { database: "test", collection: "bar", filter: "{ $gt: { foo: 5 } }" }, + { database: "test", collection: "bar", projection: "name" }, + { database: "test", collection: "bar", limit: "10" }, + { database: "test", collection: "bar", sort: [], limit: 10 }, + ]); + + it("returns 0 when database doesn't exist", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "find", + arguments: { database: "non-existent", collection: "foos" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual('Found 0 documents in the collection "foos":'); + }); + + it("returns 0 when collection doesn't exist", async () => { + await integration.connectMcpClient(); + const mongoClient = integration.mongoClient(); + await mongoClient.db(integration.randomDbName()).collection("bar").insertOne({}); + const response = await integration.mcpClient().callTool({ + name: "find", + arguments: { database: integration.randomDbName(), collection: "non-existent" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual('Found 0 documents in the collection "non-existent":'); + }); + + describe("with existing database", () => { + beforeEach(async () => { + const mongoClient = integration.mongoClient(); + const items = Array(10) + .fill(0) + .map((_, index) => ({ + value: index, + })); + + await mongoClient.db(integration.randomDbName()).collection("foo").insertMany(items); + }); + + const testCases: { + name: string; + filter?: any; + limit?: number; + projection?: any; + sort?: any; + expected: any[]; + }[] = [ + { + name: "returns all documents when no filter is provided", + expected: Array(10) + .fill(0) + .map((_, index) => ({ _id: expect.any(Object), value: index })), + }, + { + name: "returns documents matching the filter", + filter: { value: { $gt: 5 } }, + expected: Array(4) + .fill(0) + .map((_, index) => ({ _id: expect.any(Object), value: index + 6 })), + }, + { + name: "returns documents matching the filter with projection", + filter: { value: { $gt: 5 } }, + projection: { value: 1, _id: 0 }, + expected: Array(4) + .fill(0) + .map((_, index) => ({ value: index + 6 })), + }, + { + name: "returns documents matching the filter with limit", + filter: { value: { $gt: 5 } }, + limit: 2, + expected: [ + { _id: expect.any(Object), value: 6 }, + { _id: expect.any(Object), value: 7 }, + ], + }, + { + name: "returns documents matching the filter with sort", + filter: {}, + sort: { value: -1 }, + expected: Array(10) + .fill(0) + .map((_, index) => ({ _id: expect.any(Object), value: index })) + .reverse(), + }, + ]; + + for (const { name, filter, limit, projection, sort, expected } of testCases) { + it(name, async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "find", + arguments: { + database: integration.randomDbName(), + collection: "foo", + filter, + limit, + projection, + sort, + }, + }); + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(expected.length + 1); + expect(elements[0].text).toEqual(`Found ${expected.length} documents in the collection "foo":`); + + for (let i = 0; i < expected.length; i++) { + expect(JSON.parse(elements[i + 1].text)).toEqual(expected[i]); + } + }); + } + + it("returns all documents when no filter is provided", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "find", + arguments: { database: integration.randomDbName(), collection: "foo" }, + }); + const elements = getResponseElements(response.content); + expect(elements).toHaveLength(11); + expect(elements[0].text).toEqual('Found 10 documents in the collection "foo":'); + + for (let i = 0; i < 10; i++) { + expect(JSON.parse(elements[i + 1].text).value).toEqual(i); + } + }); + }); + + validateAutoConnectBehavior(integration, "find", () => { + return { + args: { database: integration.randomDbName(), collection: "coll1" }, + expectedResponse: 'Found 0 documents in the collection "coll1":', + }; + }); +}); diff --git a/tests/integration/tools/mongodb/update/renameCollection.test.ts b/tests/integration/tools/mongodb/update/renameCollection.test.ts new file mode 100644 index 00000000..1c904458 --- /dev/null +++ b/tests/integration/tools/mongodb/update/renameCollection.test.ts @@ -0,0 +1,196 @@ +import { + getResponseContent, + databaseCollectionParameters, + setupIntegrationTest, + validateToolMetadata, + validateThrowsForInvalidArguments, +} from "../../../helpers.js"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("renameCollection tool", (integration) => { + validateToolMetadata(integration, "rename-collection", "Renames a collection in a MongoDB database", [ + ...databaseCollectionParameters, + + { + name: "newName", + description: "The new name for the collection", + type: "string", + required: true, + }, + { + name: "dropTarget", + description: "If true, drops the target collection if it exists", + type: "boolean", + required: false, + }, + ]); + + validateThrowsForInvalidArguments(integration, "rename-collection", [ + {}, + { database: 123, collection: "bar" }, + { database: "test", collection: "bar", newName: "foo", extra: "extra" }, + { database: "test", collection: [], newName: "foo" }, + { database: "test", collection: "bar", newName: 10 }, + { database: "test", collection: "bar", newName: "foo", dropTarget: "true" }, + { database: "test", collection: "bar", newName: "foo", dropTarget: 1 }, + ]); + + describe("with non-existing database", () => { + it("returns an error", async () => { + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "rename-collection", + arguments: { database: "non-existent", collection: "foos", newName: "bar" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual(`Cannot rename "non-existent.foos" because it doesn't exist.`); + }); + }); + + describe("with non-existing collection", () => { + it("returns an error", async () => { + await integration.mongoClient().db(integration.randomDbName()).collection("bar").insertOne({}); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "rename-collection", + arguments: { database: integration.randomDbName(), collection: "non-existent", newName: "foo" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + `Cannot rename "${integration.randomDbName()}.non-existent" because it doesn't exist.` + ); + }); + }); + + describe("with existing collection", () => { + it("renames to non-existing collection", async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("before") + .insertOne({ value: 42 }); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "rename-collection", + arguments: { database: integration.randomDbName(), collection: "before", newName: "after" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + `Collection "before" renamed to "after" in database "${integration.randomDbName()}".` + ); + + const docsInBefore = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("before") + .find({}) + .toArray(); + expect(docsInBefore).toHaveLength(0); + + const docsInAfter = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("after") + .find({}) + .toArray(); + expect(docsInAfter).toHaveLength(1); + expect(docsInAfter[0].value).toEqual(42); + }); + + it("returns an error when renaming to an existing collection", async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("before") + .insertOne({ value: 42 }); + await integration.mongoClient().db(integration.randomDbName()).collection("after").insertOne({ value: 84 }); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "rename-collection", + arguments: { database: integration.randomDbName(), collection: "before", newName: "after" }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + `Cannot rename "${integration.randomDbName()}.before" to "after" because the target collection already exists. If you want to overwrite it, set the "dropTarget" argument to true.` + ); + + // Ensure no data was lost + const docsInBefore = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("before") + .find({}) + .toArray(); + expect(docsInBefore).toHaveLength(1); + expect(docsInBefore[0].value).toEqual(42); + + const docsInAfter = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("after") + .find({}) + .toArray(); + expect(docsInAfter).toHaveLength(1); + expect(docsInAfter[0].value).toEqual(84); + }); + + it("renames to existing collection with dropTarget", async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("before") + .insertOne({ value: 42 }); + await integration.mongoClient().db(integration.randomDbName()).collection("after").insertOne({ value: 84 }); + + await integration.connectMcpClient(); + const response = await integration.mcpClient().callTool({ + name: "rename-collection", + arguments: { + database: integration.randomDbName(), + collection: "before", + newName: "after", + dropTarget: true, + }, + }); + const content = getResponseContent(response.content); + expect(content).toEqual( + `Collection "before" renamed to "after" in database "${integration.randomDbName()}".` + ); + + // Ensure the data was moved + const docsInBefore = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("before") + .find({}) + .toArray(); + expect(docsInBefore).toHaveLength(0); + + const docsInAfter = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("after") + .find({}) + .toArray(); + expect(docsInAfter).toHaveLength(1); + expect(docsInAfter[0].value).toEqual(42); + }); + }); + + validateAutoConnectBehavior( + integration, + "rename-collection", + () => { + return { + args: { database: integration.randomDbName(), collection: "coll1", newName: "coll2" }, + expectedResponse: `Collection "coll1" renamed to "coll2" in database "${integration.randomDbName()}".`, + }; + }, + async () => { + await integration.mongoClient().db(integration.randomDbName()).createCollection("coll1"); + } + ); +}); diff --git a/tests/integration/tools/mongodb/update/updateMany.test.ts b/tests/integration/tools/mongodb/update/updateMany.test.ts new file mode 100644 index 00000000..6a05f640 --- /dev/null +++ b/tests/integration/tools/mongodb/update/updateMany.test.ts @@ -0,0 +1,239 @@ +import { + databaseCollectionParameters, + validateToolMetadata, + validateThrowsForInvalidArguments, + getResponseContent, +} from "../../../helpers.js"; +import { describeWithMongoDB, validateAutoConnectBehavior } from "../mongodbHelpers.js"; + +describeWithMongoDB("updateMany tool", (integration) => { + validateToolMetadata( + integration, + "update-many", + "Updates all documents that match the specified filter for a collection", + [ + ...databaseCollectionParameters, + + { + name: "filter", + description: + "The selection criteria for the update, matching the syntax of the filter argument of db.collection.updateOne()", + type: "object", + required: false, + }, + { + name: "update", + description: + "An update document describing the modifications to apply using update operator expressions", + type: "object", + required: true, + }, + { + name: "upsert", + description: "Controls whether to insert a new document if no documents match the filter", + type: "boolean", + required: false, + }, + ] + ); + + validateThrowsForInvalidArguments(integration, "update-many", [ + {}, + { database: 123, collection: "bar", update: {} }, + { database: [], collection: "bar", update: {} }, + { database: "test", collection: "bar", update: [] }, + { database: "test", collection: "bar", update: {}, extra: true }, + { database: "test", collection: "bar", update: {}, filter: 123 }, + { database: "test", collection: "bar", update: {}, upsert: "true" }, + { database: "test", collection: "bar", update: {}, filter: {}, upsert: "true" }, + { database: "test", collection: "bar", update: {}, filter: "TRUEPREDICATE", upsert: false }, + ]); + + describe("with non-existent database", () => { + it("doesn't update any documents", async () => { + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "update-many", + arguments: { + database: "non-existent-db", + collection: "coll1", + update: { $set: { name: "new-name" } }, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual("No documents matched the filter."); + }); + }); + + describe("with non-existent collection", () => { + it("doesn't update any documents", async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .insertOne({ name: "old-name" }); + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "update-many", + arguments: { + database: integration.randomDbName(), + collection: "non-existent", + update: { $set: { name: "new-name" } }, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual("No documents matched the filter."); + }); + }); + + describe("with existing collection", () => { + beforeEach(async () => { + await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .insertMany([ + { name: "old-name", value: 1 }, + { name: "old-name", value: 2 }, + { name: "old-name", value: 3 }, + ]); + }); + it("updates all documents without filter", async () => { + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "update-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + update: { $set: { name: "new-name" } }, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual("Matched 3 document(s). Modified 3 document(s)."); + + const docs = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .find({}) + .toArray(); + + expect(docs).toHaveLength(3); + for (const doc of docs) { + expect(doc.name).toEqual("new-name"); + } + }); + + it("updates all documents that match the filter", async () => { + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "update-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + update: { $set: { name: "new-name" } }, + filter: { value: { $gt: 1 } }, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toEqual("Matched 2 document(s). Modified 2 document(s)."); + + const docs = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .find({}) + .toArray(); + expect(docs).toHaveLength(3); + for (const doc of docs) { + if (doc.value > 1) { + expect(doc.name).toEqual("new-name"); + } else { + expect(doc.name).toEqual("old-name"); + } + } + }); + + it("upserts a new document if no documents match the filter", async () => { + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "update-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + update: { $set: { name: "new-name" } }, + filter: { value: 4 }, + upsert: true, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain("Matched 0 document(s). Upserted 1 document with id:"); + + const docs = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .find({}) + .toArray(); + + expect(docs).toHaveLength(4); + for (const doc of docs) { + if (doc.value === 4) { + expect(doc.name).toEqual("new-name"); + } else { + expect(doc.name).toEqual("old-name"); + } + } + }); + + it("doesn't upsert a new document if no documents match the filter and upsert is false", async () => { + await integration.connectMcpClient(); + + const response = await integration.mcpClient().callTool({ + name: "update-many", + arguments: { + database: integration.randomDbName(), + collection: "coll1", + update: { $set: { name: "new-name" } }, + filter: { value: 4 }, + }, + }); + + const content = getResponseContent(response.content); + expect(content).toContain("No documents matched the filter."); + + const docs = await integration + .mongoClient() + .db(integration.randomDbName()) + .collection("coll1") + .find({}) + .toArray(); + + expect(docs).toHaveLength(3); + for (const doc of docs) { + expect(doc.name).toEqual("old-name"); + } + }); + }); + + validateAutoConnectBehavior(integration, "update-many", () => { + return { + args: { + database: integration.randomDbName(), + collection: "coll1", + update: { $set: { name: "new-name" } }, + }, + expectedResponse: "No documents matched the filter.", + }; + }); +});