diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..05384e6f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +dist +node_modules +.vscode +.github +.git +# Environment variables +.env + +tests +coverage +scripts diff --git a/.github/workflows/check-pr-title.yml b/.github/workflows/check-pr-title.yml new file mode 100644 index 00000000..f6785dd3 --- /dev/null +++ b/.github/workflows/check-pr-title.yml @@ -0,0 +1,29 @@ +name: "Check PR Title" +on: + pull_request: + types: + [ + opened, + synchronize, + reopened, + ready_for_review, + labeled, + unlabeled, + converted_to_draft, + edited, + ] + +permissions: + pull-requests: read # to read PR title and labels + +jobs: + check-pr-title: + name: Check PR Title + runs-on: ubuntu-latest + steps: + - name: Enforce conventional commit style + uses: realm/ci-actions/title-checker@d6cc8f067474759d38e6d24e272027b4c88bc0a9 + with: + regex: '^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test|ops){1}(\([\w\-\.]+\))?(!)?: .*' + error-hint: 'Invalid PR title. Make sure it follows the conventional commit specification (i.e. "(): ") or add the no-title-validation label' + ignore-labels: "no-title-validation" diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 00000000..2fd17cf7 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,57 @@ +name: Daily Release Docker Image +on: + schedule: + - cron: "0 1 * * *" # Every day at 1:00 AM + workflow_dispatch: # Run the action manually +permissions: + contents: read + issues: write +jobs: + push: + runs-on: ubuntu-latest + steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + with: + config: ${{ vars.PERMISSIONS_CONFIG }} + - name: Check out code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@18ce135bb5112fa8ce4ed6c17ab05699d7f3a5e0 + - name: Login to Docker Hub + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 + with: + username: "${{ secrets.DOCKERHUB_USERNAME }}" + password: "${{ secrets.DOCKERHUB_PASSWORD }}" + - name: Set date and version + id: set-properties + run: | + DATE=$(date +'%Y-%m-%d') + VERSION=$(npm pkg get version | tr -d '"') + echo "DATE=${DATE}" >> "$GITHUB_OUTPUT" + echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT" + - name: Build and push image to dockerhub registry + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 + with: + context: . + platforms: linux/amd64,linux/arm64 + tags: ${{ vars.DOCKERHUB_IMAGE_REPOSITORY }}:latest, ${{ vars.DOCKERHUB_IMAGE_REPOSITORY }}:${{ steps.set-properties.outputs.VERSION }}, ${{ vars.DOCKERHUB_IMAGE_REPOSITORY }}:${{ steps.set-properties.outputs.VERSION }}-${{ steps.set-properties.outputs.DATE }} + file: Dockerfile + push: true + provenance: mode=max + sbom: true + build-args: | + VERSION=${{ steps.set-properties.outputs.VERSION }} + - uses: mongodb-js/devtools-shared/actions/setup-bot-token@main + id: app-token + if: ${{ failure() }} + with: + app-id: ${{ vars.DEVTOOLS_BOT_APP_ID }} + private-key: ${{ secrets.DEVTOOLS_BOT_PRIVATE_KEY }} + - name: Create Issue + if: ${{ failure() }} + uses: imjohnbo/issue-bot@572eed14422c4d6ca37e870f97e7da209422f5bd + with: + token: ${{ steps.app-token.outputs.token }} + title: Release Failure for Docker Image ${{ steps.set-properties.outputs.VERSION }}-${{ steps.set-properties.outputs.DATE }} + body: See https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + labels: "docker, release_failure" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..fb2ec4d6 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,32 @@ +--- +name: "Stale issues and PRs handler" +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +permissions: read-all + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: GitHubSecurityLab/actions-permissions/monitor@v1 + - uses: actions/stale@v9 + id: stale + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: | + This issue has gone 30 days without any activity and meets the project's definition of "stale". This will be auto-closed if there is no new activity over the next 30 days. If the issue is still relevant and active, you can simply comment with a "bump" to keep it open, or add the label "not_stale". Thanks for keeping our repository healthy! + stale-pr-message: | + This PR has gone 30 days without any activity and meets the project's definition of "stale". This will be auto-closed if there is no new activity over the next 30 days. If the issue is still relevant and active, you can simply comment with a "bump" to keep it open, or add the label "not_stale". Thanks for keeping our repository healthy! + stale-issue-label: "no-issue-activity" + stale-pr-label: "no-pr-activity" + days-before-stale: 30 + days-before-close: 30 + exempt-all-milestones: true + exempt-issue-labels: "not_stale" + exempt-pr-labels: "not_stale" diff --git a/.smithery/Dockerfile b/.smithery/Dockerfile new file mode 100644 index 00000000..e2b469da --- /dev/null +++ b/.smithery/Dockerfile @@ -0,0 +1,30 @@ +# Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile +# ----- Build Stage ----- +FROM node:lts-alpine AS builder +WORKDIR /app + +# Copy package and configuration +COPY ../package.json ../package-lock.json ../tsconfig.json ../tsconfig.build.json ./ + +# Copy source code +COPY ../src ./src + +# Install dependencies and build +RUN npm ci && npm run build + +# ----- Production Stage ----- +FROM node:lts-alpine + +# Copy built artifacts +COPY --from=builder /app/dist ./dist + +# Copy package.json for production install +COPY ../package.json ../package-lock.json ./ + +# Install only production dependencies +RUN npm ci --production --ignore-scripts + +# Expose no ports (stdio only) + +# Default command +CMD ["node", "dist/index.js"] diff --git a/.smithery/smithery.yaml b/.smithery/smithery.yaml new file mode 100644 index 00000000..e7de81be --- /dev/null +++ b/.smithery/smithery.yaml @@ -0,0 +1,63 @@ +# Smithery.ai configuration +build: + dockerfile: Dockerfile + dockerBuildPath: ../ +startCommand: + type: stdio + configSchema: + type: object + properties: + atlasClientId: + type: string + title: Atlas Client Id + description: Atlas API client ID for authentication. Required for running Atlas tools. + atlasClientSecret: + type: string + title: Atlas Client Secret + description: Atlas API client secret for authentication. Required for running Atlas tools. + connectionString: + type: string + title: MongoDB Connection string + description: MongoDB connection string for direct database connections. Optional, if not set, you'll need to call the `connect` tool before interacting with MongoDB data. + readOnly: + type: boolean + title: Read-only + description: When set to true, only allows read and metadata operation types, disabling create/update/delete operations. + default: false + exampleConfig: + atlasClientId: YOUR_ATLAS_CLIENT_ID + atlasClientSecret: YOUR_ATLAS_CLIENT_SECRET + connectionString: mongodb+srv://USERNAME:PASSWORD@YOUR_CLUSTER.mongodb.net + readOnly: true + + commandFunction: + # A function that produces the CLI command to start the MCP on stdio. + |- + (config) => { + const args = ['dist/index.js']; + if (config) { + if (config.atlasClientId) { + args.push('--apiClientId'); + args.push(config.atlasClientId); + } + + if (config.atlasClientSecret) { + args.push('--apiClientSecret'); + args.push(config.atlasClientSecret); + } + + if (config.readOnly) { + args.push('--readOnly'); + } + + if (config.connectionString) { + args.push('--connectionString'); + args.push(config.connectionString); + } + } + + return { + command: "node", + args + }; + } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9eb3620b..b35e5f4b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,7 +55,7 @@ This project implements a Model Context Protocol (MCP) server for MongoDB and Mo npm run inspect ``` -4. Commit your changes with a descriptive commit message +4. Commit your changes using [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) format. ## Adding tests to the MCP Server diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..05da379f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM node:22-alpine +ARG VERSION=latest +RUN addgroup -S mcp && adduser -S mcp -G mcp +RUN npm install -g mongodb-mcp-server@${VERSION} +USER mcp +WORKDIR /home/mcp +ENTRYPOINT ["mongodb-mcp-server"] +LABEL maintainer="MongoDB Inc " +LABEL description="MongoDB MCP Server" +LABEL version=${VERSION} diff --git a/README.md b/README.md index 28c0c755..da193cf5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?logo=data:image/svg%2bxml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciICB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiPjxwYXRoIGQ9Ik00NC45OTkgMTAuODd2MjYuMjFjMCAxLjAzLS41OSAxLjk3LTEuNTEgMi40Mi0yLjY4IDEuMjktOCAzLjg1LTguMzUgNC4wMS0uMTMuMDctLjM4LjItLjY3LjMxLjM1LS42LjUzLTEuMy41My0yLjAyVjYuMmMwLS43NS0uMi0xLjQ1LS41Ni0yLjA2LjA5LjA0LjE3LjA4LjI0LjExLjIuMSA1Ljk4IDIuODYgOC44IDQuMkM0NC40MDkgOC45IDQ0Ljk5OSA5Ljg0IDQ0Ljk5OSAxMC44N3pNNy40OTkgMjYuMDNjMS42IDEuNDYgMy40MyAzLjEzIDUuMzQgNC44NmwtNC42IDMuNWMtLjc3LjU3LTEuNzguNS0yLjU2LS4wNS0uNS0uMzYtMS44OS0xLjY1LTEuODktMS42NS0xLjAxLS44MS0xLjA2LTIuMzItLjExLTMuMTlDMy42NzkgMjkuNSA1LjE3OSAyOC4xMyA3LjQ5OSAyNi4wM3pNMzEuOTk5IDYuMnYxMC4xMWwtNy42MyA1LjgtNi44NS01LjIxYzQuOTgtNC41MyAxMC4wMS05LjExIDEyLjY1LTExLjUyQzMwLjg2OSA0Ljc0IDMxLjk5OSA1LjI1IDMxLjk5OSA2LjJ6TTMyIDQxLjc5OFYzMS42OUw4LjI0IDEzLjYxYy0uNzctLjU3LTEuNzgtLjUtMi41Ni4wNS0uNS4zNi0xLjg5IDEuNjUtMS44OSAxLjY1LTEuMDEuODEtMS4wNiAyLjMyLS4xMSAzLjE5IDAgMCAyMC4xNDUgMTguMzM4IDI2LjQ4NSAyNC4xMTZDMzAuODcxIDQzLjI2IDMyIDQyLjc1MyAzMiA0MS43OTh6Ii8+PC9zdmc+)](https://insiders.vscode.dev/redirect/mcp/install?name=mongodb&inputs=%5B%7B%22id%22%3A%22connection_string%22%2C%22type%22%3A%22promptString%22%2C%22description%22%3A%22MongoDB%20connection%20string%22%7D%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mongodb-mcp-server%22%5D%2C%22env%22%3A%7B%22MDB_MCP_CONNECTION_STRING%22%3A%22%24%7Binput%3Aconnection_string%7D%22%7D%7D) +[![Install in Cursor](https://img.shields.io/badge/Cursor-Install_Server-1e1e1e?logo=data:image/svg%2bxml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgc3R5bGU9ImZsZXg6bm9uZTtsaW5lLWhlaWdodDoxIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxZW0iCiAgICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogICAgPHRpdGxlPkN1cnNvcjwvdGl0bGU+CiAgICA8cGF0aCBkPSJNMTEuOTI1IDI0bDEwLjQyNS02LTEwLjQyNS02TDEuNSAxOGwxMC40MjUgNnoiCiAgICAgICAgZmlsbD0idXJsKCNsb2JlLWljb25zLWN1cnNvcnVuZGVmaW5lZC1maWxsLTApIj48L3BhdGg+CiAgICA8cGF0aCBkPSJNMjIuMzUgMThWNkwxMS45MjUgMHYxMmwxMC40MjUgNnoiIGZpbGw9InVybCgjbG9iZS1pY29ucy1jdXJzb3J1bmRlZmluZWQtZmlsbC0xKSI+PC9wYXRoPgogICAgPHBhdGggZD0iTTExLjkyNSAwTDEuNSA2djEybDEwLjQyNS02VjB6IiBmaWxsPSJ1cmwoI2xvYmUtaWNvbnMtY3Vyc29ydW5kZWZpbmVkLWZpbGwtMikiPjwvcGF0aD4KICAgIDxwYXRoIGQ9Ik0yMi4zNSA2TDExLjkyNSAyNFYxMkwyMi4zNSA2eiIgZmlsbD0iIzU1NSI+PC9wYXRoPgogICAgPHBhdGggZD0iTTIyLjM1IDZsLTEwLjQyNSA2TDEuNSA2aDIwLjg1eiIgZmlsbD0iI2ZmZiI+PC9wYXRoPgogICAgPGRlZnM+CiAgICAgICAgPGxpbmVhckdyYWRpZW50IGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiBpZD0ibG9iZS1pY29ucy1jdXJzb3J1bmRlZmluZWQtZmlsbC0wIgogICAgICAgICAgICB4MT0iMTEuOTI1IiB4Mj0iMTEuOTI1IiB5MT0iMTIiIHkyPSIyNCI+CiAgICAgICAgICAgIDxzdG9wIG9mZnNldD0iLjE2IiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii4zOSI+PC9zdG9wPgogICAgICAgICAgICA8c3RvcCBvZmZzZXQ9Ii42NTgiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iLjgiPjwvc3RvcD4KICAgICAgICA8L2xpbmVhckdyYWRpZW50PgogICAgICAgIDxsaW5lYXJHcmFkaWVudCBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImxvYmUtaWNvbnMtY3Vyc29ydW5kZWZpbmVkLWZpbGwtMSIKICAgICAgICAgICAgeDE9IjIyLjM1IiB4Mj0iMTEuOTI1IiB5MT0iNi4wMzciIHkyPSIxMi4xNSI+CiAgICAgICAgICAgIDxzdG9wIG9mZnNldD0iLjE4MiIgc3RvcC1jb2xvcj0iI2ZmZiIgc3RvcC1vcGFjaXR5PSIuMzEiPjwvc3RvcD4KICAgICAgICAgICAgPHN0b3Agb2Zmc2V0PSIuNzE1IiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9IjAiPjwvc3RvcD4KICAgICAgICA8L2xpbmVhckdyYWRpZW50PgogICAgICAgIDxsaW5lYXJHcmFkaWVudCBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgaWQ9ImxvYmUtaWNvbnMtY3Vyc29ydW5kZWZpbmVkLWZpbGwtMiIKICAgICAgICAgICAgeDE9IjExLjkyNSIgeDI9IjEuNSIgeTE9IjAiIHkyPSIxOCI+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iLjYiPjwvc3RvcD4KICAgICAgICAgICAgPHN0b3Agb2Zmc2V0PSIuNjY3IiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii4yMiI+PC9zdG9wPgogICAgICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8L2RlZnM+Cjwvc3ZnPgo=)](https://cursor.com/install-mcp?name=MongoDB&config=eyJjb21tYW5kIjoibnB4IC15IG1vbmdvZGItbWNwLXNlcnZlciJ9) +[![View on Smithery](https://smithery.ai/badge/@mongodb-js/mongodb-mcp-server)](https://smithery.ai/server/@mongodb-js/mongodb-mcp-server) + # MongoDB MCP Server A Model Context Protocol server for interacting with MongoDB Databases and MongoDB Atlas. @@ -22,7 +26,7 @@ A Model Context Protocol server for interacting with MongoDB Databases and Mongo ## Prerequisites -- Node.js (v20 or later) +- Node.js (v20.10.0 or later) ```shell node -v @@ -36,6 +40,8 @@ node -v ### Quick Start +> **Note:** When using Atlas API credentials, be sure to assign only the minimum required permissions to your service account. See [Atlas API Permissions](#atlas-api-permissions) for details. + Most MCP clients require a configuration file to be created or modified to add the MCP server. Note: The configuration file syntax can be different across clients. Please refer to the following links for the latest expected syntax: @@ -58,13 +64,15 @@ You can pass your connection string via args, make sure to use a valid username "-y", "mongodb-mcp-server", "--connectionString", - "mongodb+srv://username:password@cluster.mongodb.net/myDatabase" + "mongodb://localhost:27017/myDatabase" ] } } } ``` +NOTE: The connection string can be configured to connect to any MongoDB cluster, whether it's a local instance or an Atlas cluster. + #### Option 2: Atlas API credentials args Use your Atlas API Service Accounts credentials. Must follow all the steps in [Atlas API Access](#atlas-api-access) section. @@ -87,7 +95,7 @@ Use your Atlas API Service Accounts credentials. Must follow all the steps in [A } ``` -### Option 3: Standalone Service using command arguments +#### Option 3: Standalone Service using command arguments Start Server using npx command: @@ -109,6 +117,95 @@ You can use environment variables in the config file or set them and run the ser - Connection String via environment variables in the MCP file [example](#connection-string-with-environment-variables) - Atlas API credentials via environment variables in the MCP file [example](#atlas-api-credentials-with-environment-variables) +#### Option 5: Using Docker + +You can run the MongoDB MCP Server in a Docker container, which provides isolation and doesn't require a local Node.js installation. + +#### Run with Environment Variables + +You may provide either a MongoDB connection string OR Atlas API credentials: + +##### Option A: No configuration + +```shell +docker run --rm -i \ + mongodb/mongodb-mcp-server:latest +``` + +##### Option B: With MongoDB connection string + +```shell +docker run --rm -i \ + -e MDB_MCP_CONNECTION_STRING="mongodb+srv://username:password@cluster.mongodb.net/myDatabase" \ + mongodb/mongodb-mcp-server:latest +``` + +##### Option C: With Atlas API credentials + +```shell +docker run --rm -i \ + -e MDB_MCP_API_CLIENT_ID="your-atlas-service-accounts-client-id" \ + -e MDB_MCP_API_CLIENT_SECRET="your-atlas-service-accounts-client-secret" \ + mongodb/mongodb-mcp-server:latest +``` + +##### Docker in MCP Configuration File + +Without options: + +```json +{ + "mcpServers": { + "MongoDB": { + "command": "docker", + "args": ["run", "--rm", "-i", "mongodb/mongodb-mcp-server:latest"] + } + } +} +``` + +With connection string: + +```json +{ + "mcpServers": { + "MongoDB": { + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "-e", + "MDB_MCP_CONNECTION_STRING=mongodb+srv://username:password@cluster.mongodb.net/myDatabase", + "mongodb/mongodb-mcp-server:latest" + ] + } + } +} +``` + +With Atlas API credentials: + +```json +{ + "mcpServers": { + "MongoDB": { + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "-e", + "MDB_MCP_API_CLIENT_ID=your-atlas-service-accounts-client-id", + "-e", + "MDB_MCP_API_CLIENT_SECRET=your-atlas-service-accounts-client-secret", + "mongodb/mongodb-mcp-server:latest" + ] + } + } +} +``` + ## 🛠️ Supported Tools ### Tool List @@ -125,7 +222,8 @@ You can use environment variables in the config file or set them and run the ser - `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 +- `atlas-create-db-user` - Creates a MongoDB Atlas database user +- `atlas-list-alerts` - List MongoDB Atlas Alerts for a Project NOTE: atlas tools are only available when you set credentials on [configuration](#configuration) section. @@ -161,15 +259,15 @@ The MongoDB MCP Server can be configured using multiple methods, with the follow ### Configuration Options -| Option | Description | -| ------------------ | --------------------------------------------------------------------------------------------------------------------- | -| `apiClientId` | Atlas API client ID for authentication | -| `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 | -| `readOnly` | When set to true, only allows read and metadata operation types, disabling create/update/delete operations | -| `telemetry` | When set to disabled, disables telemetry collection | +| Option | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `apiClientId` | Atlas API client ID for authentication. Required for running Atlas tools. | +| `apiClientSecret` | Atlas API client secret for authentication. Required for running Atlas tools. | +| `connectionString` | MongoDB connection string for direct database connections. Optional, if not set, you'll need to call the `connect` tool before interacting with MongoDB data. | +| `logPath` | Folder to store logs. | +| `disabledTools` | An array of tool names, operation types, and/or categories of tools that will be disabled. | +| `readOnly` | When set to true, only allows read and metadata operation types, disabling create/update/delete operations. | +| `telemetry` | When set to disabled, disables telemetry collection. | #### Log Path @@ -228,13 +326,16 @@ You can disable telemetry using: To use the Atlas API tools, you'll need to create a service account in MongoDB Atlas: +> **ℹ️ Note:** For a detailed breakdown of the minimum required permissions for each Atlas operation, see the [Atlas API Permissions](#atlas-api-permissions) section below. + 1. **Create a Service Account:** - Log in to MongoDB Atlas at [cloud.mongodb.com](https://cloud.mongodb.com) - Navigate to Access Manager > Organization Access - Click Add New > Applications > Service Accounts - Enter name, description and expiration for your service account (e.g., "MCP, MCP Server Access, 7 days") - - Select appropriate permissions (for full access, use Organization Owner) + - **Assign only the minimum permissions needed for your use case.** + - See [Atlas API Permissions](#atlas-api-permissions) for details. - Click "Create" To learn more about Service Accounts, check the [MongoDB Atlas documentation](https://www.mongodb.com/docs/atlas/api/service-accounts-overview/). @@ -251,6 +352,26 @@ To learn more about Service Accounts, check the [MongoDB Atlas documentation](ht 4. **Configure the MCP Server:** - Use one of the configuration methods below to set your `apiClientId` and `apiClientSecret` +### Atlas API Permissions + +> **Security Warning:** Granting the Organization Owner role is rarely necessary and can be a security risk. Assign only the minimum permissions needed for your use case. + +#### Quick Reference: Required roles per operation + +| What you want to do | Safest Role to Assign (where) | +| ------------------------------------ | --------------------------------------- | +| List orgs/projects | Org Member or Org Read Only (Org) | +| Create new projects | Org Project Creator (Org) | +| View clusters/databases in a project | Project Read Only (Project) | +| Create/manage clusters in a project | Project Cluster Manager (Project) | +| Manage project access lists | Project IP Access List Admin (Project) | +| Manage database users | Project Database Access Admin (Project) | + +- **Prefer project-level roles** for most operations. Assign only to the specific projects you need to manage or view. +- **Avoid Organization Owner** unless you require full administrative control over all projects and settings in the organization. + +For a full list of roles and their privileges, see the [Atlas User Roles documentation](https://www.mongodb.com/docs/atlas/reference/user-roles/#service-user-roles). + ### Configuration Methods #### Environment Variables diff --git a/package-lock.json b/package-lock.json index 62b03158..041de7d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "mongodb-mcp-server", - "version": "0.1.1", + "version": "0.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mongodb-mcp-server", - "version": "0.1.1", + "version": "0.1.2", "license": "Apache-2.0", "dependencies": { - "@modelcontextprotocol/sdk": "^1.8.0", + "@modelcontextprotocol/sdk": "^1.11.2", "@mongodb-js/device-id": "^0.2.1", "@mongodb-js/devtools-connect": "^3.7.2", "@mongosh/service-provider-node-driver": "^3.6.0", @@ -21,9 +21,9 @@ "mongodb-redact": "^1.1.6", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", - "openapi-fetch": "^0.13.5", + "openapi-fetch": "^0.14.0", "simple-oauth2": "^5.1.0", - "yargs-parser": "^21.1.1", + "yargs-parser": "^22.0.0", "zod": "^3.24.2" }, "bin": { @@ -31,8 +31,8 @@ }, "devDependencies": { "@eslint/js": "^9.24.0", - "@jest/globals": "^29.7.0", - "@modelcontextprotocol/inspector": "^0.10.2", + "@jest/globals": "^30.0.0", + "@modelcontextprotocol/inspector": "^0.14.0", "@redocly/cli": "^1.34.2", "@types/jest": "^29.5.14", "@types/node": "^22.14.0", @@ -45,7 +45,7 @@ "globals": "^16.0.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", - "jest-extended": "^4.0.2", + "jest-extended": "^6.0.0", "mongodb-runner": "^5.8.2", "openapi-types": "^12.1.3", "openapi-typescript": "^7.6.1", @@ -57,7 +57,7 @@ "yaml": "^2.7.1" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.10.0" } }, "node_modules/@ampproject/remapping": { @@ -725,24 +725,24 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz", + "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==", "dev": true, "license": "MIT", "engines": { @@ -750,22 +750,22 @@ } }, "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.4", + "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -791,14 +791,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -808,14 +808,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", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -852,29 +852,29 @@ "license": "ISC" }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" }, "engines": { "node": ">=6.9.0" @@ -884,9 +884,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, "license": "MIT", "engines": { @@ -894,9 +894,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { @@ -904,9 +904,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "license": "MIT", "engines": { @@ -914,9 +914,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", "engines": { @@ -924,27 +924,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -1051,13 +1051,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1177,13 +1177,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1193,45 +1193,42 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", "dev": true, "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1250,14 +1247,14 @@ } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1933,13 +1930,16 @@ } }, "node_modules/@eslint/js": { - "version": "9.26.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", - "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "version": "9.28.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", + "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -1985,9 +1985,9 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz", - "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", + "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", "dev": true, "license": "MIT", "dependencies": { @@ -1995,20 +1995,20 @@ } }, "node_modules/@floating-ui/dom": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", - "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.1.tgz", + "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", + "@floating-ui/core": "^1.7.1", "@floating-ui/utils": "^0.2.9" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.3.tgz", + "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", "dev": true, "license": "MIT", "dependencies": { @@ -2339,6 +2339,16 @@ } } }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.0.tgz", + "integrity": "sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -2400,20 +2410,497 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/get-type": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.0.tgz", + "integrity": "sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.0.tgz", + "integrity": "sha512-OEzYes5A1xwBJVMPqFRa8NCao8Vr42nsUZuf/SpaJWoLE+4kyl6nCQZ1zqfipmCrIXQVALC5qJwKy/7NQQLPhw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "@jest/environment": "30.0.0", + "@jest/expect": "30.0.0", + "@jest/types": "30.0.0", + "jest-mock": "30.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/environment": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.0.tgz", + "integrity": "sha512-09sFbMMgS5JxYnvgmmtwIHhvoyzvR5fUPrVl8nOCrC5KdzmmErTcAxfWyAhJ2bv3rvHNQaKiS+COSG+O7oNbXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "jest-mock": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/expect": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.0.tgz", + "integrity": "sha512-XZ3j6syhMeKiBknmmc8V3mNIb44kxLTbOQtaXA4IFdHy+vEN0cnXRzbRjdGBtrp4k1PWyMWNU3Fjz3iejrhpQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.0.0", + "jest-snapshot": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/expect-utils": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.0.tgz", + "integrity": "sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/fake-timers": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.0.tgz", + "integrity": "sha512-yzBmJcrMHAMcAEbV2w1kbxmx8WFpEz8Cth3wjLMSkq+LO8VeGKRhpr5+BUp7PPK+x4njq/b6mVnDR8e/tPL5ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.0", + "jest-mock": "30.0.0", + "jest-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/schemas": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.0.tgz", + "integrity": "sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/transform": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.0.tgz", + "integrity": "sha512-8xhpsCGYJsUjqpJOgLyMkeOSSlhqggFZEWAnZquBsvATtueoEs7CkMRxOUmJliF3E5x+mXmZ7gEEsHank029Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.0.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.0", + "jest-regex-util": "30.0.0", + "jest-util": "30.0.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/types": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.0.tgz", + "integrity": "sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.0", + "@jest/schemas": "30.0.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@sinclair/typebox": { + "version": "0.34.35", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.35.tgz", + "integrity": "sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/globals/node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@jest/globals/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/globals/node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/globals/node_modules/ci-info": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", + "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/globals/node_modules/expect": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.0.tgz", + "integrity": "sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.0.0", + "@jest/get-type": "30.0.0", + "jest-matcher-utils": "30.0.0", + "jest-message-util": "30.0.0", + "jest-mock": "30.0.0", + "jest-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-diff": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.0.tgz", + "integrity": "sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.0", + "@jest/get-type": "30.0.0", + "chalk": "^4.1.2", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-haste-map": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.0.tgz", + "integrity": "sha512-p4bXAhXTawTsADgQgTpbymdLaTyPW1xWNu1oIGG7/N3LIAbZVkH2JMJqS8/IUcnGR8Kc7WFE+vWbJvsqGCWZXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.0", + "jest-util": "30.0.0", + "jest-worker": "30.0.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/@jest/globals/node_modules/jest-matcher-utils": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.0.tgz", + "integrity": "sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0", + "chalk": "^4.1.2", + "jest-diff": "30.0.0", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-message-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.0.tgz", + "integrity": "sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-mock": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.0.tgz", + "integrity": "sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "jest-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-regex-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.0.tgz", + "integrity": "sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-snapshot": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.0.tgz", + "integrity": "sha512-6oCnzjpvfj/UIOMTqKZ6gedWAUgaycMdV8Y8h2dRJPvc2wSjckN03pzeoonw8y33uVngfx7WMo1ygdRGEKOT7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.0", + "@jest/get-type": "30.0.0", + "@jest/snapshot-utils": "30.0.0", + "@jest/transform": "30.0.0", + "@jest/types": "30.0.0", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.0", + "jest-matcher-utils": "30.0.0", + "jest-message-util": "30.0.0", + "jest-util": "30.0.0", + "pretty-format": "30.0.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.0.tgz", + "integrity": "sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-worker": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.0.tgz", + "integrity": "sha512-VZvxfWIybIvwK8N/Bsfe43LfQgd/rD0c4h5nLUx78CAqPxIQcW2qDjsVAC53iUR8yxzFIeCFFvWOh8en8hGzdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/globals/node_modules/pretty-format": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.0.tgz", + "integrity": "sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.0", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/globals/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/globals/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.0.tgz", + "integrity": "sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern/node_modules/jest-regex-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.0.tgz", + "integrity": "sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/reporters": { @@ -2473,6 +2960,61 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/snapshot-utils": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.0.tgz", + "integrity": "sha512-C/QSFUmvZEYptg2Vin84FggAphwHvj6la39vkw1CNOZQORWZ7O/H0BXmdeeeGnvlXDYY8TlFM5jgFnxLAxpFjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils/node_modules/@jest/schemas": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.0.tgz", + "integrity": "sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils/node_modules/@jest/types": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.0.tgz", + "integrity": "sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.0", + "@jest/schemas": "30.0.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils/node_modules/@sinclair/typebox": { + "version": "0.34.35", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.35.tgz", + "integrity": "sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==", + "dev": true, + "license": "MIT" + }, "node_modules/@jest/source-map": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", @@ -2645,9 +3187,9 @@ } }, "node_modules/@modelcontextprotocol/inspector": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector/-/inspector-0.10.2.tgz", - "integrity": "sha512-P/ag1MJz7mdOpmlE5OUozehzw0AYDi1cuXUctcPBpNvbufpnmmIwpD79I0lN41ydH1vnH4c8MTork75KWmP/hQ==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector/-/inspector-0.14.1.tgz", + "integrity": "sha512-F9Xd/06eCfeuHkFR+6sNGhGrKAfgXFmf9VDzw+hMMoeJM3ltOUSJh/fqCvvM6tGrxvb49uAF7dr/o5Dz+rVKxw==", "dev": true, "license": "MIT", "workspaces": [ @@ -2656,11 +3198,12 @@ "cli" ], "dependencies": { - "@modelcontextprotocol/inspector-cli": "^0.10.2", - "@modelcontextprotocol/inspector-client": "^0.10.2", - "@modelcontextprotocol/inspector-server": "^0.10.2", - "@modelcontextprotocol/sdk": "^1.10.0", + "@modelcontextprotocol/inspector-cli": "^0.14.1", + "@modelcontextprotocol/inspector-client": "^0.14.1", + "@modelcontextprotocol/inspector-server": "^0.14.1", + "@modelcontextprotocol/sdk": "^1.12.1", "concurrently": "^9.0.1", + "open": "^10.1.0", "shell-quote": "^1.8.2", "spawn-rx": "^5.1.2", "ts-node": "^10.9.2", @@ -2671,13 +3214,13 @@ } }, "node_modules/@modelcontextprotocol/inspector-cli": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector-cli/-/inspector-cli-0.10.2.tgz", - "integrity": "sha512-PE5U1py8lj2TjgB705H6ENl/khQAjEskQ+HzfqGhYZ2xXO9DC7meJahbxa8NyEh5vLXweKc0Inj3tLtGpL88uQ==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector-cli/-/inspector-cli-0.14.1.tgz", + "integrity": "sha512-PDXugYewCHnhfEmoMLczJ/rtniCJN9evFkJZVq9o1CVBHme578V3MIT7uk4ap/M6xM26+9OAixdbYp9Rf7V8VA==", "dev": true, "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.10.0", + "@modelcontextprotocol/sdk": "^1.12.1", "commander": "^13.1.0", "spawn-rx": "^5.1.2" }, @@ -2686,13 +3229,13 @@ } }, "node_modules/@modelcontextprotocol/inspector-client": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector-client/-/inspector-client-0.10.2.tgz", - "integrity": "sha512-gZfdkhtLEVjQslzKyyxTppm4iV2psuw6hkTtx+RULEopj+0dwE3mX4Ddl4uGcrz6eNv0bj/u7DE6azISIHSGXA==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector-client/-/inspector-client-0.14.1.tgz", + "integrity": "sha512-nJym4J7R3xChNSDYBdfRyI/r4eS0uUl85/GQxIi4STnNJI6ajv6sicCWx5uRL74Ed5GFME9SS/xI3Tdm+aqtrg==", "dev": true, "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.10.0", + "@modelcontextprotocol/sdk": "^1.12.1", "@radix-ui/react-checkbox": "^1.1.4", "@radix-ui/react-dialog": "^1.1.3", "@radix-ui/react-icons": "^1.3.0", @@ -2703,6 +3246,7 @@ "@radix-ui/react-tabs": "^1.1.1", "@radix-ui/react-toast": "^1.2.6", "@radix-ui/react-tooltip": "^1.1.8", + "ajv": "^6.12.6", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "cmdk": "^1.0.4", @@ -2717,36 +3261,155 @@ "tailwindcss-animate": "^1.0.7", "zod": "^3.23.8" }, - "bin": { - "mcp-inspector-client": "bin/start.js" + "bin": { + "mcp-inspector-client": "bin/start.js" + } + }, + "node_modules/@modelcontextprotocol/inspector-client/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/@modelcontextprotocol/inspector-client/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/@modelcontextprotocol/inspector-server": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector-server/-/inspector-server-0.14.1.tgz", + "integrity": "sha512-w9VTdqzHHYBOOQw0QJa2QB/tn6dTZsDSGO3d4a5BJile4It283Lw1xi1W1pMgNB+MTEG471disU/qJapqETK6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.12.1", + "cors": "^2.8.5", + "express": "^5.1.0", + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "bin": { + "mcp-inspector-server": "build/index.js" + } + }, + "node_modules/@modelcontextprotocol/inspector/node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/inspector/node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/inspector/node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/inspector/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@modelcontextprotocol/inspector-server": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/inspector-server/-/inspector-server-0.10.2.tgz", - "integrity": "sha512-VXXMIdOlzyZ0eGG22glkfMH1cWOoHqrgEN6QvFaleXvRSaCp5WVe3M2gLXOyHRFVHimrDWKsGB0NjeXxb6xYuw==", + "node_modules/@modelcontextprotocol/inspector/node_modules/open": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", "dev": true, "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.10.0", - "cors": "^2.8.5", - "express": "^5.1.0", - "ws": "^8.18.0", - "zod": "^3.23.8" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" }, - "bin": { - "mcp-inspector-server": "build/index.js" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/inspector/node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "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==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.1.tgz", + "integrity": "sha512-KG1CZhZfWg+u8pxeM/mByJDScJSrjjxLc8fwQqbsS8xCjBmQfMNEBTotYdNanKekepnfRI85GtgQlctLFpcYPw==", "license": "MIT", "dependencies": { + "ajv": "^6.12.6", "content-type": "^1.0.5", "cors": "^2.8.5", - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", @@ -2759,6 +3422,28 @@ "node": ">=18" } }, + "node_modules/@modelcontextprotocol/sdk/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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/@modelcontextprotocol/sdk/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==", + "license": "MIT" + }, "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", @@ -2818,15 +3503,15 @@ } }, "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==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.4.0.tgz", + "integrity": "sha512-+xBDhZQn+tGY8bWZo9gE+Nd6Mw2r6TQWaLbgGw/H50M5ky092IS4vbTjwvJhR2m/efoxj31LZpZI0PYK7Pzu6w==", "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.4.0", "decompress": "^4.2.1", - "mongodb-download-url": "^1.5.7", + "mongodb-download-url": "^1.6.0", "node-fetch": "^2.7.0", "tar": "^6.1.15" } @@ -2884,9 +3569,9 @@ "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==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@mongodb-js/oidc-plugin/-/oidc-plugin-1.1.7.tgz", + "integrity": "sha512-+90E2JFrJuMk1dlT/LlZ4yaJj0Xtc6Qcf7FXphgu2j+EElWY/8y/GalFqf/KC/Wd1qt8EuR8Jnr6Pq+Q+ptASg==", "license": "Apache-2.0", "dependencies": { "express": "^4.18.2", @@ -3207,9 +3892,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.2.tgz", - "integrity": "sha512-EB0O3SCSNRUFk66iRCpI+cXzIjdswfCs7F6nOC3RAGJ7xr5YhaicvsRwJ9eyzYvYRlCSDUO/c7g4yNulxKC1WA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", + "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" @@ -3237,15 +3922,15 @@ } }, "node_modules/@mongosh/service-provider-core": { - "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==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@mongosh/service-provider-core/-/service-provider-core-3.3.3.tgz", + "integrity": "sha512-Cylm0JjY0iu2C91o3koGNDtx7WhhFhCo+zWSxD5+aFiuAxrQQEmVxqLGFB9QTHwUotsdk2i7zi2lMdYVtCnkCA==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/credential-providers": "^3.525.0", "@mongosh/errors": "2.4.0", "bson": "^6.10.3", - "mongodb": "^6.14.2", + "mongodb": "^6.16.0", "mongodb-build-info": "^1.7.2", "mongodb-connection-string-url": "^3.0.1" }, @@ -3257,18 +3942,18 @@ } }, "node_modules/@mongosh/service-provider-node-driver": { - "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==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/@mongosh/service-provider-node-driver/-/service-provider-node-driver-3.8.3.tgz", + "integrity": "sha512-/AN1tCy7T/wUA88M2CiUuUAZg6UxkzfJlfk3OvpN7EVezl+P80xSv2MW+MsHX9o3Qa8g6oDHog26bRqM7YehJQ==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/devtools-connect": "^3.4.1", - "@mongodb-js/oidc-plugin": "^1.1.6", + "@mongodb-js/oidc-plugin": "^1.1.7", "@mongosh/errors": "2.4.0", - "@mongosh/service-provider-core": "3.3.0", - "@mongosh/types": "3.6.0", + "@mongosh/service-provider-core": "3.3.3", + "@mongosh/types": "3.6.2", "aws4": "^1.12.0", - "mongodb": "^6.14.2", + "mongodb": "^6.16.0", "mongodb-connection-string-url": "^3.0.1", "socks": "^2.8.3" }, @@ -3331,9 +4016,9 @@ } }, "node_modules/@mongosh/types": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@mongosh/types/-/types-3.6.0.tgz", - "integrity": "sha512-p6NXCTa4FjjTQAQJk9OehfXKFIE/vdQJOqcMbVR3Cxg2zVCnfV16NDnuxpFHYnLkgqL9Cz10BtUGSZPDMFJXew==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@mongosh/types/-/types-3.6.2.tgz", + "integrity": "sha512-3qqXkdwQYVB+/u7AR1nqlUxY8QaM7O2m15/CH55n7iAlIlAgwtuSjB+DLXOBNxh4AcCPcakyilWIlZr6pCpkgA==", "license": "Apache-2.0", "dependencies": { "@mongodb-js/devtools-connect": "^3.4.1" @@ -3625,9 +4310,9 @@ } }, "node_modules/@pkgr/core": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", - "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", "dev": true, "license": "MIT", "engines": { @@ -3726,13 +4411,13 @@ "license": "MIT" }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.4.tgz", - "integrity": "sha512-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.0" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -3750,9 +4435,9 @@ } }, "node_modules/@radix-ui/react-checkbox": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.2.3.tgz", - "integrity": "sha512-pHVzDYsnaDmBlAuwim45y3soIN8H4R7KbkSVirGhXO+R/kO2OLCe0eucUEbddaTcdMHHdzcIGHtZSMSQlA+apw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.2.tgz", + "integrity": "sha512-yd+dI56KZqawxKZrJ31eENUwqc1QSqg4OZ15rybGjF2ZNwMO+wCyHzAVLRp9qoYJf7kYy0YpZ2b0JCzJ42HZpA==", "dev": true, "license": "MIT", "dependencies": { @@ -3760,7 +4445,7 @@ "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-primitive": "2.1.3", "@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" @@ -3781,16 +4466,16 @@ } }, "node_modules/@radix-ui/react-collection": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.4.tgz", - "integrity": "sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", "dev": true, "license": "MIT", "dependencies": { "@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" + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -3840,23 +4525,23 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.11.tgz", - "integrity": "sha512-yI7S1ipkP5/+99qhSI6nthfo/tR6bL6Zgxi/+1UO6qPa6UeM6nlafWcQ65vB4rU2XjgjMfMhI3k9Y5MztA62VQ==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", + "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", "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-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.4", + "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.0", - "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" @@ -3893,15 +4578,15 @@ } }, "node_modules/@radix-ui/react-dismissable-layer": { - "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==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz", + "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==", "dev": true, "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, @@ -3937,14 +4622,14 @@ } }, "node_modules/@radix-ui/react-focus-scope": { - "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==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", "dev": true, "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { @@ -3992,13 +4677,13 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.4.tgz", - "integrity": "sha512-wy3dqizZnZVV4ja0FNnUhIWNwWdoldXrneEyUcVtLYDAt8ovGS4ridtMAOGgXBBIfggL4BOveVWsjXDORdGEQg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.0" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -4016,24 +4701,24 @@ } }, "node_modules/@radix-ui/react-popover": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.11.tgz", - "integrity": "sha512-yFMfZkVA5G3GJnBgb2PxrrcLKm1ZLWXrbYVgdyTl//0TYEIHS9LJbnyz7WWcZ0qCq7hIlJZpRtxeSeIG5T5oJw==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz", + "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==", "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-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.4", + "@radix-ui/react-focus-scope": "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-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.0", - "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" @@ -4054,17 +4739,17 @@ } }, "node_modules/@radix-ui/react-popper": { - "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==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz", + "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==", "dev": true, "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.4", + "@radix-ui/react-arrow": "1.1.7", "@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-primitive": "2.1.3", "@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", @@ -4087,13 +4772,13 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.6.tgz", - "integrity": "sha512-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { @@ -4137,13 +4822,13 @@ } }, "node_modules/@radix-ui/react-primitive": { - "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==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.2.0" + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -4161,19 +4846,19 @@ } }, "node_modules/@radix-ui/react-roving-focus": { - "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==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz", + "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==", "dev": true, "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-collection": "1.1.4", + "@radix-ui/react-collection": "1.1.7", "@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-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, @@ -4193,31 +4878,31 @@ } }, "node_modules/@radix-ui/react-select": { - "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==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz", + "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==", "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-collection": "1.1.7", "@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-dismissable-layer": "1.1.10", "@radix-ui/react-focus-guards": "1.1.2", - "@radix-ui/react-focus-scope": "1.1.4", + "@radix-ui/react-focus-scope": "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-primitive": "2.1.0", - "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", "@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", + "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, @@ -4237,9 +4922,9 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.0.tgz", - "integrity": "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "dev": true, "license": "MIT", "dependencies": { @@ -4256,9 +4941,9 @@ } }, "node_modules/@radix-ui/react-tabs": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.9.tgz", - "integrity": "sha512-KIjtwciYvquiW/wAFkELZCVnaNLBsYNhTNcvl+zfMAbMhRkcvNuCLXDDd22L0j7tagpzVh/QwbFpwAATg7ILPw==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz", + "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==", "dev": true, "license": "MIT", "dependencies": { @@ -4267,8 +4952,8 @@ "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.0", - "@radix-ui/react-roving-focus": "1.1.7", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { @@ -4287,24 +4972,24 @@ } }, "node_modules/@radix-ui/react-toast": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.11.tgz", - "integrity": "sha512-Ed2mlOmT+tktOsu2NZBK1bCSHh/uqULu1vWOkpQTVq53EoOuZUZw7FInQoDB3uil5wZc2oe0XN9a7uVZB7/6AQ==", + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.14.tgz", + "integrity": "sha512-nAP5FBxBJGQ/YfUB+r+O6USFVkWq3gAInkxyEnmvEV5jtSbfDhfa4hwX8CraCnbjMLsE7XSf/K75l9xXY7joWg==", "dev": true, "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", - "@radix-ui/react-collection": "1.1.4", + "@radix-ui/react-collection": "1.1.7", "@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-dismissable-layer": "1.1.10", + "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.0", + "@radix-ui/react-primitive": "2.1.3", "@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" + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -4322,24 +5007,24 @@ } }, "node_modules/@radix-ui/react-tooltip": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.4.tgz", - "integrity": "sha512-DyW8VVeeMSSLFvAmnVnCwvI3H+1tpJFHT50r+tdOoMse9XqYDBCcyux8u3G2y+LOpt7fPQ6KKH0mhs+ce1+Z5w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz", + "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", "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-dismissable-layer": "1.1.10", "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.4", - "@radix-ui/react-portal": "1.1.6", + "@radix-ui/react-popper": "1.2.7", + "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.4", - "@radix-ui/react-primitive": "2.1.0", - "@radix-ui/react-slot": "1.2.0", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-visually-hidden": "1.2.0" + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", @@ -4501,13 +5186,13 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "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==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.0" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", @@ -4549,9 +5234,9 @@ } }, "node_modules/@redocly/cli": { - "version": "1.34.2", - "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-1.34.2.tgz", - "integrity": "sha512-XnKG7yrr0GUZ7MyqHk9hRt//HGUSnLDwwEXI8HDQdyDFp+YFbddqcQPOWc/sDeDBTEiBXqwPOb3/VKA+8NtSMw==", + "version": "1.34.3", + "resolved": "https://registry.npmjs.org/@redocly/cli/-/cli-1.34.3.tgz", + "integrity": "sha512-GJNBTMfm5wTCtH6K+RtPQZuGbqflMclXqAZ5My12tfux6xFDMW1l0MNd5RMpnIS1aeFcDX++P1gnnROWlesj4w==", "dev": true, "license": "MIT", "dependencies": { @@ -4561,8 +5246,8 @@ "@opentelemetry/sdk-trace-node": "1.26.0", "@opentelemetry/semantic-conventions": "1.27.0", "@redocly/config": "^0.22.0", - "@redocly/openapi-core": "1.34.2", - "@redocly/respect-core": "1.34.2", + "@redocly/openapi-core": "1.34.3", + "@redocly/respect-core": "1.34.3", "abort-controller": "^3.0.0", "chokidar": "^3.5.1", "colorette": "^1.2.0", @@ -4576,7 +5261,7 @@ "pluralize": "^8.0.0", "react": "^17.0.0 || ^18.2.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.2.0 || ^19.0.0", - "redoc": "2.4.0", + "redoc": "2.5.0", "semver": "^7.5.2", "simple-websocket": "^9.0.0", "styled-components": "^6.0.7", @@ -4599,9 +5284,9 @@ "license": "MIT" }, "node_modules/@redocly/openapi-core": { - "version": "1.34.2", - "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.2.tgz", - "integrity": "sha512-glfkQFJizLdq2fBkNvc2FJW0sxDb5exd0wIXhFk+WHaFLMREBC3CxRo2Zq7uJIdfV9U3YTceMbXJklpDfmmwFQ==", + "version": "1.34.3", + "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.3.tgz", + "integrity": "sha512-3arRdUp1fNx55itnjKiUhO6t4Mf91TsrTIYINDNLAZPS0TPd5YpiXRctwjel0qqWoOOhjA34cZ3m4dksLDFUYg==", "dev": true, "license": "MIT", "dependencies": { @@ -4621,15 +5306,15 @@ } }, "node_modules/@redocly/respect-core": { - "version": "1.34.2", - "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-1.34.2.tgz", - "integrity": "sha512-X6VR9bbHXrI01Wh5t6TIHxFCVHcP4Iy42micKLIk/Cg6EmHVbaSDGOD6mxChXtEIrwnY+bqyUbjlXr9+YM7B9A==", + "version": "1.34.3", + "resolved": "https://registry.npmjs.org/@redocly/respect-core/-/respect-core-1.34.3.tgz", + "integrity": "sha512-vo/gu7dRGwTVsRueVSjVk04jOQuL0w22RBJRdRUWkfyse791tYXgMCOx35ijKekL83Q/7Okxf/YX6UY1v5CAug==", "dev": true, "license": "MIT", "dependencies": { "@faker-js/faker": "^7.6.0", "@redocly/ajv": "8.11.2", - "@redocly/openapi-core": "1.34.2", + "@redocly/openapi-core": "1.34.3", "better-ajv-errors": "^1.2.0", "colorette": "^2.0.20", "concat-stream": "^2.0.0", @@ -4773,9 +5458,9 @@ } }, "node_modules/@redocly/respect-core/node_modules/open": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.1.tgz", - "integrity": "sha512-zy1wx4+P3PfhXSEPJNtZmJXfhkkIaxU1VauWIrDZw1O7uJRDRJtKr9n3Ic4NgbA16KyOxOXO2ng9gYwCdXuSXA==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz", + "integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==", "dev": true, "license": "MIT", "dependencies": { @@ -5565,9 +6250,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.9.tgz", - "integrity": "sha512-l6QaCgJSJQ0HngL1TjvEY2DlefKggyGeXP1KYvYLBX41ZDPM1FsgDMAr5c+T673NMy7VCptMOzXOuJqf5uB0bA==", + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", "dev": true, "license": "MIT", "dependencies": { @@ -5636,19 +6321,19 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", - "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.0.tgz", + "integrity": "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/type-utils": "8.32.0", - "@typescript-eslint/utils": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/type-utils": "8.34.0", + "@typescript-eslint/utils": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, @@ -5660,22 +6345,32 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.34.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", - "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.0.tgz", + "integrity": "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4" }, "engines": { @@ -5690,33 +6385,72 @@ "typescript": ">=4.8.4 <5.9.0" } }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.0.tgz", + "integrity": "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.34.0", + "@typescript-eslint/types": "^8.34.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", - "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.0.tgz", + "integrity": "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0" + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.0.tgz", + "integrity": "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==", + "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", - "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.0.tgz", + "integrity": "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/typescript-estree": "8.34.0", + "@typescript-eslint/utils": "8.34.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -5733,9 +6467,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", - "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.0.tgz", + "integrity": "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==", "dev": true, "license": "MIT", "engines": { @@ -5747,14 +6481,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", - "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.0.tgz", + "integrity": "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/project-service": "8.34.0", + "@typescript-eslint/tsconfig-utils": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -5790,16 +6526,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.0.tgz", + "integrity": "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0" + "@typescript-eslint/scope-manager": "8.34.0", + "@typescript-eslint/types": "8.34.0", + "@typescript-eslint/typescript-estree": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5814,13 +6550,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", - "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.0.tgz", + "integrity": "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/types": "8.34.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -5831,6 +6567,13 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -6001,9 +6744,9 @@ "license": "Python-2.0" }, "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "dev": true, "license": "MIT", "dependencies": { @@ -6390,9 +7133,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "dev": true, "funding": [ { @@ -6410,10 +7153,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -6446,9 +7189,9 @@ } }, "node_modules/bson": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.3.tgz", - "integrity": "sha512-MTxGsqgYTwfshYWTRdmZRC+M7FnG1b4y7RO7p2k3X24Wq0yv1m77Wsj0BzlPzd/IowgESfsruQCUToa7vbOpPQ==", + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", "license": "Apache-2.0", "engines": { "node": ">=16.20.1" @@ -6621,9 +7364,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001715", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", - "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "dev": true, "funding": [ { @@ -6981,6 +7724,16 @@ "node": ">=12" } }, + "node_modules/concurrently/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/content-disposition": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", @@ -7028,9 +7781,9 @@ } }, "node_modules/core-js": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", - "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", + "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7711,9 +8464,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.144", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.144.tgz", - "integrity": "sha512-eJIaMRKeAzxfBSxtjYnoIAw/tdD6VIH6tHBZepZnAbE3Gyqqs5mGN87DvcldPUbVkIljTK8pY0CMcUljP64lfQ==", + "version": "1.5.168", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.168.tgz", + "integrity": "sha512-RUNQmFLNIWVW6+z32EJQ5+qx8ci6RGvdtDC0Ls+F89wz6I2AthpXF0w0DIrn2jpLX0/PU9ZCo+Qp7bg/EckJmA==", "dev": true, "license": "ISC" }, @@ -7974,22 +8727,25 @@ } }, "node_modules/eslint-config-prettier": { - "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==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-plugin-jest": { - "version": "28.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.11.0.tgz", - "integrity": "sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==", + "version": "28.12.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.12.0.tgz", + "integrity": "sha512-J6zmDp8WiQ9tyvYXE+3RFy7/+l4hraWLzmsabYXyehkmmDd36qV4VQFc7XzcsD8C1PTNt646MSx25bO1mdd9Yw==", "dev": true, "license": "MIT", "dependencies": { @@ -8013,14 +8769,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz", - "integrity": "sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz", + "integrity": "sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.11.0" + "synckit": "^0.11.7" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -8073,6 +8829,16 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", + "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -8376,7 +9142,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -8407,7 +9172,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -8964,9 +9728,9 @@ } }, "node_modules/globals": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.0.0.tgz", - "integrity": "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==", + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", + "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", "dev": true, "license": "MIT", "engines": { @@ -9755,6 +10519,16 @@ "node": ">=12" } }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -9866,24 +10640,27 @@ } }, "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==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-6.0.0.tgz", + "integrity": "sha512-SM249N/q33YQ9XE8E06qZSnFuuV4GQFx7WrrmIj4wQUAP43jAo6budLT482jdBhf8ASwUiEEfJNjej0UusYs5A==", "dev": true, "license": "MIT", "dependencies": { - "jest-diff": "^29.0.0", - "jest-get-type": "^29.0.0" + "jest-diff": "^29.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^18.12.0 || ^20.9.0 || ^22.11.0 || >=23.0.0" }, "peerDependencies": { - "jest": ">=27.2.5" + "jest": ">=27.2.5", + "typescript": ">=5.0.0" }, "peerDependenciesMeta": { "jest": { "optional": true + }, + "typescript": { + "optional": false } } }, @@ -10119,6 +10896,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-runtime/node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -11003,9 +11796,9 @@ } }, "node_modules/mongodb-download-url": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.5.7.tgz", - "integrity": "sha512-GpQJAfYmfYwqVXUyfIUQXe5kFoiCK5kORBJnPixAmQGmabZix6fBTpX7vSy3J46VgiAe+VEOjSikK/TcGKTw+A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.6.0.tgz", + "integrity": "sha512-IQcQfKi3zdejKIAPaCpsW2F1FpMBsdifzY5K0YdddmJSFDJAGY7xUbCVm0pdL36+1ck6+c2ytTSqzProLhvGoA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -11090,14 +11883,14 @@ "license": "Apache-2.0" }, "node_modules/mongodb-runner": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.8.3.tgz", - "integrity": "sha512-LLmbE9A/aGqABaaTmxFJ+TiHjmhZx1kZRLV14nFLvBz2zV3F/rLBo9kJ/Pz00h0IYk3zi7abL82I+WKZVzkoSQ==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.9.0.tgz", + "integrity": "sha512-31oyYEmLvkuqDV9J9kuwwOE2SHV1LaPyqr+fZsgYT56ceynqq4ABUOXmmdZBXm3zdLM1QGUft5UJokkkhXGPCQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@mongodb-js/mongodb-downloader": "^0.3.9", - "@mongodb-js/saslprep": "^1.2.2", + "@mongodb-js/mongodb-downloader": "^0.4.0", + "@mongodb-js/saslprep": "^1.3.0", "debug": "^4.4.0", "mongodb": "^6.9.0", "mongodb-connection-string-url": "^3.0.0", @@ -11141,6 +11934,16 @@ "node": ">=12" } }, + "node_modules/mongodb-runner/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/mongodb-schema": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/mongodb-schema/-/mongodb-schema-12.6.2.tgz", @@ -11198,6 +12001,16 @@ "node": ">=12" } }, + "node_modules/mongodb-schema/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -11601,9 +12414,9 @@ } }, "node_modules/openapi-fetch": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.13.5.tgz", - "integrity": "sha512-AQK8T9GSKFREFlN1DBXTYsLjs7YV2tZcJ7zUWxbjMoQmj8dDSFRrzhLCbHPZWA1TMV3vACqfCxLEZcwf2wxV6Q==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.14.0.tgz", + "integrity": "sha512-PshIdm1NgdLvb05zp8LqRQMNSKzIlPkyMxYFxwyHR+UlKD4t2nUjkDhNxeRbhRSEd3x5EUNh2w5sJYwkhOH4fg==", "license": "MIT", "dependencies": { "openapi-typescript-helpers": "^0.0.15" @@ -11648,17 +12461,17 @@ "license": "MIT" }, "node_modules/openapi-typescript": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.6.1.tgz", - "integrity": "sha512-F7RXEeo/heF3O9lOXo2bNjCOtfp7u+D6W3a3VNEH2xE6v+fxLtn5nq0uvUcA1F5aT+CMhNeC5Uqtg5tlXFX/ag==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.8.0.tgz", + "integrity": "sha512-1EeVWmDzi16A+siQlo/SwSGIT7HwaFAVjvMA7/jG5HMLSnrUOzPL7uSTRZZa4v/LCRxHTApHKtNY6glApEoiUQ==", "dev": true, "license": "MIT", "dependencies": { - "@redocly/openapi-core": "^1.28.0", + "@redocly/openapi-core": "^1.34.3", "ansi-colors": "^4.1.3", "change-case": "^5.4.4", - "parse-json": "^8.1.0", - "supports-color": "^9.4.0", + "parse-json": "^8.3.0", + "supports-color": "^10.0.0", "yargs-parser": "^21.1.1" }, "bin": { @@ -11693,13 +12506,13 @@ } }, "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", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.0.0.tgz", + "integrity": "sha512-HRVVSbCCMbj7/kdWF9Q+bbckjBHLtHMEoJWlkmYzzdwhYMkjkOwubLM6t7NbWKjgKamGDrWL1++KrjUO1t9oAQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" @@ -11718,6 +12531,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-typescript/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/openid-client": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", @@ -12540,9 +13363,9 @@ "license": "MIT" }, "node_modules/react-remove-scroll": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz", - "integrity": "sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", "dev": true, "license": "MIT", "dependencies": { @@ -12665,16 +13488,16 @@ } }, "node_modules/redoc": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.4.0.tgz", - "integrity": "sha512-rFlfzFVWS9XJ6aYAs/bHnLhHP5FQEhwAHDBVgwb9L2FqDQ8Hu8rQ1G84iwaWXxZfPP9UWn7JdWkxI6MXr2ZDjw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.5.0.tgz", + "integrity": "sha512-NpYsOZ1PD9qFdjbLVBZJWptqE+4Y6TkUuvEOqPUmoH7AKOmPcE+hYjotLxQNTqVoWL4z0T2uxILmcc8JGDci+Q==", "dev": true, "license": "MIT", "dependencies": { "@redocly/openapi-core": "^1.4.0", "classnames": "^2.3.2", "decko": "^1.2.0", - "dompurify": "^3.0.6", + "dompurify": "^3.2.4", "eventemitter3": "^5.0.1", "json-pointer": "^0.6.2", "lunr": "^2.3.9", @@ -12715,13 +13538,6 @@ "url": "https://github.com/Mermade/oas-kit?sponsor=1" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -12969,9 +13785,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "devOptional": true, "license": "ISC", "bin": { @@ -13020,9 +13836,9 @@ } }, "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==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -13716,9 +14532,9 @@ "license": "MIT" }, "node_modules/styled-components": { - "version": "6.1.17", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.17.tgz", - "integrity": "sha512-97D7DwWanI7nN24v0D4SvbfjLE9656umNSJZkBkDIWL37aZqG/wRQ+Y9pWtXyBIM/NSfcBzHLErEsqHmJNSVUg==", + "version": "6.1.18", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.18.tgz", + "integrity": "sha512-Mvf3gJFzZCkhjY2Y/Fx9z1m3dxbza0uI9H1CbNZm/jSHCojzJhQ0R7bByrlFJINnMzz/gPulpoFFGymNwrsMcw==", "dev": true, "license": "MIT", "dependencies": { @@ -13869,14 +14685,13 @@ } }, "node_modules/synckit": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz", - "integrity": "sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.3", - "tslib": "^2.8.1" + "@pkgr/core": "^0.2.4" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -13907,9 +14722,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.4.tgz", - "integrity": "sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz", + "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==", "dev": true, "license": "MIT", "peer": true @@ -13943,9 +14758,9 @@ } }, "node_modules/tar-fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz", - "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", "license": "MIT", "optional": true, "dependencies": { @@ -14173,21 +14988,20 @@ } }, "node_modules/ts-jest": { - "version": "29.3.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz", - "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==", + "version": "29.4.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz", + "integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==", "dev": true, "license": "MIT", "dependencies": { "bs-logger": "^0.2.6", "ejs": "^3.1.10", "fast-json-stable-stringify": "^2.1.0", - "jest-util": "^29.0.0", "json5": "^2.2.3", "lodash.memoize": "^4.1.2", "make-error": "^1.3.6", - "semver": "^7.7.1", - "type-fest": "^4.39.1", + "semver": "^7.7.2", + "type-fest": "^4.41.0", "yargs-parser": "^21.1.1" }, "bin": { @@ -14198,10 +15012,11 @@ }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { @@ -14219,13 +15034,16 @@ }, "esbuild": { "optional": true + }, + "jest-util": { + "optional": true } } }, "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.1.tgz", - "integrity": "sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA==", + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -14235,6 +15053,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -14286,9 +15114,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.4", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", - "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14396,15 +15224,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.0.tgz", - "integrity": "sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==", + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.34.0.tgz", + "integrity": "sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.32.0", - "@typescript-eslint/parser": "8.32.0", - "@typescript-eslint/utils": "8.32.0" + "@typescript-eslint/eslint-plugin": "8.34.0", + "@typescript-eslint/parser": "8.34.0", + "@typescript-eslint/utils": "8.34.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -14513,7 +15341,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -14782,9 +15609,9 @@ } }, "node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "version": "8.18.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", + "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "dev": true, "license": "MIT", "engines": { @@ -14830,16 +15657,16 @@ "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==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" } }, "node_modules/yaml-ast-parser": { @@ -14869,12 +15696,12 @@ } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "license": "ISC", "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs/node_modules/yargs-parser": { @@ -14922,9 +15749,9 @@ } }, "node_modules/zod": { - "version": "3.24.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", + "version": "3.25.49", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.49.tgz", + "integrity": "sha512-JMMPMy9ZBk3XFEdbM3iL1brx4NUSejd6xr3ELrrGEfGb355gjhiAWtG3K5o+AViV/3ZfkIrCzXsZn6SbLwTR8Q==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index e4b40acc..54d28a9c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongodb-mcp-server", "description": "MongoDB Model Context Protocol Server", - "version": "0.1.1", + "version": "0.1.2", "main": "dist/index.js", "author": "MongoDB ", "homepage": "https://github.com/mongodb-js/mongodb-mcp-server", @@ -34,8 +34,8 @@ "license": "Apache-2.0", "devDependencies": { "@eslint/js": "^9.24.0", - "@jest/globals": "^29.7.0", - "@modelcontextprotocol/inspector": "^0.10.2", + "@jest/globals": "^30.0.0", + "@modelcontextprotocol/inspector": "^0.14.0", "@redocly/cli": "^1.34.2", "@types/jest": "^29.5.14", "@types/node": "^22.14.0", @@ -48,7 +48,7 @@ "globals": "^16.0.0", "jest": "^29.7.0", "jest-environment-node": "^29.7.0", - "jest-extended": "^4.0.2", + "jest-extended": "^6.0.0", "mongodb-runner": "^5.8.2", "openapi-types": "^12.1.3", "openapi-typescript": "^7.6.1", @@ -60,7 +60,7 @@ "yaml": "^2.7.1" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.8.0", + "@modelcontextprotocol/sdk": "^1.11.2", "@mongodb-js/device-id": "^0.2.1", "@mongodb-js/devtools-connect": "^3.7.2", "@mongosh/service-provider-node-driver": "^3.6.0", @@ -72,12 +72,12 @@ "mongodb-redact": "^1.1.6", "mongodb-schema": "^12.6.2", "node-machine-id": "1.1.12", - "openapi-fetch": "^0.13.5", + "openapi-fetch": "^0.14.0", "simple-oauth2": "^5.1.0", - "yargs-parser": "^21.1.1", + "yargs-parser": "^22.0.0", "zod": "^3.24.2" }, "engines": { - "node": ">=20.0.0" + "node": ">=20.10.0" } } diff --git a/scripts/apply.ts b/scripts/apply.ts index 7ab36b97..c051c4ee 100755 --- a/scripts/apply.ts +++ b/scripts/apply.ts @@ -58,11 +58,11 @@ async function main() { const httpCode = parseInt(code, 10); if (httpCode >= 200 && httpCode < 300) { const response = operation.responses[code]; - const responseObject = findObjectFromRef(response, openapi); - if (responseObject.content) { + const responseObject = findObjectFromRef(response, openapi) as OpenAPIV3_1.ResponseObject; + if (responseObject && responseObject.content) { for (const contentType in responseObject.content) { const content = responseObject.content[contentType]; - hasResponseBody = !!content.schema; + hasResponseBody = !!content?.schema; } } } @@ -84,7 +84,7 @@ async function main() { operationId: operation.operationId || "", requiredParams, hasResponseBody, - tag: operation.tags[0], + tag: operation.tags?.[0] ?? "", }); } } diff --git a/scripts/filter.ts b/scripts/filter.ts index 0c724451..06340078 100755 --- a/scripts/filter.ts +++ b/scripts/filter.ts @@ -40,6 +40,7 @@ function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document { "createProjectIpAccessList", "deleteProjectIpAccessList", "listOrganizationProjects", + "listAlerts", ]; const filteredPaths = {}; diff --git a/src/common/atlas/apiClient.ts b/src/common/atlas/apiClient.ts index 4cbd34d6..1773aba5 100644 --- a/src/common/atlas/apiClient.ts +++ b/src/common/atlas/apiClient.ts @@ -34,7 +34,9 @@ export class ApiClient { private getAccessToken = async () => { if (this.oauth2Client && (!this.accessToken || this.accessToken.expired())) { - this.accessToken = await this.oauth2Client.getToken({}); + this.accessToken = await this.oauth2Client.getToken({ + agent: this.options.userAgent, + }); } return this.accessToken?.token.access_token as string | undefined; }; @@ -247,6 +249,14 @@ export class ApiClient { } } + async listAlerts(options: FetchOptions) { + const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/alerts", options); + if (error) { + throw ApiClientError.fromError(response, error); + } + return data; + } + async listClusters(options: FetchOptions) { const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/clusters", options); if (error) { diff --git a/src/common/atlas/cluster.ts b/src/common/atlas/cluster.ts index b2bbd172..793cd99b 100644 --- a/src/common/atlas/cluster.ts +++ b/src/common/atlas/cluster.ts @@ -50,8 +50,7 @@ export function formatCluster(cluster: ClusterDescription20240805): Cluster { }; }); - const instanceSize = (regionConfigs.length <= 0 ? undefined : regionConfigs[0].instanceSize) || "UNKNOWN"; - + const instanceSize = regionConfigs[0]?.instanceSize ?? "UNKNOWN"; const clusterInstanceType = instanceSize == "M0" ? "FREE" : "DEDICATED"; return { diff --git a/src/common/atlas/openapi.d.ts b/src/common/atlas/openapi.d.ts index 1a50b8f4..dbc88950 100644 --- a/src/common/atlas/openapi.d.ts +++ b/src/common/atlas/openapi.d.ts @@ -116,6 +116,28 @@ export interface paths { patch?: never; trace?: never; }; + "/api/atlas/v2/groups/{groupId}/alerts": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * Return All Alerts from One Project + * @description Returns all alerts. These alerts apply to all components in one project. You receive an alert when a monitored component meets or exceeds a value you set. To use this resource, the requesting Service Account or API Key must have the Project Read Only role. + * + * This resource remains under revision and may change. + */ + get: operations["listAlerts"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/atlas/v2/groups/{groupId}/clusters": { parameters: { query?: never; @@ -628,6 +650,7 @@ export interface components { /** @description Flag that indicates whether the instance size may scale down via reactive auto-scaling. MongoDB Cloud requires this parameter if **replicationSpecs[n].regionConfigs[m].autoScaling.compute.enabled** is `true`. If you enable this option, specify a value for **replicationSpecs[n].regionConfigs[m].autoScaling.compute.minInstanceSize**. */ scaleDownEnabled?: boolean; }; + AlertViewForNdsGroup: components["schemas"]["AppServiceAlertView"] | components["schemas"]["ClusterAlertView"] | components["schemas"]["HostAlertViewForNdsGroup"] | components["schemas"]["HostMetricAlert"] | components["schemas"]["ReplicaSetAlertViewForNdsGroup"] | components["schemas"]["StreamProcessorAlertViewForNdsGroup"] | components["schemas"]["DefaultAlertViewForNdsGroup"]; /** @description Object that contains the identifying characteristics of the Amazon Web Services (AWS) Key Management Service (KMS). This field always returns a null value. */ ApiAtlasCloudProviderAccessFeatureUsageFeatureIdView: Record | null; /** @description Group of settings that configures a subset of the advanced configuration details. */ @@ -697,6 +720,87 @@ export interface components { /** @description Application error message returned with this error. */ readonly reason?: string; }; + /** + * App Services Alerts + * @description App Services alert notifies different activities about a BAAS application. + */ + AppServiceAlertView: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + eventTypeName: components["schemas"]["AppServiceEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * App Services Event Types + * @description Incident that triggered this alert. + * @example DEPLOYMENT_FAILURE + * @enum {string} + */ + AppServiceEventTypeViewAlertable: "URL_CONFIRMATION" | "SUCCESSFUL_DEPLOY" | "DEPLOYMENT_FAILURE" | "DEPLOYMENT_MODEL_CHANGE_SUCCESS" | "DEPLOYMENT_MODEL_CHANGE_FAILURE" | "REQUEST_RATE_LIMIT" | "LOG_FORWARDER_FAILURE" | "OUTSIDE_REALM_METRIC_THRESHOLD" | "SYNC_FAILURE" | "TRIGGER_FAILURE" | "TRIGGER_AUTO_RESUMED"; /** @description Details that describe the organization. */ AtlasOrganization: { /** @@ -1737,6 +1841,85 @@ export interface components { /** @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_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_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 Alerts + * @description Cluster alert notifies different activities and conditions about cluster of mongod hosts. + */ + ClusterAlertView: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + eventTypeName: components["schemas"]["ClusterEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; /** * Cluster Connection Strings * @description Collection of Uniform Resource Locators that point to the MongoDB database. @@ -1941,6 +2124,13 @@ export interface components { /** @description Region where the private endpoint is deployed. */ readonly region?: string; }; + /** + * Cluster Event Types + * @description Event type that triggers an alert. + * @example CLUSTER_MONGOS_IS_MISSING + * @enum {string} + */ + ClusterEventTypeViewAlertable: "CLUSTER_MONGOS_IS_MISSING" | "CLUSTER_AGENT_IN_CRASH_LOOP"; ClusterFlexProviderSettings: Omit & { /** * @description Cloud service provider on which MongoDB Cloud provisioned the multi-tenant host. The resource returns this parameter when **providerSettings.providerName** is `FLEX` and **providerSetting.instanceSizeName** is `FLEX`. @@ -2468,6 +2658,120 @@ export interface components { 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"]); + DataMetricAlertView: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + currentValue?: components["schemas"]["DataMetricValueView"]; + eventTypeName: components["schemas"]["HostMetricEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Name of the metric against which Atlas checks the configured `metricThreshold.threshold`. + * + * To learn more about the available metrics, see Host Metrics. + * + * **NOTE**: If you set eventTypeName to OUTSIDE_SERVERLESS_METRIC_THRESHOLD, you can specify only metrics available for serverless. To learn more, see Serverless Measurements. + * @example ASSERT_USER + */ + readonly metricName?: string; + /** + * @description Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * Data Metric Units + * @description Element used to express the quantity. This can be an element of time, storage capacity, and the like. + * @example BYTES + * @enum {string} + */ + DataMetricUnits: "BITS" | "KILOBITS" | "MEGABITS" | "GIGABITS" | "BYTES" | "KILOBYTES" | "MEGABYTES" | "GIGABYTES" | "TERABYTES" | "PETABYTES"; + /** + * Data Metric Value + * @description Measurement of the **metricName** recorded at the time of the event. + */ + DataMetricValueView: { + /** + * Format: double + * @description Amount of the **metricName** recorded at the time of the event. This value triggered the alert. + */ + readonly number?: number; + units?: components["schemas"]["DataMetricUnits"]; + }; /** @description Settings to configure the region where you wish to store your archived data. */ DataProcessRegionView: { /** @@ -2550,6 +2854,81 @@ export interface components { */ nodeCount?: number; } & (components["schemas"]["AWSHardwareSpec20240805"] | components["schemas"]["AzureHardwareSpec20240805"] | components["schemas"]["GCPHardwareSpec20240805"]); + /** + * Any Other Alerts + * @description Other alerts which don't have extra details beside of basic one. + */ + DefaultAlertViewForNdsGroup: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + /** @description Incident that triggered this alert. */ + readonly eventTypeName: ("CREDIT_CARD_ABOUT_TO_EXPIRE" | "PENDING_INVOICE_OVER_THRESHOLD" | "DAILY_BILL_OVER_THRESHOLD") | ("CPS_SNAPSHOT_STARTED" | "CPS_SNAPSHOT_SUCCESSFUL" | "CPS_SNAPSHOT_FAILED" | "CPS_CONCURRENT_SNAPSHOT_FAILED_WILL_RETRY" | "CPS_SNAPSHOT_BEHIND" | "CPS_COPY_SNAPSHOT_STARTED" | "CPS_COPY_SNAPSHOT_FAILED" | "CPS_COPY_SNAPSHOT_FAILED_WILL_RETRY" | "CPS_COPY_SNAPSHOT_SUCCESSFUL" | "CPS_PREV_SNAPSHOT_OLD" | "CPS_SNAPSHOT_FALLBACK_SUCCESSFUL" | "CPS_SNAPSHOT_FALLBACK_FAILED" | "CPS_RESTORE_SUCCESSFUL" | "CPS_EXPORT_SUCCESSFUL" | "CPS_RESTORE_FAILED" | "CPS_EXPORT_FAILED" | "CPS_AUTO_EXPORT_FAILED" | "CPS_SNAPSHOT_DOWNLOAD_REQUEST_FAILED" | "CPS_OPLOG_BEHIND" | "CPS_OPLOG_CAUGHT_UP") | ("AWS_ENCRYPTION_KEY_NEEDS_ROTATION" | "AZURE_ENCRYPTION_KEY_NEEDS_ROTATION" | "GCP_ENCRYPTION_KEY_NEEDS_ROTATION" | "AWS_ENCRYPTION_KEY_INVALID" | "AZURE_ENCRYPTION_KEY_INVALID" | "GCP_ENCRYPTION_KEY_INVALID") | ("FTS_INDEX_DELETION_FAILED" | "FTS_INDEX_BUILD_COMPLETE" | "FTS_INDEX_BUILD_FAILED" | "FTS_INDEXES_RESTORE_FAILED" | "FTS_INDEXES_SYNONYM_MAPPING_INVALID") | ("USERS_WITHOUT_MULTI_FACTOR_AUTH" | "ENCRYPTION_AT_REST_KMS_NETWORK_ACCESS_DENIED" | "ENCRYPTION_AT_REST_CONFIG_NO_LONGER_VALID") | ("CLUSTER_INSTANCE_STOP_START" | "CLUSTER_INSTANCE_RESYNC_REQUESTED" | "CLUSTER_INSTANCE_UPDATE_REQUESTED" | "SAMPLE_DATASET_LOAD_REQUESTED" | "TENANT_UPGRADE_TO_SERVERLESS_SUCCESSFUL" | "TENANT_UPGRADE_TO_SERVERLESS_FAILED" | "NETWORK_PERMISSION_ENTRY_ADDED" | "NETWORK_PERMISSION_ENTRY_REMOVED" | "NETWORK_PERMISSION_ENTRY_UPDATED") | ("MAINTENANCE_IN_ADVANCED" | "MAINTENANCE_AUTO_DEFERRED" | "MAINTENANCE_STARTED" | "MAINTENANCE_NO_LONGER_NEEDED") | ("NDS_X509_USER_AUTHENTICATION_CUSTOMER_CA_EXPIRATION_CHECK" | "NDS_X509_USER_AUTHENTICATION_CUSTOMER_CRL_EXPIRATION_CHECK" | "NDS_X509_USER_AUTHENTICATION_MANAGED_USER_CERTS_EXPIRATION_CHECK") | ("ONLINE_ARCHIVE_INSUFFICIENT_INDEXES_CHECK" | "ONLINE_ARCHIVE_MAX_CONSECUTIVE_OFFLOAD_WINDOWS_CHECK") | "OUTSIDE_SERVERLESS_METRIC_THRESHOLD" | "OUTSIDE_FLEX_METRIC_THRESHOLD" | ("JOINED_GROUP" | "REMOVED_FROM_GROUP" | "USER_ROLES_CHANGED_AUDIT") | ("TAGS_MODIFIED" | "CLUSTER_TAGS_MODIFIED" | "GROUP_TAGS_MODIFIED") | ("STREAM_PROCESSOR_STATE_IS_FAILED" | "OUTSIDE_STREAM_PROCESSOR_METRIC_THRESHOLD") | ("COMPUTE_AUTO_SCALE_INITIATED_BASE" | "COMPUTE_AUTO_SCALE_INITIATED_ANALYTICS" | "COMPUTE_AUTO_SCALE_SCALE_DOWN_FAIL_BASE" | "COMPUTE_AUTO_SCALE_SCALE_DOWN_FAIL_ANALYTICS" | "COMPUTE_AUTO_SCALE_MAX_INSTANCE_SIZE_FAIL_BASE" | "COMPUTE_AUTO_SCALE_MAX_INSTANCE_SIZE_FAIL_ANALYTICS" | "COMPUTE_AUTO_SCALE_OPLOG_FAIL_BASE" | "COMPUTE_AUTO_SCALE_OPLOG_FAIL_ANALYTICS" | "DISK_AUTO_SCALE_INITIATED" | "DISK_AUTO_SCALE_MAX_DISK_SIZE_FAIL" | "DISK_AUTO_SCALE_OPLOG_FAIL" | "PREDICTIVE_COMPUTE_AUTO_SCALE_INITIATED_BASE" | "PREDICTIVE_COMPUTE_AUTO_SCALE_MAX_INSTANCE_SIZE_FAIL_BASE" | "PREDICTIVE_COMPUTE_AUTO_SCALE_OPLOG_FAIL_BASE") | ("CPS_DATA_PROTECTION_ENABLE_REQUESTED" | "CPS_DATA_PROTECTION_ENABLED" | "CPS_DATA_PROTECTION_UPDATE_REQUESTED" | "CPS_DATA_PROTECTION_UPDATED" | "CPS_DATA_PROTECTION_DISABLE_REQUESTED" | "CPS_DATA_PROTECTION_DISABLED" | "CPS_DATA_PROTECTION_APPROVED_FOR_DISABLEMENT") | "RESOURCE_POLICY_VIOLATED"; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; DefaultScheduleView: Omit, "type"> & { /** * @description discriminator enum property added by openapi-typescript @@ -3240,41 +3619,256 @@ export interface components { diskSizeGB?: number; } & (components["schemas"]["AWSHardwareSpec20240805"] | components["schemas"]["AzureHardwareSpec20240805"] | components["schemas"]["GCPHardwareSpec20240805"] | components["schemas"]["TenantHardwareSpec20240805"]); /** - * Ingestion Destination - * @description Ingestion destination of a Data Lake Pipeline. + * Host Alerts + * @description Host alert notifies about activities on mongod host. */ - IngestionSink: { + HostAlertViewForNdsGroup: { /** - * @description Type of ingestion destination of this Data Lake Pipeline. - * @enum {string} + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. */ - readonly type?: "DLS"; - }; - /** - * Ingestion Source - * @description Ingestion Source of a Data Lake Pipeline. - */ - IngestionSource: { + acknowledgedUntil?: string; /** - * @description Type of ingestion source of this Data Lake Pipeline. - * @enum {string} + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. */ - type?: "PERIODIC_CPS" | "ON_DEMAND_CPS"; - }; - /** - * Line Item - * @description One service included in this invoice. - */ - InvoiceLineItem: { - /** @description Human-readable label that identifies the cluster that incurred the charge. */ - readonly clusterName?: string; + acknowledgementComment?: string; /** - * Format: date-time - * @description Date and time when MongoDB Cloud created this line item. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. */ - readonly created?: string; + readonly acknowledgingUsername?: string; /** - * Format: int64 + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + eventTypeName: components["schemas"]["HostEventTypeViewForNdsGroupAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * Host Event Types + * @description Event type that triggers an alert. + * @example HOST_DOWN + * @enum {string} + */ + HostEventTypeViewForNdsGroupAlertable: "HOST_DOWN" | "HOST_HAS_INDEX_SUGGESTIONS" | "HOST_MONGOT_CRASHING_OOM" | "HOST_MONGOT_STOP_REPLICATION" | "HOST_NOT_ENOUGH_DISK_SPACE" | "SSH_KEY_NDS_HOST_ACCESS_REQUESTED" | "SSH_KEY_NDS_HOST_ACCESS_REFRESHED" | "PUSH_BASED_LOG_EXPORT_STOPPED" | "PUSH_BASED_LOG_EXPORT_DROPPED_LOG" | "HOST_VERSION_BEHIND" | "VERSION_BEHIND" | "HOST_EXPOSED" | "HOST_SSL_CERTIFICATE_STALE" | "HOST_SECURITY_CHECKUP_NOT_MET"; + /** + * Host Metric Alerts + * @description Host Metric Alert notifies about changes of measurements or metrics for mongod host. + */ + HostMetricAlert: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + currentValue?: components["schemas"]["HostMetricValue"]; + eventTypeName: components["schemas"]["HostMetricEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Name of the metric against which Atlas checks the configured `metricThreshold.threshold`. + * + * To learn more about the available metrics, see Host Metrics. + * + * **NOTE**: If you set eventTypeName to OUTSIDE_SERVERLESS_METRIC_THRESHOLD, you can specify only metrics available for serverless. To learn more, see Serverless Measurements. + * @example ASSERT_USER + */ + readonly metricName?: string; + /** + * @description Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * Host Metric Event Types + * @description Event type that triggers an alert. + * @example OUTSIDE_METRIC_THRESHOLD + * @enum {string} + */ + HostMetricEventTypeViewAlertable: "OUTSIDE_METRIC_THRESHOLD"; + /** @description Value of the metric that triggered the alert. The resource returns this parameter for alerts of events impacting hosts. */ + HostMetricValue: { + /** + * Format: double + * @description Amount of the **metricName** recorded at the time of the event. This value triggered the alert. + */ + readonly number?: number; + /** + * @description Element used to express the quantity in **currentValue.number**. This can be an element of time, storage capacity, and the like. This metric triggered the alert. + * @enum {string} + */ + readonly units?: "bits" | "Kbits" | "Mbits" | "Gbits" | "bytes" | "KB" | "MB" | "GB" | "TB" | "PB" | "nsec" | "msec" | "sec" | "min" | "hours" | "million minutes" | "days" | "requests" | "1000 requests" | "GB seconds" | "GB hours" | "GB days" | "RPU" | "thousand RPU" | "million RPU" | "WPU" | "thousand WPU" | "million WPU" | "count" | "thousand" | "million" | "billion"; + }; + /** + * Ingestion Destination + * @description Ingestion destination of a Data Lake Pipeline. + */ + IngestionSink: { + /** + * @description Type of ingestion destination of this Data Lake Pipeline. + * @enum {string} + */ + readonly type?: "DLS"; + }; + /** + * Ingestion Source + * @description Ingestion Source of a Data Lake Pipeline. + */ + IngestionSource: { + /** + * @description Type of ingestion source of this Data Lake Pipeline. + * @enum {string} + */ + type?: "PERIODIC_CPS" | "ON_DEMAND_CPS"; + }; + /** + * Line Item + * @description One service included in this invoice. + */ + InvoiceLineItem: { + /** @description Human-readable label that identifies the cluster that incurred the charge. */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this line item. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created?: string; + /** + * Format: int64 * @description Sum by which MongoDB discounted this line item. MongoDB Cloud expresses this value in cents (100ths of one US Dollar). The resource returns this parameter when a discount applies. */ readonly discountCents?: number; @@ -3306,7 +3900,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" | "ATLAS_FLEX_AWS_LEGACY_100_USAGE_HOURS" | "ATLAS_FLEX_AWS_LEGACY_200_USAGE_HOURS" | "ATLAS_FLEX_AWS_LEGACY_300_USAGE_HOURS" | "ATLAS_FLEX_AWS_LEGACY_400_USAGE_HOURS" | "ATLAS_FLEX_AWS_LEGACY_500_USAGE_HOURS" | "ATLAS_FLEX_AZURE_LEGACY_100_USAGE_HOURS" | "ATLAS_FLEX_AZURE_LEGACY_200_USAGE_HOURS" | "ATLAS_FLEX_AZURE_LEGACY_300_USAGE_HOURS" | "ATLAS_FLEX_AZURE_LEGACY_400_USAGE_HOURS" | "ATLAS_FLEX_AZURE_LEGACY_500_USAGE_HOURS" | "ATLAS_FLEX_GCP_LEGACY_100_USAGE_HOURS" | "ATLAS_FLEX_GCP_LEGACY_200_USAGE_HOURS" | "ATLAS_FLEX_GCP_LEGACY_300_USAGE_HOURS" | "ATLAS_FLEX_GCP_LEGACY_400_USAGE_HOURS" | "ATLAS_FLEX_GCP_LEGACY_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. @@ -3418,6 +4012,120 @@ 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"][]; }; + NumberMetricAlertView: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + currentValue?: components["schemas"]["NumberMetricValueView"]; + eventTypeName: components["schemas"]["HostMetricEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Name of the metric against which Atlas checks the configured `metricThreshold.threshold`. + * + * To learn more about the available metrics, see Host Metrics. + * + * **NOTE**: If you set eventTypeName to OUTSIDE_SERVERLESS_METRIC_THRESHOLD, you can specify only metrics available for serverless. To learn more, see Serverless Measurements. + * @example ASSERT_USER + */ + readonly metricName?: string; + /** + * @description Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * Number Metric Units + * @description Element used to express the quantity. This can be an element of time, storage capacity, and the like. + * @example COUNT + * @enum {string} + */ + NumberMetricUnits: "COUNT" | "THOUSAND" | "MILLION" | "BILLION"; + /** + * Number Metric Value + * @description Measurement of the **metricName** recorded at the time of the event. + */ + NumberMetricValueView: { + /** + * Format: double + * @description Amount of the **metricName** recorded at the time of the event. This value triggered the alert. + */ + readonly number?: number; + units?: components["schemas"]["NumberMetricUnits"]; + }; /** * On-Demand Cloud Provider Snapshot Source * @description On-Demand Cloud Provider Snapshots as Source for a Data Lake Pipeline. @@ -3565,6 +4273,17 @@ export interface components { /** @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")[]; }; + PaginatedAlertView: { + /** @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"]["AlertViewForNdsGroup"][]; + /** + * 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; + }; /** @description List of MongoDB Database users granted access to databases in the specified project. */ PaginatedApiAtlasDatabaseUserView: { /** @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. */ @@ -3671,6 +4390,223 @@ export interface components { */ type: "PERIODIC_CPS"; }; + RawMetricAlertView: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + currentValue?: components["schemas"]["RawMetricValueView"]; + eventTypeName: components["schemas"]["HostMetricEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Name of the metric against which Atlas checks the configured `metricThreshold.threshold`. + * + * To learn more about the available metrics, see Host Metrics. + * + * **NOTE**: If you set eventTypeName to OUTSIDE_SERVERLESS_METRIC_THRESHOLD, you can specify only metrics available for serverless. To learn more, see Serverless Measurements. + * @example ASSERT_USER + */ + readonly metricName?: string; + /** + * @description Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * Raw Metric Units + * @description Element used to express the quantity. This can be an element of time, storage capacity, and the like. + * @default RAW + * @enum {string} + */ + RawMetricUnits: "RAW"; + /** + * Raw Metric Value + * @description Measurement of the **metricName** recorded at the time of the event. + */ + RawMetricValueView: { + /** + * Format: double + * @description Amount of the **metricName** recorded at the time of the event. This value triggered the alert. + */ + readonly number?: number; + units?: components["schemas"]["RawMetricUnits"]; + }; + /** + * ReplicaSet Alerts + * @description ReplicaSet alert notifies about different activities on replica set of mongod instances. + */ + ReplicaSetAlertViewForNdsGroup: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + eventTypeName: components["schemas"]["ReplicaSetEventTypeViewForNdsGroupAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 unique 24-hexadecimal character strings that identify the replica set members that are not in PRIMARY nor SECONDARY state. */ + readonly nonRunningHostIds?: string[]; + /** + * @description Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Unique 24-hexadecimal character string that identifies the parent cluster to which this alert applies. The parent cluster contains the sharded nodes. MongoDB Cloud returns this parameter only for alerts of events impacting sharded clusters. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly parentClusterId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * ReplicaSet Event Types + * @description Incident that triggered this alert. + * @example NO_PRIMARY + * @enum {string} + */ + ReplicaSetEventTypeViewForNdsGroupAlertable: "REPLICATION_OPLOG_WINDOW_RUNNING_OUT" | "NO_PRIMARY" | "PRIMARY_ELECTED" | "TOO_MANY_ELECTIONS" | "TOO_FEW_HEALTHY_MEMBERS" | "TOO_MANY_UNHEALTHY_MEMBERS"; /** * Replication Specifications * @description Details that explain how MongoDB Cloud replicates data on the specified MongoDB database. @@ -3962,6 +4898,100 @@ export interface components { */ providerName: "AWS" | "AZURE"; }; + /** + * Stream Processor Alerts + * @description Stream Processor alert notifies about activities on Stream Processor in AtlasStreams. + */ + StreamProcessorAlertViewForNdsGroup: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + eventTypeName: components["schemas"]["HostEventTypeViewForNdsGroupAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * @description The name of the Stream Processing Instance to which this alert applies. The resource returns this parameter for alerts of events impacting Stream Processing Instances. + * @example foobar + */ + readonly instanceName?: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description The error message associated with the Stream Processor to which this alert applies. + * @example MongoServerError: Failed to start stream processor: (Location77175) Could not connect to the Kafka topic with kafka error code: -195, message: Local: Broker transport failure.: (Location77175) + */ + readonly processorErrorMsg?: string; + /** + * @description The name of the Stream Processor to which this alert applies. The resource returns this parameter for alerts of events impacting Stream Processors. + * @example foobar + */ + readonly processorName?: string; + /** + * @description The state of the Stream Processor to which this alert applies. The resource returns this parameter for alerts of events impacting Stream Processors. + * @example STARTED + */ + readonly processorState?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; /** @description AWS configurations for AWS-based connection types. */ StreamsAWSConnectionConfig: { /** @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. */ @@ -4398,6 +5428,120 @@ export interface components { /** @description List of synonym statuses by mapping. */ synonymMappingStatusDetail?: components["schemas"]["SynonymMappingStatusDetailMap"][]; }; + TimeMetricAlertView: { + /** + * Format: date-time + * @description Date and time until which this alert has been acknowledged. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if a MongoDB User previously acknowledged this alert. + * + * - To acknowledge this alert forever, set the parameter value to 100 years in the future. + * + * - To unacknowledge a previously acknowledged alert, do not set this parameter value. + */ + acknowledgedUntil?: string; + /** + * @description Comment that a MongoDB Cloud user submitted when acknowledging the alert. + * @example Expiration on 3/19. Silencing for 7days. + */ + acknowledgementComment?: string; + /** + * Format: email + * @description MongoDB Cloud username of the person who acknowledged the alert. The response returns this parameter if a MongoDB Cloud user previously acknowledged this alert. + */ + readonly acknowledgingUsername?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies the alert configuration that sets this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly alertConfigId: string; + /** + * @description Human-readable label that identifies the cluster to which this alert applies. This resource returns this parameter for alerts of events impacting backups, replica sets, or sharded clusters. + * @example cluster1 + */ + readonly clusterName?: string; + /** + * Format: date-time + * @description Date and time when MongoDB Cloud created this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly created: string; + currentValue?: components["schemas"]["TimeMetricValueView"]; + eventTypeName: components["schemas"]["HostMetricEventTypeViewAlertable"]; + /** + * @description Unique 24-hexadecimal digit string that identifies the project that owns this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly groupId?: string; + /** + * @description Hostname and port of the host to which this alert applies. The resource returns this parameter for alerts of events impacting hosts or replica sets. + * @example cloud-test.mongodb.com:27017 + */ + readonly hostnameAndPort?: string; + /** + * @description Unique 24-hexadecimal digit string that identifies this alert. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly id: string; + /** + * Format: date-time + * @description Date and time that any notifications were last sent for this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter if MongoDB Cloud has sent notifications for this alert. + */ + readonly lastNotified?: string; + /** @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 Name of the metric against which Atlas checks the configured `metricThreshold.threshold`. + * + * To learn more about the available metrics, see Host Metrics. + * + * **NOTE**: If you set eventTypeName to OUTSIDE_SERVERLESS_METRIC_THRESHOLD, you can specify only metrics available for serverless. To learn more, see Serverless Measurements. + * @example ASSERT_USER + */ + readonly metricName?: string; + /** + * @description Unique 24-hexadecimal character string that identifies the organization that owns the project to which this alert applies. + * @example 32b6e34b3d91647abb20e7b8 + */ + readonly orgId?: string; + /** + * @description Name of the replica set to which this alert applies. The response returns this parameter for alerts of events impacting backups, hosts, or replica sets. + * @example event-replica-set + */ + readonly replicaSetName?: string; + /** + * Format: date-time + * @description Date and time that this alert changed to `"status" : "CLOSED"`. This parameter expresses its value in the ISO 8601 timestamp format in UTC. The resource returns this parameter once `"status" : "CLOSED"`. + */ + readonly resolved?: string; + /** + * @description State of this alert at the time you requested its details. + * @example OPEN + * @enum {string} + */ + readonly status: "CANCELLED" | "CLOSED" | "OPEN" | "TRACKING"; + /** + * Format: date-time + * @description Date and time when someone last updated this alert. This parameter expresses its value in the ISO 8601 timestamp format in UTC. + */ + readonly updated: string; + }; + /** + * Time Metric Units + * @description Element used to express the quantity. This can be an element of time, storage capacity, and the like. + * @default HOURS + * @enum {string} + */ + TimeMetricUnits: "NANOSECONDS" | "MILLISECONDS" | "MILLION_MINUTES" | "SECONDS" | "MINUTES" | "HOURS" | "DAYS"; + /** + * Time Metric Value + * @description Measurement of the **metricName** recorded at the time of the event. + */ + TimeMetricValueView: { + /** + * Format: double + * @description Amount of the **metricName** recorded at the time of the event. This value triggered the alert. + */ + readonly number?: number; + units?: components["schemas"]["TimeMetricUnits"]; + }; /** * englishPossessive * @description Filter that removes possessives (trailing 's) from words. @@ -5189,11 +6333,14 @@ 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 AlertViewForNdsGroup = components['schemas']['AlertViewForNdsGroup']; 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 AppServiceAlertView = components['schemas']['AppServiceAlertView']; +export type AppServiceEventTypeViewAlertable = components['schemas']['AppServiceEventTypeViewAlertable']; export type AtlasOrganization = components['schemas']['AtlasOrganization']; export type AtlasSearchAnalyzer = components['schemas']['AtlasSearchAnalyzer']; export type AzureCloudProviderContainer = components['schemas']['AzureCloudProviderContainer']; @@ -5238,10 +6385,12 @@ export type CloudProviderContainer = components['schemas']['CloudProviderContain export type CloudProviderGcpAutoScaling = components['schemas']['CloudProviderGCPAutoScaling']; export type CloudRegionConfig = components['schemas']['CloudRegionConfig']; export type CloudRegionConfig20240805 = components['schemas']['CloudRegionConfig20240805']; +export type ClusterAlertView = components['schemas']['ClusterAlertView']; 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 ClusterEventTypeViewAlertable = components['schemas']['ClusterEventTypeViewAlertable']; export type ClusterFlexProviderSettings = components['schemas']['ClusterFlexProviderSettings']; export type ClusterFreeAutoScaling = components['schemas']['ClusterFreeAutoScaling']; export type ClusterFreeProviderSettings = components['schemas']['ClusterFreeProviderSettings']; @@ -5272,11 +6421,15 @@ 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 DataMetricAlertView = components['schemas']['DataMetricAlertView']; +export type DataMetricUnits = components['schemas']['DataMetricUnits']; +export type DataMetricValueView = components['schemas']['DataMetricValueView']; 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 DefaultAlertViewForNdsGroup = components['schemas']['DefaultAlertViewForNdsGroup']; export type DefaultScheduleView = components['schemas']['DefaultScheduleView']; export type DiskBackupSnapshotAwsExportBucketRequest = components['schemas']['DiskBackupSnapshotAWSExportBucketRequest']; export type DiskBackupSnapshotAwsExportBucketResponse = components['schemas']['DiskBackupSnapshotAWSExportBucketResponse']; @@ -5312,12 +6465,20 @@ 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 HostAlertViewForNdsGroup = components['schemas']['HostAlertViewForNdsGroup']; +export type HostEventTypeViewForNdsGroupAlertable = components['schemas']['HostEventTypeViewForNdsGroupAlertable']; +export type HostMetricAlert = components['schemas']['HostMetricAlert']; +export type HostMetricEventTypeViewAlertable = components['schemas']['HostMetricEventTypeViewAlertable']; +export type HostMetricValue = components['schemas']['HostMetricValue']; 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 NumberMetricAlertView = components['schemas']['NumberMetricAlertView']; +export type NumberMetricUnits = components['schemas']['NumberMetricUnits']; +export type NumberMetricValueView = components['schemas']['NumberMetricValueView']; export type OnDemandCpsSnapshotSource = components['schemas']['OnDemandCpsSnapshotSource']; export type OnlineArchiveSchedule = components['schemas']['OnlineArchiveSchedule']; export type OrgActiveUserResponse = components['schemas']['OrgActiveUserResponse']; @@ -5325,6 +6486,7 @@ 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 PaginatedAlertView = components['schemas']['PaginatedAlertView']; export type PaginatedApiAtlasDatabaseUserView = components['schemas']['PaginatedApiAtlasDatabaseUserView']; export type PaginatedAtlasGroupView = components['schemas']['PaginatedAtlasGroupView']; export type PaginatedClusterDescription20240805 = components['schemas']['PaginatedClusterDescription20240805']; @@ -5333,6 +6495,11 @@ export type PaginatedNetworkAccessView = components['schemas']['PaginatedNetwork export type PaginatedOrgGroupView = components['schemas']['PaginatedOrgGroupView']; export type PaginatedOrganizationView = components['schemas']['PaginatedOrganizationView']; export type PeriodicCpsSnapshotSource = components['schemas']['PeriodicCpsSnapshotSource']; +export type RawMetricAlertView = components['schemas']['RawMetricAlertView']; +export type RawMetricUnits = components['schemas']['RawMetricUnits']; +export type RawMetricValueView = components['schemas']['RawMetricValueView']; +export type ReplicaSetAlertViewForNdsGroup = components['schemas']['ReplicaSetAlertViewForNdsGroup']; +export type ReplicaSetEventTypeViewForNdsGroupAlertable = components['schemas']['ReplicaSetEventTypeViewForNdsGroupAlertable']; export type ReplicationSpec20240805 = components['schemas']['ReplicationSpec20240805']; export type ResourceTag = components['schemas']['ResourceTag']; export type SearchHostStatusDetail = components['schemas']['SearchHostStatusDetail']; @@ -5348,6 +6515,7 @@ export type SearchSynonymMappingDefinition = components['schemas']['SearchSynony export type ServerlessAwsTenantEndpointUpdate = components['schemas']['ServerlessAWSTenantEndpointUpdate']; export type ServerlessAzureTenantEndpointUpdate = components['schemas']['ServerlessAzureTenantEndpointUpdate']; export type ServerlessTenantEndpointUpdate = components['schemas']['ServerlessTenantEndpointUpdate']; +export type StreamProcessorAlertViewForNdsGroup = components['schemas']['StreamProcessorAlertViewForNdsGroup']; export type StreamsAwsConnectionConfig = components['schemas']['StreamsAWSConnectionConfig']; export type StreamsAwsLambdaConnection = components['schemas']['StreamsAWSLambdaConnection']; export type StreamsClusterConnection = components['schemas']['StreamsClusterConnection']; @@ -5372,6 +6540,9 @@ export type TextSearchIndexCreateRequest = components['schemas']['TextSearchInde export type TextSearchIndexDefinition = components['schemas']['TextSearchIndexDefinition']; export type TextSearchIndexResponse = components['schemas']['TextSearchIndexResponse']; export type TextSearchIndexStatusDetail = components['schemas']['TextSearchIndexStatusDetail']; +export type TimeMetricAlertView = components['schemas']['TimeMetricAlertView']; +export type TimeMetricUnits = components['schemas']['TimeMetricUnits']; +export type TimeMetricValueView = components['schemas']['TimeMetricValueView']; export type TokenFilterEnglishPossessive = components['schemas']['TokenFilterEnglishPossessive']; export type TokenFilterFlattenGraph = components['schemas']['TokenFilterFlattenGraph']; export type TokenFilterPorterStemming = components['schemas']['TokenFilterPorterStemming']; @@ -5734,6 +6905,49 @@ export interface operations { 500: components["responses"]["internalServerError"]; }; }; + listAlerts: { + 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 Status of the alerts to return. Omit to return all alerts in all statuses. */ + status?: "OPEN" | "TRACKING" | "CLOSED"; + }; + 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 OK */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/vnd.atlas.2023-01-01+json": components["schemas"]["PaginatedAlertView"]; + }; + }; + 400: components["responses"]["badRequest"]; + 401: components["responses"]["unauthorized"]; + 403: components["responses"]["forbidden"]; + 404: components["responses"]["notFound"]; + 500: components["responses"]["internalServerError"]; + }; + }; listClusters: { parameters: { query?: { diff --git a/src/index.ts b/src/index.ts index ee332072..02f9ca36 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,6 +31,26 @@ try { const transport = createEJsonTransport(); + const shutdown = () => { + logger.info(LogId.serverCloseRequested, "server", `Server close requested`); + + server + .close() + .then(() => { + logger.info(LogId.serverClosed, "server", `Server closed successfully`); + process.exit(0); + }) + .catch((err: unknown) => { + const error = err instanceof Error ? err : new Error(String(err)); + logger.error(LogId.serverCloseFailure, "server", `Error closing server: ${error.message}`); + process.exit(1); + }); + }; + + process.once("SIGINT", shutdown); + process.once("SIGTERM", shutdown); + process.once("SIGQUIT", shutdown); + await server.connect(transport); } catch (error: unknown) { logger.emergency(LogId.serverStartFailure, "server", `Fatal error running server: ${error as string}`); diff --git a/src/logger.ts b/src/logger.ts index 1fa694bd..7adf1263 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -9,6 +9,9 @@ export type LogLevel = LoggingMessageNotification["params"]["level"]; export const LogId = { serverStartFailure: mongoLogId(1_000_001), serverInitialized: mongoLogId(1_000_002), + serverCloseRequested: mongoLogId(1_000_003), + serverClosed: mongoLogId(1_000_004), + serverCloseFailure: mongoLogId(1_000_005), atlasCheckCredentials: mongoLogId(1_001_001), atlasDeleteDatabaseUserFailure: mongoLogId(1_001_002), @@ -22,6 +25,7 @@ export const LogId = { telemetryMetadataError: mongoLogId(1_002_005), telemetryDeviceIdFailure: mongoLogId(1_002_006), telemetryDeviceIdTimeout: mongoLogId(1_002_007), + telemetryContainerEnvFailure: mongoLogId(1_002_008), toolExecute: mongoLogId(1_003_001), toolExecuteFailure: mongoLogId(1_003_002), @@ -29,6 +33,8 @@ export const LogId = { mongodbConnectFailure: mongoLogId(1_004_001), mongodbDisconnectFailure: mongoLogId(1_004_002), + + toolUpdateFailure: mongoLogId(1_005_001), } as const; abstract class LoggerBase { diff --git a/src/server.ts b/src/server.ts index b0e8e19c..9012fdf5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -130,7 +130,7 @@ export class Server { } } - this.telemetry.emitEvents([event]).catch(() => {}); + this.telemetry.emitEvents([event]); } private registerTools() { diff --git a/src/telemetry/telemetry.ts b/src/telemetry/telemetry.ts index ccf0eb41..3f543341 100644 --- a/src/telemetry/telemetry.ts +++ b/src/telemetry/telemetry.ts @@ -7,114 +7,152 @@ import { MACHINE_METADATA } from "./constants.js"; import { EventCache } from "./eventCache.js"; import nodeMachineId from "node-machine-id"; import { getDeviceId } from "@mongodb-js/device-id"; +import fs from "fs/promises"; + +async function fileExists(filePath: string): Promise { + try { + await fs.access(filePath, fs.constants.F_OK); + return true; // File exists + } catch (e: unknown) { + if ( + e instanceof Error && + ( + e as Error & { + code: string; + } + ).code === "ENOENT" + ) { + return false; // File does not exist + } + throw e; // Re-throw unexpected errors + } +} -type EventResult = { - success: boolean; - error?: Error; -}; +async function isContainerized(): Promise { + if (process.env.container) { + return true; + } + + const exists = await Promise.all(["/.dockerenv", "/run/.containerenv", "/var/run/.containerenv"].map(fileExists)); -export const DEVICE_ID_TIMEOUT = 3000; + return exists.includes(true); +} export class Telemetry { - private isBufferingEvents: boolean = true; - /** Resolves when the device ID is retrieved or timeout occurs */ - public deviceIdPromise: Promise | undefined; private deviceIdAbortController = new AbortController(); private eventCache: EventCache; private getRawMachineId: () => Promise; + private getContainerEnv: () => Promise; + private cachedCommonProperties?: CommonProperties; + private flushing: boolean = false; private constructor( private readonly session: Session, private readonly userConfig: UserConfig, - private readonly commonProperties: CommonProperties, - { eventCache, getRawMachineId }: { eventCache: EventCache; getRawMachineId: () => Promise } + { + eventCache, + getRawMachineId, + getContainerEnv, + }: { + eventCache: EventCache; + getRawMachineId: () => Promise; + getContainerEnv: () => Promise; + } ) { this.eventCache = eventCache; this.getRawMachineId = getRawMachineId; + this.getContainerEnv = getContainerEnv; } static create( session: Session, userConfig: UserConfig, { - commonProperties = { ...MACHINE_METADATA }, eventCache = EventCache.getInstance(), getRawMachineId = () => nodeMachineId.machineId(true), + getContainerEnv = isContainerized, }: { eventCache?: EventCache; getRawMachineId?: () => Promise; - commonProperties?: CommonProperties; + getContainerEnv?: () => Promise; } = {} ): Telemetry { - const instance = new Telemetry(session, userConfig, commonProperties, { eventCache, getRawMachineId }); - - void instance.start(); - return instance; - } - - private async start(): Promise { - if (!this.isTelemetryEnabled()) { - return; - } - this.deviceIdPromise = getDeviceId({ - getMachineId: () => this.getRawMachineId(), - onError: (reason, error) => { - switch (reason) { - case "resolutionError": - logger.debug(LogId.telemetryDeviceIdFailure, "telemetry", String(error)); - break; - case "timeout": - logger.debug(LogId.telemetryDeviceIdTimeout, "telemetry", "Device ID retrieval timed out"); - break; - case "abort": - // No need to log in the case of aborts - break; - } - }, - abortSignal: this.deviceIdAbortController.signal, + const instance = new Telemetry(session, userConfig, { + eventCache, + getRawMachineId, + getContainerEnv, }); - this.commonProperties.device_id = await this.deviceIdPromise; - - this.isBufferingEvents = false; + return instance; } public async close(): Promise { this.deviceIdAbortController.abort(); - this.isBufferingEvents = false; - await this.emitEvents(this.eventCache.getEvents()); + await this.flush(); } /** * Emits events through the telemetry pipeline * @param events - The events to emit */ - public async emitEvents(events: BaseEvent[]): Promise { - try { - if (!this.isTelemetryEnabled()) { - logger.info(LogId.telemetryEmitFailure, "telemetry", `Telemetry is disabled.`); - return; - } - - await this.emit(events); - } catch { - logger.debug(LogId.telemetryEmitFailure, "telemetry", `Error emitting telemetry events.`); - } + public emitEvents(events: BaseEvent[]): void { + void this.flush(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, - config_atlas_auth: this.session.apiClient.hasCredentials() ? "true" : "false", - config_connection_string: this.userConfig.connectionString ? "true" : "false", - }; + private async getCommonProperties(): Promise { + if (!this.cachedCommonProperties) { + let deviceId: string | undefined; + let containerEnv: boolean | undefined; + try { + await Promise.all([ + getDeviceId({ + getMachineId: () => this.getRawMachineId(), + onError: (reason, error) => { + switch (reason) { + case "resolutionError": + logger.debug(LogId.telemetryDeviceIdFailure, "telemetry", String(error)); + break; + case "timeout": + logger.debug( + LogId.telemetryDeviceIdTimeout, + "telemetry", + "Device ID retrieval timed out" + ); + break; + case "abort": + // No need to log in the case of aborts + break; + } + }, + abortSignal: this.deviceIdAbortController.signal, + }).then((id) => { + deviceId = id; + }), + this.getContainerEnv().then((env) => { + containerEnv = env; + }), + ]); + } catch (error: unknown) { + const err = error instanceof Error ? error : new Error(String(error)); + logger.debug(LogId.telemetryDeviceIdFailure, "telemetry", err.message); + } + this.cachedCommonProperties = { + ...MACHINE_METADATA, + mcp_client_version: this.session.agentRunner?.version, + mcp_client_name: this.session.agentRunner?.name, + session_id: this.session.sessionId, + config_atlas_auth: this.session.apiClient.hasCredentials() ? "true" : "false", + config_connection_string: this.userConfig.connectionString ? "true" : "false", + is_container_env: containerEnv ? "true" : "false", + device_id: deviceId, + }; + } + + return this.cachedCommonProperties; } /** @@ -135,60 +173,74 @@ export class Telemetry { } /** - * Attempts to emit events through authenticated and unauthenticated clients + * Attempts to flush events through authenticated and unauthenticated clients * Falls back to caching if both attempts fail */ - private async emit(events: BaseEvent[]): Promise { - if (this.isBufferingEvents) { - this.eventCache.appendEvents(events); + public async flush(events?: BaseEvent[]): Promise { + if (!this.isTelemetryEnabled()) { + logger.info(LogId.telemetryEmitFailure, "telemetry", `Telemetry is disabled.`); return; } - const cachedEvents = this.eventCache.getEvents(); - const allEvents = [...cachedEvents, ...events]; + if (this.flushing) { + this.eventCache.appendEvents(events ?? []); + process.nextTick(async () => { + // try again if in the middle of a flush + await this.flush(); + }); + return; + } - logger.debug( - LogId.telemetryEmitStart, - "telemetry", - `Attempting to send ${allEvents.length} events (${cachedEvents.length} cached)` - ); + this.flushing = true; - const result = await this.sendEvents(this.session.apiClient, allEvents); - if (result.success) { + try { + const cachedEvents = this.eventCache.getEvents(); + const allEvents = [...cachedEvents, ...(events ?? [])]; + if (allEvents.length <= 0) { + this.flushing = false; + return; + } + + logger.debug( + LogId.telemetryEmitStart, + "telemetry", + `Attempting to send ${allEvents.length} events (${cachedEvents.length} cached)` + ); + + await this.sendEvents(this.session.apiClient, allEvents); this.eventCache.clearEvents(); logger.debug( LogId.telemetryEmitSuccess, "telemetry", `Sent ${allEvents.length} events successfully: ${JSON.stringify(allEvents, null, 2)}` ); - return; + } catch (error: unknown) { + logger.debug( + LogId.telemetryEmitFailure, + "telemetry", + `Error sending event to client: ${error instanceof Error ? error.message : String(error)}` + ); + this.eventCache.appendEvents(events ?? []); + process.nextTick(async () => { + // try again + await this.flush(); + }); } - logger.debug( - LogId.telemetryEmitFailure, - "telemetry", - `Error sending event to client: ${result.error instanceof Error ? result.error.message : String(result.error)}` - ); - this.eventCache.appendEvents(events); + this.flushing = false; } /** * Attempts to send events through the provided API client */ - private async sendEvents(client: ApiClient, events: BaseEvent[]): Promise { - try { - await client.sendEvents( - events.map((event) => ({ - ...event, - properties: { ...this.getCommonProperties(), ...event.properties }, - })) - ); - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error : new Error(String(error)), - }; - } + private async sendEvents(client: ApiClient, events: BaseEvent[]): Promise { + const commonProperties = await this.getCommonProperties(); + + await client.sendEvents( + events.map((event) => ({ + ...event, + properties: { ...commonProperties, ...event.properties }, + })) + ); } } diff --git a/src/telemetry/types.ts b/src/telemetry/types.ts index d77cc010..05ce8f3f 100644 --- a/src/telemetry/types.ts +++ b/src/telemetry/types.ts @@ -71,4 +71,5 @@ export type CommonProperties = { config_atlas_auth?: TelemetryBoolSet; config_connection_string?: TelemetryBoolSet; session_id?: string; + is_container_env?: TelemetryBoolSet; } & CommonStaticProperties; diff --git a/src/tools/atlas/create/createProject.ts b/src/tools/atlas/create/createProject.ts index 8cb6e1a9..cdf71b9c 100644 --- a/src/tools/atlas/create/createProject.ts +++ b/src/tools/atlas/create/createProject.ts @@ -28,7 +28,13 @@ export class CreateProjectTool extends AtlasToolBase { "No organizations were found in your MongoDB Atlas account. Please create an organization first." ); } - organizationId = organizations.results[0].id; + const firstOrg = organizations.results[0]; + if (!firstOrg?.id) { + throw new Error( + "The first organization found does not have an ID. Please check your Atlas account." + ); + } + organizationId = firstOrg.id; assumedOrg = true; } catch { throw new Error( diff --git a/src/tools/atlas/read/listAlerts.ts b/src/tools/atlas/read/listAlerts.ts new file mode 100644 index 00000000..bbbf6f14 --- /dev/null +++ b/src/tools/atlas/read/listAlerts.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { AtlasToolBase } from "../atlasTool.js"; +import { ToolArgs, OperationType } from "../../tool.js"; + +export class ListAlertsTool extends AtlasToolBase { + protected name = "atlas-list-alerts"; + protected description = "List MongoDB Atlas alerts"; + protected operationType: OperationType = "read"; + protected argsShape = { + projectId: z.string().describe("Atlas project ID to list alerts for"), + }; + + protected async execute({ projectId }: ToolArgs): Promise { + const data = await this.session.apiClient.listAlerts({ + params: { + path: { + groupId: projectId, + }, + }, + }); + + if (!data?.results?.length) { + return { content: [{ type: "text", text: "No alerts found in your MongoDB Atlas project." }] }; + } + + // Format alerts as a table + const output = + `Alert ID | Status | Created | Updated | Type | Comment +----------|---------|----------|----------|------|-------- +` + + data.results + .map((alert) => { + const created = alert.created ? new Date(alert.created).toLocaleString() : "N/A"; + const updated = alert.updated ? new Date(alert.updated).toLocaleString() : "N/A"; + const comment = alert.acknowledgementComment ?? "N/A"; + return `${alert.id} | ${alert.status} | ${created} | ${updated} | ${alert.eventTypeName} | ${comment}`; + }) + .join("\n"); + + return { + content: [{ type: "text", text: output }], + }; + } +} diff --git a/src/tools/atlas/read/listProjects.ts b/src/tools/atlas/read/listProjects.ts index 3e30d38d..1a9ab523 100644 --- a/src/tools/atlas/read/listProjects.ts +++ b/src/tools/atlas/read/listProjects.ts @@ -21,7 +21,8 @@ export class ListProjectsTool extends AtlasToolBase { const orgs: Record = orgData.results .map((org) => [org.id || "", org.name]) - .reduce((acc, [id, name]) => ({ ...acc, [id]: name }), {}); + .filter(([id]) => id) + .reduce((acc, [id, name]) => ({ ...acc, [id as string]: name }), {}); const data = orgId ? await this.session.apiClient.listOrganizationProjects({ @@ -41,7 +42,8 @@ export class ListProjectsTool extends AtlasToolBase { const rows = data.results .map((project) => { const createdAt = project.created ? new Date(project.created).toLocaleString() : "N/A"; - return `${project.name} | ${project.id} | ${orgs[project.orgId]} | ${project.orgId} | ${createdAt}`; + const orgName = orgs[project.orgId] ?? "N/A"; + return `${project.name} | ${project.id} | ${orgName} | ${project.orgId} | ${createdAt}`; }) .join("\n"); const formattedProjects = `Project Name | Project ID | Organization Name | Organization ID | Created At diff --git a/src/tools/atlas/tools.ts b/src/tools/atlas/tools.ts index 6ba21a4e..9c27740d 100644 --- a/src/tools/atlas/tools.ts +++ b/src/tools/atlas/tools.ts @@ -9,6 +9,7 @@ import { CreateDBUserTool } from "./create/createDBUser.js"; import { CreateProjectTool } from "./create/createProject.js"; import { ListOrganizationsTool } from "./read/listOrgs.js"; import { ConnectClusterTool } from "./metadata/connectCluster.js"; +import { ListAlertsTool } from "./read/listAlerts.js"; export const AtlasTools = [ ListClustersTool, @@ -22,4 +23,5 @@ export const AtlasTools = [ CreateProjectTool, ListOrganizationsTool, ConnectClusterTool, + ListAlertsTool, ]; diff --git a/src/tools/mongodb/metadata/listDatabases.ts b/src/tools/mongodb/metadata/listDatabases.ts index ce943a69..fe324f07 100644 --- a/src/tools/mongodb/metadata/listDatabases.ts +++ b/src/tools/mongodb/metadata/listDatabases.ts @@ -7,7 +7,6 @@ export class ListDatabasesTool extends MongoDBToolBase { protected name = "list-databases"; protected description = "List all databases for a MongoDB connection"; protected argsShape = {}; - protected operationType: OperationType = "metadata"; protected async execute(): Promise { diff --git a/src/tools/mongodb/read/count.ts b/src/tools/mongodb/read/count.ts index bd86169b..5d97afa9 100644 --- a/src/tools/mongodb/read/count.ts +++ b/src/tools/mongodb/read/count.ts @@ -8,13 +8,14 @@ export const CountArgs = { .record(z.string(), z.unknown()) .optional() .describe( - "The query filter to count documents. Matches the syntax of the filter argument of db.collection.count()" + "A filter/query parameter. Allows users to filter the documents to count. Matches the syntax of the filter argument of db.collection.count()." ), }; export class CountTool extends MongoDBToolBase { protected name = "count"; - protected description = "Gets the number of documents in a MongoDB collection"; + protected description = + "Gets the number of documents in a MongoDB collection using db.collection.count() and query as an optional filter parameter"; protected argsShape = { ...DbOperationArgs, ...CountArgs, diff --git a/src/tools/tool.ts b/src/tools/tool.ts index 5e4fc1a3..37375f70 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -1,6 +1,6 @@ import { z, type ZodRawShape, type ZodNever, AnyZodObject } from "zod"; import type { McpServer, RegisteredTool, ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js"; -import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import type { CallToolResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js"; import { Session } from "../session.js"; import logger, { LogId } from "../logger.js"; import { Telemetry } from "../telemetry/telemetry.js"; @@ -27,6 +27,34 @@ export abstract class ToolBase { protected abstract argsShape: ZodRawShape; + protected get annotations(): ToolAnnotations { + const annotations: ToolAnnotations = { + title: this.name, + description: this.description, + }; + + switch (this.operationType) { + case "read": + case "metadata": + annotations.readOnlyHint = true; + annotations.destructiveHint = false; + break; + case "delete": + annotations.readOnlyHint = false; + annotations.destructiveHint = true; + break; + case "create": + case "update": + annotations.destructiveHint = false; + annotations.readOnlyHint = false; + break; + default: + break; + } + + return annotations; + } + protected abstract execute(...args: Parameters>): Promise; constructor( @@ -43,20 +71,20 @@ export abstract class ToolBase { const callback: ToolCallback = async (...args) => { const startTime = Date.now(); try { - logger.debug(LogId.toolExecute, "tool", `Executing ${this.name} with args: ${JSON.stringify(args)}`); + logger.debug(LogId.toolExecute, "tool", `Executing tool ${this.name}`); const result = await this.execute(...args); - await this.emitToolEvent(startTime, result, ...args).catch(() => {}); + this.emitToolEvent(startTime, result, ...args); return result; } catch (error: unknown) { logger.error(LogId.toolExecuteFailure, "tool", `Error executing ${this.name}: ${error as string}`); const toolResult = await this.handleError(error, args[0] as ToolArgs); - await this.emitToolEvent(startTime, toolResult, ...args).catch(() => {}); + this.emitToolEvent(startTime, toolResult, ...args); return toolResult; } }; - server.tool(this.name, this.description, this.argsShape, callback); + server.tool(this.name, this.description, this.argsShape, this.annotations, callback); // This is very similar to RegisteredTool.update, but without the bugs around the name. // In the upstream update method, the name is captured in the closure and not updated when @@ -66,13 +94,22 @@ export abstract class ToolBase { const tools = server["_registeredTools"] as { [toolName: string]: RegisteredTool }; const existingTool = tools[this.name]; + if (!existingTool) { + logger.warning(LogId.toolUpdateFailure, "tool", `Tool ${this.name} not found in update`); + return; + } + + existingTool.annotations = this.annotations; + if (updates.name && updates.name !== this.name) { + existingTool.annotations.title = updates.name; delete tools[this.name]; this.name = updates.name; tools[this.name] = existingTool; } if (updates.description) { + existingTool.annotations.description = updates.description; existingTool.description = updates.description; this.description = updates.description; } @@ -142,11 +179,11 @@ export abstract class ToolBase { * @param result - Whether the command succeeded or failed * @param args - The arguments passed to the tool */ - private async emitToolEvent( + private emitToolEvent( startTime: number, result: CallToolResult, ...args: Parameters> - ): Promise { + ): void { if (!this.telemetry.isTelemetryEnabled()) { return; } @@ -172,6 +209,6 @@ export abstract class ToolBase { event.properties.project_id = metadata.projectId; } - await this.telemetry.emitEvents([event]); + this.telemetry.emitEvents([event]); } } diff --git a/tests/integration/helpers.ts b/tests/integration/helpers.ts index 9d529376..e407e250 100644 --- a/tests/integration/helpers.ts +++ b/tests/integration/helpers.ts @@ -206,6 +206,7 @@ export function validateToolMetadata( expectDefined(tool); expect(tool.description).toBe(description); + validateToolAnnotations(tool, name, description); const toolParameters = getParameters(tool); expect(toolParameters).toHaveLength(parameters.length); expect(toolParameters).toIncludeAllMembers(parameters); @@ -240,3 +241,25 @@ export function expectDefined(arg: T): asserts arg is Exclude { - it("should resolve the actual machine ID", async () => { - const actualId: string = await nodeMachineId.machineId(true); - - const actualHashedId = createHmac("sha256", actualId.toUpperCase()).update("atlascli").digest("hex"); - - const telemetry = Telemetry.create( - new Session({ - apiBaseUrl: "", - }), - config - ); - - expect(telemetry.getCommonProperties().device_id).toBe(undefined); - expect(telemetry["isBufferingEvents"]).toBe(true); - - await telemetry.deviceIdPromise; - - expect(telemetry.getCommonProperties().device_id).toBe(actualHashedId); - expect(telemetry["isBufferingEvents"]).toBe(false); - }); -}); diff --git a/tests/integration/tools/atlas/accessLists.test.ts b/tests/integration/tools/atlas/accessLists.test.ts index a194a351..d2dc219c 100644 --- a/tests/integration/tools/atlas/accessLists.test.ts +++ b/tests/integration/tools/atlas/accessLists.test.ts @@ -67,7 +67,7 @@ describeWithAtlas("ip access lists", (integration) => { })) as CallToolResult; expect(response.content).toBeArray(); expect(response.content).toHaveLength(1); - expect(response.content[0].text).toContain("IP/CIDR ranges added to access list"); + expect(response.content[0]?.text).toContain("IP/CIDR ranges added to access list"); }); }); @@ -90,7 +90,7 @@ describeWithAtlas("ip access lists", (integration) => { expect(response.content).toBeArray(); expect(response.content).toHaveLength(1); for (const value of values) { - expect(response.content[0].text).toContain(value); + expect(response.content[0]?.text).toContain(value); } }); }); diff --git a/tests/integration/tools/atlas/alerts.test.ts b/tests/integration/tools/atlas/alerts.test.ts new file mode 100644 index 00000000..3e95cced --- /dev/null +++ b/tests/integration/tools/atlas/alerts.test.ts @@ -0,0 +1,42 @@ +import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { expectDefined } from "../../helpers.js"; +import { parseTable, describeWithAtlas, withProject } from "./atlasHelpers.js"; + +describeWithAtlas("alerts", (integration) => { + describe("atlas-list-alerts", () => { + it("should have correct metadata", async () => { + const { tools } = await integration.mcpClient().listTools(); + const listAlerts = tools.find((tool) => tool.name === "atlas-list-alerts"); + expectDefined(listAlerts); + expect(listAlerts.inputSchema.type).toBe("object"); + expectDefined(listAlerts.inputSchema.properties); + expect(listAlerts.inputSchema.properties).toHaveProperty("projectId"); + }); + + withProject(integration, ({ getProjectId }) => { + it("returns alerts in table format", async () => { + const response = (await integration.mcpClient().callTool({ + name: "atlas-list-alerts", + arguments: { projectId: getProjectId() }, + })) as CallToolResult; + + expect(response.content).toBeArray(); + expect(response.content).toHaveLength(1); + + const data = parseTable(response.content[0]?.text as string); + expect(data).toBeArray(); + + // Since we can't guarantee alerts will exist, we just verify the table structure + if (data.length > 0) { + const alert = data[0]; + expect(alert).toHaveProperty("Alert ID"); + expect(alert).toHaveProperty("Status"); + expect(alert).toHaveProperty("Created"); + expect(alert).toHaveProperty("Updated"); + expect(alert).toHaveProperty("Type"); + expect(alert).toHaveProperty("Comment"); + } + }); + }); + }); +}); diff --git a/tests/integration/tools/atlas/atlasHelpers.ts b/tests/integration/tools/atlas/atlasHelpers.ts index aecf0479..f03e1dc7 100644 --- a/tests/integration/tools/atlas/atlasHelpers.ts +++ b/tests/integration/tools/atlas/atlasHelpers.ts @@ -75,7 +75,9 @@ export function parseTable(text: string): Record[] { .map((cells) => { const row: Record = {}; cells.forEach((cell, index) => { - row[headers[index]] = cell; + if (headers) { + row[headers[index] ?? ""] = cell; + } }); return row; }); @@ -87,14 +89,14 @@ async function createProject(apiClient: ApiClient): Promise { const projectName: string = `testProj-` + randomId; const orgs = await apiClient.listOrganizations(); - if (!orgs?.results?.length || !orgs.results[0].id) { + 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, + orgId: orgs.results[0]?.id ?? "", } as Group, }); diff --git a/tests/integration/tools/atlas/clusters.test.ts b/tests/integration/tools/atlas/clusters.test.ts index f9e07943..166ee637 100644 --- a/tests/integration/tools/atlas/clusters.test.ts +++ b/tests/integration/tools/atlas/clusters.test.ts @@ -88,7 +88,7 @@ describeWithAtlas("clusters", (integration) => { })) as CallToolResult; expect(response.content).toBeArray(); expect(response.content).toHaveLength(2); - expect(response.content[0].text).toContain("has been created"); + expect(response.content[0]?.text).toContain("has been created"); }); }); @@ -113,7 +113,7 @@ describeWithAtlas("clusters", (integration) => { })) as CallToolResult; expect(response.content).toBeArray(); expect(response.content).toHaveLength(1); - expect(response.content[0].text).toContain(`${clusterName} | `); + expect(response.content[0]?.text).toContain(`${clusterName} | `); }); }); @@ -135,7 +135,7 @@ describeWithAtlas("clusters", (integration) => { .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} | `); + expect(response.content[1]?.text).toContain(`${clusterName} | `); }); }); @@ -178,7 +178,7 @@ describeWithAtlas("clusters", (integration) => { })) as CallToolResult; expect(response.content).toBeArray(); expect(response.content).toHaveLength(1); - expect(response.content[0].text).toContain(`Connected to cluster "${clusterName}"`); + expect(response.content[0]?.text).toContain(`Connected to cluster "${clusterName}"`); }); }); }); diff --git a/tests/integration/tools/atlas/dbUsers.test.ts b/tests/integration/tools/atlas/dbUsers.test.ts index 2bcb95fa..3bfb979e 100644 --- a/tests/integration/tools/atlas/dbUsers.test.ts +++ b/tests/integration/tools/atlas/dbUsers.test.ts @@ -65,18 +65,18 @@ describeWithAtlas("db users", (integration) => { const elements = getResponseElements(response); expect(elements).toHaveLength(1); - expect(elements[0].text).toContain("created successfully"); - expect(elements[0].text).toContain(userName); - expect(elements[0].text).not.toContain("testpassword"); + expect(elements[0]?.text).toContain("created successfully"); + expect(elements[0]?.text).toContain(userName); + expect(elements[0]?.text).not.toContain("testpassword"); }); it("should create a database user with generated password", async () => { const response = await createUserWithMCP(); const elements = getResponseElements(response); expect(elements).toHaveLength(1); - expect(elements[0].text).toContain("created successfully"); - expect(elements[0].text).toContain(userName); - expect(elements[0].text).toContain("with password: `"); + expect(elements[0]?.text).toContain("created successfully"); + expect(elements[0]?.text).toContain(userName); + expect(elements[0]?.text).toContain("with password: `"); }); }); describe("atlas-list-db-users", () => { @@ -98,7 +98,7 @@ describeWithAtlas("db users", (integration) => { .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); + 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 index 83143404..246a37db 100644 --- a/tests/integration/tools/atlas/orgs.test.ts +++ b/tests/integration/tools/atlas/orgs.test.ts @@ -16,9 +16,9 @@ describeWithAtlas("orgs", (integration) => { .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); + const data = parseTable(response.content[0]?.text as string); expect(data).toHaveLength(1); - expect(data[0]["Organization Name"]).toEqual("MongoDB MCP Test"); + 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 index 7d773c7e..d7258fa1 100644 --- a/tests/integration/tools/atlas/projects.test.ts +++ b/tests/integration/tools/atlas/projects.test.ts @@ -43,7 +43,7 @@ describeWithAtlas("projects", (integration) => { })) as CallToolResult; expect(response.content).toBeArray(); expect(response.content).toHaveLength(1); - expect(response.content[0].text).toContain(projName); + expect(response.content[0]?.text).toContain(projName); }); }); describe("atlas-list-projects", () => { @@ -62,8 +62,8 @@ describeWithAtlas("projects", (integration) => { .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(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; diff --git a/tests/integration/tools/mongodb/create/createCollection.test.ts b/tests/integration/tools/mongodb/create/createCollection.test.ts index ef8da5f1..3e0d1689 100644 --- a/tests/integration/tools/mongodb/create/createCollection.test.ts +++ b/tests/integration/tools/mongodb/create/createCollection.test.ts @@ -34,7 +34,7 @@ describeWithMongoDB("createCollection tool", (integration) => { collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); expect(collections).toHaveLength(1); - expect(collections[0].name).toEqual("bar"); + expect(collections[0]?.name).toEqual("bar"); }); }); @@ -78,7 +78,7 @@ describeWithMongoDB("createCollection tool", (integration) => { 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"); + 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(); diff --git a/tests/integration/tools/mongodb/create/createIndex.test.ts b/tests/integration/tools/mongodb/create/createIndex.test.ts index b1a2a5df..f4929b92 100644 --- a/tests/integration/tools/mongodb/create/createIndex.test.ts +++ b/tests/integration/tools/mongodb/create/createIndex.test.ts @@ -38,10 +38,10 @@ describeWithMongoDB("createIndex tool", (integration) => { const mongoClient = integration.mongoClient(); const collections = await mongoClient.db(integration.randomDbName()).listCollections().toArray(); expect(collections).toHaveLength(1); - expect(collections[0].name).toEqual("coll1"); + 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_"); + expect(indexes[0]?.name).toEqual("_id_"); for (const index of expected) { const foundIndex = indexes.find((i) => i.name === index.name); expectDefined(foundIndex); diff --git a/tests/integration/tools/mongodb/create/insertMany.test.ts b/tests/integration/tools/mongodb/create/insertMany.test.ts index a49c3a4e..eb8e1ef4 100644 --- a/tests/integration/tools/mongodb/create/insertMany.test.ts +++ b/tests/integration/tools/mongodb/create/insertMany.test.ts @@ -82,7 +82,7 @@ describeWithMongoDB("insertMany tool", (integration) => { const content = getResponseContent(response.content); expect(content).toContain("Error running insert-many"); expect(content).toContain("duplicate key error"); - expect(content).toContain(insertedIds[0].toString()); + expect(content).toContain(insertedIds[0]?.toString()); }); validateAutoConnectBehavior(integration, "insert-many", () => { diff --git a/tests/integration/tools/mongodb/delete/dropCollection.test.ts b/tests/integration/tools/mongodb/delete/dropCollection.test.ts index 1dcaa218..48707156 100644 --- a/tests/integration/tools/mongodb/delete/dropCollection.test.ts +++ b/tests/integration/tools/mongodb/delete/dropCollection.test.ts @@ -54,7 +54,7 @@ describeWithMongoDB("dropCollection tool", (integration) => { ); const collections = await integration.mongoClient().db(integration.randomDbName()).listCollections().toArray(); expect(collections).toHaveLength(1); - expect(collections[0].name).toBe("coll2"); + expect(collections[0]?.name).toBe("coll2"); }); validateAutoConnectBehavior(integration, "drop-collection", () => { diff --git a/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts b/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts index 1b7481a2..e67b0ce5 100644 --- a/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts +++ b/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts @@ -132,11 +132,11 @@ describeWithMongoDB("collectionSchema tool", (integration) => { expect(items).toHaveLength(2); // Expect to find _id, name, age - expect(items[0].text).toEqual( + 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; + const schema = JSON.parse(items[1]?.text ?? "{}") as SimplifiedSchema; expect(schema).toEqual(testCase.expectedSchema); }); } diff --git a/tests/integration/tools/mongodb/metadata/dbStats.test.ts b/tests/integration/tools/mongodb/metadata/dbStats.test.ts index b26a2cf2..2ce4a84c 100644 --- a/tests/integration/tools/mongodb/metadata/dbStats.test.ts +++ b/tests/integration/tools/mongodb/metadata/dbStats.test.ts @@ -28,9 +28,9 @@ describeWithMongoDB("dbStats tool", (integration) => { }); const elements = getResponseElements(response.content); expect(elements).toHaveLength(2); - expect(elements[0].text).toBe(`Statistics for database ${integration.randomDbName()}`); + expect(elements[0]?.text).toBe(`Statistics for database ${integration.randomDbName()}`); - const stats = JSON.parse(elements[1].text) as { + const stats = JSON.parse(elements[1]?.text ?? "{}") as { db: string; collections: number; storageSize: number; @@ -75,9 +75,9 @@ describeWithMongoDB("dbStats tool", (integration) => { }); const elements = getResponseElements(response.content); expect(elements).toHaveLength(2); - expect(elements[0].text).toBe(`Statistics for database ${integration.randomDbName()}`); + expect(elements[0]?.text).toBe(`Statistics for database ${integration.randomDbName()}`); - const stats = JSON.parse(elements[1].text) as { + const stats = JSON.parse(elements[1]?.text ?? "{}") as { db: string; collections: unknown; storageSize: unknown; diff --git a/tests/integration/tools/mongodb/metadata/explain.test.ts b/tests/integration/tools/mongodb/metadata/explain.test.ts index 0aeb92ea..44cfe6ff 100644 --- a/tests/integration/tools/mongodb/metadata/explain.test.ts +++ b/tests/integration/tools/mongodb/metadata/explain.test.ts @@ -89,12 +89,12 @@ describeWithMongoDB("explain tool", (integration) => { const content = getResponseElements(response.content); expect(content).toHaveLength(2); - expect(content[0].text).toEqual( + 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"); + expect(content[1]?.text).toContain("queryPlanner"); + expect(content[1]?.text).toContain("winningPlan"); }); } }); @@ -139,22 +139,22 @@ describeWithMongoDB("explain tool", (integration) => { const content = getResponseElements(response.content); expect(content).toHaveLength(2); - expect(content[0].text).toEqual( + 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"); + 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"); + expect(content[1]?.text).toContain("COUNT_SCAN"); } else { - expect(content[1].text).toContain("IXSCAN"); + expect(content[1]?.text).toContain("IXSCAN"); } - expect(content[1].text).toContain("name_1"); + expect(content[1]?.text).toContain("name_1"); } else { - expect(content[1].text).toContain("COLLSCAN"); + expect(content[1]?.text).toContain("COLLSCAN"); } }); } diff --git a/tests/integration/tools/mongodb/metadata/listCollections.test.ts b/tests/integration/tools/mongodb/metadata/listCollections.test.ts index cef0a59d..c975d8de 100644 --- a/tests/integration/tools/mongodb/metadata/listCollections.test.ts +++ b/tests/integration/tools/mongodb/metadata/listCollections.test.ts @@ -45,7 +45,7 @@ describeWithMongoDB("listCollections tool", (integration) => { }); const items = getResponseElements(response.content); expect(items).toHaveLength(1); - expect(items[0].text).toContain('Name: "collection-1"'); + expect(items[0]?.text).toContain('Name: "collection-1"'); await mongoClient.db(integration.randomDbName()).createCollection("collection-2"); diff --git a/tests/integration/tools/mongodb/metadata/listDatabases.test.ts b/tests/integration/tools/mongodb/metadata/listDatabases.test.ts index de803c6c..b828d743 100644 --- a/tests/integration/tools/mongodb/metadata/listDatabases.test.ts +++ b/tests/integration/tools/mongodb/metadata/listDatabases.test.ts @@ -65,9 +65,13 @@ describeWithMongoDB("listDatabases tool", (integration) => { 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; - }); + return responseItems + .map((item) => { + if (item && typeof item.text === "string") { + const match = item.text.match(/Name: ([^,]+), Size: \d+ bytes/); + return match ? match[1] : null; + } + return null; + }) + .filter((item): item is string | null => item !== undefined); } diff --git a/tests/integration/tools/mongodb/metadata/logs.test.ts b/tests/integration/tools/mongodb/metadata/logs.test.ts index bc7f79bc..debbb1ae 100644 --- a/tests/integration/tools/mongodb/metadata/logs.test.ts +++ b/tests/integration/tools/mongodb/metadata/logs.test.ts @@ -37,11 +37,11 @@ describeWithMongoDB("logs tool", (integration) => { // Default limit is 50 expect(elements.length).toBeLessThanOrEqual(51); - expect(elements[0].text).toMatch(/Found: \d+ messages/); + expect(elements[0]?.text).toMatch(/Found: \d+ messages/); for (let i = 1; i < elements.length; i++) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const log = JSON.parse(elements[i].text); + const log = JSON.parse(elements[i]?.text ?? "{}"); expect(log).toHaveProperty("t"); expect(log).toHaveProperty("msg"); } @@ -59,7 +59,7 @@ describeWithMongoDB("logs tool", (integration) => { const elements = getResponseElements(response); expect(elements.length).toBeLessThanOrEqual(51); for (let i = 1; i < elements.length; i++) { - const log = JSON.parse(elements[i].text) as { tags: string[] }; + const log = JSON.parse(elements[i]?.text ?? "{}") as { tags: string[] }; expect(log).toHaveProperty("t"); expect(log).toHaveProperty("msg"); expect(log).toHaveProperty("tags"); @@ -76,7 +76,7 @@ describeWithMongoDB("logs tool", (integration) => { validate: (content) => { const elements = getResponseElements(content); expect(elements.length).toBeLessThanOrEqual(51); - expect(elements[0].text).toMatch(/Found: \d+ messages/); + expect(elements[0]?.text).toMatch(/Found: \d+ messages/); }, }; }); diff --git a/tests/integration/tools/mongodb/read/aggregate.test.ts b/tests/integration/tools/mongodb/read/aggregate.test.ts index 65d243d9..6cf6aff0 100644 --- a/tests/integration/tools/mongodb/read/aggregate.test.ts +++ b/tests/integration/tools/mongodb/read/aggregate.test.ts @@ -35,7 +35,7 @@ describeWithMongoDB("aggregate tool", (integration) => { const elements = getResponseElements(response.content); expect(elements).toHaveLength(1); - expect(elements[0].text).toEqual('Found 0 documents in the collection "people":'); + expect(elements[0]?.text).toEqual('Found 0 documents in the collection "people":'); }); it("can run aggragation on an empty collection", async () => { @@ -53,7 +53,7 @@ describeWithMongoDB("aggregate tool", (integration) => { const elements = getResponseElements(response.content); expect(elements).toHaveLength(1); - expect(elements[0].text).toEqual('Found 0 documents in the collection "people":'); + expect(elements[0]?.text).toEqual('Found 0 documents in the collection "people":'); }); it("can run aggragation on an existing collection", async () => { @@ -79,11 +79,21 @@ describeWithMongoDB("aggregate tool", (integration) => { const elements = getResponseElements(response.content); expect(elements).toHaveLength(3); - expect(elements[0].text).toEqual('Found 2 documents in the collection "people":'); - /* eslint-disable @typescript-eslint/no-unsafe-assignment */ - 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 }); - /* eslint-enable @typescript-eslint/no-unsafe-assignment */ + expect(elements[0]?.text).toEqual('Found 2 documents in the collection "people":'); + expect(asObject(JSON.parse(elements[1]?.text ?? "{}"))).toEqual( + expect.objectContaining({ + _id: expect.any(Object) as object, + name: "Søren", + age: 15, + }) + ); + expect(asObject(JSON.parse(elements[2]?.text ?? "{}"))).toEqual( + expect.objectContaining({ + _id: expect.any(Object) as object, + name: "Laura", + age: 10, + }) + ); }); validateAutoConnectBehavior(integration, "aggregate", () => { @@ -97,3 +107,8 @@ describeWithMongoDB("aggregate tool", (integration) => { }; }); }); + +function asObject(val: unknown): Record { + if (typeof val === "object" && val !== null) return val as Record; + throw new Error("Expected an object"); +} diff --git a/tests/integration/tools/mongodb/read/collectionIndexes.test.ts b/tests/integration/tools/mongodb/read/collectionIndexes.test.ts index 3c5b2eb1..5902cfb7 100644 --- a/tests/integration/tools/mongodb/read/collectionIndexes.test.ts +++ b/tests/integration/tools/mongodb/read/collectionIndexes.test.ts @@ -28,7 +28,7 @@ describeWithMongoDB("collectionIndexes tool", (integration) => { const elements = getResponseElements(response.content); expect(elements).toHaveLength(1); - expect(elements[0].text).toEqual( + expect(elements[0]?.text).toEqual( 'The indexes for "non-existent.people" cannot be determined because the collection does not exist.' ); }); @@ -47,8 +47,8 @@ describeWithMongoDB("collectionIndexes tool", (integration) => { 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}'); + 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 () => { @@ -74,8 +74,8 @@ describeWithMongoDB("collectionIndexes tool", (integration) => { 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}'); + 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}`)); diff --git a/tests/integration/tools/mongodb/read/count.test.ts b/tests/integration/tools/mongodb/read/count.test.ts index 5b288448..39b88607 100644 --- a/tests/integration/tools/mongodb/read/count.test.ts +++ b/tests/integration/tools/mongodb/read/count.test.ts @@ -8,16 +8,21 @@ import { } 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, - ]); + validateToolMetadata( + integration, + "count", + "Gets the number of documents in a MongoDB collection using db.collection.count() and query as an optional filter parameter", + [ + { + name: "query", + description: + "A filter/query parameter. Allows users to filter the documents to count. Matches the syntax of the filter argument of db.collection.count().", + type: "object", + required: false, + }, + ...databaseCollectionParameters, + ] + ); validateThrowsForInvalidArguments(integration, "count", [ {}, diff --git a/tests/integration/tools/mongodb/read/find.test.ts b/tests/integration/tools/mongodb/read/find.test.ts index 05fd0b75..209ed1a5 100644 --- a/tests/integration/tools/mongodb/read/find.test.ts +++ b/tests/integration/tools/mongodb/read/find.test.ts @@ -149,10 +149,10 @@ describeWithMongoDB("find tool", (integration) => { }); const elements = getResponseElements(response.content); expect(elements).toHaveLength(expected.length + 1); - expect(elements[0].text).toEqual(`Found ${expected.length} documents in the collection "foo":`); + 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]); + expect(JSON.parse(elements[i + 1]?.text ?? "{}")).toEqual(expected[i]); } }); } @@ -165,11 +165,11 @@ describeWithMongoDB("find tool", (integration) => { }); const elements = getResponseElements(response.content); expect(elements).toHaveLength(11); - expect(elements[0].text).toEqual('Found 10 documents in the collection "foo":'); + expect(elements[0]?.text).toEqual('Found 10 documents in the collection "foo":'); for (let i = 0; i < 10; i++) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - expect(JSON.parse(elements[i + 1].text).value).toEqual(i); + expect(JSON.parse(elements[i + 1]?.text ?? "{}").value).toEqual(i); } }); @@ -194,10 +194,10 @@ describeWithMongoDB("find tool", (integration) => { const elements = getResponseElements(response.content); expect(elements).toHaveLength(2); - expect(elements[0].text).toEqual('Found 1 documents in the collection "foo":'); + expect(elements[0]?.text).toEqual('Found 1 documents in the collection "foo":'); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - expect(JSON.parse(elements[1].text).value).toEqual(fooObject.value); + expect(JSON.parse(elements[1]?.text ?? "{}").value).toEqual(fooObject.value); }); }); diff --git a/tests/integration/tools/mongodb/update/renameCollection.test.ts b/tests/integration/tools/mongodb/update/renameCollection.test.ts index e3d00e54..6e7a4128 100644 --- a/tests/integration/tools/mongodb/update/renameCollection.test.ts +++ b/tests/integration/tools/mongodb/update/renameCollection.test.ts @@ -94,7 +94,7 @@ describeWithMongoDB("renameCollection tool", (integration) => { .find({}) .toArray(); expect(docsInAfter).toHaveLength(1); - expect(docsInAfter[0].value).toEqual(42); + expect(docsInAfter[0]?.value).toEqual(42); }); it("returns an error when renaming to an existing collection", async () => { @@ -123,7 +123,7 @@ describeWithMongoDB("renameCollection tool", (integration) => { .find({}) .toArray(); expect(docsInBefore).toHaveLength(1); - expect(docsInBefore[0].value).toEqual(42); + expect(docsInBefore[0]?.value).toEqual(42); const docsInAfter = await integration .mongoClient() @@ -132,7 +132,7 @@ describeWithMongoDB("renameCollection tool", (integration) => { .find({}) .toArray(); expect(docsInAfter).toHaveLength(1); - expect(docsInAfter[0].value).toEqual(84); + expect(docsInAfter[0]?.value).toEqual(84); }); it("renames to existing collection with dropTarget", async () => { @@ -174,7 +174,7 @@ describeWithMongoDB("renameCollection tool", (integration) => { .find({}) .toArray(); expect(docsInAfter).toHaveLength(1); - expect(docsInAfter[0].value).toEqual(42); + expect(docsInAfter[0]?.value).toEqual(42); }); }); diff --git a/tests/unit/EJsonTransport.test.ts b/tests/unit/EJsonTransport.test.ts index f0371cf4..6bbb7999 100644 --- a/tests/unit/EJsonTransport.test.ts +++ b/tests/unit/EJsonTransport.test.ts @@ -37,7 +37,7 @@ describe("EJsonTransport", () => { ); expect(messages.length).toBe(1); - const message = messages[0].message; + const message = messages[0]?.message; expect(message).toEqual({ jsonrpc: "2.0", diff --git a/tests/unit/session.test.ts b/tests/unit/session.test.ts index f60feca1..44126359 100644 --- a/tests/unit/session.test.ts +++ b/tests/unit/session.test.ts @@ -53,7 +53,7 @@ describe("Session", () => { typeof NodeDriverServiceProvider.connect >; expect(connectMock).toHaveBeenCalledOnce(); - const connectionString = connectMock.mock.calls[0][0]; + const connectionString = connectMock.mock.calls[0]?.[0]; if (testCase.expectAppName) { expect(connectionString).toContain("appName=MongoDB+MCP+Server"); } else { diff --git a/tests/unit/telemetry.test.ts b/tests/unit/telemetry.test.ts index c1ae28ea..3e27f9eb 100644 --- a/tests/unit/telemetry.test.ts +++ b/tests/unit/telemetry.test.ts @@ -1,6 +1,6 @@ import { ApiClient } from "../../src/common/atlas/apiClient.js"; import { Session } from "../../src/session.js"; -import { DEVICE_ID_TIMEOUT, Telemetry } from "../../src/telemetry/telemetry.js"; +import { Telemetry } from "../../src/telemetry/telemetry.js"; import { BaseEvent, TelemetryResult } from "../../src/telemetry/types.js"; import { EventCache } from "../../src/telemetry/eventCache.js"; import { config } from "../../src/config.js"; @@ -16,6 +16,8 @@ const MockApiClient = ApiClient as jest.MockedClass; jest.mock("../../src/telemetry/eventCache.js"); const MockEventCache = EventCache as jest.MockedClass; +const nextTick = () => new Promise((resolve) => process.nextTick(resolve)); + describe("Telemetry", () => { const machineId = "test-machine-id"; const hashedMachineId = createHmac("sha256", machineId.toUpperCase()).update("atlascli").digest("hex"); @@ -24,6 +26,11 @@ describe("Telemetry", () => { let mockEventCache: jest.Mocked; let session: Session; let telemetry: Telemetry; + let telemetryConfig: { + eventCache: EventCache; + getRawMachineId: () => Promise; + getContainerEnv: () => Promise; + }; // Helper function to create properly typed test events function createTestEvent(options?: { @@ -77,19 +84,11 @@ describe("Telemetry", () => { expect(appendEvents.length).toBe(appendEventsCalls); if (sendEventsCalledWith) { - expect(sendEvents[0]?.[0]).toEqual( - sendEventsCalledWith.map((event) => ({ - ...event, - properties: { - ...telemetry.getCommonProperties(), - ...event.properties, - }, - })) - ); + expect(sendEvents[0]?.[0]).toMatchObject(sendEventsCalledWith); } if (appendEventsCalledWith) { - expect(appendEvents[0]?.[0]).toEqual(appendEventsCalledWith); + expect(appendEvents[0]?.[0]).toMatchObject(appendEventsCalledWith); } } @@ -125,10 +124,13 @@ describe("Telemetry", () => { setAgentRunner: jest.fn().mockResolvedValue(undefined), } as unknown as Session; - telemetry = Telemetry.create(session, config, { + telemetryConfig = { eventCache: mockEventCache, getRawMachineId: () => Promise.resolve(machineId), - }); + getContainerEnv: () => Promise.resolve(false), + }; + + telemetry = Telemetry.create(session, config, telemetryConfig); config.telemetry = "enabled"; }); @@ -138,7 +140,8 @@ describe("Telemetry", () => { it("should send events successfully", async () => { const testEvent = createTestEvent(); - await telemetry.emitEvents([testEvent]); + telemetry.emitEvents([testEvent]); + await nextTick(); // wait for the event to be sent verifyMockCalls({ sendEventsCalls: 1, @@ -152,7 +155,8 @@ describe("Telemetry", () => { const testEvent = createTestEvent(); - await telemetry.emitEvents([testEvent]); + telemetry.emitEvents([testEvent]); + await nextTick(); // wait for the event to be sent verifyMockCalls({ sendEventsCalls: 1, @@ -175,7 +179,8 @@ describe("Telemetry", () => { // Set up mock to return cached events mockEventCache.getEvents.mockReturnValueOnce([cachedEvent]); - await telemetry.emitEvents([newEvent]); + telemetry.emitEvents([newEvent]); + await nextTick(); // wait for the event to be sent verifyMockCalls({ sendEventsCalls: 1, @@ -184,9 +189,7 @@ describe("Telemetry", () => { }); }); - it("should correctly add common properties to events", () => { - const commonProps = telemetry.getCommonProperties(); - + it("should correctly add common properties to events", async () => { // Use explicit type assertion const expectedProps: Record = { mcp_client_version: "1.0.0", @@ -197,48 +200,86 @@ describe("Telemetry", () => { device_id: hashedMachineId, }; - expect(commonProps).toMatchObject(expectedProps); + const testEvent = createTestEvent(); + + telemetry.emitEvents([testEvent]); + await nextTick(); // wait for the event to be sent + + const checkEvent = { + ...testEvent, + properties: { + ...testEvent.properties, + ...expectedProps, + }, + }; + + verifyMockCalls({ + sendEventsCalls: 1, + clearEventsCalls: 1, + sendEventsCalledWith: [checkEvent], + }); }); - describe("machine ID resolution", () => { - beforeEach(() => { - jest.clearAllMocks(); - jest.useFakeTimers(); + it("should send cache new event while sending another event", async () => { + const newEvent = createTestEvent({ + command: "new-command", + component: "new-component", }); - afterEach(() => { - jest.clearAllMocks(); - jest.useRealTimers(); + const newEvent2 = createTestEvent({ + command: "new-command-2", + component: "new-component-2", }); - it("should successfully resolve the machine ID", async () => { - telemetry = Telemetry.create(session, config, { - getRawMachineId: () => Promise.resolve(machineId), - }); + telemetry.emitEvents([newEvent]); + telemetry.emitEvents([newEvent2]); - expect(telemetry["isBufferingEvents"]).toBe(true); - expect(telemetry.getCommonProperties().device_id).toBe(undefined); + await nextTick(); // wait for the event to be sent - await telemetry.deviceIdPromise; + verifyMockCalls({ + sendEventsCalls: 1, + clearEventsCalls: 1, + appendEventsCalls: 1, + sendEventsCalledWith: [newEvent], + appendEventsCalledWith: [newEvent2], + }); + }); - expect(telemetry["isBufferingEvents"]).toBe(false); - expect(telemetry.getCommonProperties().device_id).toBe(hashedMachineId); + describe("machine ID resolution", () => { + it("should successfully resolve the machine ID", async () => { + const testEvent = createTestEvent(); + + telemetry.emitEvents([testEvent]); + await nextTick(); // wait for the event to be sent + + const checkEvent = { + ...testEvent, + properties: { + ...testEvent.properties, + device_id: hashedMachineId, + }, + }; + + verifyMockCalls({ + sendEventsCalls: 1, + clearEventsCalls: 1, + sendEventsCalledWith: [checkEvent], + }); }); it("should handle machine ID resolution failure", async () => { const loggerSpy = jest.spyOn(logger, "debug"); telemetry = Telemetry.create(session, config, { + ...telemetryConfig, getRawMachineId: () => Promise.reject(new Error("Failed to get device ID")), }); - expect(telemetry["isBufferingEvents"]).toBe(true); - expect(telemetry.getCommonProperties().device_id).toBe(undefined); + const testEvent = createTestEvent(); - await telemetry.deviceIdPromise; + telemetry.emitEvents([testEvent]); - expect(telemetry["isBufferingEvents"]).toBe(false); - expect(telemetry.getCommonProperties().device_id).toBe("unknown"); + await nextTick(); // wait for the event to be sent expect(loggerSpy).toHaveBeenCalledWith( LogId.telemetryDeviceIdFailure, @@ -247,27 +288,28 @@ describe("Telemetry", () => { ); }); - it("should timeout if machine ID resolution takes too long", async () => { + it("should timeout if machine ID resolution takes too long", () => { const loggerSpy = jest.spyOn(logger, "debug"); - telemetry = Telemetry.create(session, config, { getRawMachineId: () => new Promise(() => {}) }); + jest.useFakeTimers(); - expect(telemetry["isBufferingEvents"]).toBe(true); - expect(telemetry.getCommonProperties().device_id).toBe(undefined); + telemetry = Telemetry.create(session, config, { + ...telemetryConfig, + getRawMachineId: () => new Promise(() => {}), // Never resolves + }); - jest.advanceTimersByTime(DEVICE_ID_TIMEOUT / 2); + const testEvent = createTestEvent(); - // Make sure the timeout doesn't happen prematurely. - expect(telemetry["isBufferingEvents"]).toBe(true); - expect(telemetry.getCommonProperties().device_id).toBe(undefined); + telemetry.emitEvents([testEvent]); - jest.advanceTimersByTime(DEVICE_ID_TIMEOUT); + jest.advanceTimersByTime(5000); - await telemetry.deviceIdPromise; + jest.useRealTimers(); - expect(telemetry.getCommonProperties().device_id).toBe("unknown"); - expect(telemetry["isBufferingEvents"]).toBe(false); - expect(loggerSpy).toHaveBeenCalledWith( + expect(loggerSpy).toHaveBeenCalledTimes(2); + + expect(loggerSpy).toHaveBeenNthCalledWith( + 2, LogId.telemetryDeviceIdTimeout, "telemetry", "Device ID retrieval timed out" @@ -288,9 +330,12 @@ describe("Telemetry", () => { it("should not send events", async () => { const testEvent = createTestEvent(); - await telemetry.emitEvents([testEvent]); + telemetry.emitEvents([testEvent]); + await nextTick(); // wait for the event to be sent - verifyMockCalls(); + verifyMockCalls({ + sendEventsCalls: 0, + }); }); }); @@ -313,9 +358,12 @@ describe("Telemetry", () => { it("should not send events", async () => { const testEvent = createTestEvent(); - await telemetry.emitEvents([testEvent]); + telemetry.emitEvents([testEvent]); + await nextTick(); // wait for the event to be sent - verifyMockCalls(); + verifyMockCalls({ + sendEventsCalls: 0, + }); }); }); }); diff --git a/tsconfig.build.json b/tsconfig.build.json index 1fe57f10..57edf983 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -7,6 +7,7 @@ "outDir": "./dist", "strict": true, "strictNullChecks": true, + "noUncheckedIndexedAccess": true, "esModuleInterop": true, "types": ["node"], "sourceMap": true,