diff --git a/.github/workflows/api-breakage-check.yml b/.github/workflows/api-breakage-check.yml
new file mode 100644
index 00000000000..06e5140a10c
--- /dev/null
+++ b/.github/workflows/api-breakage-check.yml
@@ -0,0 +1,234 @@
+name: SNAPI API Breakage Check
+
+on:
+ pull_request:
+ paths:
+ - 'packages/**'
+ - 'tools/snapi/**'
+ push:
+ branches:
+ - main
+ paths:
+ - 'packages/**'
+ - 'tools/snapi/**'
+ workflow_dispatch: # Keep workflow_dispatch
+
+concurrency:
+ group: snapi-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ detect-api-changes:
+ runs-on: ubuntu-latest # Changed from blacksmith runner for simplicity, adjust if needed
+ timeout-minutes: 15 # Adjusted timeout
+ permissions:
+ contents: read
+ pull-requests: write
+ statuses: write
+ # id-token: write # Not needed if not using WIF for GCS
+
+ # env: # GCS env vars removed
+ # GCS_PROJECT_ID: ${{ secrets.GCS_PROJECT_ID }}
+ # GCS_BUCKET: ${{ secrets.GCS_BUCKET }}
+ # TURBO_TEAM: ${{ vars.TURBO_TEAM }}
+ # TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Need full history
+
+ - name: Setup
+ id: config
+ uses: ./.github/actions/init-blacksmith
+ with:
+ turbo-signature: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }}
+ turbo-team: ${{ vars.TURBO_TEAM }} # Keep turbo if init-blacksmith needs it
+ turbo-token: ${{ secrets.TURBO_TOKEN }} # Keep turbo if init-blacksmith needs it
+
+ # GCS Auth step removed
+ # - name: Authenticate to Google Cloud
+ # uses: 'google-github-actions/auth@v2'
+ # with:
+ # workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
+ # service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
+
+ - name: Build packages
+ run: pnpm build
+
+ - name: Build Snapi
+ run: pnpm turbo build --filter=@clerk/snapi
+
+ # Storage health check removed
+ # - name: Check storage health
+ # id: storage-health
+ # run: |
+ # echo "GCS_PROJECT_ID: $GCS_PROJECT_ID"
+ # echo "GCS_BUCKET: $GCS_BUCKET"
+ # if ! pnpm snapi storage health --ci; then
+ # echo "::error::Storage health check failed"
+ # exit 1
+ # fi
+
+ - name: Download LATEST baseline from main (for PRs)
+ if: github.event_name == 'pull_request'
+ uses: dawidd6/action-download-artifact@v6 # Using v6, check for latest stable
+ with:
+ workflow: ${{ github.workflow_id }} # Use workflow_id for more robust self-referencing
+ branch: main
+ name: api-baseline-latest-main
+ path: .api-snapshots/baseline # Download to a 'baseline' subdirectory
+ if_no_artifact_found: warn # Don't fail if not found, just warn
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Generate and store initial snapshots if needed
+ if: github.event_name == 'pull_request'
+ id: initial-snapshots
+ run: |
+ # Check if baseline directory is empty
+ if [ ! "$(ls -A .api-snapshots/baseline)" ]; then
+ echo "No baseline snapshots found. Generating initial snapshots..."
+ # Generate current snapshots with --no-cleanup to prevent premature deletion
+ pnpm snapi:snapshot --config snapi.config.json --no-cleanup
+
+ # Copy current snapshots to baseline
+ mkdir -p .api-snapshots/baseline
+ cp -r .api-snapshots/current/* .api-snapshots/baseline/
+
+ # Upload initial snapshots as artifacts
+ echo "COMMIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
+ echo "initial_snapshots_generated=true" >> $GITHUB_OUTPUT
+ echo "Uploading initial snapshots as artifacts..."
+ else
+ echo "Baseline snapshots found, skipping initial snapshot generation."
+ echo "initial_snapshots_generated=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Upload initial snapshots (if generated)
+ if: github.event_name == 'pull_request' && steps.initial-snapshots.outputs.initial_snapshots_generated == 'true'
+ uses: actions/upload-artifact@v4
+ with:
+ name: api-baseline-${{ env.COMMIT_SHA }}
+ path: .api-snapshots/
+ retention-days: 90
+
+ - name: Run API breakage detection (PR)
+ if: github.event_name == 'pull_request'
+ id: api-check-pr
+ run: |
+ # Ensure baseline directory exists if artifact wasn't downloaded, to prevent errors if SNAPI expects it
+ mkdir -p .api-snapshots/baseline
+ # Generate current snapshots
+ pnpm snapi:snapshot --config snapi.config.json
+
+ # Run breaking changes detection
+ echo "🔍 Detecting API changes..."
+ if pnpm snapi:check --config snapi.config.json --format markdown --output api-changes-report.md; then
+ echo "api_check_passed=true" >> $GITHUB_OUTPUT
+ else
+ echo "api_check_passed=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Update baseline cache and upload LATEST (main branch)
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ run: |
+ pnpm snapi:snapshot --config snapi.config.json --force
+ echo "COMMIT_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
+
+ - name: Upload commit-specific baseline snapshots (main branch)
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ uses: actions/upload-artifact@v4
+ with:
+ name: api-baseline-${{ env.COMMIT_SHA }}
+ path: .api-snapshots/
+ retention-days: 90
+
+ - name: Upload LATEST baseline snapshot (main branch)
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ uses: actions/upload-artifact@v4
+ with:
+ name: api-baseline-latest-main
+ path: .api-snapshots/ # This should contain the generated snapshots
+ retention-days: 90 # Adjust as needed, this will be overwritten frequently
+
+ - name: Comment on PR
+ if: github.event_name == 'pull_request'
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const fs = require('fs');
+
+ // Read the generated report
+ let reportContent = '';
+ try {
+ reportContent = fs.readFileSync('api-changes-report.md', 'utf8');
+ } catch (error) {
+ reportContent = '❌ **Error**: Could not generate API changes report.\n\n' + error.message;
+ }
+
+ // Find existing comment
+ const comments = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number
+ });
+
+ const existingComment = comments.data.find(
+ comment => comment.user.login === 'github-actions[bot]' &&
+ comment.body.includes('API Changes Report')
+ );
+
+ const commentBody = `## 🔍 API Changes Report
+
+ ${reportContent}
+
+ ---
+ 🤖 This comment was automatically generated by the API Breakage Detector`;
+
+ if (existingComment) {
+ // Update existing comment
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: existingComment.id,
+ body: commentBody
+ });
+ } else {
+ // Create new comment
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: commentBody
+ });
+ }
+
+ - name: Set commit status
+ if: github.event_name == 'pull_request'
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const apiCheckPassed = '${{ steps.api-check-pr.outputs.api_check_passed }}' === 'true';
+
+ await github.rest.repos.createCommitStatus({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ sha: context.payload.pull_request.head.sha,
+ state: apiCheckPassed ? 'success' : 'failure',
+ target_url: `${context.payload.pull_request.html_url}/checks`,
+ description: apiCheckPassed ?
+ 'No breaking API changes detected' :
+ 'Breaking API changes detected - review required',
+ context: 'snapi'
+ });
+
+ - name: Upload API snapshots and reports (debug)
+ if: always() # Keep this for debugging all runs
+ uses: actions/upload-artifact@v4
+ with:
+ name: api-debug-${{ github.run_id }}
+ path: |
+ .api-snapshots/
+ api-changes-report.md
+ retention-days: 7
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 473948c0d6d..f850235755a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,6 +40,7 @@ testem.log
/typings
**/coverage/**
*.tsbuildinfo
+.tmp
# System Files
.DS_Store
@@ -99,3 +100,10 @@ scripts/.env
# typedoc
.typedoc/docs
.typedoc/docs.json
+
+# API Breakage Detection
+.api-snapshots/current/
+.api-snapshots/temp/
+.api-snapshots/.baseline-cache.json
+# Keep baseline snapshots in Git for CI
+!.api-snapshots/baseline/
diff --git a/package.json b/package.json
index 29d75bf844a..15f7a5bdc1f 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,11 @@
"release:canary": "changeset publish --tag canary --no-git-tag",
"release:snapshot": "changeset publish --tag snapshot --no-git-tag",
"release:verdaccio": "if [ \"$(npm config get registry)\" = \"https://registry.npmjs.org/\" ]; then echo 'Error: Using default registry' && exit 1; else TURBO_CONCURRENCY=1 pnpm build && changeset publish --no-git-tag; fi",
+ "snapi:detect": "pnpm snapi detect",
+ "snapi:health": "pnpm snapi storage health",
+ "snapi:init": "pnpm snapi init --output snapi.config.json",
+ "snapi:snapshot": "pnpm snapi snapshot",
+ "snapi:suppress": "pnpm snapi suppress",
"test": "FORCE_COLOR=1 turbo test --concurrency=${TURBO_CONCURRENCY:-80%}",
"test:cache:clear": "FORCE_COLOR=1 turbo test:cache:clear --continue --concurrency=${TURBO_CONCURRENCY:-80%}",
"test:integration:ap-flows": "pnpm test:integration:base --grep @ap-flows",
@@ -68,6 +73,7 @@
"@changesets/get-github-info": "^0.6.0",
"@clerk/backend": "workspace:*",
"@clerk/shared": "workspace:*",
+ "@clerk/snapi": "workspace:*",
"@clerk/testing": "workspace:*",
"@commitlint/cli": "^19.8.0",
"@commitlint/config-conventional": "^19.8.0",
diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts
index e8215708399..dcddb161b09 100644
--- a/packages/backend/src/index.ts
+++ b/packages/backend/src/index.ts
@@ -50,6 +50,7 @@ export function createClerkClient(options: ClerkOptions): ClerkClient {
*/
export type { OrganizationMembershipRole } from './api/resources';
export type { VerifyTokenOptions } from './tokens/verify';
+export type { LoadClerkJWKFromRemoteOptions } from './tokens/keys';
/**
* JSON types
*/
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ec205479983..6769b782305 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -70,6 +70,9 @@ importers:
'@clerk/shared':
specifier: workspace:*
version: link:packages/shared
+ '@clerk/snapi':
+ specifier: workspace:*
+ version: link:tools/snapi
'@clerk/testing':
specifier: workspace:*
version: link:packages/testing
@@ -105,7 +108,7 @@ importers:
version: 10.1.0
'@testing-library/jest-dom':
specifier: ^6.4.6
- version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.18.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.6)(typescript@5.8.3)))(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
+ version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.18.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.6)(typescript@5.8.3)))(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
'@testing-library/react':
specifier: ^16.0.0
version: 16.0.0(@testing-library/dom@10.1.0)(@types/react-dom@18.3.7(@types/react@18.3.24))(@types/react@18.3.24)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -132,7 +135,7 @@ importers:
version: 4.5.2(vite@7.1.5(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
'@vitest/coverage-v8':
specifier: 3.0.5
- version: 3.0.5(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
+ version: 3.0.5(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
chalk:
specifier: 4.1.2
version: 4.1.2
@@ -276,7 +279,7 @@ importers:
version: 29.2.5(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@22.18.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.6)(typescript@5.8.3)))(typescript@5.8.3)
tsup:
specifier: catalog:repo
- version: 8.5.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1)
+ version: 8.5.0(@microsoft/api-extractor@7.52.13(@types/node@22.18.6))(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1)
turbo:
specifier: ^2.5.4
version: 2.5.4
@@ -306,7 +309,7 @@ importers:
version: 5.33.0(typanion@3.14.0)
vitest:
specifier: 3.0.5
- version: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
+ version: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
yalc:
specifier: 1.0.0-pre.53
version: 1.0.0-pre.53(patch_hash=2737a4bf8dd6ebdc410626225fe706ae0bb73b142e398279afff04d1b02dfc1f)
@@ -399,7 +402,7 @@ importers:
version: 9.0.2
vitest-environment-miniflare:
specifier: 2.14.4
- version: 2.14.4(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
+ version: 2.14.4(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
packages/chrome-extension:
dependencies:
@@ -1036,7 +1039,7 @@ importers:
devDependencies:
tsup:
specifier: catalog:repo
- version: 8.5.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1)
+ version: 8.5.0(@microsoft/api-extractor@7.52.13(@types/node@24.3.1))(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1)
packages/types:
dependencies:
@@ -1139,6 +1142,71 @@ importers:
specifier: ^2.2.12
version: 2.2.12(typescript@5.8.3)
+ tools/snapi:
+ dependencies:
+ '@microsoft/api-extractor':
+ specifier: ^7.47.9
+ version: 7.52.13(@types/node@20.19.17)
+ '@microsoft/api-extractor-model':
+ specifier: ^7.29.4
+ version: 7.30.7(@types/node@20.19.17)
+ '@octokit/rest':
+ specifier: ^21.0.0
+ version: 21.1.1
+ chalk:
+ specifier: ^5.3.0
+ version: 5.6.0
+ commander:
+ specifier: ^12.1.0
+ version: 12.1.0
+ diff:
+ specifier: ^7.0.0
+ version: 7.0.0
+ fs-extra:
+ specifier: ^11.2.0
+ version: 11.3.0
+ globby:
+ specifier: ^14.0.2
+ version: 14.1.0
+ semver:
+ specifier: ^7.6.0
+ version: 7.7.2
+ yaml:
+ specifier: ^2.4.0
+ version: 2.8.1
+ zod:
+ specifier: ^3.23.8
+ version: 3.24.2
+ devDependencies:
+ '@types/diff':
+ specifier: ^5.2.0
+ version: 5.2.3
+ '@types/fs-extra':
+ specifier: ^11.0.4
+ version: 11.0.4
+ '@types/node':
+ specifier: ^20.11.0
+ version: 20.19.17
+ '@types/semver':
+ specifier: ^7.5.0
+ version: 7.7.1
+ eslint:
+ specifier: ^9.0.0
+ version: 9.31.0(jiti@2.5.1)
+ tsup:
+ specifier: catalog:repo
+ version: 8.5.0(@microsoft/api-extractor@7.52.13(@types/node@20.19.17))(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1)
+ typescript:
+ specifier: catalog:repo
+ version: 5.8.3
+ vitest:
+ specifier: ^2.0.0
+ version: 2.1.9(@edge-runtime/vm@5.0.0)(@types/node@20.19.17)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@20.19.17)(typescript@5.8.3))(terser@5.44.0)
+ optionalDependencies:
+ '@google-cloud/storage':
+ specifier: ^7.16.0
+ version: 7.17.1
+
packages:
'@0no-co/graphql.web@1.1.2':
@@ -1221,8 +1289,17 @@ packages:
resolution: {integrity: sha512-Izvir8iIoU+X4SKtDAa5kpb+9cpifclzsbA8x/AZY0k0gIfXYQ1fa1B6Epfe6vNA2YfDX8VtrZFgvnXB6aPEoQ==}
engines: {node: '>=18'}
- '@asamuzakjp/css-color@3.1.5':
- resolution: {integrity: sha512-w7AmVyTTiU41fNLsFDf+gA2Dwtbx2EJtn2pbJNAGSRAg50loXy1uLXA3hEpD8+eydcomTurw09tq5/AyceCaGg==}
+ '@asamuzakjp/css-color@3.2.0':
+ resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
+
+ '@asamuzakjp/css-color@4.0.4':
+ resolution: {integrity: sha512-cKjSKvWGmAziQWbCouOsFwb14mp1betm8Y7Fn+yglDMUUu3r9DCbJ9iJbeFDenLMqFbIMC0pQP8K+B8LAxX3OQ==}
+
+ '@asamuzakjp/dom-selector@6.5.5':
+ resolution: {integrity: sha512-kI2MX9pmImjxWT8nxDZY+MuN6r1jJGe7WxizEbsAEPB/zxfW5wYLIiPG1v3UKgEOOP8EsDkp0ZL99oRFAdPM8g==}
+
+ '@asamuzakjp/nwsapi@2.3.9':
+ resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==}
'@astrojs/compiler@2.12.2':
resolution: {integrity: sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==}
@@ -2139,32 +2216,38 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
- '@csstools/color-helpers@5.0.2':
- resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==}
+ '@csstools/color-helpers@5.1.0':
+ resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
+ engines: {node: '>=18'}
+
+ '@csstools/css-calc@2.1.4':
+ resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==}
engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
- '@csstools/css-calc@2.1.3':
- resolution: {integrity: sha512-XBG3talrhid44BY1x3MHzUx/aTG8+x/Zi57M4aTKK9RFB4aLlF3TTSzfzn8nWVHWL3FgAXAxmupmDd6VWww+pw==}
+ '@csstools/css-color-parser@3.1.0':
+ resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==}
engines: {node: '>=18'}
peerDependencies:
- '@csstools/css-parser-algorithms': ^3.0.4
- '@csstools/css-tokenizer': ^3.0.3
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
- '@csstools/css-color-parser@3.0.9':
- resolution: {integrity: sha512-wILs5Zk7BU86UArYBJTPy/FMPPKVKHMj1ycCEyf3VUptol0JNRLFU/BZsJ4aiIHJEbSLiizzRrw8Pc1uAEDrXw==}
+ '@csstools/css-parser-algorithms@3.0.5':
+ resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==}
engines: {node: '>=18'}
peerDependencies:
- '@csstools/css-parser-algorithms': ^3.0.4
- '@csstools/css-tokenizer': ^3.0.3
+ '@csstools/css-tokenizer': ^3.0.4
- '@csstools/css-parser-algorithms@3.0.4':
- resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==}
+ '@csstools/css-syntax-patches-for-csstree@1.0.14':
+ resolution: {integrity: sha512-zSlIxa20WvMojjpCSy8WrNpcZ61RqfTfX3XTaOeVlGJrt/8HF3YbzgFZa01yTbT4GWQLwfTcC3EB8i3XnB647Q==}
engines: {node: '>=18'}
peerDependencies:
- '@csstools/css-tokenizer': ^3.0.3
+ postcss: ^8.4
- '@csstools/css-tokenizer@3.0.3':
- resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==}
+ '@csstools/css-tokenizer@3.0.4':
+ resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
engines: {node: '>=18'}
'@cypress/request@3.0.6':
@@ -2261,6 +2344,12 @@ packages:
resolution: {integrity: sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==}
engines: {node: '>=18'}
+ '@esbuild/aix-ppc64@0.21.5':
+ resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+
'@esbuild/aix-ppc64@0.23.1':
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
engines: {node: '>=18'}
@@ -2279,6 +2368,12 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/android-arm64@0.21.5':
+ resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm64@0.23.1':
resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
engines: {node: '>=18'}
@@ -2297,6 +2392,12 @@ packages:
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm@0.21.5':
+ resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-arm@0.23.1':
resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
engines: {node: '>=18'}
@@ -2315,6 +2416,12 @@ packages:
cpu: [arm]
os: [android]
+ '@esbuild/android-x64@0.21.5':
+ resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/android-x64@0.23.1':
resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
engines: {node: '>=18'}
@@ -2333,6 +2440,12 @@ packages:
cpu: [x64]
os: [android]
+ '@esbuild/darwin-arm64@0.21.5':
+ resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-arm64@0.23.1':
resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
engines: {node: '>=18'}
@@ -2351,6 +2464,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-x64@0.21.5':
+ resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.23.1':
resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
engines: {node: '>=18'}
@@ -2369,6 +2488,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@esbuild/freebsd-arm64@0.21.5':
+ resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-arm64@0.23.1':
resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
engines: {node: '>=18'}
@@ -2387,6 +2512,12 @@ packages:
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.21.5':
+ resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.23.1':
resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
engines: {node: '>=18'}
@@ -2405,6 +2536,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@esbuild/linux-arm64@0.21.5':
+ resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm64@0.23.1':
resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
engines: {node: '>=18'}
@@ -2423,6 +2560,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm@0.21.5':
+ resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-arm@0.23.1':
resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
engines: {node: '>=18'}
@@ -2441,6 +2584,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@esbuild/linux-ia32@0.21.5':
+ resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-ia32@0.23.1':
resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
engines: {node: '>=18'}
@@ -2459,6 +2608,12 @@ packages:
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-loong64@0.21.5':
+ resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-loong64@0.23.1':
resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
engines: {node: '>=18'}
@@ -2477,6 +2632,12 @@ packages:
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-mips64el@0.21.5':
+ resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.23.1':
resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
engines: {node: '>=18'}
@@ -2495,6 +2656,12 @@ packages:
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-ppc64@0.21.5':
+ resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.23.1':
resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
engines: {node: '>=18'}
@@ -2513,6 +2680,12 @@ packages:
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-riscv64@0.21.5':
+ resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.23.1':
resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
engines: {node: '>=18'}
@@ -2531,6 +2704,12 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-s390x@0.21.5':
+ resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-s390x@0.23.1':
resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
engines: {node: '>=18'}
@@ -2549,6 +2728,12 @@ packages:
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-x64@0.21.5':
+ resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/linux-x64@0.23.1':
resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
engines: {node: '>=18'}
@@ -2579,6 +2764,12 @@ packages:
cpu: [arm64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.21.5':
+ resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.23.1':
resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
engines: {node: '>=18'}
@@ -2615,6 +2806,12 @@ packages:
cpu: [arm64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.21.5':
+ resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.23.1':
resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
engines: {node: '>=18'}
@@ -2639,6 +2836,12 @@ packages:
cpu: [arm64]
os: [openharmony]
+ '@esbuild/sunos-x64@0.21.5':
+ resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/sunos-x64@0.23.1':
resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
engines: {node: '>=18'}
@@ -2657,6 +2860,12 @@ packages:
cpu: [x64]
os: [sunos]
+ '@esbuild/win32-arm64@0.21.5':
+ resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-arm64@0.23.1':
resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
engines: {node: '>=18'}
@@ -2675,6 +2884,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-ia32@0.21.5':
+ resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-ia32@0.23.1':
resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
engines: {node: '>=18'}
@@ -2693,6 +2908,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-x64@0.21.5':
+ resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
'@esbuild/win32-x64@0.23.1':
resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
engines: {node: '>=18'}
@@ -2755,7 +2976,7 @@ packages:
'@expo/bunyan@4.0.1':
resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==}
- engines: {node: '>=0.10.0'}
+ engines: {'0': node >=0.10.0}
'@expo/cli@0.22.26':
resolution: {integrity: sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==}
@@ -2904,6 +3125,22 @@ packages:
'@gerrit0/mini-shiki@3.2.2':
resolution: {integrity: sha512-vaZNGhGLKMY14HbF53xxHNgFO9Wz+t5lTlGNpl2N9xFiKQ0I5oIe0vKjU9dh7Nb3Dw6lZ7wqUE0ri+zcdpnK+Q==}
+ '@google-cloud/paginator@5.0.2':
+ resolution: {integrity: sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==}
+ engines: {node: '>=14.0.0'}
+
+ '@google-cloud/projectify@4.0.0':
+ resolution: {integrity: sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==}
+ engines: {node: '>=14.0.0'}
+
+ '@google-cloud/promisify@4.0.0':
+ resolution: {integrity: sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==}
+ engines: {node: '>=14'}
+
+ '@google-cloud/storage@7.17.1':
+ resolution: {integrity: sha512-2FMQbpU7qK+OtBPaegC6n+XevgZksobUGo6mGKnXNmeZpvLiAo1gTAE3oTKsrMGDV4VtL8Zzpono0YsK/Q7Iqg==}
+ engines: {node: '>=14'}
+
'@hapi/hoek@9.3.0':
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
@@ -3160,8 +3397,8 @@ packages:
resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- '@jest/create-cache-key-function@30.0.2':
- resolution: {integrity: sha512-AwlDAHwEHDi+etw9vKWx9HeIApVos8GD/sSTpHtDkqhm9OWuEUPKKPP6EaS17yv0GSzBB3TeeJFLyJ5LPjRqWg==}
+ '@jest/create-cache-key-function@30.0.5':
+ resolution: {integrity: sha512-W1kmkwPq/WTMQWgvbzWSCbXSqvjI6rkqBQCxuvYmd+g6o4b5gHP98ikfh/Ei0SKzHvWdI84TOXp0hRcbpr8Q0w==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
'@jest/environment@29.7.0':
@@ -3201,8 +3438,8 @@ packages:
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- '@jest/schemas@30.0.1':
- resolution: {integrity: sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==}
+ '@jest/schemas@30.0.5':
+ resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
'@jest/source-map@29.6.3':
@@ -3229,8 +3466,8 @@ packages:
resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
- '@jest/types@30.0.1':
- resolution: {integrity: sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==}
+ '@jest/types@30.0.5':
+ resolution: {integrity: sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
'@jridgewell/gen-mapping@0.3.13':
@@ -3300,6 +3537,19 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ '@microsoft/api-extractor-model@7.30.7':
+ resolution: {integrity: sha512-TBbmSI2/BHpfR9YhQA7nH0nqVmGgJ0xH0Ex4D99/qBDAUpnhA2oikGmdXanbw9AWWY/ExBYIpkmY8dBHdla3YQ==}
+
+ '@microsoft/api-extractor@7.52.13':
+ resolution: {integrity: sha512-K6/bBt8zZfn9yc06gNvA+/NlBGJC/iJlObpdufXHEJtqcD4Dln4ITCLZpwP3DNZ5NyBFeTkKdv596go3V72qlA==}
+ hasBin: true
+
+ '@microsoft/tsdoc-config@0.17.1':
+ resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==}
+
+ '@microsoft/tsdoc@0.15.1':
+ resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
+
'@miniflare/cache@2.14.4':
resolution: {integrity: sha512-ayzdjhcj+4mjydbNK7ZGDpIXNliDbQY4GPcY2KrYw0v1OSUdj5kZUkygD09fqoGRfAks0d91VelkyRsAXX8FQA==}
engines: {node: '>=16.13'}
@@ -3582,10 +3832,22 @@ packages:
resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
engines: {node: '>= 18'}
+ '@octokit/auth-token@5.1.2':
+ resolution: {integrity: sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==}
+ engines: {node: '>= 18'}
+
'@octokit/core@5.2.0':
resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==}
engines: {node: '>= 18'}
+ '@octokit/core@6.1.6':
+ resolution: {integrity: sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==}
+ engines: {node: '>= 18'}
+
+ '@octokit/endpoint@10.1.4':
+ resolution: {integrity: sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==}
+ engines: {node: '>= 18'}
+
'@octokit/endpoint@9.0.6':
resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==}
engines: {node: '>= 18'}
@@ -3594,42 +3856,88 @@ packages:
resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==}
engines: {node: '>= 18'}
+ '@octokit/graphql@8.2.2':
+ resolution: {integrity: sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==}
+ engines: {node: '>= 18'}
+
'@octokit/openapi-types@23.0.1':
resolution: {integrity: sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==}
+ '@octokit/openapi-types@24.2.0':
+ resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==}
+
+ '@octokit/openapi-types@25.1.0':
+ resolution: {integrity: sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==}
+
'@octokit/plugin-paginate-rest@11.4.4-cjs.2':
resolution: {integrity: sha512-2dK6z8fhs8lla5PaOTgqfCGBxgAv/le+EhPs27KklPhm1bKObpu6lXzwfUEQ16ajXzqNrKMujsFyo9K2eaoISw==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '5'
+ '@octokit/plugin-paginate-rest@11.6.0':
+ resolution: {integrity: sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@octokit/core': '>=6'
+
'@octokit/plugin-request-log@4.0.0':
resolution: {integrity: sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': '>=5'
+ '@octokit/plugin-request-log@5.3.1':
+ resolution: {integrity: sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@octokit/core': '>=6'
+
'@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1':
resolution: {integrity: sha512-VUjIjOOvF2oELQmiFpWA1aOPdawpyaCUqcEBc/UOUnj3Xp6DJGrJ1+bjUIIDzdHjnFNO6q57ODMfdEZnoBkCwQ==}
engines: {node: '>= 18'}
peerDependencies:
'@octokit/core': ^5
+ '@octokit/plugin-rest-endpoint-methods@13.5.0':
+ resolution: {integrity: sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@octokit/core': '>=6'
+
'@octokit/request-error@5.1.1':
resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==}
engines: {node: '>= 18'}
+ '@octokit/request-error@6.1.8':
+ resolution: {integrity: sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==}
+ engines: {node: '>= 18'}
+
'@octokit/request@8.4.1':
resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==}
engines: {node: '>= 18'}
+ '@octokit/request@9.2.4':
+ resolution: {integrity: sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==}
+ engines: {node: '>= 18'}
+
'@octokit/rest@20.1.2':
resolution: {integrity: sha512-GmYiltypkHHtihFwPRxlaorG5R9VAHuk/vbszVoRTGXnAsY60wYLkh/E2XiFmdZmqrisw+9FaazS1i5SbdWYgA==}
engines: {node: '>= 18'}
+ '@octokit/rest@21.1.1':
+ resolution: {integrity: sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==}
+ engines: {node: '>= 18'}
+
+ '@octokit/types@13.10.0':
+ resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==}
+
'@octokit/types@13.8.0':
resolution: {integrity: sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==}
+ '@octokit/types@14.1.0':
+ resolution: {integrity: sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==}
+
'@one-ini/wasm@0.1.1':
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
@@ -4626,6 +4934,28 @@ packages:
'@rtsao/scc@1.1.0':
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+ '@rushstack/node-core-library@5.14.0':
+ resolution: {integrity: sha512-eRong84/rwQUlATGFW3TMTYVyqL1vfW9Lf10PH+mVGfIb9HzU3h5AASNIw+axnBLjnD0n3rT5uQBwu9fvzATrg==}
+ peerDependencies:
+ '@types/node': '*'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
+ '@rushstack/rig-package@0.5.3':
+ resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==}
+
+ '@rushstack/terminal@0.16.0':
+ resolution: {integrity: sha512-WEvNuKkoR1PXorr9SxO0dqFdSp1BA+xzDrIm/Bwlc5YHg2FFg6oS+uCTYjerOhFuqCW+A3vKBm6EmKWSHfgx/A==}
+ peerDependencies:
+ '@types/node': '*'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
+ '@rushstack/ts-command-line@5.0.3':
+ resolution: {integrity: sha512-bgPhQEqLVv/2hwKLYv/XvsTWNZ9B/+X1zJ7WgQE9rO5oiLzrOZvkIW4pk13yOQBhHyjcND5qMOa6p83t+Z66iQ==}
+
'@scure/base@1.2.6':
resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==}
@@ -4674,8 +5004,8 @@ packages:
'@sinclair/typebox@0.27.8':
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
- '@sinclair/typebox@0.34.38':
- resolution: {integrity: sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==}
+ '@sinclair/typebox@0.34.41':
+ resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==}
'@sindresorhus/is@4.6.0':
resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
@@ -5103,6 +5433,9 @@ packages:
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+ '@types/argparse@1.0.38':
+ resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==}
+
'@types/aria-query@5.0.1':
resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==}
@@ -5133,6 +5466,9 @@ packages:
'@types/bonjour@3.5.13':
resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==}
+ '@types/caseless@0.12.5':
+ resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==}
+
'@types/chrome@0.0.114':
resolution: {integrity: sha512-i7qRr74IrxHtbnrZSKUuP5Uvd5EOKwlwJq/yp7+yTPihOXnPhNQO4Z5bqb1XTnrjdbUKEJicaVVbhcgtRijmLA==}
@@ -5169,6 +5505,9 @@ packages:
'@types/diff-match-patch@1.0.36':
resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==}
+ '@types/diff@5.2.3':
+ resolution: {integrity: sha512-K0Oqlrq3kQMaO2RhfrNQX5trmt+XLyom88zS0u84nnIcLvFnRUMRRHmrGny5GSM+kNO9IZLARsdQHDzkhAgmrQ==}
+
'@types/estree@1.0.5':
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
@@ -5268,6 +5607,9 @@ packages:
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
+ '@types/node@20.19.17':
+ resolution: {integrity: sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==}
+
'@types/node@22.18.6':
resolution: {integrity: sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==}
@@ -5300,6 +5642,9 @@ packages:
'@types/react@18.3.24':
resolution: {integrity: sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==}
+ '@types/request@2.48.13':
+ resolution: {integrity: sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==}
+
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
@@ -5666,9 +6011,23 @@ packages:
'@vitest/browser':
optional: true
+ '@vitest/expect@2.1.9':
+ resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
+
'@vitest/expect@3.0.5':
resolution: {integrity: sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==}
+ '@vitest/mocker@2.1.9':
+ resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
'@vitest/mocker@3.0.5':
resolution: {integrity: sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==}
peerDependencies:
@@ -5680,18 +6039,36 @@ packages:
vite:
optional: true
+ '@vitest/pretty-format@2.1.9':
+ resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
+
'@vitest/pretty-format@3.0.5':
resolution: {integrity: sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==}
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
+
+ '@vitest/runner@2.1.9':
+ resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==}
+
'@vitest/runner@3.0.5':
resolution: {integrity: sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==}
+ '@vitest/snapshot@2.1.9':
+ resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==}
+
'@vitest/snapshot@3.0.5':
resolution: {integrity: sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==}
+ '@vitest/spy@2.1.9':
+ resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==}
+
'@vitest/spy@3.0.5':
resolution: {integrity: sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==}
+ '@vitest/utils@2.1.9':
+ resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
+
'@vitest/utils@3.0.5':
resolution: {integrity: sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==}
@@ -6025,6 +6402,14 @@ packages:
zod:
optional: true
+ ajv-draft-04@1.0.0:
+ resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
+ peerDependencies:
+ ajv: ^8.5.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
@@ -6054,6 +6439,12 @@ packages:
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ ajv@8.12.0:
+ resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
+
+ ajv@8.13.0:
+ resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==}
+
ajv@8.17.1:
resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
@@ -6232,6 +6623,10 @@ packages:
resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
engines: {node: '>=0.10.0'}
+ arrify@2.0.1:
+ resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==}
+ engines: {node: '>=8'}
+
arrify@3.0.0:
resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==}
engines: {node: '>=12'}
@@ -6289,6 +6684,9 @@ packages:
async-limiter@1.0.1:
resolution: {integrity: sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==}
+ async-retry@1.3.3:
+ resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==}
+
async-sema@3.1.1:
resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==}
@@ -6467,6 +6865,9 @@ packages:
before-after-hook@2.2.3:
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
+ before-after-hook@3.0.2:
+ resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==}
+
better-opn@3.0.2:
resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
engines: {node: '>=12.0.0'}
@@ -6475,10 +6876,16 @@ packages:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
+ bidi-js@1.0.3:
+ resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
+
big-integer@1.6.52:
resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
engines: {node: '>=0.6'}
+ bignumber.js@9.3.1:
+ resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==}
+
binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
@@ -6706,9 +7113,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
- chai@5.1.2:
- resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==}
- engines: {node: '>=12'}
+ chai@5.3.3:
+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
+ engines: {node: '>=18'}
chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
@@ -7363,10 +7770,14 @@ packages:
resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==}
engines: {node: '>=8'}
- cssstyle@4.3.1:
- resolution: {integrity: sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==}
+ cssstyle@4.6.0:
+ resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
engines: {node: '>=18'}
+ cssstyle@5.3.0:
+ resolution: {integrity: sha512-RveJPnk3m7aarYQ2bJ6iw+Urh55S6FzUiqtBq+TihnTDP4cI8y/TYDqGOyqgnG1J1a6BxJXZsV9JFSTulm9Z7g==}
+ engines: {node: '>=20'}
+
csstype@3.1.3:
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
@@ -7398,6 +7809,10 @@ packages:
resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
engines: {node: '>=18'}
+ data-urls@6.0.0:
+ resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==}
+ engines: {node: '>=20'}
+
data-view-buffer@1.0.2:
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
engines: {node: '>= 0.4'}
@@ -7687,6 +8102,10 @@ packages:
resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
engines: {node: '>=0.3.1'}
+ diff@7.0.0:
+ resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==}
+ engines: {node: '>=0.3.1'}
+
diff@8.0.2:
resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==}
engines: {node: '>=0.3.1'}
@@ -7957,6 +8376,11 @@ packages:
resolution: {integrity: sha512-lNjylaAsJMprYg28zjUyBivP3y0ms9b7RJZ5tdhDUFLa3sCbqZw4wDnbFUSmnyZYWhCYDPxxp7KkXM2TXGw3PQ==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
+ esbuild@0.21.5:
+ resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
+ engines: {node: '>=12'}
+ hasBin: true
+
esbuild@0.23.1:
resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
engines: {node: '>=18'}
@@ -8275,8 +8699,8 @@ packages:
resolution: {integrity: sha512-uHaC9LYNv6BcW+8SvXcwUUDCrrUxt3GSa61DFvTHj8JC+M0hekMFBwMlCarLQDk5bbpZ2vStpnQPIwRuV98YMw==}
engines: {node: '>=12.0.0'}
- expect-type@1.1.0:
- resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==}
+ expect-type@1.2.2:
+ resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==}
engines: {node: '>=12.0.0'}
expect@29.7.0:
@@ -8428,6 +8852,9 @@ packages:
resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
engines: {'0': node >=0.6.0}
+ fast-content-type-parse@2.0.1:
+ resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==}
+
fast-decode-uri-component@1.0.1:
resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
@@ -8650,6 +9077,10 @@ packages:
forever-agent@0.6.1:
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
+ form-data@2.5.5:
+ resolution: {integrity: sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==}
+ engines: {node: '>= 0.12'}
+
form-data@3.0.2:
resolution: {integrity: sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ==}
engines: {node: '>= 6'}
@@ -8743,6 +9174,14 @@ packages:
resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==}
engines: {node: '>=10'}
+ gaxios@6.7.1:
+ resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==}
+ engines: {node: '>=14'}
+
+ gcp-metadata@6.1.1:
+ resolution: {integrity: sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==}
+ engines: {node: '>=14'}
+
gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
@@ -8908,6 +9347,14 @@ packages:
resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
engines: {node: '>=18'}
+ google-auth-library@9.15.1:
+ resolution: {integrity: sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==}
+ engines: {node: '>=14'}
+
+ google-logging-utils@0.0.2:
+ resolution: {integrity: sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==}
+ engines: {node: '>=14'}
+
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@@ -8930,6 +9377,10 @@ packages:
resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
engines: {node: '>=6.0'}
+ gtoken@7.1.0:
+ resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==}
+ engines: {node: '>=14.0.0'}
+
gunzip-maybe@1.4.2:
resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==}
hasBin: true
@@ -9261,6 +9712,10 @@ packages:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
+ import-lazy@4.0.0:
+ resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==}
+ engines: {node: '>=8'}
+
import-local@3.1.0:
resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==}
engines: {node: '>=8'}
@@ -9936,6 +10391,9 @@ packages:
resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==}
hasBin: true
+ jju@1.4.0:
+ resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
+
joi@17.13.3:
resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==}
@@ -10016,6 +10474,15 @@ packages:
canvas:
optional: true
+ jsdom@27.0.0:
+ resolution: {integrity: sha512-lIHeR1qlIRrIN5VMccd8tI2Sgw6ieYXSVktcSHaNe3Z5nE/tcPQYQWOq00wxMvYOsz+73eAkNenVvmPC6bba9A==}
+ engines: {node: '>=20'}
+ peerDependencies:
+ canvas: ^3.0.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
jsesc@3.0.2:
resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
engines: {node: '>=6'}
@@ -10026,6 +10493,9 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ json-bigint@1.0.0:
+ resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==}
+
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
@@ -10109,9 +10579,15 @@ packages:
jwa@1.4.1:
resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
+ jwa@2.0.1:
+ resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==}
+
jws@3.2.2:
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
+ jws@4.0.0:
+ resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==}
+
keygrip@1.1.0:
resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==}
engines: {node: '>= 0.6'}
@@ -10429,8 +10905,8 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
- loupe@3.1.2:
- resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
lowdb@1.0.0:
resolution: {integrity: sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==}
@@ -10439,8 +10915,8 @@ packages:
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
- lru-cache@11.0.2:
- resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==}
+ lru-cache@11.2.1:
+ resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==}
engines: {node: 20 || >=22}
lru-cache@5.1.1:
@@ -12651,6 +13127,10 @@ packages:
retext@9.0.0:
resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==}
+ retry-request@7.0.2:
+ resolution: {integrity: sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==}
+ engines: {node: '>=14'}
+
retry@0.13.1:
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
engines: {node: '>= 4'}
@@ -12830,6 +13310,11 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ semver@7.5.4:
+ resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
semver@7.6.3:
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
engines: {node: '>=10'}
@@ -13214,6 +13699,9 @@ packages:
resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==}
engines: {node: '>= 0.10.0'}
+ stream-events@1.0.5:
+ resolution: {integrity: sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==}
+
stream-shift@1.0.3:
resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==}
@@ -13355,6 +13843,9 @@ packages:
structured-headers@0.4.1:
resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==}
+ stubs@3.0.0:
+ resolution: {integrity: sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==}
+
styled-jsx@5.1.1:
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
engines: {node: '>= 12.0.0'}
@@ -13499,6 +13990,10 @@ packages:
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
engines: {node: '>=18'}
+ teeny-request@9.0.0:
+ resolution: {integrity: sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==}
+ engines: {node: '>=14'}
+
temp-dir@2.0.0:
resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
engines: {node: '>=8'}
@@ -13632,10 +14127,14 @@ packages:
tinygradient@1.1.5:
resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==}
- tinypool@1.0.2:
- resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==}
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
+ tinyrainbow@1.2.0:
+ resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
+ engines: {node: '>=14.0.0'}
+
tinyrainbow@2.0.0:
resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
engines: {node: '>=14.0.0'}
@@ -13714,6 +14213,10 @@ packages:
resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
engines: {node: '>=18'}
+ tr46@6.0.0:
+ resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==}
+ engines: {node: '>=20'}
+
tree-dump@1.0.2:
resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==}
engines: {node: '>=10.0'}
@@ -13984,6 +14487,11 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ typescript@5.8.2:
+ resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
typescript@5.8.3:
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
engines: {node: '>=14.17'}
@@ -14134,6 +14642,9 @@ packages:
universal-user-agent@6.0.1:
resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==}
+ universal-user-agent@7.0.3:
+ resolution: {integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==}
+
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
@@ -14407,6 +14918,11 @@ packages:
peerDependencies:
vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
+ vite-node@2.1.9:
+ resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+
vite-node@3.0.5:
resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -14467,6 +14983,37 @@ packages:
vite: ^6.0.0 || ^7.0.0
vue: ^3.5.0
+ vite@5.4.20:
+ resolution: {integrity: sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+
vite@6.3.6:
resolution: {integrity: sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -14562,6 +15109,31 @@ packages:
peerDependencies:
vitest: '>=0.23.0'
+ vitest@2.1.9:
+ resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/node': ^18.0.0 || >=20.0.0
+ '@vitest/browser': 2.1.9
+ '@vitest/ui': 2.1.9
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
vitest@3.0.5:
resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -14672,6 +15244,10 @@ packages:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'}
+ webidl-conversions@8.0.0:
+ resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==}
+ engines: {node: '>=20'}
+
webpack-bundle-analyzer@4.10.2:
resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==}
engines: {node: '>= 10.13.0'}
@@ -14759,6 +15335,10 @@ packages:
resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
engines: {node: '>=18'}
+ whatwg-url@15.1.0:
+ resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==}
+ engines: {node: '>=20'}
+
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
@@ -15206,14 +15786,34 @@ snapshots:
typescript: 5.6.1-rc
validate-npm-package-name: 5.0.1
- '@asamuzakjp/css-color@3.1.5':
+ '@asamuzakjp/css-color@3.2.0':
dependencies:
- '@csstools/css-calc': 2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
- '@csstools/css-color-parser': 3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
- '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
- '@csstools/css-tokenizer': 3.0.3
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
lru-cache: 10.4.3
+ '@asamuzakjp/css-color@4.0.4':
+ dependencies:
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+ lru-cache: 11.2.1
+ optional: true
+
+ '@asamuzakjp/dom-selector@6.5.5':
+ dependencies:
+ '@asamuzakjp/nwsapi': 2.3.9
+ bidi-js: 1.0.3
+ css-tree: 3.1.0
+ is-potential-custom-element-name: 1.0.1
+ optional: true
+
+ '@asamuzakjp/nwsapi@2.3.9':
+ optional: true
+
'@astrojs/compiler@2.12.2': {}
'@astrojs/internal-helpers@0.7.2': {}
@@ -16508,25 +17108,30 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.9
optional: true
- '@csstools/color-helpers@5.0.2': {}
+ '@csstools/color-helpers@5.1.0': {}
+
+ '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
- '@csstools/css-calc@2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)':
+ '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
dependencies:
- '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
- '@csstools/css-tokenizer': 3.0.3
+ '@csstools/color-helpers': 5.1.0
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
- '@csstools/css-color-parser@3.0.9(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)':
+ '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)':
dependencies:
- '@csstools/color-helpers': 5.0.2
- '@csstools/css-calc': 2.1.3(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
- '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
- '@csstools/css-tokenizer': 3.0.3
+ '@csstools/css-tokenizer': 3.0.4
- '@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3)':
+ '@csstools/css-syntax-patches-for-csstree@1.0.14(postcss@8.5.6)':
dependencies:
- '@csstools/css-tokenizer': 3.0.3
+ postcss: 8.5.6
+ optional: true
- '@csstools/css-tokenizer@3.0.3': {}
+ '@csstools/css-tokenizer@3.0.4': {}
'@cypress/request@3.0.6':
dependencies:
@@ -16690,6 +17295,9 @@ snapshots:
esquery: 1.6.0
jsdoc-type-pratt-parser: 4.1.0
+ '@esbuild/aix-ppc64@0.21.5':
+ optional: true
+
'@esbuild/aix-ppc64@0.23.1':
optional: true
@@ -16699,6 +17307,9 @@ snapshots:
'@esbuild/aix-ppc64@0.25.9':
optional: true
+ '@esbuild/android-arm64@0.21.5':
+ optional: true
+
'@esbuild/android-arm64@0.23.1':
optional: true
@@ -16708,6 +17319,9 @@ snapshots:
'@esbuild/android-arm64@0.25.9':
optional: true
+ '@esbuild/android-arm@0.21.5':
+ optional: true
+
'@esbuild/android-arm@0.23.1':
optional: true
@@ -16717,6 +17331,9 @@ snapshots:
'@esbuild/android-arm@0.25.9':
optional: true
+ '@esbuild/android-x64@0.21.5':
+ optional: true
+
'@esbuild/android-x64@0.23.1':
optional: true
@@ -16726,6 +17343,9 @@ snapshots:
'@esbuild/android-x64@0.25.9':
optional: true
+ '@esbuild/darwin-arm64@0.21.5':
+ optional: true
+
'@esbuild/darwin-arm64@0.23.1':
optional: true
@@ -16735,6 +17355,9 @@ snapshots:
'@esbuild/darwin-arm64@0.25.9':
optional: true
+ '@esbuild/darwin-x64@0.21.5':
+ optional: true
+
'@esbuild/darwin-x64@0.23.1':
optional: true
@@ -16744,6 +17367,9 @@ snapshots:
'@esbuild/darwin-x64@0.25.9':
optional: true
+ '@esbuild/freebsd-arm64@0.21.5':
+ optional: true
+
'@esbuild/freebsd-arm64@0.23.1':
optional: true
@@ -16753,6 +17379,9 @@ snapshots:
'@esbuild/freebsd-arm64@0.25.9':
optional: true
+ '@esbuild/freebsd-x64@0.21.5':
+ optional: true
+
'@esbuild/freebsd-x64@0.23.1':
optional: true
@@ -16762,6 +17391,9 @@ snapshots:
'@esbuild/freebsd-x64@0.25.9':
optional: true
+ '@esbuild/linux-arm64@0.21.5':
+ optional: true
+
'@esbuild/linux-arm64@0.23.1':
optional: true
@@ -16771,6 +17403,9 @@ snapshots:
'@esbuild/linux-arm64@0.25.9':
optional: true
+ '@esbuild/linux-arm@0.21.5':
+ optional: true
+
'@esbuild/linux-arm@0.23.1':
optional: true
@@ -16780,6 +17415,9 @@ snapshots:
'@esbuild/linux-arm@0.25.9':
optional: true
+ '@esbuild/linux-ia32@0.21.5':
+ optional: true
+
'@esbuild/linux-ia32@0.23.1':
optional: true
@@ -16789,6 +17427,9 @@ snapshots:
'@esbuild/linux-ia32@0.25.9':
optional: true
+ '@esbuild/linux-loong64@0.21.5':
+ optional: true
+
'@esbuild/linux-loong64@0.23.1':
optional: true
@@ -16798,6 +17439,9 @@ snapshots:
'@esbuild/linux-loong64@0.25.9':
optional: true
+ '@esbuild/linux-mips64el@0.21.5':
+ optional: true
+
'@esbuild/linux-mips64el@0.23.1':
optional: true
@@ -16807,6 +17451,9 @@ snapshots:
'@esbuild/linux-mips64el@0.25.9':
optional: true
+ '@esbuild/linux-ppc64@0.21.5':
+ optional: true
+
'@esbuild/linux-ppc64@0.23.1':
optional: true
@@ -16816,6 +17463,9 @@ snapshots:
'@esbuild/linux-ppc64@0.25.9':
optional: true
+ '@esbuild/linux-riscv64@0.21.5':
+ optional: true
+
'@esbuild/linux-riscv64@0.23.1':
optional: true
@@ -16825,6 +17475,9 @@ snapshots:
'@esbuild/linux-riscv64@0.25.9':
optional: true
+ '@esbuild/linux-s390x@0.21.5':
+ optional: true
+
'@esbuild/linux-s390x@0.23.1':
optional: true
@@ -16834,6 +17487,9 @@ snapshots:
'@esbuild/linux-s390x@0.25.9':
optional: true
+ '@esbuild/linux-x64@0.21.5':
+ optional: true
+
'@esbuild/linux-x64@0.23.1':
optional: true
@@ -16849,6 +17505,9 @@ snapshots:
'@esbuild/netbsd-arm64@0.25.9':
optional: true
+ '@esbuild/netbsd-x64@0.21.5':
+ optional: true
+
'@esbuild/netbsd-x64@0.23.1':
optional: true
@@ -16867,6 +17526,9 @@ snapshots:
'@esbuild/openbsd-arm64@0.25.9':
optional: true
+ '@esbuild/openbsd-x64@0.21.5':
+ optional: true
+
'@esbuild/openbsd-x64@0.23.1':
optional: true
@@ -16879,6 +17541,9 @@ snapshots:
'@esbuild/openharmony-arm64@0.25.9':
optional: true
+ '@esbuild/sunos-x64@0.21.5':
+ optional: true
+
'@esbuild/sunos-x64@0.23.1':
optional: true
@@ -16888,6 +17553,9 @@ snapshots:
'@esbuild/sunos-x64@0.25.9':
optional: true
+ '@esbuild/win32-arm64@0.21.5':
+ optional: true
+
'@esbuild/win32-arm64@0.23.1':
optional: true
@@ -16897,6 +17565,9 @@ snapshots:
'@esbuild/win32-arm64@0.25.9':
optional: true
+ '@esbuild/win32-ia32@0.21.5':
+ optional: true
+
'@esbuild/win32-ia32@0.23.1':
optional: true
@@ -16906,6 +17577,9 @@ snapshots:
'@esbuild/win32-ia32@0.25.9':
optional: true
+ '@esbuild/win32-x64@0.21.5':
+ optional: true
+
'@esbuild/win32-x64@0.23.1':
optional: true
@@ -17380,6 +18054,40 @@ snapshots:
'@shikijs/types': 3.12.2
'@shikijs/vscode-textmate': 10.0.2
+ '@google-cloud/paginator@5.0.2':
+ dependencies:
+ arrify: 2.0.1
+ extend: 3.0.2
+ optional: true
+
+ '@google-cloud/projectify@4.0.0':
+ optional: true
+
+ '@google-cloud/promisify@4.0.0':
+ optional: true
+
+ '@google-cloud/storage@7.17.1':
+ dependencies:
+ '@google-cloud/paginator': 5.0.2
+ '@google-cloud/projectify': 4.0.0
+ '@google-cloud/promisify': 4.0.0
+ abort-controller: 3.0.0
+ async-retry: 1.3.3
+ duplexify: 4.1.3
+ fast-xml-parser: 4.5.3
+ gaxios: 6.7.1
+ google-auth-library: 9.15.1
+ html-entities: 2.6.0
+ mime: 3.0.0
+ p-limit: 3.1.0
+ retry-request: 7.0.2
+ teeny-request: 9.0.0
+ uuid: 8.3.2
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
'@hapi/hoek@9.3.0':
optional: true
@@ -17497,6 +18205,14 @@ snapshots:
figures: 6.1.0
ink: 5.0.1(@types/react@18.3.24)(react-devtools-core@4.28.5)(react@18.3.1)
+ '@inquirer/confirm@5.1.13(@types/node@20.19.17)':
+ dependencies:
+ '@inquirer/core': 10.1.14(@types/node@20.19.17)
+ '@inquirer/type': 3.0.7(@types/node@20.19.17)
+ optionalDependencies:
+ '@types/node': 20.19.17
+ optional: true
+
'@inquirer/confirm@5.1.13(@types/node@22.18.6)':
dependencies:
'@inquirer/core': 10.1.14(@types/node@22.18.6)
@@ -17512,6 +18228,20 @@ snapshots:
optionalDependencies:
'@types/node': 24.3.1
+ '@inquirer/core@10.1.14(@types/node@20.19.17)':
+ dependencies:
+ '@inquirer/figures': 1.0.12
+ '@inquirer/type': 3.0.7(@types/node@20.19.17)
+ ansi-escapes: 4.3.2
+ cli-width: 4.1.0
+ mute-stream: 2.0.0
+ signal-exit: 4.1.0
+ wrap-ansi: 6.2.0
+ yoctocolors-cjs: 2.1.2
+ optionalDependencies:
+ '@types/node': 20.19.17
+ optional: true
+
'@inquirer/core@10.1.14(@types/node@22.18.6)':
dependencies:
'@inquirer/figures': 1.0.12
@@ -17541,6 +18271,11 @@ snapshots:
'@inquirer/figures@1.0.12': {}
+ '@inquirer/type@3.0.7(@types/node@20.19.17)':
+ optionalDependencies:
+ '@types/node': 20.19.17
+ optional: true
+
'@inquirer/type@3.0.7(@types/node@22.18.6)':
optionalDependencies:
'@types/node': 22.18.6
@@ -17638,9 +18373,9 @@ snapshots:
dependencies:
'@jest/types': 29.6.3
- '@jest/create-cache-key-function@30.0.2':
+ '@jest/create-cache-key-function@30.0.5':
dependencies:
- '@jest/types': 30.0.1
+ '@jest/types': 30.0.5
'@jest/environment@29.7.0':
dependencies:
@@ -17716,9 +18451,9 @@ snapshots:
dependencies:
'@sinclair/typebox': 0.27.8
- '@jest/schemas@30.0.1':
+ '@jest/schemas@30.0.5':
dependencies:
- '@sinclair/typebox': 0.34.38
+ '@sinclair/typebox': 0.34.41
'@jest/source-map@29.6.3':
dependencies:
@@ -17778,10 +18513,10 @@ snapshots:
'@types/yargs': 17.0.33
chalk: 4.1.2
- '@jest/types@30.0.1':
+ '@jest/types@30.0.5':
dependencies:
'@jest/pattern': 30.0.1
- '@jest/schemas': 30.0.1
+ '@jest/schemas': 30.0.5
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
'@types/node': 22.18.6
@@ -17894,6 +18629,97 @@ snapshots:
- encoding
- supports-color
+ '@microsoft/api-extractor-model@7.30.7(@types/node@20.19.17)':
+ dependencies:
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@20.19.17)
+ transitivePeerDependencies:
+ - '@types/node'
+
+ '@microsoft/api-extractor-model@7.30.7(@types/node@22.18.6)':
+ dependencies:
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@22.18.6)
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
+ '@microsoft/api-extractor-model@7.30.7(@types/node@24.3.1)':
+ dependencies:
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@24.3.1)
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
+ '@microsoft/api-extractor@7.52.13(@types/node@20.19.17)':
+ dependencies:
+ '@microsoft/api-extractor-model': 7.30.7(@types/node@20.19.17)
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@20.19.17)
+ '@rushstack/rig-package': 0.5.3
+ '@rushstack/terminal': 0.16.0(@types/node@20.19.17)
+ '@rushstack/ts-command-line': 5.0.3(@types/node@20.19.17)
+ lodash: 4.17.21
+ minimatch: 10.0.3
+ resolve: 1.22.10
+ semver: 7.5.4
+ source-map: 0.6.1
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - '@types/node'
+
+ '@microsoft/api-extractor@7.52.13(@types/node@22.18.6)':
+ dependencies:
+ '@microsoft/api-extractor-model': 7.30.7(@types/node@22.18.6)
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@22.18.6)
+ '@rushstack/rig-package': 0.5.3
+ '@rushstack/terminal': 0.16.0(@types/node@22.18.6)
+ '@rushstack/ts-command-line': 5.0.3(@types/node@22.18.6)
+ lodash: 4.17.21
+ minimatch: 10.0.3
+ resolve: 1.22.10
+ semver: 7.5.4
+ source-map: 0.6.1
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
+ '@microsoft/api-extractor@7.52.13(@types/node@24.3.1)':
+ dependencies:
+ '@microsoft/api-extractor-model': 7.30.7(@types/node@24.3.1)
+ '@microsoft/tsdoc': 0.15.1
+ '@microsoft/tsdoc-config': 0.17.1
+ '@rushstack/node-core-library': 5.14.0(@types/node@24.3.1)
+ '@rushstack/rig-package': 0.5.3
+ '@rushstack/terminal': 0.16.0(@types/node@24.3.1)
+ '@rushstack/ts-command-line': 5.0.3(@types/node@24.3.1)
+ lodash: 4.17.21
+ minimatch: 10.0.3
+ resolve: 1.22.10
+ semver: 7.5.4
+ source-map: 0.6.1
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
+ '@microsoft/tsdoc-config@0.17.1':
+ dependencies:
+ '@microsoft/tsdoc': 0.15.1
+ ajv: 8.12.0
+ jju: 1.4.0
+ resolve: 1.22.10
+
+ '@microsoft/tsdoc@0.15.1': {}
+
'@miniflare/cache@2.14.4':
dependencies:
'@miniflare/core': 2.14.4
@@ -18393,6 +19219,8 @@ snapshots:
'@octokit/auth-token@4.0.0': {}
+ '@octokit/auth-token@5.1.2': {}
+
'@octokit/core@5.2.0':
dependencies:
'@octokit/auth-token': 4.0.0
@@ -18403,6 +19231,21 @@ snapshots:
before-after-hook: 2.2.3
universal-user-agent: 6.0.1
+ '@octokit/core@6.1.6':
+ dependencies:
+ '@octokit/auth-token': 5.1.2
+ '@octokit/graphql': 8.2.2
+ '@octokit/request': 9.2.4
+ '@octokit/request-error': 6.1.8
+ '@octokit/types': 14.1.0
+ before-after-hook: 3.0.2
+ universal-user-agent: 7.0.3
+
+ '@octokit/endpoint@10.1.4':
+ dependencies:
+ '@octokit/types': 14.1.0
+ universal-user-agent: 7.0.3
+
'@octokit/endpoint@9.0.6':
dependencies:
'@octokit/types': 13.8.0
@@ -18414,28 +19257,56 @@ snapshots:
'@octokit/types': 13.8.0
universal-user-agent: 6.0.1
+ '@octokit/graphql@8.2.2':
+ dependencies:
+ '@octokit/request': 9.2.4
+ '@octokit/types': 14.1.0
+ universal-user-agent: 7.0.3
+
'@octokit/openapi-types@23.0.1': {}
+ '@octokit/openapi-types@24.2.0': {}
+
+ '@octokit/openapi-types@25.1.0': {}
+
'@octokit/plugin-paginate-rest@11.4.4-cjs.2(@octokit/core@5.2.0)':
dependencies:
'@octokit/core': 5.2.0
'@octokit/types': 13.8.0
+ '@octokit/plugin-paginate-rest@11.6.0(@octokit/core@6.1.6)':
+ dependencies:
+ '@octokit/core': 6.1.6
+ '@octokit/types': 13.10.0
+
'@octokit/plugin-request-log@4.0.0(@octokit/core@5.2.0)':
dependencies:
'@octokit/core': 5.2.0
+ '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.6)':
+ dependencies:
+ '@octokit/core': 6.1.6
+
'@octokit/plugin-rest-endpoint-methods@13.3.2-cjs.1(@octokit/core@5.2.0)':
dependencies:
'@octokit/core': 5.2.0
'@octokit/types': 13.8.0
+ '@octokit/plugin-rest-endpoint-methods@13.5.0(@octokit/core@6.1.6)':
+ dependencies:
+ '@octokit/core': 6.1.6
+ '@octokit/types': 13.10.0
+
'@octokit/request-error@5.1.1':
dependencies:
'@octokit/types': 13.8.0
deprecation: 2.3.1
once: 1.4.0
+ '@octokit/request-error@6.1.8':
+ dependencies:
+ '@octokit/types': 14.1.0
+
'@octokit/request@8.4.1':
dependencies:
'@octokit/endpoint': 9.0.6
@@ -18443,6 +19314,14 @@ snapshots:
'@octokit/types': 13.8.0
universal-user-agent: 6.0.1
+ '@octokit/request@9.2.4':
+ dependencies:
+ '@octokit/endpoint': 10.1.4
+ '@octokit/request-error': 6.1.8
+ '@octokit/types': 14.1.0
+ fast-content-type-parse: 2.0.1
+ universal-user-agent: 7.0.3
+
'@octokit/rest@20.1.2':
dependencies:
'@octokit/core': 5.2.0
@@ -18450,10 +19329,25 @@ snapshots:
'@octokit/plugin-request-log': 4.0.0(@octokit/core@5.2.0)
'@octokit/plugin-rest-endpoint-methods': 13.3.2-cjs.1(@octokit/core@5.2.0)
+ '@octokit/rest@21.1.1':
+ dependencies:
+ '@octokit/core': 6.1.6
+ '@octokit/plugin-paginate-rest': 11.6.0(@octokit/core@6.1.6)
+ '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.6)
+ '@octokit/plugin-rest-endpoint-methods': 13.5.0(@octokit/core@6.1.6)
+
+ '@octokit/types@13.10.0':
+ dependencies:
+ '@octokit/openapi-types': 24.2.0
+
'@octokit/types@13.8.0':
dependencies:
'@octokit/openapi-types': 23.0.1
+ '@octokit/types@14.1.0':
+ dependencies:
+ '@octokit/openapi-types': 25.1.0
+
'@one-ini/wasm@0.1.1': {}
'@oozcitak/dom@1.15.10':
@@ -19470,6 +20364,104 @@ snapshots:
'@rtsao/scc@1.1.0': {}
+ '@rushstack/node-core-library@5.14.0(@types/node@20.19.17)':
+ dependencies:
+ ajv: 8.13.0
+ ajv-draft-04: 1.0.0(ajv@8.13.0)
+ ajv-formats: 3.0.1(ajv@8.13.0)
+ fs-extra: 11.3.0
+ import-lazy: 4.0.0
+ jju: 1.4.0
+ resolve: 1.22.10
+ semver: 7.5.4
+ optionalDependencies:
+ '@types/node': 20.19.17
+
+ '@rushstack/node-core-library@5.14.0(@types/node@22.18.6)':
+ dependencies:
+ ajv: 8.13.0
+ ajv-draft-04: 1.0.0(ajv@8.13.0)
+ ajv-formats: 3.0.1(ajv@8.13.0)
+ fs-extra: 11.3.0
+ import-lazy: 4.0.0
+ jju: 1.4.0
+ resolve: 1.22.10
+ semver: 7.5.4
+ optionalDependencies:
+ '@types/node': 22.18.6
+ optional: true
+
+ '@rushstack/node-core-library@5.14.0(@types/node@24.3.1)':
+ dependencies:
+ ajv: 8.13.0
+ ajv-draft-04: 1.0.0(ajv@8.13.0)
+ ajv-formats: 3.0.1(ajv@8.13.0)
+ fs-extra: 11.3.0
+ import-lazy: 4.0.0
+ jju: 1.4.0
+ resolve: 1.22.10
+ semver: 7.5.4
+ optionalDependencies:
+ '@types/node': 24.3.1
+ optional: true
+
+ '@rushstack/rig-package@0.5.3':
+ dependencies:
+ resolve: 1.22.10
+ strip-json-comments: 3.1.1
+
+ '@rushstack/terminal@0.16.0(@types/node@20.19.17)':
+ dependencies:
+ '@rushstack/node-core-library': 5.14.0(@types/node@20.19.17)
+ supports-color: 8.1.1
+ optionalDependencies:
+ '@types/node': 20.19.17
+
+ '@rushstack/terminal@0.16.0(@types/node@22.18.6)':
+ dependencies:
+ '@rushstack/node-core-library': 5.14.0(@types/node@22.18.6)
+ supports-color: 8.1.1
+ optionalDependencies:
+ '@types/node': 22.18.6
+ optional: true
+
+ '@rushstack/terminal@0.16.0(@types/node@24.3.1)':
+ dependencies:
+ '@rushstack/node-core-library': 5.14.0(@types/node@24.3.1)
+ supports-color: 8.1.1
+ optionalDependencies:
+ '@types/node': 24.3.1
+ optional: true
+
+ '@rushstack/ts-command-line@5.0.3(@types/node@20.19.17)':
+ dependencies:
+ '@rushstack/terminal': 0.16.0(@types/node@20.19.17)
+ '@types/argparse': 1.0.38
+ argparse: 1.0.10
+ string-argv: 0.3.2
+ transitivePeerDependencies:
+ - '@types/node'
+
+ '@rushstack/ts-command-line@5.0.3(@types/node@22.18.6)':
+ dependencies:
+ '@rushstack/terminal': 0.16.0(@types/node@22.18.6)
+ '@types/argparse': 1.0.38
+ argparse: 1.0.10
+ string-argv: 0.3.2
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
+ '@rushstack/ts-command-line@5.0.3(@types/node@24.3.1)':
+ dependencies:
+ '@rushstack/terminal': 0.16.0(@types/node@24.3.1)
+ '@types/argparse': 1.0.38
+ argparse: 1.0.10
+ string-argv: 0.3.2
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
'@scure/base@1.2.6': {}
'@scure/bip32@1.7.0':
@@ -19536,7 +20528,7 @@ snapshots:
'@sinclair/typebox@0.27.8': {}
- '@sinclair/typebox@0.34.38': {}
+ '@sinclair/typebox@0.34.41': {}
'@sindresorhus/is@4.6.0': {}
@@ -19730,7 +20722,7 @@ snapshots:
'@swc/jest@0.2.39(@swc/core@1.11.29(@swc/helpers@0.5.17))':
dependencies:
- '@jest/create-cache-key-function': 30.0.2
+ '@jest/create-cache-key-function': 30.0.5
'@swc/core': 1.11.29(@swc/helpers@0.5.17)
'@swc/counter': 0.1.3
jsonc-parser: 3.3.1
@@ -20079,7 +21071,7 @@ snapshots:
lz-string: 1.5.0
pretty-format: 27.5.1
- '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.18.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.6)(typescript@5.8.3)))(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))':
+ '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.18.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.6)(typescript@5.8.3)))(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))':
dependencies:
'@adobe/css-tools': 4.4.0
'@babel/runtime': 7.27.6
@@ -20093,7 +21085,7 @@ snapshots:
'@jest/globals': 29.7.0
'@types/jest': 29.5.12
jest: 29.7.0(@types/node@22.18.6)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.18.6)(typescript@5.8.3))
- vitest: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
+ vitest: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
'@testing-library/react@16.0.0(@testing-library/dom@10.1.0)(@types/react-dom@18.3.7(@types/react@18.3.24))(@types/react@18.3.24)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
@@ -20139,6 +21131,8 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@types/argparse@1.0.38': {}
+
'@types/aria-query@5.0.1': {}
'@types/babel__code-frame@7.0.6': {}
@@ -20179,6 +21173,9 @@ snapshots:
dependencies:
'@types/node': 22.18.6
+ '@types/caseless@0.12.5':
+ optional: true
+
'@types/chrome@0.0.114':
dependencies:
'@types/filesystem': 0.0.32
@@ -20222,6 +21219,8 @@ snapshots:
'@types/diff-match-patch@1.0.36': {}
+ '@types/diff@5.2.3': {}
+
'@types/estree@1.0.5': {}
'@types/estree@1.0.8': {}
@@ -20253,7 +21252,7 @@ snapshots:
'@types/fs-extra@11.0.4':
dependencies:
'@types/jsonfile': 6.1.1
- '@types/node': 22.18.6
+ '@types/node': 20.19.17
'@types/glob-to-regexp@0.4.4': {}
@@ -20311,7 +21310,7 @@ snapshots:
'@types/jsonfile@6.1.1':
dependencies:
- '@types/node': 22.18.6
+ '@types/node': 20.19.17
'@types/mdast@4.0.4':
dependencies:
@@ -20335,6 +21334,10 @@ snapshots:
'@types/node@12.20.55': {}
+ '@types/node@20.19.17':
+ dependencies:
+ undici-types: 6.21.0
+
'@types/node@22.18.6':
dependencies:
undici-types: 6.21.0
@@ -20365,6 +21368,14 @@ snapshots:
'@types/prop-types': 15.7.5
csstype: 3.1.3
+ '@types/request@2.48.13':
+ dependencies:
+ '@types/caseless': 0.12.5
+ '@types/node': 20.19.17
+ '@types/tough-cookie': 4.0.5
+ form-data: 2.5.5
+ optional: true
+
'@types/resolve@1.20.2': {}
'@types/retry@0.12.0': {}
@@ -20834,7 +21845,7 @@ snapshots:
vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
vue: 3.5.21(typescript@5.8.3)
- '@vitest/coverage-v8@3.0.5(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))':
+ '@vitest/coverage-v8@3.0.5(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2
@@ -20848,17 +21859,33 @@ snapshots:
std-env: 3.9.0
test-exclude: 7.0.1
tinyrainbow: 2.0.0
- vitest: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
+ vitest: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
+ '@vitest/expect@2.1.9':
+ dependencies:
+ '@vitest/spy': 2.1.9
+ '@vitest/utils': 2.1.9
+ chai: 5.3.3
+ tinyrainbow: 1.2.0
+
'@vitest/expect@3.0.5':
dependencies:
'@vitest/spy': 3.0.5
'@vitest/utils': 3.0.5
- chai: 5.1.2
+ chai: 5.3.3
tinyrainbow: 2.0.0
+ '@vitest/mocker@2.1.9(msw@2.11.2(@types/node@20.19.17)(typescript@5.8.3))(vite@5.4.20(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0))':
+ dependencies:
+ '@vitest/spy': 2.1.9
+ estree-walker: 3.0.3
+ magic-string: 0.30.19
+ optionalDependencies:
+ msw: 2.11.2(@types/node@20.19.17)(typescript@5.8.3)
+ vite: 5.4.20(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0)
+
'@vitest/mocker@3.0.5(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(vite@6.3.6(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))':
dependencies:
'@vitest/spy': 3.0.5
@@ -20877,29 +21904,58 @@ snapshots:
msw: 2.11.2(@types/node@24.3.1)(typescript@5.8.3)
vite: 6.3.6(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
+ '@vitest/pretty-format@2.1.9':
+ dependencies:
+ tinyrainbow: 1.2.0
+
'@vitest/pretty-format@3.0.5':
dependencies:
tinyrainbow: 2.0.0
+ '@vitest/pretty-format@3.2.4':
+ dependencies:
+ tinyrainbow: 2.0.0
+
+ '@vitest/runner@2.1.9':
+ dependencies:
+ '@vitest/utils': 2.1.9
+ pathe: 1.1.2
+
'@vitest/runner@3.0.5':
dependencies:
'@vitest/utils': 3.0.5
pathe: 2.0.3
+ '@vitest/snapshot@2.1.9':
+ dependencies:
+ '@vitest/pretty-format': 2.1.9
+ magic-string: 0.30.19
+ pathe: 1.1.2
+
'@vitest/snapshot@3.0.5':
dependencies:
'@vitest/pretty-format': 3.0.5
magic-string: 0.30.19
pathe: 2.0.3
+ '@vitest/spy@2.1.9':
+ dependencies:
+ tinyspy: 3.0.2
+
'@vitest/spy@3.0.5':
dependencies:
tinyspy: 3.0.2
+ '@vitest/utils@2.1.9':
+ dependencies:
+ '@vitest/pretty-format': 2.1.9
+ loupe: 3.2.1
+ tinyrainbow: 1.2.0
+
'@vitest/utils@3.0.5':
dependencies:
'@vitest/pretty-format': 3.0.5
- loupe: 3.1.2
+ loupe: 3.2.1
tinyrainbow: 2.0.0
'@volar/language-core@2.1.6':
@@ -21350,10 +22406,18 @@ snapshots:
react: 18.3.1
zod: 3.24.2
+ ajv-draft-04@1.0.0(ajv@8.13.0):
+ optionalDependencies:
+ ajv: 8.13.0
+
ajv-formats@2.1.1(ajv@8.17.1):
optionalDependencies:
ajv: 8.17.1
+ ajv-formats@3.0.1(ajv@8.13.0):
+ optionalDependencies:
+ ajv: 8.13.0
+
ajv-formats@3.0.1(ajv@8.17.1):
optionalDependencies:
ajv: 8.17.1
@@ -21374,6 +22438,20 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
+ ajv@8.12.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+
+ ajv@8.13.0:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+
ajv@8.17.1:
dependencies:
fast-deep-equal: 3.1.3
@@ -21572,6 +22650,9 @@ snapshots:
arrify@1.0.1: {}
+ arrify@2.0.1:
+ optional: true
+
arrify@3.0.0: {}
asap@2.0.6: {}
@@ -21717,6 +22798,11 @@ snapshots:
async-limiter@1.0.1: {}
+ async-retry@1.3.3:
+ dependencies:
+ retry: 0.13.1
+ optional: true
+
async-sema@3.1.1: {}
async@2.6.4:
@@ -21936,6 +23022,8 @@ snapshots:
before-after-hook@2.2.3: {}
+ before-after-hook@3.0.2: {}
+
better-opn@3.0.2:
dependencies:
open: 8.4.2
@@ -21944,8 +23032,16 @@ snapshots:
dependencies:
is-windows: 1.0.2
+ bidi-js@1.0.3:
+ dependencies:
+ require-from-string: 2.0.2
+ optional: true
+
big-integer@1.6.52: {}
+ bignumber.js@9.3.1:
+ optional: true
+
binary-extensions@2.3.0: {}
bindings@1.5.0:
@@ -22235,12 +23331,12 @@ snapshots:
supports-color: 8.1.1
window-size: 1.1.1
- chai@5.1.2:
+ chai@5.3.3:
dependencies:
assertion-error: 2.0.1
check-error: 2.1.1
deep-eql: 5.0.2
- loupe: 3.1.2
+ loupe: 3.2.1
pathval: 2.0.0
chalk@2.4.2:
@@ -22944,10 +24040,19 @@ snapshots:
dependencies:
cssom: 0.3.8
- cssstyle@4.3.1:
+ cssstyle@4.6.0:
+ dependencies:
+ '@asamuzakjp/css-color': 3.2.0
+ rrweb-cssom: 0.8.0
+
+ cssstyle@5.3.0(postcss@8.5.6):
dependencies:
- '@asamuzakjp/css-color': 3.1.5
- rrweb-cssom: 0.8.0
+ '@asamuzakjp/css-color': 4.0.4
+ '@csstools/css-syntax-patches-for-csstree': 1.0.14(postcss@8.5.6)
+ css-tree: 3.1.0
+ transitivePeerDependencies:
+ - postcss
+ optional: true
csstype@3.1.3: {}
@@ -23020,6 +24125,12 @@ snapshots:
whatwg-mimetype: 4.0.0
whatwg-url: 14.2.0
+ data-urls@6.0.0:
+ dependencies:
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 15.1.0
+ optional: true
+
data-view-buffer@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -23242,6 +24353,8 @@ snapshots:
diff@5.2.0: {}
+ diff@7.0.0: {}
+
diff@8.0.2: {}
dir-glob@3.0.1:
@@ -23582,6 +24695,32 @@ snapshots:
esbuild-plugin-file-path-extensions@2.1.4: {}
+ esbuild@0.21.5:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.21.5
+ '@esbuild/android-arm': 0.21.5
+ '@esbuild/android-arm64': 0.21.5
+ '@esbuild/android-x64': 0.21.5
+ '@esbuild/darwin-arm64': 0.21.5
+ '@esbuild/darwin-x64': 0.21.5
+ '@esbuild/freebsd-arm64': 0.21.5
+ '@esbuild/freebsd-x64': 0.21.5
+ '@esbuild/linux-arm': 0.21.5
+ '@esbuild/linux-arm64': 0.21.5
+ '@esbuild/linux-ia32': 0.21.5
+ '@esbuild/linux-loong64': 0.21.5
+ '@esbuild/linux-mips64el': 0.21.5
+ '@esbuild/linux-ppc64': 0.21.5
+ '@esbuild/linux-riscv64': 0.21.5
+ '@esbuild/linux-s390x': 0.21.5
+ '@esbuild/linux-x64': 0.21.5
+ '@esbuild/netbsd-x64': 0.21.5
+ '@esbuild/openbsd-x64': 0.21.5
+ '@esbuild/sunos-x64': 0.21.5
+ '@esbuild/win32-arm64': 0.21.5
+ '@esbuild/win32-ia32': 0.21.5
+ '@esbuild/win32-x64': 0.21.5
+
esbuild@0.23.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.23.1
@@ -24069,7 +25208,7 @@ snapshots:
expect-type@0.20.0: {}
- expect-type@1.1.0: {}
+ expect-type@1.2.2: {}
expect@29.7.0:
dependencies:
@@ -24397,6 +25536,8 @@ snapshots:
extsprintf@1.3.0: {}
+ fast-content-type-parse@2.0.1: {}
+
fast-decode-uri-component@1.0.1: {}
fast-deep-equal@3.1.3: {}
@@ -24669,6 +25810,16 @@ snapshots:
forever-agent@0.6.1: {}
+ form-data@2.5.5:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
+ mime-types: 2.1.35
+ safe-buffer: 5.2.1
+ optional: true
+
form-data@3.0.2:
dependencies:
asynckit: 0.4.0
@@ -24770,6 +25921,28 @@ snapshots:
fuse.js@7.1.0: {}
+ gaxios@6.7.1:
+ dependencies:
+ extend: 3.0.2
+ https-proxy-agent: 7.0.6
+ is-stream: 2.0.1
+ node-fetch: 2.7.0
+ uuid: 9.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ gcp-metadata@6.1.1:
+ dependencies:
+ gaxios: 6.7.1
+ google-logging-utils: 0.0.2
+ json-bigint: 1.0.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
gensync@1.0.0-beta.2: {}
get-caller-file@2.0.5: {}
@@ -24970,6 +26143,22 @@ snapshots:
slash: 5.1.0
unicorn-magic: 0.3.0
+ google-auth-library@9.15.1:
+ dependencies:
+ base64-js: 1.5.1
+ ecdsa-sig-formatter: 1.0.11
+ gaxios: 6.7.1
+ gcp-metadata: 6.1.1
+ gtoken: 7.1.0
+ jws: 4.0.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
+ google-logging-utils@0.0.2:
+ optional: true
+
gopd@1.2.0: {}
graceful-fs@4.2.11: {}
@@ -24990,6 +26179,15 @@ snapshots:
section-matter: 1.0.0
strip-bom-string: 1.0.0
+ gtoken@7.1.0:
+ dependencies:
+ gaxios: 6.7.1
+ jws: 4.0.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
gunzip-maybe@1.4.2:
dependencies:
browserify-zlib: 0.1.4
@@ -25405,6 +26603,8 @@ snapshots:
parent-module: 1.0.1
resolve-from: 4.0.0
+ import-lazy@4.0.0: {}
+
import-local@3.1.0:
dependencies:
pkg-dir: 4.2.0
@@ -26246,6 +27446,8 @@ snapshots:
jiti@2.5.1: {}
+ jju@1.4.0: {}
+
joi@17.13.3:
dependencies:
'@hapi/hoek': 9.3.0
@@ -26377,7 +27579,7 @@ snapshots:
jsdom@24.1.3:
dependencies:
- cssstyle: 4.3.1
+ cssstyle: 4.6.0
data-urls: 5.0.0
decimal.js: 10.5.0
form-data: 4.0.4
@@ -26403,10 +27605,44 @@ snapshots:
- supports-color
- utf-8-validate
+ jsdom@27.0.0(postcss@8.5.6):
+ dependencies:
+ '@asamuzakjp/dom-selector': 6.5.5
+ cssstyle: 5.3.0(postcss@8.5.6)
+ data-urls: 6.0.0
+ decimal.js: 10.5.0
+ html-encoding-sniffer: 4.0.0
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ is-potential-custom-element-name: 1.0.1
+ parse5: 7.3.0
+ rrweb-cssom: 0.8.0
+ saxes: 6.0.0
+ symbol-tree: 3.2.4
+ tough-cookie: 6.0.0
+ w3c-xmlserializer: 5.0.0
+ webidl-conversions: 8.0.0
+ whatwg-encoding: 3.1.1
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 15.1.0
+ ws: 8.18.3
+ xml-name-validator: 5.0.0
+ transitivePeerDependencies:
+ - bufferutil
+ - postcss
+ - supports-color
+ - utf-8-validate
+ optional: true
+
jsesc@3.0.2: {}
jsesc@3.1.0: {}
+ json-bigint@1.0.0:
+ dependencies:
+ bignumber.js: 9.3.1
+ optional: true
+
json-buffer@3.0.1: {}
json-cycle@1.5.0: {}
@@ -26494,11 +27730,24 @@ snapshots:
ecdsa-sig-formatter: 1.0.11
safe-buffer: 5.2.1
+ jwa@2.0.1:
+ dependencies:
+ buffer-equal-constant-time: 1.0.1
+ ecdsa-sig-formatter: 1.0.11
+ safe-buffer: 5.2.1
+ optional: true
+
jws@3.2.2:
dependencies:
jwa: 1.4.1
safe-buffer: 5.2.1
+ jws@4.0.0:
+ dependencies:
+ jwa: 2.0.1
+ safe-buffer: 5.2.1
+ optional: true
+
keygrip@1.1.0:
dependencies:
tsscmp: 1.0.6
@@ -26810,7 +28059,7 @@ snapshots:
dependencies:
js-tokens: 4.0.0
- loupe@3.1.2: {}
+ loupe@3.2.1: {}
lowdb@1.0.0:
dependencies:
@@ -26822,7 +28071,7 @@ snapshots:
lru-cache@10.4.3: {}
- lru-cache@11.0.2: {}
+ lru-cache@11.2.1: {}
lru-cache@5.1.1:
dependencies:
@@ -27603,6 +28852,33 @@ snapshots:
ms@2.1.3: {}
+ msw@2.11.2(@types/node@20.19.17)(typescript@5.8.3):
+ dependencies:
+ '@bundled-es-modules/cookie': 2.0.1
+ '@bundled-es-modules/statuses': 1.0.1
+ '@inquirer/confirm': 5.1.13(@types/node@20.19.17)
+ '@mswjs/interceptors': 0.39.3
+ '@open-draft/deferred-promise': 2.2.0
+ '@open-draft/until': 2.1.0
+ '@types/cookie': 0.6.0
+ '@types/statuses': 2.0.6
+ graphql: 16.11.0
+ headers-polyfill: 4.0.3
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ path-to-regexp: 6.3.0
+ picocolors: 1.1.1
+ rettime: 0.7.0
+ strict-event-emitter: 0.5.1
+ tough-cookie: 6.0.0
+ type-fest: 4.41.0
+ yargs: 17.7.2
+ optionalDependencies:
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3):
dependencies:
'@bundled-es-modules/cookie': 2.0.1
@@ -28624,7 +29900,7 @@ snapshots:
path-scurry@2.0.0:
dependencies:
- lru-cache: 11.0.2
+ lru-cache: 11.2.1
minipass: 7.1.2
path-to-regexp@0.1.10: {}
@@ -29662,6 +30938,16 @@ snapshots:
retext-stringify: 4.0.0
unified: 11.0.5
+ retry-request@7.0.2:
+ dependencies:
+ '@types/request': 2.48.13
+ extend: 3.0.2
+ teeny-request: 9.0.0
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
retry@0.13.1: {}
rettime@0.7.0: {}
@@ -29845,6 +31131,10 @@ snapshots:
dependencies:
lru-cache: 6.0.0
+ semver@7.5.4:
+ dependencies:
+ lru-cache: 6.0.0
+
semver@7.6.3: {}
semver@7.7.2: {}
@@ -30348,6 +31638,11 @@ snapshots:
stream-buffers@2.2.0: {}
+ stream-events@1.0.5:
+ dependencies:
+ stubs: 3.0.0
+ optional: true
+
stream-shift@1.0.3: {}
streamsearch@1.1.0: {}
@@ -30508,6 +31803,9 @@ snapshots:
structured-headers@0.4.1: {}
+ stubs@3.0.0:
+ optional: true
+
styled-jsx@5.1.1(@babel/core@7.28.4)(babel-plugin-macros@3.1.0)(react@18.3.1):
dependencies:
client-only: 0.0.1
@@ -30677,6 +31975,18 @@ snapshots:
mkdirp: 3.0.1
yallist: 5.0.0
+ teeny-request@9.0.0:
+ dependencies:
+ http-proxy-agent: 5.0.0
+ https-proxy-agent: 5.0.1
+ node-fetch: 2.7.0
+ stream-events: 1.0.5
+ uuid: 9.0.1
+ transitivePeerDependencies:
+ - encoding
+ - supports-color
+ optional: true
+
temp-dir@2.0.0: {}
temp-dir@3.0.0: {}
@@ -30804,7 +32114,9 @@ snapshots:
'@types/tinycolor2': 1.4.6
tinycolor2: 1.6.0
- tinypool@1.0.2: {}
+ tinypool@1.1.1: {}
+
+ tinyrainbow@1.2.0: {}
tinyrainbow@2.0.0: {}
@@ -30871,6 +32183,11 @@ snapshots:
dependencies:
punycode: 2.3.1
+ tr46@6.0.0:
+ dependencies:
+ punycode: 2.3.1
+ optional: true
+
tree-dump@1.0.2(tslib@2.8.1):
dependencies:
tslib: 2.8.1
@@ -30944,7 +32261,67 @@ snapshots:
tsscmp@1.0.6: {}
- tsup@8.5.0(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1):
+ tsup@8.5.0(@microsoft/api-extractor@7.52.13(@types/node@20.19.17))(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1):
+ dependencies:
+ bundle-require: 5.1.0(esbuild@0.25.0)
+ cac: 6.7.14
+ chokidar: 4.0.3
+ consola: 3.4.2
+ debug: 4.4.1(supports-color@8.1.1)
+ esbuild: 0.25.0
+ fix-dts-default-cjs-exports: 1.0.1
+ joycon: 3.1.1
+ picocolors: 1.1.1
+ postcss-load-config: 6.0.1(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(yaml@2.8.1)
+ resolve-from: 5.0.0
+ rollup: 4.50.1
+ source-map: 0.8.0-beta.0
+ sucrase: 3.35.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tree-kill: 1.2.2
+ optionalDependencies:
+ '@microsoft/api-extractor': 7.52.13(@types/node@20.19.17)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
+ postcss: 8.5.6
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - jiti
+ - supports-color
+ - tsx
+ - yaml
+
+ tsup@8.5.0(@microsoft/api-extractor@7.52.13(@types/node@22.18.6))(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1):
+ dependencies:
+ bundle-require: 5.1.0(esbuild@0.25.0)
+ cac: 6.7.14
+ chokidar: 4.0.3
+ consola: 3.4.2
+ debug: 4.4.1(supports-color@8.1.1)
+ esbuild: 0.25.0
+ fix-dts-default-cjs-exports: 1.0.1
+ joycon: 3.1.1
+ picocolors: 1.1.1
+ postcss-load-config: 6.0.1(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(yaml@2.8.1)
+ resolve-from: 5.0.0
+ rollup: 4.50.1
+ source-map: 0.8.0-beta.0
+ sucrase: 3.35.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tree-kill: 1.2.2
+ optionalDependencies:
+ '@microsoft/api-extractor': 7.52.13(@types/node@22.18.6)
+ '@swc/core': 1.11.29(@swc/helpers@0.5.17)
+ postcss: 8.5.6
+ typescript: 5.8.3
+ transitivePeerDependencies:
+ - jiti
+ - supports-color
+ - tsx
+ - yaml
+
+ tsup@8.5.0(@microsoft/api-extractor@7.52.13(@types/node@24.3.1))(@swc/core@1.11.29(@swc/helpers@0.5.17))(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.2)(typescript@5.8.3)(yaml@2.8.1):
dependencies:
bundle-require: 5.1.0(esbuild@0.25.0)
cac: 6.7.14
@@ -30964,6 +32341,7 @@ snapshots:
tinyglobby: 0.2.15
tree-kill: 1.2.2
optionalDependencies:
+ '@microsoft/api-extractor': 7.52.13(@types/node@24.3.1)
'@swc/core': 1.11.29(@swc/helpers@0.5.17)
postcss: 8.5.6
typescript: 5.8.3
@@ -31125,6 +32503,8 @@ snapshots:
typescript@5.6.1-rc: {}
+ typescript@5.8.2: {}
+
typescript@5.8.3: {}
ua-parser-js@1.0.40: {}
@@ -31307,6 +32687,8 @@ snapshots:
universal-user-agent@6.0.1: {}
+ universal-user-agent@7.0.3: {}
+
universalify@0.1.2: {}
universalify@0.2.0: {}
@@ -31645,6 +33027,24 @@ snapshots:
dependencies:
vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
+ vite-node@2.1.9(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.1(supports-color@8.1.1)
+ es-module-lexer: 1.7.0
+ pathe: 1.1.2
+ vite: 5.4.20(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
vite-node@3.0.5(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1):
dependencies:
cac: 6.7.14
@@ -31753,6 +33153,17 @@ snapshots:
vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
vue: 3.5.21(typescript@5.8.3)
+ vite@5.4.20(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0):
+ dependencies:
+ esbuild: 0.21.5
+ postcss: 8.5.6
+ rollup: 4.50.1
+ optionalDependencies:
+ '@types/node': 20.19.17
+ fsevents: 2.3.3
+ lightningcss: 1.27.0
+ terser: 5.44.0
+
vite@6.3.6(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1):
dependencies:
esbuild: 0.25.0
@@ -31829,36 +33240,73 @@ snapshots:
optionalDependencies:
vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
- vitest-environment-miniflare@2.14.4(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)):
+ vitest-environment-miniflare@2.14.4(vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)):
dependencies:
'@miniflare/queues': 2.14.4
'@miniflare/runner-vm': 2.14.4
'@miniflare/shared': 2.14.4
'@miniflare/shared-test-environment': 2.14.4
undici: 5.28.4
- vitest: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
+ vitest: 3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
transitivePeerDependencies:
- bufferutil
- utf-8-validate
- vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1):
+ vitest@2.1.9(@edge-runtime/vm@5.0.0)(@types/node@20.19.17)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@20.19.17)(typescript@5.8.3))(terser@5.44.0):
+ dependencies:
+ '@vitest/expect': 2.1.9
+ '@vitest/mocker': 2.1.9(msw@2.11.2(@types/node@20.19.17)(typescript@5.8.3))(vite@5.4.20(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0))
+ '@vitest/pretty-format': 2.1.9
+ '@vitest/runner': 2.1.9
+ '@vitest/snapshot': 2.1.9
+ '@vitest/spy': 2.1.9
+ '@vitest/utils': 2.1.9
+ chai: 5.3.3
+ debug: 4.4.1(supports-color@8.1.1)
+ expect-type: 1.2.2
+ magic-string: 0.30.19
+ pathe: 1.1.2
+ std-env: 3.9.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinypool: 1.1.1
+ tinyrainbow: 1.2.0
+ vite: 5.4.20(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0)
+ vite-node: 2.1.9(@types/node@20.19.17)(lightningcss@1.27.0)(terser@5.44.0)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@edge-runtime/vm': 5.0.0
+ '@types/node': 20.19.17
+ jsdom: 27.0.0(postcss@8.5.6)
+ transitivePeerDependencies:
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
+ vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.18.6)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1):
dependencies:
'@vitest/expect': 3.0.5
'@vitest/mocker': 3.0.5(msw@2.11.2(@types/node@22.18.6)(typescript@5.8.3))(vite@6.3.6(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
- '@vitest/pretty-format': 3.0.5
+ '@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.0.5
'@vitest/snapshot': 3.0.5
'@vitest/spy': 3.0.5
'@vitest/utils': 3.0.5
- chai: 5.1.2
+ chai: 5.3.3
debug: 4.4.1(supports-color@8.1.1)
- expect-type: 1.1.0
+ expect-type: 1.2.2
magic-string: 0.30.19
pathe: 2.0.3
std-env: 3.9.0
tinybench: 2.9.0
tinyexec: 0.3.2
- tinypool: 1.0.2
+ tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 6.3.6(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
vite-node: 3.0.5(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
@@ -31867,7 +33315,7 @@ snapshots:
'@edge-runtime/vm': 5.0.0
'@types/debug': 4.1.12
'@types/node': 22.18.6
- jsdom: 24.1.3
+ jsdom: 27.0.0(postcss@8.5.6)
transitivePeerDependencies:
- jiti
- less
@@ -31882,24 +33330,24 @@ snapshots:
- tsx
- yaml
- vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@24.1.3)(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1):
+ vitest@3.0.5(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@24.3.1)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.27.0)(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1):
dependencies:
'@vitest/expect': 3.0.5
'@vitest/mocker': 3.0.5(msw@2.11.2(@types/node@24.3.1)(typescript@5.8.3))(vite@6.3.6(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1))
- '@vitest/pretty-format': 3.0.5
+ '@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.0.5
'@vitest/snapshot': 3.0.5
'@vitest/spy': 3.0.5
'@vitest/utils': 3.0.5
- chai: 5.1.2
+ chai: 5.3.3
debug: 4.4.1(supports-color@8.1.1)
- expect-type: 1.1.0
+ expect-type: 1.2.2
magic-string: 0.30.19
pathe: 2.0.3
std-env: 3.9.0
tinybench: 2.9.0
tinyexec: 0.3.2
- tinypool: 1.0.2
+ tinypool: 1.1.1
tinyrainbow: 2.0.0
vite: 6.3.6(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
vite-node: 3.0.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.27.0)(terser@5.44.0)(tsx@4.19.2)(yaml@2.8.1)
@@ -31908,7 +33356,7 @@ snapshots:
'@edge-runtime/vm': 5.0.0
'@types/debug': 4.1.12
'@types/node': 24.3.1
- jsdom: 24.1.3
+ jsdom: 27.0.0(postcss@8.5.6)
transitivePeerDependencies:
- jiti
- less
@@ -32000,6 +33448,9 @@ snapshots:
webidl-conversions@7.0.0: {}
+ webidl-conversions@8.0.0:
+ optional: true
+
webpack-bundle-analyzer@4.10.2:
dependencies:
'@discoveryjs/json-ext': 0.5.7
@@ -32145,6 +33596,12 @@ snapshots:
tr46: 5.1.1
webidl-conversions: 7.0.0
+ whatwg-url@15.1.0:
+ dependencies:
+ tr46: 6.0.0
+ webidl-conversions: 8.0.0
+ optional: true
+
whatwg-url@5.0.0:
dependencies:
tr46: 0.0.3
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 5f78eb562ab..1ae89055b89 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,5 +1,6 @@
packages:
- 'packages/*'
+ - 'tools/*'
minimumReleaseAge: 2880
diff --git a/snapi.config.json b/snapi.config.json
new file mode 100644
index 00000000000..ac63d7d2391
--- /dev/null
+++ b/snapi.config.json
@@ -0,0 +1,36 @@
+{
+ "packages": ["@clerk/backend"],
+ "excludePackages": ["@clerk/testing", "@clerk/eslint-config"],
+ "snapshotsDir": ".api-snapshots",
+ "mainBranch": "main",
+ "checkVersionBump": true,
+ "suppressedChanges": [],
+ "enableLLMAnalysis": false,
+ "llmProvider": "openai",
+ "ci": {
+ "enableStatusChecks": true,
+ "failOnBreakingChanges": true,
+ "artifactRetentionDays": 7,
+ "parallelSnapshots": true,
+ "batchSize": 5
+ },
+ "github": {
+ "token": "${GITHUB_TOKEN}",
+ "repository": "${GITHUB_REPOSITORY}",
+ "commentOnPR": true,
+ "addStatusChecks": true,
+ "createAnnotations": true
+ },
+ "reporting": {
+ "format": "markdown",
+ "includeCodeDiffs": true,
+ "includeSuggestions": true,
+ "maxChangesPerPackage": 50
+ },
+ "performance": {
+ "maxConcurrentPackages": 3,
+ "timeoutMs": 300000,
+ "cacheBaseline": true,
+ "cacheExpirationDays": 1
+ }
+}
diff --git a/tools/snapi/README.md b/tools/snapi/README.md
new file mode 100644
index 00000000000..5ed59aeaac2
--- /dev/null
+++ b/tools/snapi/README.md
@@ -0,0 +1,371 @@
+# SNAPI (Snapshot API)
+
+A comprehensive tool for detecting breaking changes in TypeScript package APIs, designed for production use with robust cloud storage integration.
+
+## 🚀 Features
+
+### Core Functionality
+
+- **API Snapshot Generation**: Uses Microsoft API Extractor to create detailed API snapshots
+- **Breaking Change Detection**: Intelligent analysis of API changes with severity classification
+- **Version Bump Validation**: Ensures semantic versioning compliance
+- **Suppression Management**: Flexible system for managing false positives
+- **Rich Reporting**: Markdown reports with code diffs and actionable insights
+
+### Production Storage Solutions
+
+- **Google Cloud Storage (GCS)**: Primary production storage with lifecycle management
+- **Multi-Backend Support**: Automatic failover between storage backends
+- **Health Monitoring**: Real-time storage backend health checks
+- **Cost Optimization**: Intelligent storage class transitions and cleanup
+- **Batch Operations**: Efficient bulk snapshot operations
+
+### CI/CD Integration
+
+- **GitHub Actions**: Automated PR checking and status updates
+- **Turborepo Integration**: Leverages existing cache infrastructure
+- **Parallel Processing**: Concurrent package analysis for speed
+- **Artifact Management**: Efficient storage and retrieval of snapshots
+
+## 📦 Installation
+
+```bash
+# Install the tool
+pnpm install @clerk/snapi
+
+# Install optional cloud storage dependencies
+pnpm install @google-cloud/storage # For GCS support
+pnpm install @aws-sdk/client-s3 # For S3 support
+pnpm install @azure/storage-blob # For Azure support
+```
+
+## 🔧 Configuration
+
+### Basic Configuration
+
+Create `snapi.config.json` in your repository root:
+
+```json
+{
+ "packages": ["@your-org/package1", "@your-org/package2"],
+ "excludePackages": ["@your-org/testing"],
+ "snapshotsDir": ".api-snapshots",
+ "mainBranch": "main",
+ "checkVersionBump": true,
+ "suppressedChanges": []
+}
+```
+
+### Production GCS Configuration
+
+```json
+{
+ "packages": ["@your-org/package1", "@your-org/package2"],
+ "excludePackages": ["@your-org/testing"],
+ "snapshotsDir": ".api-snapshots",
+ "mainBranch": "main",
+ "checkVersionBump": true,
+ "suppressedChanges": [],
+ "storage": {
+ "primary": {
+ "type": "gcs",
+ "options": {
+ "projectId": "your-gcp-project",
+ "bucket": "your-api-snapshots-bucket",
+ "prefix": "api-snapshots",
+ "multiRegion": true,
+ "enableVersioning": true,
+ "lifecycle": {
+ "enabled": true,
+ "deleteAfterDays": 365,
+ "archiveAfterDays": 90
+ },
+ "storageClass": "STANDARD"
+ }
+ },
+ "fallback": [
+ {
+ "type": "git-lfs",
+ "options": {
+ "repositoryUrl": "https://github.com/your-org/api-snapshots.git",
+ "branch": "main",
+ "snapshotsPath": "snapshots"
+ }
+ }
+ ],
+ "healthCheckInterval": 10,
+ "retryAttempts": 3,
+ "retryDelay": 1000
+ }
+}
+```
+
+## 🛠️ Usage
+
+### CLI Commands
+
+```bash
+# Initialize configuration
+snapi init
+
+# Generate API snapshots
+snapi snapshot
+
+# Detect breaking changes
+snapi detect
+
+# Storage management
+snapi storage health
+snapi storage stats
+snapi storage cleanup --days 30
+
+# Suppression management
+snapi suppress -p @your-org/package -i change-id -r "Reason"
+snapi cleanup
+```
+
+### Programmatic Usage
+
+```typescript
+import { BreakingChangesDetector } from '@clerk/snapi';
+
+const detector = new BreakingChangesDetector({
+ workspaceRoot: process.cwd(),
+ config: {
+ packages: ['@your-org/package'],
+ excludePackages: [],
+ snapshotsDir: '.api-snapshots',
+ mainBranch: 'main',
+ checkVersionBump: true,
+ suppressedChanges: [],
+ storage: {
+ primary: {
+ type: 'gcs',
+ options: {
+ projectId: 'your-project',
+ bucket: 'your-bucket',
+ },
+ },
+ },
+ },
+});
+
+const result = await detector.detectBreakingChanges();
+console.log(result);
+```
+
+## ☁️ Google Cloud Storage Setup
+
+### Prerequisites
+
+1. Google Cloud Project with billing enabled
+2. Cloud Storage API enabled
+3. Service account with Storage Object Admin permissions
+
+### Quick Setup
+
+```bash
+# Set up GCS bucket
+export PROJECT_ID="your-project-id"
+export BUCKET_NAME="your-api-snapshots"
+
+gsutil mb -p $PROJECT_ID -c STANDARD -l us-central1 gs://$BUCKET_NAME
+gsutil versioning set on gs://$BUCKET_NAME
+
+# Create service account
+gcloud iam service-accounts create snapi \
+ --display-name="SNAPI (Snapshot API)"
+
+# Generate key
+gcloud iam service-accounts keys create sa-key.json \
+ --iam-account=snapi@$PROJECT_ID.iam.gserviceaccount.com
+
+# Set permissions
+gsutil iam ch serviceAccount:snapi@$PROJECT_ID.iam.gserviceaccount.com:objectAdmin gs://$BUCKET_NAME
+```
+
+### Environment Variables
+
+```bash
+export GOOGLE_APPLICATION_CREDENTIALS="/path/to/sa-key.json"
+export GOOGLE_CLOUD_PROJECT="your-project-id"
+export GCS_BUCKET="your-api-snapshots"
+```
+
+## 🔄 GitHub Actions Integration
+
+```yaml
+name: API Breakage Check
+
+on:
+ pull_request:
+ branches: [main]
+
+jobs:
+ api-breakage-check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '18'
+
+ - name: Setup GCS credentials
+ run: |
+ echo '${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}' > /tmp/gcs-key.json
+ echo "GOOGLE_APPLICATION_CREDENTIALS=/tmp/gcs-key.json" >> $GITHUB_ENV
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Check API breaking changes
+ run: |
+ snapi detect \
+ --fail-on-breaking \
+ --output api-breakage-report.md
+ env:
+ GOOGLE_CLOUD_PROJECT: ${{ secrets.GCS_PROJECT_ID }}
+ GCS_BUCKET: ${{ secrets.GCS_BUCKET }}
+
+ - name: Comment PR
+ uses: actions/github-script@v7
+ if: always()
+ with:
+ script: |
+ const fs = require('fs');
+ if (fs.existsSync('api-breakage-report.md')) {
+ const report = fs.readFileSync('api-breakage-report.md', 'utf8');
+ github.rest.issues.createComment({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: report
+ });
+ }
+```
+
+## 📊 Storage Features
+
+### Cost Optimization
+
+- **Lifecycle Management**: Automatic transition to cheaper storage classes
+- **Compression**: Automatic gzip compression for files > 1KB
+- **Cleanup**: Configurable retention policies
+- **Monitoring**: Built-in cost tracking and alerts
+
+### Reliability
+
+- **Multi-Regional**: Global availability and redundancy
+- **Versioning**: Object versioning for data protection
+- **Health Checks**: Continuous monitoring and failover
+- **Retry Logic**: Exponential backoff for transient failures
+
+### Performance
+
+- **Parallel Operations**: Concurrent uploads and downloads
+- **Caching**: Intelligent baseline caching
+- **Batch Processing**: Efficient bulk operations
+- **Edge Caching**: Global CDN integration
+
+## 🔍 Monitoring and Observability
+
+### Health Checks
+
+```bash
+# Check storage backend health
+snapi storage health
+
+# Get storage statistics
+snapi storage stats
+
+# Monitor costs and usage
+gsutil du -sh gs://your-bucket
+```
+
+### Metrics
+
+- Storage usage and costs
+- API request rates and errors
+- Upload/download latency
+- Health check failures
+- Snapshot generation times
+
+## 🛡️ Security
+
+### Best Practices
+
+- **Least Privilege**: Minimal IAM permissions
+- **Encryption**: Automatic encryption at rest
+- **Audit Logging**: Comprehensive access logs
+- **Private Access**: No public bucket access
+- **Key Management**: Secure credential handling
+
+### Compliance
+
+- **Data Retention**: Configurable retention policies
+- **Access Control**: Fine-grained permissions
+- **Audit Trail**: Complete operation logging
+- **Backup**: Multi-region redundancy
+
+## 📚 Documentation
+
+- [GCS Production Setup Guide](./docs/GCS_PRODUCTION_SETUP.md)
+- [Configuration Reference](./docs/CONFIGURATION.md)
+- [Troubleshooting Guide](./docs/TROUBLESHOOTING.md)
+- [API Reference](./docs/API.md)
+
+## 🤝 Contributing
+
+1. Fork the repository
+2. Create a feature branch
+3. Make your changes
+4. Add tests
+5. Submit a pull request
+
+## 📄 License
+
+MIT License - see [LICENSE](./LICENSE) for details.
+
+## 🆘 Support
+
+- [GitHub Issues](https://github.com/your-org/api-breakage-detector/issues)
+- [Documentation](./docs/)
+- [GCS Support](https://cloud.google.com/support)
+
+---
+
+Built with ❤️ for reliable API evolution in production environments.
+
+## 🔐 Environment Variables
+
+The API Breakage Detector uses the following environment variables for authentication:
+
+### Google Cloud Storage Configuration
+
+| Variable | Description | Required | Example |
+| ---------------- | -------------------- | -------- | -------------------- |
+| `GCS_PROJECT_ID` | Your GCP project ID | **Yes** | `'my-gcp-project'` |
+| `GCS_BUCKET` | Your GCS bucket name | **Yes** | `'my-api-snapshots'` |
+
+### Google Cloud Storage Authentication (choose one)
+
+| Variable | Description | Example |
+| -------------------------------- | ------------------------------------ | --------------------------------------- |
+| `GOOGLE_SERVICE_ACCOUNT_KEY` | JSON service account key content | `'{"type":"service_account",...}'` |
+| `GOOGLE_APPLICATION_CREDENTIALS` | Path to service account key file | `'/path/to/key.json'` |
+| _(none)_ | Uses default application credentials | `gcloud auth application-default login` |
+
+### GitHub Integration (for CI/CD)
+
+| Variable | Description | Example |
+| ------------------- | ------------------------------- | -------------------- |
+| `GITHUB_TOKEN` | GitHub API token | `'ghp_...'` |
+| `GITHUB_REPOSITORY` | Repository in owner/repo format | `'clerk/javascript'` |
+
+For detailed setup instructions, see [`docs/GCS_ENV_SETUP.md`](./docs/GCS_ENV_SETUP.md).
+
+## �� Storage Backends
diff --git a/tools/snapi/bin/cli.js b/tools/snapi/bin/cli.js
new file mode 100755
index 00000000000..2ec4997953a
--- /dev/null
+++ b/tools/snapi/bin/cli.js
@@ -0,0 +1,10 @@
+#!/usr/bin/env node
+
+import('../dist/cli.js')
+ .then(({ default: cli }) => {
+ // The CLI module should handle everything
+ })
+ .catch(error => {
+ console.error('Failed to load CLI:', error);
+ process.exit(1);
+ });
diff --git a/tools/snapi/package.json b/tools/snapi/package.json
new file mode 100644
index 00000000000..01541286ff0
--- /dev/null
+++ b/tools/snapi/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "@clerk/snapi",
+ "version": "1.0.0",
+ "description": "Snapshot API (SNAPI) - Detect breaking changes in TypeScript package APIs",
+ "type": "module",
+ "exports": "./dist/index.js",
+ "main": "./dist/index.js",
+ "types": "./dist/index.d.ts",
+ "bin": {
+ "snapi": "./bin/cli.js"
+ },
+ "scripts": {
+ "build": "tsup",
+ "clean": "rimraf dist",
+ "cleanup": "node ./dist/cli.js cleanup",
+ "detect": "node ./dist/cli.js detect",
+ "dev": "tsup --watch",
+ "format": "prettier --write .",
+ "format:check": "prettier --check .",
+ "health:storage": "node dist/cli.js storage health",
+ "init": "node ./dist/cli.js init",
+ "lint": "eslint src",
+ "setup:gcs": "node scripts/setup-gcs.js",
+ "storage:stats": "node dist/cli.js storage stats",
+ "suppress": "node ./dist/cli.js suppress",
+ "test": "vitest run",
+ "test:watch": "vitest watch"
+ },
+ "dependencies": {
+ "@microsoft/api-extractor": "^7.47.9",
+ "@microsoft/api-extractor-model": "^7.29.4",
+ "@octokit/rest": "^21.0.0",
+ "chalk": "^5.3.0",
+ "commander": "^12.1.0",
+ "diff": "^7.0.0",
+ "fs-extra": "^11.2.0",
+ "globby": "^14.0.2",
+ "semver": "^7.6.0",
+ "yaml": "^2.4.0",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@types/diff": "^5.2.0",
+ "@types/fs-extra": "^11.0.4",
+ "@types/node": "^20.11.0",
+ "@types/semver": "^7.5.0",
+ "eslint": "^9.0.0",
+ "tsup": "catalog:repo",
+ "typescript": "catalog:repo",
+ "vitest": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "@google-cloud/storage": "^7.16.0"
+ },
+ "engines": {
+ "node": ">=22.0.0"
+ }
+}
diff --git a/tools/snapi/src/analyzers/api-diff.ts b/tools/snapi/src/analyzers/api-diff.ts
new file mode 100644
index 00000000000..32232cee807
--- /dev/null
+++ b/tools/snapi/src/analyzers/api-diff.ts
@@ -0,0 +1,461 @@
+import type {
+ ApiClass,
+ ApiEnum,
+ ApiFunction,
+ ApiInterface,
+ ApiItem,
+ ExcerptToken,
+} from '@microsoft/api-extractor-model';
+import { ApiItemKind, ApiModel } from '@microsoft/api-extractor-model';
+import { createHash } from 'crypto';
+import fs from 'fs-extra';
+
+import type { ApiChange } from '../types.js';
+import { ChangeSeverity, ChangeType } from '../types.js';
+
+interface ComparisonContext {
+ currentModel: ApiModel;
+ previousModel: ApiModel;
+ packageName: string;
+}
+
+/**
+ * Analyzes differences between API models and categorizes changes
+ */
+export class ApiDiffAnalyzer {
+ async compareApiModels(
+ currentApiJsonPath: string,
+ previousApiJsonPath: string,
+ packageName: string,
+ ): Promise {
+ if (!(await fs.pathExists(previousApiJsonPath))) {
+ // No previous version to compare against - all current exports are additions
+ return this.analyzeAsNewPackage(currentApiJsonPath, packageName);
+ }
+
+ const currentModel = new ApiModel();
+ const previousModel = new ApiModel();
+
+ try {
+ currentModel.loadPackage(currentApiJsonPath);
+ previousModel.loadPackage(previousApiJsonPath);
+ } catch (error) {
+ throw new Error(`Failed to load API models: ${error}`);
+ }
+
+ const context: ComparisonContext = {
+ currentModel,
+ previousModel,
+ packageName,
+ };
+
+ return this.analyzeChanges(context);
+ }
+
+ private async analyzeAsNewPackage(apiJsonPath: string, packageName: string): Promise {
+ const model = new ApiModel();
+ model.loadPackage(apiJsonPath);
+
+ const changes: ApiChange[] = [];
+ const apiPackage = model.packages[0];
+
+ if (!apiPackage) return changes;
+
+ // All items in new package are additions
+ this.visitApiItems(apiPackage, item => {
+ if (this.isPublicApi(item)) {
+ changes.push(this.createAdditionChange(item, packageName));
+ }
+ });
+
+ return changes;
+ }
+
+ private analyzeChanges(context: ComparisonContext): ApiChange[] {
+ const changes: ApiChange[] = [];
+
+ const currentPackage = context.currentModel.packages[0];
+ const previousPackage = context.previousModel.packages[0];
+
+ if (!currentPackage || !previousPackage) {
+ return changes;
+ }
+
+ // Create maps for efficient lookup
+ const currentItems = this.createItemMap(currentPackage);
+ const previousItems = this.createItemMap(previousPackage);
+
+ // Find removed items (breaking changes)
+ for (const [key, previousItem] of previousItems) {
+ if (!currentItems.has(key) && this.isPublicApi(previousItem)) {
+ changes.push(this.createRemovalChange(previousItem, context.packageName));
+ }
+ }
+
+ // Find added items (additions)
+ for (const [key, currentItem] of currentItems) {
+ if (!previousItems.has(key) && this.isPublicApi(currentItem)) {
+ changes.push(this.createAdditionChange(currentItem, context.packageName));
+ }
+ }
+
+ // Find modified items (potential breaking changes)
+ for (const [key, currentItem] of currentItems) {
+ const previousItem = previousItems.get(key);
+ if (previousItem && this.isPublicApi(currentItem)) {
+ const itemChanges = this.compareApiItems(currentItem, previousItem, context.packageName);
+ changes.push(...itemChanges);
+ }
+ }
+
+ return changes;
+ }
+
+ private createItemMap(packageItem: ApiItem): Map {
+ const map = new Map();
+
+ this.visitApiItems(packageItem, item => {
+ const key = this.getItemKey(item);
+ map.set(key, item);
+ });
+
+ return map;
+ }
+
+ private visitApiItems(root: ApiItem, callback: (item: ApiItem) => void): void {
+ const visit = (item: ApiItem) => {
+ callback(item);
+ for (const child of item.members) {
+ visit(child);
+ }
+ };
+
+ visit(root);
+ }
+
+ private getItemKey(item: ApiItem): string {
+ // Create a unique key that includes parent context
+ const parts = [];
+ let current: ApiItem | undefined = item;
+
+ while (current && current.kind !== ApiItemKind.Package) {
+ parts.unshift(current.displayName);
+ current = current.parent;
+ }
+
+ return parts.join('.');
+ }
+
+ private compareApiItems(currentItem: ApiItem, previousItem: ApiItem, packageName: string): ApiChange[] {
+ const changes: ApiChange[] = [];
+
+ // Compare based on item type
+ switch (currentItem.kind) {
+ case ApiItemKind.Function:
+ changes.push(...this.compareFunctions(currentItem as ApiFunction, previousItem as ApiFunction, packageName));
+ break;
+
+ case ApiItemKind.Interface:
+ changes.push(...this.compareInterfaces(currentItem as ApiInterface, previousItem as ApiInterface, packageName));
+ break;
+
+ case ApiItemKind.Class:
+ changes.push(...this.compareClasses(currentItem as ApiClass, previousItem as ApiClass, packageName));
+ break;
+
+ case ApiItemKind.Enum:
+ changes.push(...this.compareEnums(currentItem as ApiEnum, previousItem as ApiEnum, packageName));
+ break;
+
+ default:
+ // Generic comparison for other types
+ changes.push(...this.compareGenericItems(currentItem, previousItem, packageName));
+ }
+
+ return changes;
+ }
+
+ private compareFunctions(currentFunc: ApiFunction, previousFunc: ApiFunction, packageName: string): ApiChange[] {
+ const changes: ApiChange[] = [];
+
+ // Get simplified signatures for comparison
+ const currentSig = this.getFunctionSignature(currentFunc);
+ const previousSig = this.getFunctionSignature(previousFunc);
+
+ if (currentSig !== previousSig) {
+ const isBreaking = this.isFunctionChangeBreaking(currentFunc, previousFunc);
+
+ changes.push({
+ id: this.generateChangeId(packageName, 'function', currentFunc.displayName, currentSig),
+ type: isBreaking ? ChangeType.BREAKING : ChangeType.NON_BREAKING,
+ severity: isBreaking ? ChangeSeverity.MAJOR : ChangeSeverity.MINOR,
+ category: 'function',
+ description: `Function '${currentFunc.displayName}' signature changed`,
+ beforeSnippet: previousSig,
+ afterSnippet: currentSig,
+ location: this.getItemLocation(currentFunc),
+ });
+ }
+
+ return changes;
+ }
+
+ private compareInterfaces(
+ currentInterface: ApiInterface,
+ previousInterface: ApiInterface,
+ packageName: string,
+ ): ApiChange[] {
+ const changes: ApiChange[] = [];
+
+ // Compare interface members
+ const currentMembers = this.getInterfaceMembers(currentInterface);
+ const previousMembers = this.getInterfaceMembers(previousInterface);
+
+ // Check for removed members (breaking)
+ for (const [name, previousMember] of previousMembers) {
+ if (!currentMembers.has(name)) {
+ changes.push({
+ id: this.generateChangeId(packageName, 'interface', currentInterface.displayName, `removed-${name}`),
+ type: ChangeType.BREAKING,
+ severity: ChangeSeverity.MAJOR,
+ category: 'interface',
+ description: `Interface '${currentInterface.displayName}' removed member '${name}'`,
+ beforeSnippet: previousMember,
+ location: this.getItemLocation(currentInterface),
+ });
+ }
+ }
+
+ // Check for added members (potentially breaking if required)
+ for (const [name, currentMember] of currentMembers) {
+ if (!previousMembers.has(name)) {
+ const isRequired = this.isRequiredMember(currentMember);
+ changes.push({
+ id: this.generateChangeId(packageName, 'interface', currentInterface.displayName, `added-${name}`),
+ type: isRequired ? ChangeType.BREAKING : ChangeType.ADDITION,
+ severity: isRequired ? ChangeSeverity.MAJOR : ChangeSeverity.MINOR,
+ category: 'interface',
+ description: `Interface '${currentInterface.displayName}' added ${isRequired ? 'required' : 'optional'} member '${name}'`,
+ afterSnippet: currentMember,
+ location: this.getItemLocation(currentInterface),
+ });
+ }
+ }
+
+ // Check for modified members
+ for (const [name, currentMember] of currentMembers) {
+ const previousMember = previousMembers.get(name);
+ if (previousMember && currentMember !== previousMember) {
+ const isBreaking = this.isMemberChangeBreaking(currentMember, previousMember);
+ changes.push({
+ id: this.generateChangeId(packageName, 'interface', currentInterface.displayName, `modified-${name}`),
+ type: isBreaking ? ChangeType.BREAKING : ChangeType.NON_BREAKING,
+ severity: isBreaking ? ChangeSeverity.MAJOR : ChangeSeverity.MINOR,
+ category: 'interface',
+ description: `Interface '${currentInterface.displayName}' modified member '${name}'`,
+ beforeSnippet: previousMember,
+ afterSnippet: currentMember,
+ location: this.getItemLocation(currentInterface),
+ });
+ }
+ }
+
+ return changes;
+ }
+
+ private compareClasses(currentClass: ApiClass, previousClass: ApiClass, packageName: string): ApiChange[] {
+ // Similar logic to interfaces but with additional considerations for:
+ // - Constructor changes
+ // - Method visibility changes
+ // - Inheritance changes
+ return this.compareGenericItems(currentClass, previousClass, packageName);
+ }
+
+ private compareEnums(currentEnum: ApiEnum, previousEnum: ApiEnum, packageName: string): ApiChange[] {
+ const changes: ApiChange[] = [];
+
+ const currentMembers = this.getEnumMembers(currentEnum);
+ const previousMembers = this.getEnumMembers(previousEnum);
+
+ // Removed enum members are breaking
+ for (const previousMember of previousMembers) {
+ if (!currentMembers.includes(previousMember)) {
+ changes.push({
+ id: this.generateChangeId(packageName, 'enum', currentEnum.displayName, `removed-${previousMember}`),
+ type: ChangeType.BREAKING,
+ severity: ChangeSeverity.MAJOR,
+ category: 'enum',
+ description: `Enum '${currentEnum.displayName}' removed member '${previousMember}'`,
+ beforeSnippet: previousMember,
+ location: this.getItemLocation(currentEnum),
+ });
+ }
+ }
+
+ // Added enum members are additions
+ for (const currentMember of currentMembers) {
+ if (!previousMembers.includes(currentMember)) {
+ changes.push({
+ id: this.generateChangeId(packageName, 'enum', currentEnum.displayName, `added-${currentMember}`),
+ type: ChangeType.ADDITION,
+ severity: ChangeSeverity.MINOR,
+ category: 'enum',
+ description: `Enum '${currentEnum.displayName}' added member '${currentMember}'`,
+ afterSnippet: currentMember,
+ location: this.getItemLocation(currentEnum),
+ });
+ }
+ }
+
+ return changes;
+ }
+
+ private compareGenericItems(currentItem: ApiItem, previousItem: ApiItem, packageName: string): ApiChange[] {
+ // Generic comparison based on excerpt text
+ const currentExcerpt = this.getItemExcerpt(currentItem);
+ const previousExcerpt = this.getItemExcerpt(previousItem);
+
+ if (currentExcerpt !== previousExcerpt) {
+ return [
+ {
+ id: this.generateChangeId(packageName, 'generic', currentItem.displayName, 'modified'),
+ type: ChangeType.BREAKING, // Conservative assumption
+ severity: ChangeSeverity.MAJOR,
+ category: this.getCategoryFromKind(currentItem.kind),
+ description: `${this.getCategoryFromKind(currentItem.kind)} '${currentItem.displayName}' was modified`,
+ beforeSnippet: previousExcerpt,
+ afterSnippet: currentExcerpt,
+ location: this.getItemLocation(currentItem),
+ },
+ ];
+ }
+
+ return [];
+ }
+
+ // Helper methods
+ private isPublicApi(item: ApiItem): boolean {
+ // Only consider items that are not marked as internal
+ return (
+ !item.displayName.startsWith('_') && item.kind !== ApiItemKind.Package && item.kind !== ApiItemKind.EntryPoint
+ );
+ }
+
+ private getFunctionSignature(func: ApiFunction): string {
+ // Simplified signature extraction using the excerpt tokens
+ try {
+ if (func.excerpt && Array.isArray((func.excerpt as any).tokens)) {
+ return (func.excerpt as any).tokens.map((token: ExcerptToken) => token.text).join('');
+ }
+ } catch {
+ // Fall back to display name
+ }
+ return func.displayName;
+ }
+
+ private isFunctionChangeBreaking(current: ApiFunction, previous: ApiFunction): boolean {
+ // This is a simplified check - you'd want more sophisticated analysis
+ const currentParams = this.extractParameters(current);
+ const previousParams = this.extractParameters(previous);
+
+ // More required parameters = breaking
+ // Fewer parameters = potentially breaking
+ // Changed parameter types = breaking
+
+ return currentParams.required.length > previousParams.required.length || currentParams.total < previousParams.total;
+ }
+
+ private extractParameters(_func: ApiFunction): { required: string[]; total: number } {
+ // This would need proper implementation based on API Extractor model
+ return { required: [], total: 0 };
+ }
+
+ private getInterfaceMembers(interfaceItem: ApiInterface): Map {
+ const members = new Map();
+
+ for (const member of interfaceItem.members) {
+ members.set(member.displayName, this.getItemExcerpt(member));
+ }
+
+ return members;
+ }
+
+ private getEnumMembers(enumItem: ApiEnum): string[] {
+ return enumItem.members.map(member => member.displayName);
+ }
+
+ private isRequiredMember(memberSignature: string): boolean {
+ // Check if member is optional (ends with ?)
+ return !memberSignature.includes('?:');
+ }
+
+ private isMemberChangeBreaking(current: string, previous: string): boolean {
+ // Conservative approach - most changes are considered breaking
+ return current !== previous;
+ }
+
+ private getItemExcerpt(item: ApiItem): string {
+ // Use the excerpt tokens to build the text representation
+ try {
+ const itemWithExcerpt = item as any;
+ if (itemWithExcerpt.excerpt && Array.isArray(itemWithExcerpt.excerpt.tokens)) {
+ return itemWithExcerpt.excerpt.tokens.map((token: ExcerptToken) => token.text).join('');
+ }
+ } catch {
+ // Fall back to display name
+ }
+ return item.displayName || '';
+ }
+
+ private getCategoryFromKind(kind: ApiItemKind): ApiChange['category'] {
+ switch (kind) {
+ case ApiItemKind.Function:
+ return 'function';
+ case ApiItemKind.Interface:
+ return 'interface';
+ case ApiItemKind.Class:
+ return 'class';
+ case ApiItemKind.Enum:
+ return 'enum';
+ case ApiItemKind.TypeAlias:
+ return 'type';
+ default:
+ return 'export';
+ }
+ }
+
+ private getItemLocation(_item: ApiItem): { file: string; line?: number } | undefined {
+ // This would need proper implementation to extract source location
+ // API Extractor model doesn't directly provide source locations
+ return undefined;
+ }
+
+ private createRemovalChange(item: ApiItem, packageName: string): ApiChange {
+ return {
+ id: this.generateChangeId(packageName, 'removal', item.displayName, 'removed'),
+ type: ChangeType.BREAKING,
+ severity: ChangeSeverity.MAJOR,
+ category: this.getCategoryFromKind(item.kind),
+ description: `Removed ${this.getCategoryFromKind(item.kind)} '${item.displayName}'`,
+ beforeSnippet: this.getItemExcerpt(item),
+ location: this.getItemLocation(item),
+ };
+ }
+
+ private createAdditionChange(item: ApiItem, packageName: string): ApiChange {
+ return {
+ id: this.generateChangeId(packageName, 'addition', item.displayName, 'added'),
+ type: ChangeType.ADDITION,
+ severity: ChangeSeverity.MINOR,
+ category: this.getCategoryFromKind(item.kind),
+ description: `Added ${this.getCategoryFromKind(item.kind)} '${item.displayName}'`,
+ afterSnippet: this.getItemExcerpt(item),
+ location: this.getItemLocation(item),
+ };
+ }
+
+ private generateChangeId(packageName: string, category: string, itemName: string, changeType: string): string {
+ const content = `${packageName}:${category}:${itemName}:${changeType}`;
+ return createHash('sha256').update(content).digest('hex').substring(0, 8);
+ }
+}
diff --git a/tools/snapi/src/analyzers/version-analyzer.ts b/tools/snapi/src/analyzers/version-analyzer.ts
new file mode 100644
index 00000000000..67a834ab41c
--- /dev/null
+++ b/tools/snapi/src/analyzers/version-analyzer.ts
@@ -0,0 +1,147 @@
+import semver from 'semver';
+
+import type { ApiChange } from '../types.js';
+import { ChangeSeverity } from '../types.js';
+
+export interface VersionBumpAnalysis {
+ recommendedBump: ChangeSeverity;
+ actualBump?: ChangeSeverity;
+ isValid: boolean;
+ reasons: string[];
+}
+
+/**
+ * Analyzes version bumps in relation to API changes
+ */
+export class VersionAnalyzer {
+ async analyzeVersionBump(
+ changes: ApiChange[],
+ currentVersion: string,
+ previousVersion: string,
+ ): Promise {
+ const recommendedBump = this.calculateRecommendedBump(changes);
+ const actualBump = this.calculateActualBump(currentVersion, previousVersion);
+ const isValid = this.isValidVersionBump(recommendedBump, actualBump);
+ const reasons = this.generateReasons(changes, recommendedBump, actualBump);
+
+ return {
+ recommendedBump,
+ actualBump,
+ isValid,
+ reasons,
+ };
+ }
+
+ public calculateRecommendedBump(changes: ApiChange[]): ChangeSeverity {
+ // No changes = patch bump (or no bump)
+ if (changes.length === 0) {
+ return ChangeSeverity.PATCH;
+ }
+
+ // Any breaking change requires major bump
+ const hasBreakingChanges = changes.some(c => c.type === 'breaking' && !c.isSuppressed);
+ if (hasBreakingChanges) {
+ return ChangeSeverity.MAJOR;
+ }
+
+ // New features or non-breaking changes require minor bump
+ const hasNewFeatures = changes.some(c => (c.type === 'addition' || c.type === 'non-breaking') && !c.isSuppressed);
+ if (hasNewFeatures) {
+ return ChangeSeverity.MINOR;
+ }
+
+ // Fallback to patch
+ return ChangeSeverity.PATCH;
+ }
+
+ private calculateActualBump(currentVersion: string, previousVersion: string): ChangeSeverity | undefined {
+ if (!semver.valid(currentVersion) || !semver.valid(previousVersion)) {
+ return undefined;
+ }
+
+ if (semver.eq(currentVersion, previousVersion)) {
+ return undefined; // No version bump
+ }
+
+ const diff = semver.diff(previousVersion, currentVersion);
+
+ switch (diff) {
+ case 'major':
+ return ChangeSeverity.MAJOR;
+ case 'minor':
+ return ChangeSeverity.MINOR;
+ case 'patch':
+ return ChangeSeverity.PATCH;
+ default:
+ return undefined;
+ }
+ }
+
+ private isValidVersionBump(recommended: ChangeSeverity, actual?: ChangeSeverity): boolean {
+ if (!actual) {
+ // No version bump is only valid if recommended is patch and there are no changes
+ return recommended === ChangeSeverity.PATCH;
+ }
+
+ // Convert to numeric for comparison
+ const severityOrder = {
+ [ChangeSeverity.PATCH]: 1,
+ [ChangeSeverity.MINOR]: 2,
+ [ChangeSeverity.MAJOR]: 3,
+ };
+
+ // Actual bump must be >= recommended bump
+ return severityOrder[actual] >= severityOrder[recommended];
+ }
+
+ private generateReasons(changes: ApiChange[], recommended: ChangeSeverity, actual?: ChangeSeverity): string[] {
+ const reasons: string[] = [];
+
+ // Explain why the recommended bump is needed
+ const breakingChanges = changes.filter(c => c.type === 'breaking' && !c.isSuppressed);
+ const newFeatures = changes.filter(c => c.type === 'addition' && !c.isSuppressed);
+ const nonBreakingChanges = changes.filter(c => c.type === 'non-breaking' && !c.isSuppressed);
+
+ if (breakingChanges.length > 0) {
+ reasons.push(`Major version bump required due to ${breakingChanges.length} breaking change(s)`);
+ } else if (newFeatures.length > 0) {
+ reasons.push(`Minor version bump required due to ${newFeatures.length} new feature(s)`);
+ } else if (nonBreakingChanges.length > 0) {
+ reasons.push(`Minor version bump recommended due to ${nonBreakingChanges.length} non-breaking change(s)`);
+ }
+
+ // Explain version bump validation
+ if (!actual) {
+ if (recommended !== ChangeSeverity.PATCH) {
+ reasons.push('⚠️ No version bump detected, but changes require version update');
+ }
+ } else if (!this.isValidVersionBump(recommended, actual)) {
+ reasons.push(`⚠️ Version bump (${actual}) is insufficient for the detected changes (requires ${recommended})`);
+ } else {
+ reasons.push(`✅ Version bump (${actual}) is appropriate for the detected changes`);
+ }
+
+ return reasons;
+ }
+
+ /**
+ * Check if a version is a prerelease
+ */
+ isPrerelease(version: string): boolean {
+ return semver.prerelease(version) !== null;
+ }
+
+ /**
+ * Get next version based on bump type
+ */
+ getNextVersion(currentVersion: string, bump: ChangeSeverity): string {
+ switch (bump) {
+ case ChangeSeverity.MAJOR:
+ return semver.inc(currentVersion, 'major') || currentVersion;
+ case ChangeSeverity.MINOR:
+ return semver.inc(currentVersion, 'minor') || currentVersion;
+ case ChangeSeverity.PATCH:
+ return semver.inc(currentVersion, 'patch') || currentVersion;
+ }
+ }
+}
diff --git a/tools/snapi/src/cli.ts b/tools/snapi/src/cli.ts
new file mode 100644
index 00000000000..4741058a38c
--- /dev/null
+++ b/tools/snapi/src/cli.ts
@@ -0,0 +1,584 @@
+#!/usr/bin/env node
+
+import chalk from 'chalk';
+import { Command } from 'commander';
+import fs from 'fs-extra';
+import * as path from 'path';
+
+import { BreakingChangesDetector } from './core/detector.js';
+import { type Config, ConfigSchema } from './types.js';
+
+const program = new Command();
+
+// Helper to find the workspace root
+function findWorkspaceRoot(startPath: string = process.cwd()): string {
+ let currentPath = startPath;
+
+ while (currentPath !== path.dirname(currentPath)) {
+ // Check for pnpm-workspace.yaml or package.json with workspaces
+ const pnpmWorkspace = path.join(currentPath, 'pnpm-workspace.yaml');
+ const packageJson = path.join(currentPath, 'package.json');
+
+ if (fs.existsSync(pnpmWorkspace)) {
+ return currentPath;
+ }
+
+ if (fs.existsSync(packageJson)) {
+ try {
+ const pkg = fs.readJsonSync(packageJson);
+ if (pkg.workspaces) {
+ return currentPath;
+ }
+ } catch {
+ // Continue searching
+ }
+ }
+
+ currentPath = path.dirname(currentPath);
+ }
+
+ // Fallback to current directory
+ return process.cwd();
+}
+
+program
+ .name('snapi')
+ .description('Snapshot API (SNAPI) - Detect breaking changes in TypeScript package APIs')
+ .version('1.0.0');
+
+program
+ .command('detect')
+ .description('Detect API breaking changes')
+ .option('-c, --config ', 'Path to configuration file', 'snapi.config.json')
+ .option('-o, --output ', 'Output path for report')
+ .option('--format ', 'Output format (markdown|json)', 'markdown')
+ .option('--workspace ', 'Workspace root path', findWorkspaceRoot())
+ .option('--main-branch ', 'Main branch name', 'main')
+ .option('--no-version-check', 'Skip version bump validation')
+ .option('--fail-on-breaking', 'Exit with error code if breaking changes detected')
+ .action(
+ async (options: {
+ config: string;
+ output?: string;
+ format: 'markdown' | 'json';
+ workspace: string;
+ mainBranch: string;
+ noVersionCheck?: boolean;
+ failOnBreaking?: boolean;
+ }) => {
+ try {
+ const config = await loadConfig(options.config, options);
+ const detector = new BreakingChangesDetector({
+ workspaceRoot: options.workspace,
+ config,
+ });
+
+ console.log(chalk.blue('🔍 Starting API breaking changes detection...'));
+
+ const result = await detector.detectBreakingChanges();
+ const report = await detector.generateReport(result, options.format);
+
+ // Output report
+ if (options.output) {
+ await fs.writeFile(options.output, report);
+ console.log(chalk.green(`📄 Report saved to ${options.output}`));
+ } else {
+ console.log('\n' + report);
+ }
+
+ // Exit codes
+ if (options.failOnBreaking && result.hasBreakingChanges) {
+ console.error(chalk.red('💥 Breaking changes detected!'));
+ process.exit(1);
+ }
+
+ if (result.ciShouldFail) {
+ console.error(chalk.red('❌ CI validation failed - version bumps required'));
+ process.exit(1);
+ }
+
+ console.log(chalk.green('✅ API breaking changes detection completed successfully'));
+ } catch (error) {
+ console.error(chalk.red('❌ Error:'), error instanceof Error ? error.message : error);
+ process.exit(1);
+ }
+ },
+ );
+
+program
+ .command('snapshot')
+ .description('Generate API snapshots without comparison')
+ .option('-c, --config ', 'Path to configuration file', 'snapi.config.json')
+ .option('-o, --output ', 'Output directory for snapshots')
+ .option('--workspace ', 'Workspace root path', findWorkspaceRoot())
+ .option('--no-cleanup', 'Skip cleanup of temporary files (useful for caching)')
+ .action(async (options: { config: string; output?: string; workspace: string; cleanup?: boolean }) => {
+ try {
+ const config = await loadConfig(options.config, {});
+
+ // Override snapshots directory if provided
+ if (options.output) {
+ config.snapshotsDir = options.output;
+ }
+
+ const detector = new BreakingChangesDetector({
+ workspaceRoot: options.workspace,
+ config,
+ skipCleanup: !options.cleanup,
+ });
+
+ console.log(chalk.blue('📸 Starting API snapshot generation...'));
+
+ // Discover packages
+ const packages = await detector.discoverPackages();
+ console.log(chalk.blue(`📦 Found ${packages.length} packages to snapshot`));
+
+ // Generate snapshots only
+ const snapshots = await detector.generateCurrentSnapshots(packages);
+
+ console.log(`DEBUG: options.cleanup = ${options.cleanup}`);
+ console.log(`DEBUG: !options.cleanup = ${!options.cleanup}`);
+
+ // Clean up temporary files unless --no-cleanup is specified
+ if (options.cleanup) {
+ console.log('DEBUG: Calling cleanup because options.cleanup is true');
+ await detector.cleanup();
+ } else {
+ console.log('DEBUG: Skipping cleanup because options.cleanup is false (--no-cleanup was used)');
+ }
+
+ console.log(chalk.green(`✅ Generated ${snapshots.size} API snapshots`));
+
+ // List what was created
+ for (const [packageName, snapshotPath] of snapshots) {
+ console.log(chalk.gray(` 📄 ${packageName}: ${snapshotPath}`));
+ }
+ } catch (error) {
+ console.error(chalk.red('❌ Error:'), error instanceof Error ? error.message : error);
+ process.exit(1);
+ }
+ });
+
+program
+ .command('init')
+ .description('Initialize configuration file')
+ .option('-o, --output ', 'Output path for config file', 'snapi.config.json')
+ .action(async (options: { output: string }) => {
+ try {
+ const defaultConfig: Config = {
+ excludePackages: [],
+ snapshotsDir: '.api-snapshots',
+ mainBranch: 'main',
+ checkVersionBump: true,
+ suppressedChanges: [],
+ enableLLMAnalysis: false,
+ llmProvider: 'openai',
+ };
+
+ await fs.writeJson(options.output, defaultConfig, { spaces: 2 });
+ console.log(chalk.green(`✅ Configuration file created at ${options.output}`));
+ } catch (error) {
+ console.error(chalk.red('❌ Error:'), error instanceof Error ? error.message : error);
+ process.exit(1);
+ }
+ });
+
+program
+ .command('suppress')
+ .description('Add a suppression for a specific change')
+ .requiredOption('-p, --package ', 'Package name')
+ .requiredOption('-i, --change-id ', 'Change ID to suppress')
+ .requiredOption('-r, --reason ', 'Reason for suppression')
+ .option('-d, --days ', 'Days until suppression expires', '0')
+ .option('-c, --config ', 'Path to configuration file', 'snapi.config.json')
+ .action(async (options: { package: string; changeId: string; reason: string; days: string; config: string }) => {
+ try {
+ const configPath = path.resolve(options.config);
+ let config: Config;
+
+ if (await fs.pathExists(configPath)) {
+ config = await fs.readJson(configPath);
+ } else {
+ console.log(chalk.yellow('⚠️ Config file not found, creating new one'));
+ config = {
+ excludePackages: [],
+ snapshotsDir: '.api-snapshots',
+ mainBranch: 'main',
+ checkVersionBump: true,
+ suppressedChanges: [],
+ enableLLMAnalysis: false,
+ llmProvider: 'openai',
+ };
+ }
+
+ // Add suppression
+ const expires =
+ parseInt(options.days) > 0
+ ? new Date(Date.now() + parseInt(options.days) * 24 * 60 * 60 * 1000).toISOString()
+ : undefined;
+
+ config.suppressedChanges.push({
+ package: options.package,
+ changeId: options.changeId,
+ reason: options.reason,
+ expires,
+ });
+
+ await fs.writeJson(configPath, config, { spaces: 2 });
+ console.log(chalk.green(`✅ Suppression added for ${options.package}:${options.changeId}`));
+ } catch (error) {
+ console.error(chalk.red('❌ Error:'), error instanceof Error ? error.message : error);
+ process.exit(1);
+ }
+ });
+
+program
+ .command('cleanup')
+ .description('Clean up expired suppressions and temporary files')
+ .option('-c, --config ', 'Path to configuration file', 'snapi.config.json')
+ .option('--workspace ', 'Workspace root path', findWorkspaceRoot())
+ .action(async (options: { config: string; workspace: string }) => {
+ try {
+ const configPath = path.resolve(options.config);
+
+ if (await fs.pathExists(configPath)) {
+ const config: Config = await fs.readJson(configPath);
+
+ // Remove expired suppressions
+ const now = new Date();
+ const validSuppressions = config.suppressedChanges.filter((suppression: { expires?: string }) => {
+ if (!suppression.expires) return true;
+ return new Date(suppression.expires) > now;
+ });
+
+ const removedCount = config.suppressedChanges.length - validSuppressions.length;
+
+ if (removedCount > 0) {
+ config.suppressedChanges = validSuppressions;
+ await fs.writeJson(configPath, config, { spaces: 2 });
+ console.log(chalk.green(`✅ Removed ${removedCount} expired suppression(s)`));
+ } else {
+ console.log(chalk.blue('ℹ️ No expired suppressions found'));
+ }
+ }
+
+ // Clean up snapshots
+ const snapshotsDir = path.join(options.workspace, '.api-snapshots');
+ if (await fs.pathExists(snapshotsDir)) {
+ const currentDir = path.join(snapshotsDir, 'current');
+ if (await fs.pathExists(currentDir)) {
+ await fs.remove(currentDir);
+ console.log(chalk.green('✅ Cleaned up temporary snapshots'));
+ }
+ }
+ } catch (error) {
+ console.error(chalk.red('❌ Error:'), error instanceof Error ? error.message : error);
+ process.exit(1);
+ }
+ });
+
+// Add storage commands
+program
+ .command('storage')
+ .description('Storage management commands')
+ .addCommand(
+ new Command('health')
+ .description('Check storage backend health')
+ .option('-c, --config ', 'Configuration file path', 'snapi.config.json')
+ .option('-v, --verbose', 'Show detailed health information')
+ .option('--ci', 'Run in CI mode with minimal output')
+ .action(async options => {
+ try {
+ const configPath = path.resolve(process.cwd(), options.config);
+ const config = await loadConfig(configPath);
+
+ if (!config.storage) {
+ console.log('❌ No storage configuration found');
+ process.exit(1);
+ }
+
+ const { StorageManager } = await import('./storage/storage-manager.js');
+ const storageManager = new StorageManager(config.storage);
+
+ if (!options.ci) {
+ console.log('🔍 Checking storage health...\n');
+ }
+
+ // Get basic health status
+ const [healthStatus, stats] = await Promise.all([
+ storageManager.getHealthStatus(),
+ storageManager.getStats(),
+ ]);
+
+ // Check if any backend is unhealthy
+ const unhealthyBackends = healthStatus.filter(h => !h.healthy);
+ if (unhealthyBackends.length > 0) {
+ if (options.ci) {
+ console.log('FAILED: Unhealthy storage backends detected');
+ for (const health of unhealthyBackends) {
+ console.log(`ERROR: ${health.backend} - ${health.error || 'Unknown error'}`);
+ }
+ } else {
+ for (const health of healthStatus) {
+ const status = health.healthy ? '✅' : '❌';
+ const latency = health.latency ? ` (${health.latency}ms)` : '';
+ console.log(`${status} ${health.backend}${latency}`);
+ if (health.error) {
+ console.log(` Error: ${health.error}`);
+ }
+ if (health.lastCheck) {
+ console.log(` Last check: ${health.lastCheck.toISOString()}`);
+ }
+ }
+ }
+ process.exit(1);
+ }
+
+ // Perform read-write-delete test
+ if (!options.ci) {
+ console.log('\n🧪 Performing read-write-delete test...');
+ }
+ const testKey = `health-test_test.api.json`;
+ const testData = { timestamp: new Date().toISOString(), test: true };
+ const testMetadata = {
+ commitHash: 'test',
+ timestamp: new Date().toISOString(),
+ branch: 'test',
+ packageName: 'health-test',
+ version: '0.0.0',
+ fileSize: 0,
+ checksum: 'test',
+ };
+
+ try {
+ // Write test
+ if (!options.ci) {
+ console.log(' Writing test file...');
+ }
+ const tempPath = path.join(process.cwd(), '.tmp', 'health-test', testKey);
+ await fs.ensureDir(path.dirname(tempPath));
+ await fs.writeJson(tempPath, testData);
+ await storageManager.store('health-test', tempPath, testMetadata);
+ if (!options.ci) {
+ console.log(' ✅ Write successful');
+ }
+
+ // Read test
+ if (!options.ci) {
+ console.log(' Reading test file...');
+ }
+ const readData = await storageManager.retrieve('health-test', 'test');
+ if (!readData) {
+ throw new Error('Read failed - no data returned');
+ }
+ const parsedData = await fs.readJson(readData);
+ if (parsedData.test !== testData.test) {
+ throw new Error('Read data mismatch');
+ }
+ if (!options.ci) {
+ console.log(' ✅ Read successful');
+ }
+
+ // Delete test
+ if (!options.ci) {
+ console.log(' Deleting test file...');
+ }
+ await storageManager.delete(testKey);
+ if (!options.ci) {
+ console.log(' ✅ Delete successful');
+ }
+
+ // Clean up temp files
+ await fs.remove(path.dirname(tempPath));
+
+ if (!options.ci) {
+ console.log('\n✅ All storage operations successful');
+ }
+ } catch (error) {
+ if (options.ci) {
+ console.log(`FAILED: Storage operation failed - ${error instanceof Error ? error.message : error}`);
+ } else {
+ console.log(`\n❌ Storage operation failed: ${error instanceof Error ? error.message : error}`);
+ }
+ process.exit(1);
+ }
+
+ // Print storage stats
+ if (!options.ci) {
+ console.log('\n📊 Storage Statistics:');
+ console.log(`Total Size: ${formatBytes(stats.totalSize)}`);
+ console.log(`Snapshot Count: ${stats.snapshotCount}`);
+ console.log(`Oldest Snapshot: ${stats.oldestSnapshot || 'N/A'}`);
+ console.log(`Newest Snapshot: ${stats.newestSnapshot || 'N/A'}`);
+
+ // Print detailed backend information if verbose
+ if (options.verbose) {
+ console.log('\n🔧 Backend Details:');
+ for (const backend of stats.backendStats) {
+ const status = backend.healthy ? '✅' : '❌';
+ console.log(`\n${status} ${backend.backend}`);
+
+ if (backend.stats) {
+ console.log(` Size: ${formatBytes(backend.stats.totalSize)}`);
+ console.log(` Count: ${backend.stats.snapshotCount}`);
+ console.log(` Oldest: ${backend.stats.oldestSnapshot || 'N/A'}`);
+ console.log(` Newest: ${backend.stats.newestSnapshot || 'N/A'}`);
+ }
+
+ if (!backend.healthy) {
+ console.log(' Status: Unhealthy');
+ }
+ }
+ }
+ } else {
+ console.log('PASSED: Storage health check completed successfully');
+ }
+
+ await storageManager.shutdown();
+ } catch (error) {
+ if (options.ci) {
+ console.log(`FAILED: ${error instanceof Error ? error.message : error}`);
+ } else {
+ console.error('❌ Storage health check failed:', error);
+ }
+ process.exit(1);
+ }
+ }),
+ )
+ .addCommand(
+ new Command('stats')
+ .description('Get storage statistics')
+ .option('-c, --config ', 'Configuration file path', 'snapi.config.json')
+ .action(async options => {
+ try {
+ const configPath = path.resolve(process.cwd(), options.config);
+ const config = await loadConfig(configPath);
+
+ if (!config.storage) {
+ console.log('❌ No storage configuration found');
+ process.exit(1);
+ }
+
+ const { StorageManager } = await import('./storage/storage-manager.js');
+ const storageManager = new StorageManager(config.storage);
+
+ console.log('📊 Getting storage statistics...\n');
+
+ const stats = await storageManager.getStats();
+
+ console.log(`Total Size: ${formatBytes(stats.totalSize)}`);
+ console.log(`Snapshot Count: ${stats.snapshotCount}`);
+ console.log(`Oldest Snapshot: ${stats.oldestSnapshot || 'N/A'}`);
+ console.log(`Newest Snapshot: ${stats.newestSnapshot || 'N/A'}\n`);
+
+ console.log('Backend Details:');
+ for (const backend of stats.backendStats) {
+ const status = backend.healthy ? '✅' : '❌';
+ console.log(`${status} ${backend.backend}`);
+
+ if (backend.stats) {
+ console.log(` Size: ${formatBytes(backend.stats.totalSize)}`);
+ console.log(` Count: ${backend.stats.snapshotCount}`);
+ }
+ }
+
+ await storageManager.shutdown();
+ } catch (error) {
+ console.error('❌ Failed to get storage stats:', error);
+ process.exit(1);
+ }
+ }),
+ )
+ .addCommand(
+ new Command('cleanup')
+ .description('Clean up old snapshots')
+ .option('-c, --config ', 'Configuration file path', 'snapi.config.json')
+ .option('-d, --days ', 'Retention period in days', '30')
+ .action(async options => {
+ try {
+ const configPath = path.resolve(process.cwd(), options.config);
+ const config = await loadConfig(configPath);
+
+ if (!config.storage) {
+ console.log('❌ No storage configuration found');
+ process.exit(1);
+ }
+
+ const { StorageManager } = await import('./storage/storage-manager.js');
+ const storageManager = new StorageManager(config.storage);
+
+ const days = parseInt(options.days);
+ console.log(`🧹 Cleaning up snapshots older than ${days} days...`);
+
+ await storageManager.cleanup(days);
+
+ console.log('✅ Cleanup completed');
+ await storageManager.shutdown();
+ } catch (error) {
+ console.error('❌ Cleanup failed:', error);
+ process.exit(1);
+ }
+ }),
+ );
+
+async function loadConfig(
+ configPath: string,
+ cliOptions?: {
+ mainBranch?: string;
+ noVersionCheck?: boolean;
+ },
+): Promise {
+ let config: Partial = {};
+
+ // Load from file if it exists
+ const resolvedConfigPath = path.resolve(configPath);
+ if (await fs.pathExists(resolvedConfigPath)) {
+ const fileConfig = await fs.readJson(resolvedConfigPath);
+ config = { ...fileConfig };
+ }
+
+ // Override with CLI options if provided
+ if (cliOptions?.mainBranch) {
+ config.mainBranch = cliOptions.mainBranch;
+ }
+ if (cliOptions?.noVersionCheck) {
+ config.checkVersionBump = false;
+ }
+
+ // Parse environment variables
+ if (process.env.GITHUB_TOKEN) {
+ config.githubToken = process.env.GITHUB_TOKEN;
+ }
+ if (process.env.OPENAI_API_KEY) {
+ config.llmApiKey = process.env.OPENAI_API_KEY;
+ config.enableLLMAnalysis = true;
+ }
+ if (process.env.ANTHROPIC_API_KEY) {
+ config.llmApiKey = process.env.ANTHROPIC_API_KEY;
+ config.llmProvider = 'anthropic';
+ config.enableLLMAnalysis = true;
+ }
+
+ // Validate configuration
+ try {
+ return ConfigSchema.parse(config);
+ } catch (error) {
+ throw new Error(`Invalid configuration: ${error instanceof Error ? error.message : error}`);
+ }
+}
+
+function formatBytes(bytes: number): string {
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
+ let size = bytes;
+ let unitIndex = 0;
+
+ while (size >= 1024 && unitIndex < units.length - 1) {
+ size /= 1024;
+ unitIndex++;
+ }
+
+ return `${size.toFixed(1)} ${units[unitIndex]}`;
+}
+
+// Run the CLI
+program.parse();
diff --git a/tools/snapi/src/core/detector.ts b/tools/snapi/src/core/detector.ts
new file mode 100644
index 00000000000..6e4aedffe23
--- /dev/null
+++ b/tools/snapi/src/core/detector.ts
@@ -0,0 +1,383 @@
+import fs from 'fs-extra';
+import path from 'path';
+
+import { ApiDiffAnalyzer } from '../analyzers/api-diff.js';
+import { VersionAnalyzer, type VersionBumpAnalysis } from '../analyzers/version-analyzer.js';
+import { ReportGenerator } from '../reporters/markdown-reporter.js';
+import type { BaselineSnapshot, SnapshotMetadata } from '../storage/base-storage.js';
+import { StorageManager } from '../storage/storage-manager.js';
+import {
+ type AnalysisResult,
+ type ApiChange,
+ type ApiSnapshot,
+ ChangeSeverity,
+ type Config,
+ type PackageAnalysis,
+ type PackageInfo,
+} from '../types.js';
+import { ApiExtractorRunner } from '../utils/api-extractor.js';
+import { PackageDiscovery } from '../utils/package-discovery.js';
+import { SuppressionManager } from '../utils/suppression-manager.js';
+
+export interface BreakingChangesDetectorOptions {
+ workspaceRoot: string;
+ config: Config;
+ skipCleanup?: boolean;
+}
+
+/**
+ * Main orchestrator for API breaking changes detection
+ */
+export class BreakingChangesDetector {
+ private packageDiscovery: PackageDiscovery;
+ private extractorRunner: ApiExtractorRunner;
+ private diffAnalyzer: ApiDiffAnalyzer;
+ private versionAnalyzer: VersionAnalyzer;
+ private suppressionManager: SuppressionManager;
+ private storageManager?: StorageManager;
+ private options: BreakingChangesDetectorOptions;
+ private reportGenerator: ReportGenerator;
+
+ constructor(options: BreakingChangesDetectorOptions) {
+ this.options = options;
+ this.packageDiscovery = new PackageDiscovery(options.workspaceRoot);
+ this.extractorRunner = new ApiExtractorRunner(options.workspaceRoot);
+ this.diffAnalyzer = new ApiDiffAnalyzer();
+ this.versionAnalyzer = new VersionAnalyzer();
+ this.suppressionManager = new SuppressionManager(options.config.suppressedChanges || []);
+ this.reportGenerator = new ReportGenerator();
+
+ if (options.config.storage) {
+ this.storageManager = new StorageManager(options.config.storage);
+ }
+ }
+
+ async detectBreakingChanges(): Promise {
+ console.log('[SNAPI] 🔍 Starting API breaking changes detection...');
+
+ try {
+ const packages = await this.discoverPackages();
+ console.log(`[SNAPI] 📦 Found ${packages.length} packages to analyze`);
+
+ console.log('[SNAPI] 📸 Generating current API snapshots...');
+ const currentSnapshots = await this.generateCurrentSnapshots(packages);
+
+ console.log('[SNAPI] 🌿 Fetching baseline snapshots...');
+ const baselineSnapshots = await this.getBaselineSnapshots(packages);
+
+ console.log('[SNAPI] 🔄 Analyzing API changes...');
+ const packageAnalyses = await this.analyzePackageChanges(packages, currentSnapshots, baselineSnapshots);
+
+ const suppressedAnalyses = this.applySuppressions(packageAnalyses);
+ const result = this.buildAnalysisResult(suppressedAnalyses);
+
+ console.log('[SNAPI] ✅ API breaking changes detection completed');
+ return result;
+ } catch (error) {
+ console.error('[SNAPI] ❌ API breaking changes detection failed:', error);
+ throw error;
+ } finally {
+ await this.cleanup();
+ }
+ }
+
+ async discoverPackages(): Promise {
+ return this.packageDiscovery.discoverPackages(this.options.config.packages, this.options.config.excludePackages);
+ }
+
+ async generateCurrentSnapshots(packages: PackageInfo[]): Promise