From 098898c63f73e62e3a1b7eb40506aa8c63d29b28 Mon Sep 17 00:00:00 2001 From: Matthew Valancy Date: Tue, 27 Oct 2026 15:32:51 -0700 Subject: [PATCH 1/2] Upgrade Vite and Vitest with preserved browser and test contracts --- ...n-upgrades-must-preserve-test-contracts.md | 48 + .agents/issues/INDEX.md | 1 + .agents/issues/security-audit-index.md | 1 + .github/workflows/ci.yml | 2 + .github/workflows/comprehensive-tests.yml | 2 +- .../quality/TOOLCHAIN_MIGRATION_2026-10-27.md | 111 + package-lock.json | 1935 ++++++----------- package.json | 3 +- packages/core/package.json | 5 +- packages/core/vitest.config.ts | 4 +- packages/mcp-server/package.json | 5 +- packages/mcp-server/vitest.config.ts | 14 +- packages/server/package.json | 5 +- packages/server/tests/captcha-auth.test.ts | 13 +- packages/server/vitest.config.ts | 5 +- packages/web/package.json | 8 +- .../components/WorkItemDetailsModal.test.tsx | 36 +- packages/web/src/test/setup.ts | 6 +- packages/web/vite.config.ts | 6 +- tests/lib/dependencies/toolchain.test.mjs | 60 + tests/toolchain/vite-contract.mjs | 129 ++ 21 files changed, 1112 insertions(+), 1287 deletions(-) create mode 100644 .agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md create mode 100644 docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md create mode 100644 tests/lib/dependencies/toolchain.test.mjs create mode 100644 tests/toolchain/vite-contract.mjs diff --git a/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md b/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md new file mode 100644 index 00000000..0120ef78 --- /dev/null +++ b/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md @@ -0,0 +1,48 @@ +# Toolchain upgrades must preserve discovery, coverage and consumer behavior + +Date: 2026-10-27. Issue #185; source based on reviewed auth stack `d83fd9a`. +Searches of the symptom/security indices found dependency-scope and consumer +lessons but no current Vite/Vitest migration procedure. + +## Evidence + +The initial Vite 7.3.7 / Vitest 4.1.12 build failed DOM matcher types. A nested +runner layout prevented the matcher augmentation resolving its consumer. The +supported Vitest matcher import and deduplication fixed the build. Unrelated +lint patch drift was restored rather than accepted as part of the upgrade. + +`npm run test` initially reported 237 server cases rather than 211: Vitest 4 +also discovered the built copies of 26 source tests. The explicit dist exclusion +restored exactly the tracked source file set. Discovery with and without build +outputs is identical: core 3, server 16, MCP 11, web 45. Coverage explicitly keeps +unimported source and the executable offline-shell plugin at zero hits. + +Node 22 and 24 coverage exposed expensive editor queries and asynchronous test +proof solving. The five-second editor and 20-second CAPTCHA deadlines were +retained. Direct accessible-label queries preserve all editor assertions; a +native SHA-256 search still solves the actual signed 100,000-bound challenge. +A local CPU-protected database run failed six cases on the busy host; a separate +CI-equivalent run passed all 136, without claiming production CPU acceptance. +All earlier failures remain under the dated evidence directory on the test host. + +Current harness: 190/190; actual unified web adapter: 353/353. An owned browser +contract exercises real HMR/state, HTTP/WebSocket proxying, secret denial and +compiled offline loading. Supported-Node coverage is a required CI matrix check. +See [the migration evidence and limits](../../docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md) +for commands, versions, authoritative references and remaining work. + +## Cause and corrective rule + +A successful install or lower audit count does not preserve runner behavior. +Upgrade runner, coverage, transformer and Vite as compatible consumers. Compare +actual source discovery, inspect zero-hit coverage, exercise real reporter output +through the strict harness, and test worker/database and browser behavior. Never +count compiled duplicates, skipped required cases or earlier failed attempts as +passes. Do not replace timeouts with retries to mask migration failures. + +## Limits + +This is a toolchain slice, not runtime-image security clearance. Turbo and +Mermaid/KaTeX remain separately scoped; image packaging/scanning, hosted acceptance, +main promotion and deployment are unfinished. Native browser/database checks +used owned Linux fixtures. Final exact-head review and CI remain required. diff --git a/.agents/issues/INDEX.md b/.agents/issues/INDEX.md index 180d34e6..82447406 100644 --- a/.agents/issues/INDEX.md +++ b/.agents/issues/INDEX.md @@ -2,6 +2,7 @@ | Symptom | Canonical lesson and regression | | --- | --- | +| A toolchain upgrade changes test counts, loses matcher types or drops unimported coverage | [Preserve discovery and consumer behavior](../inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md); [migration evidence](../../docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md) | | OAuth links an unverified email, changes accounts after a provider email change, or leaves an orphan user after a link failure | [Provider proof and isolated atomic linking](../inbox/2026-10-27-oauth-linking-needs-provider-proof-and-atomicity.md); `oauth-identity`, `oauth-profiles` and actual `oauth-strategies` tests | | Login and reset links cross-use, or a reset/reactivation revives old sessions | [Bind purpose and session revision at the write](../inbox/2026-10-27-email-purpose-and-revision-are-auth-boundaries.md); real SQLite/HTTP/WebSocket `auth-link-boundary.test.ts` | | CAPTCHA widget is visible but an immediate verification event leaves proof empty | [Attach widget listeners during commit](../inbox/2026-10-27-widget-events-need-commit-phase-listeners.md); `AuthCaptcha.test.tsx` Profiler regression | diff --git a/.agents/issues/security-audit-index.md b/.agents/issues/security-audit-index.md index 51005c6b..a6f68624 100644 --- a/.agents/issues/security-audit-index.md +++ b/.agents/issues/security-audit-index.md @@ -2,6 +2,7 @@ | Symptom | Evidence and corrective rule | | --- | --- | +| A toolchain upgrade changes test counts, loses matcher types or drops unimported coverage | [Preserve discovery and consumer behavior](../inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md); [migration evidence](../../docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md) | | OAuth email metadata loses verification or callbacks log credential-bearing redirects | [Provider proof and isolated atomic linking](../inbox/2026-10-27-oauth-linking-needs-provider-proof-and-atomicity.md); [provider/recovery contract](../../docs/quality/OAUTH_IDENTITY.md) | | Login and reset links cross-use, or a reset/reactivation revives old sessions | [Bind purpose and session revision at the write](../inbox/2026-10-27-email-purpose-and-revision-are-auth-boundaries.md); real SQLite/HTTP/WebSocket `auth-link-boundary.test.ts` | | CAPTCHA validates only a client string's format or skips missing GraphQL proof | [Server policy, signed action/expiry and bounded replay](../inbox/2026-10-27-captcha-proof-must-be-server-issued.md); `packages/server/tests/captcha*.test.ts`, `qc:captcha` | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e389bb08..7d00fb8e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -169,6 +169,8 @@ jobs: run: npm run build - name: Install Playwright (chromium) run: npx playwright install --with-deps chromium + - name: Vite proxy, hot reload and offline-shell contract + run: npm run test:toolchain - name: Start GraphDone (dev stack) run: | npm run dev > /tmp/dev.log 2>&1 & diff --git a/.github/workflows/comprehensive-tests.yml b/.github/workflows/comprehensive-tests.yml index b20f98af..2f06d519 100644 --- a/.github/workflows/comprehensive-tests.yml +++ b/.github/workflows/comprehensive-tests.yml @@ -36,7 +36,7 @@ jobs: - name: Install dependencies run: npm ci --legacy-peer-deps - name: Run all unit suites (core, web, server, mcp-server) - run: npm run test && npm run test:unified:lib + run: npm run test:coverage && npm run test:unified:lib # Genuinely-real checks: the installer exists, deployment compose parses installer-and-deploy-config: diff --git a/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md b/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md new file mode 100644 index 00000000..fa00adf8 --- /dev/null +++ b/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md @@ -0,0 +1,111 @@ +# Patched build and test toolchain — 2026-10-27 + +This is the compatible-toolchain slice of #185. Runtime-image packaging and +Turbo/Mermaid updates remain separate. This evidence does not establish image, +Windows, hosted-backend or deployment clearance. + +## Versions and compatibility + +| Consumer | Previous lock | Reviewed line | +| --- | --- | --- | +| Vite, declared in all four tested packages | 5.4.21 | 7.3.7 | +| React transform | 4.7.0 | 5.2.0 | +| Vitest and matching V8 coverage | 1.6.1 | 4.1.12 | +| Worker implementation | tinypool 0.8.4 | Vitest 4 native pool; tinypool removed | + +Node 22.18 and 24 satisfy the installed engine/peer contracts. Vite 7 and +Vitest 4 are patched compatible lines; this change does not require adopting +Vite 8's different bundler. All locked and actually resolved copies are guarded +by `tests/lib/dependencies/toolchain.test.mjs`. The guard fails ten cases against +the old lock/install, with one compatibility control still passing. + +Authoritative references: + +- [Vite 7 migration](https://v7.vite.dev/guide/migration): explicit build targets + retain ES2020, Chrome 87, Edge 88, Firefox 78 and Safari 14. +- [Vite non-Windows file boundary advisory](https://github.com/advisories/GHSA-rq7h-c2jc-7f22): + 7.3.7 is patched; network exposure and path conditions matter. +- [Vite Windows alternate-path advisory](https://github.com/advisories/GHSA-fx2h-pf6j-xcff): + the selected line also contains its fix; this is not a Windows execution test. +- [Vitest UI advisory](https://github.com/advisories/GHSA-5xrq-8626-4rwp): + 4.1.0 and later on this line are patched; ordinary run mode does not prove UI exposure. +- [Vitest 4 migration](https://v4.vitest.dev/guide/migration): worker pool, + test discovery and coverage behavior require explicit migration. +- [Tinypool advisory](https://github.com/advisories/GHSA-85c8-ppgw-ccpr): + removing its actual dependency paths avoids replacing a worker major under Vitest 1. + +## Preserved contracts + +- Explicit `**/dist/**` exclusion prevents compiled server tests being counted + twice. Exact discovered files match tracked sources both with and without + compiled outputs: core 3, server 16, MCP 11, web 45. +- Coverage explicitly includes every package's source plus executable + `packages/web/offline-shell.ts`. Unimported modules remain zero-hit entries; + tests and compiled output are excluded. V8's new mapping changes percentages, + so compare scope and exercised behavior rather than equating old percentages. +- MCP remains isolated forks, one worker, no parallel test files. Web/server + use two workers; existing test deadlines and retry policy are unchanged. +- DOM matcher setup uses the Vitest entry point. Lock deduplication makes its + augmentation resolve the same installed runner; unrelated ESLint patches and + their placements were restored. +- The editor lifecycle fixture queries the controls' explicit accessible labels + and still asserts native button semantics, all writes, pending refetches, + drafts and undo snapshots. It avoids repeatedly computing roles across the + entire dialog during the same five-second test. +- The HTTP CAPTCHA fixture searches the actual signed SHA-256 challenge using + native hashing with the unchanged 100,000 bound. Server verification, action + binding, replay rejection and the 20-second deadline remain unchanged. Real + browser acceptance still uses ALTCHA's browser solver. + +## Validation and retained failures + +Pinned clean install, build, types and lint passed. Current Node 22 coverage +runs pass core 41, server 211, web 353 and MCP 110; the 26 explicitly opted-in +MCP database cases are not counted as passes in ordinary unit mode. The actual +owned Neo4j run passed all 136 MCP cases with the existing CI CPU-monitor mode. + +Node 24 core/server/MCP coverage passed; current web coverage passed all 353 +cases after correcting the fixture costs below. Final branch CI runs coverage +for both supported Node versions and remains required before integration. + +The current harness passes 190/190. The real unified web adapter passes 353 +with no skips or warnings. The installed runner's real pass/fail/skip JSON is +also checked through the adapter; required skips must fail. + +`npm run test:toolchain` uses an owned browser/backend/build fixture and proves +React hot reload preserves state and document identity, HTTP and GraphQL +WebSocket proxy paths, denied `.env` content, a compiled offline shell that +works offline, and exclusion of API/auth responses from shell caching. It runs +as a required Smoke Gate step. The normal application, LOD, mobile and runtime +checks remain required too. + +Retained failures and corrections: + +1. Initial build lost DOM matcher types with nested runner installations; + the supported matcher import and deduplicated runner fixed resolution. +2. Initial Vitest 4 discovery ran 26 compiled duplicate server cases; + explicit dist exclusion restores source-only discovery, not fewer source tests. +3. Unbounded coverage hit the editor fixture's five-second budget. Bounded + workers passed on Node 22, but Node 24 still exposed costly repeated role + queries. Direct accessible-label queries preserve all lifecycle assertions; + the corrected 18-case file and complete web suite passed with unchanged budgets. +4. Node 24 HTTP CAPTCHA coverage hit 20 seconds while using the asynchronous + WebCrypto search loop. The independent native-hash fixture solver passed all + four cases without changing the issued work factor or production code. +5. A local real-DB run was blocked in six cases by the host CPU monitor at + 95–100% load. The full 136-case CI-mode run passed; this proves CI parity, + not production CPU-exhaustion behavior. The failed run is retained separately. +6. Initial dependency guards assumed a coverage-package engine field and an + exported React-plugin manifest. Corrected guards check the actual contracts; + they do not weaken supported-runner or version checks. + +Fresh isolated-cache audit: full inventory has three residual package entries +(Turbo moderate, Mermaid/KaTeX low); production-only has zero. Historical counts +remain dated evidence, not distinct exploit counts or a claim about why registry +metadata changed. Runtime images can still contain development packages and +require the separate packaging and image inventory work in #185. + +Vite's existing all-interface development binding is retained for the repo's +LAN/container workflows. Keep access within an intentionally trusted development +network or authenticated tunnel; do not expose Vite/Vitest UI/API as a public +production service. No host allowlist, credential scope or deployment is changed. diff --git a/package-lock.json b/package-lock.json index 213cef61..0a4069ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,18 +52,6 @@ "integrity": "sha512-qZMdnoD3lAyvfSUMNtC2adRi666Pxdcw9zqfMU5qBOaJWqpN9K+eqQGWqeiKDMqL0SF+EytNG4kR/Pr/99GJ6g==", "license": "MIT" }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@antfu/install-pkg": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-2.0.1.tgz", @@ -913,9 +901,14 @@ } }, "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/@braintree/sanitize-url": { "version": "7.1.2", @@ -1518,30 +1511,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/config-helpers": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", @@ -1590,17 +1559,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "13.24.0", "dev": true, @@ -1615,17 +1573,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { @@ -1819,30 +1777,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "dev": true, @@ -1964,25 +1898,6 @@ "node": ">=18.0.0" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "license": "MIT", @@ -2012,7 +1927,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2584,11 +2501,6 @@ "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", "license": "BSD-3-Clause" }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.63.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.63.1.tgz", @@ -2938,8 +2850,10 @@ "win32" ] }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, @@ -3056,6 +2970,17 @@ "@types/node": "*" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/connect": { "version": "3.4.38", "license": "MIT", @@ -3271,6 +3196,13 @@ "@types/ms": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -3830,200 +3762,150 @@ "d3-transition": "^3.0.1" } }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, "node_modules/@vitest/coverage-v8": { - "version": "1.6.1", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.12.tgz", + "integrity": "sha512-6S7/iVknKglLAxMFxQGNppBI0iqJS2NgM6FBxavitj7KaDq/vywOWGf6dGu7F2L1Qy0G6S3uTp7aGshHrzK8JA==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@bcoe/v8-coverage": "^0.2.3", - "debug": "^4.3.4", + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.12", + "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^5.0.4", - "istanbul-reports": "^3.1.6", - "magic-string": "^0.30.5", - "magicast": "^0.3.3", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "test-exclude": "^6.0.0" + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "1.6.1" + "@vitest/browser": "4.1.12", + "vitest": "4.1.12" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, "node_modules/@vitest/expect": { - "version": "1.6.1", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.12.tgz", + "integrity": "sha512-vFlTt+YEu9WBpNjdGayNmlMVzrWPi1+sv853/7t2FU7hpO5gAFBKHzQmkCq5Xjpr+evegF2994LQT3hF3mRlqQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "1.6.1", - "@vitest/utils": "1.6.1", - "chai": "^4.3.10" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.12", + "@vitest/utils": "4.1.12", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/runner": { - "version": "1.6.1", + "node_modules/@vitest/mocker": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.12.tgz", + "integrity": "sha512-fKShNpKZzupWZuY0z7egydvL0sqW4INEZBEExMBMAa6izlENEVHwoXgdaTCaBZ5fwlr4xf2o1wXC83n9RpO+NA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "1.6.1", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" + "@vitest/spy": "4.1.12", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/runner/node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/@vitest/snapshot": { - "version": "1.6.1", + "node_modules/@vitest/pretty-format": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.12.tgz", + "integrity": "sha512-XW9O8+Mxx4VpCtkYdMJLZQQwsVryP9wk7cPKDxtXFfwSak6yRh5+2fep/Y0XF/ElBvJHq8bcYdi6aeuai0opZA==", "dev": true, "license": "MIT", "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/ansi-styles": { - "version": "5.2.0", + "node_modules/@vitest/runner": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.12.tgz", + "integrity": "sha512-NKlVKCr5QnCe8jijdMnmkpHHU+WTqiLFR6G0pHji9uRjXK9xJl1k1nTw6F3pOOj2PDcsDt2GKQMI7wIsaT491w==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@vitest/utils": "4.1.12", + "pathe": "^2.0.3" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/pretty-format": { - "version": "29.7.0", + "node_modules/@vitest/snapshot": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.12.tgz", + "integrity": "sha512-ko1y1Qgb/slzQ9mr+b89Cuqud8WG1TKtsPD8r7ZUBdvVOGt85Af2HwCqHujrhwJq95hs/9RM7fcAPg57o1vlzw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@vitest/pretty-format": "4.1.12", + "@vitest/utils": "4.1.12", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, "node_modules/@vitest/spy": { - "version": "1.6.1", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.12.tgz", + "integrity": "sha512-RGq9x4JNGNTZHEJxvN0oSiJjeSCExm0n2gZKKJZHY9cX5AVA6M7VJILBT3ZJ/tJ/0J9uWT7fETV9/btoi//vSg==", "dev": true, "license": "MIT", - "dependencies": { - "tinyspy": "^2.2.0" - }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "1.6.1", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.12.tgz", + "integrity": "sha512-Q3awXrwOfEV+qc3WmO5ONyE0yO7Q1gQ9/oyHxGLZ/pl7N3NO/ZztqQwKLuwMkV+CA1JYSIeO3gkHnRDIo4AVaA==", "dev": true, "license": "MIT", "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" + "@vitest/pretty-format": "4.1.12", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/utils/node_modules/ansi-styles": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/utils/node_modules/pretty-format": { - "version": "29.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/utils/node_modules/react-is": { - "version": "18.3.1", - "dev": true, - "license": "MIT" - }, "node_modules/@wry/caches": { "version": "1.0.1", "license": "MIT", @@ -4104,17 +3986,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "7.1.4", "dev": true, @@ -4388,13 +4259,34 @@ } }, "node_modules/assertion-error": { - "version": "1.1.0", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { - "node": "*" + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.7.tgz", + "integrity": "sha512-kFL68AG6ajd8fg248zwM9GQrUWEp79gsmjum34OEXjs4yHuUMZfYKwOLW9GMmB4oNvVrj+EAGxsP7ye2UR9UlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" } }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "dev": true, @@ -4730,14 +4622,6 @@ "node": ">= 0.8" } }, - "node_modules/cac": { - "version": "6.7.14", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.8", "license": "MIT", @@ -4836,20 +4720,13 @@ } }, "node_modules/chai": { - "version": "4.5.0", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.3.0.tgz", + "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, "engines": { - "node": ">=4" + "node": ">=18" } }, "node_modules/chalk": { @@ -4906,17 +4783,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/check-error": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, "node_modules/chokidar": { "version": "3.6.0", "license": "MIT", @@ -5001,11 +4867,8 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/confbox": { - "version": "0.1.8", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, @@ -5701,19 +5564,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-eql": { - "version": "4.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", + "node_modules/deep-equal": { + "version": "2.2.3", "dev": true, "license": "MIT", "dependencies": { @@ -5848,14 +5700,6 @@ "version": "1.2.2", "license": "Apache-2.0" }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "dev": true, @@ -6119,6 +5963,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "license": "MIT", @@ -6356,17 +6207,6 @@ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "dev": true, @@ -6378,19 +6218,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-react/node_modules/semver": { "version": "6.3.1", "dev": true, @@ -6433,17 +6260,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/globals": { "version": "13.24.0", "dev": true, @@ -6458,19 +6274,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { "version": "9.6.1", "dev": true, @@ -6571,28 +6374,6 @@ "node": ">=18.0.0" } }, - "node_modules/execa": { - "version": "8.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, "node_modules/expand-template": { "version": "2.0.3", "license": "(MIT OR WTFPL)", @@ -6600,6 +6381,16 @@ "node": ">=6" } }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/exponential-backoff": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", @@ -7081,14 +6872,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-func-name": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "license": "MIT", @@ -7122,17 +6905,6 @@ "node": ">= 0.4" } }, - "node_modules/get-stream": { - "version": "8.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.1.0", "dev": true, @@ -7193,30 +6965,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { "version": "16.3.0", "dev": true, @@ -7623,14 +7371,6 @@ "node": ">= 14" } }, - "node_modules/human-signals": { - "version": "5.0.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.0" - } - }, "node_modules/iconv-lite": { "version": "0.6.3", "license": "MIT", @@ -8134,17 +7874,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-string": { "version": "1.1.1", "dev": true, @@ -8258,19 +7987,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/istanbul-reports": { "version": "3.2.0", "dev": true, @@ -8573,21 +8289,6 @@ "version": "1.2.4", "license": "MIT" }, - "node_modules/local-pkg": { - "version": "0.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "mlly": "^1.7.3", - "pkg-types": "^1.2.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, @@ -8687,14 +8388,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "2.3.7", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, "node_modules/lowlight": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", @@ -8731,7 +8424,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.19", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8739,13 +8434,15 @@ } }, "node_modules/magicast": { - "version": "0.3.5", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.5.tgz", + "integrity": "sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.25.4", - "@babel/types": "^7.25.4", - "source-map-js": "^1.2.0" + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "source-map-js": "^1.2.1" } }, "node_modules/make-dir": { @@ -9095,11 +8792,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "license": "MIT", @@ -9760,17 +9452,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mimic-response": { "version": "3.1.0", "license": "MIT", @@ -9789,6 +9470,30 @@ "node": ">=4" } }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/minimist": { "version": "1.2.8", "license": "MIT", @@ -9821,22 +9526,6 @@ "version": "0.5.3", "license": "MIT" }, - "node_modules/mlly": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.15.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.1" - } - }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, "node_modules/ms": { "version": "2.1.3", "license": "MIT" @@ -10090,31 +9779,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/oauth": { "version": "0.10.2", "license": "MIT" @@ -10233,6 +9897,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz", + "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "license": "MIT", @@ -10257,20 +9935,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optimism": { "version": "0.18.1", "license": "MIT", @@ -10560,22 +10224,16 @@ } }, "node_modules/pathe": { - "version": "1.1.2", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, - "node_modules/pathval": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/pause": { - "version": "0.0.1" - }, - "node_modules/picocolors": { + "node_modules/pause": { + "version": "0.0.1" + }, + "node_modules/picocolors": { "version": "1.1.1", "license": "ISC" }, @@ -10614,21 +10272,6 @@ "node": ">=16.20.0" } }, - "node_modules/pkg-types": { - "version": "1.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.3", - "dev": true, - "license": "MIT" - }, "node_modules/playwright": { "version": "1.63.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz", @@ -11157,14 +10800,6 @@ "react": ">=18" } }, - "node_modules/react-refresh": { - "version": "0.17.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/react-syntax-highlighter": { "version": "16.1.1", "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-16.1.1.tgz", @@ -12020,7 +11655,9 @@ } }, "node_modules/std-env": { - "version": "3.9.0", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz", + "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==", "dev": true, "license": "MIT" }, @@ -12043,13 +11680,6 @@ "dev": true, "license": "MIT" }, - "node_modules/string_decoder": { - "version": "1.3.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "4.2.3", "license": "MIT", @@ -12163,6 +11793,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -12198,17 +11835,6 @@ "node": ">=8" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-indent": { "version": "3.0.0", "dev": true, @@ -12231,22 +11857,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-literal": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/style-to-js": { "version": "1.1.21", "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", @@ -12471,43 +12081,6 @@ "node": ">=6" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/text-table": { "version": "0.2.0", "dev": true, @@ -12575,16 +12148,10 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tinypool": { - "version": "0.8.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", + "node_modules/tinyrainbow": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.2.0.tgz", + "integrity": "sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==", "dev": true, "license": "MIT", "engines": { @@ -12845,14 +12412,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.20.2", "dev": true, @@ -12962,11 +12521,6 @@ "version": "1.1.1", "license": "MIT" }, - "node_modules/ufo": { - "version": "1.6.1", - "dev": true, - "license": "MIT" - }, "node_modules/uid-safe": { "version": "2.1.5", "license": "MIT", @@ -13229,21 +12783,24 @@ } }, "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.7.tgz", + "integrity": "sha512-AHEzTORMbi7/7aXp7w7KZ5+DCUdSeLsJz0grY8xHpc9DHdYb0vQu6DqJfm2tOw3gDExNgPgnJTXxM6syYFHaCA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -13252,19 +12809,25 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, + "jiti": { + "optional": true + }, "less": { "optional": true }, @@ -13285,34 +12848,19 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "node_modules/vite-node": { - "version": "1.6.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -13323,13 +12871,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -13340,13 +12888,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -13357,13 +12905,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -13374,11 +12922,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -13389,13 +12939,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -13406,13 +12956,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -13423,13 +12973,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -13440,13 +12990,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -13457,13 +13007,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -13474,13 +13024,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -13491,13 +13041,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -13508,13 +13058,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -13525,13 +13075,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -13542,13 +13092,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -13559,13 +13109,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -13576,13 +13126,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -13593,13 +13143,30 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -13610,13 +13177,30 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -13627,13 +13211,30 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -13644,13 +13245,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -13661,13 +13262,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -13678,13 +13279,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -13695,11 +13296,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -13707,85 +13310,124 @@ "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "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/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/vitest": { - "version": "1.6.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "1.6.1", - "@vitest/runner": "1.6.1", - "@vitest/snapshot": "1.6.1", - "@vitest/spy": "1.6.1", - "@vitest/utils": "1.6.1", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", - "vite": "^5.0.0", - "vite-node": "1.6.1", - "why-is-node-running": "^2.2.2" + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.12.tgz", + "integrity": "sha512-5eWdz2yb3ajxWF3C8C4TjkXl7FGm3n2E/VlazALrQHzK7nYMSGFnCZto0bbPNl77AwkOZVLk0YnBAejUu0NiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.12", + "@vitest/mocker": "4.1.12", + "@vitest/pretty-format": "4.1.12", + "@vitest/runner": "4.1.12", + "@vitest/snapshot": "4.1.12", + "@vitest/spy": "4.1.12", + "@vitest/utils": "4.1.12", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.1", - "@vitest/ui": "1.6.1", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.12", + "@vitest/browser-preview": "4.1.12", + "@vitest/browser-webdriverio": "^4.1.11", + "@vitest/coverage-istanbul": "4.1.12", + "@vitest/coverage-v8": "4.1.12", + "@vitest/ui": "4.1.12", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, + "@opentelemetry/api": { + "optional": true + }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { @@ -13796,14 +13438,30 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", - "dependencies": { + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { "xml-name-validator": "^5.0.0" }, "engines": { @@ -14210,10 +13868,11 @@ "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitest/coverage-v8": "^1.0.0", + "@vitest/coverage-v8": "^4.1.12", "eslint": "^9.33.0", "globals": "^16.3.0", - "vitest": "^1.0.0" + "vite": "^7.3.7", + "vitest": "^4.1.12" } }, "packages/core/node_modules/@eslint-community/eslint-utils": { @@ -14269,17 +13928,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/core/node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "packages/core/node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -14293,32 +13941,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/core/node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "packages/core/node_modules/@eslint/js": { - "version": "9.39.5", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", - "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, "packages/core/node_modules/@typescript-eslint/eslint-plugin": { "version": "8.72.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.0.tgz", @@ -14468,6 +14090,22 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "packages/core/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/core/node_modules/@typescript-eslint/utils": { "version": "8.72.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", @@ -14510,17 +14148,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/core/node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "packages/core/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "18 || 20 || >=22" } }, "packages/core/node_modules/brace-expansion": { @@ -14536,16 +14171,6 @@ "node": "20 || >=22" } }, - "packages/core/node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, "packages/core/node_modules/eslint": { "version": "9.39.5", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", @@ -14622,15 +14247,17 @@ "url": "https://opencollective.com/eslint" } }, - "packages/core/node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "packages/core/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "packages/core/node_modules/eslint/node_modules/eslint-visitor-keys": { @@ -14646,19 +14273,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/core/node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "packages/core/node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -14713,22 +14327,6 @@ "node": ">=16" } }, - "packages/core/node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.8" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "packages/core/node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -14757,12 +14355,13 @@ "@types/node": "^20.10.0", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitest/coverage-v8": "^1.0.0", + "@vitest/coverage-v8": "^4.1.12", "eslint": "^9.33.0", "globals": "^16.3.0", "tsx": "^4.6.0", "typescript": "^5.3.0", - "vitest": "^1.0.0" + "vite": "^7.3.7", + "vitest": "^4.1.12" } }, "packages/mcp-server/node_modules/@eslint-community/eslint-utils": { @@ -14818,17 +14417,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/mcp-server/node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "packages/mcp-server/node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -14842,32 +14430,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/mcp-server/node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "packages/mcp-server/node_modules/@eslint/js": { - "version": "9.39.5", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", - "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, "packages/mcp-server/node_modules/@typescript-eslint/eslint-plugin": { "version": "8.72.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.0.tgz", @@ -15017,6 +14579,22 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "packages/mcp-server/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/mcp-server/node_modules/@typescript-eslint/utils": { "version": "8.72.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", @@ -15059,17 +14637,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/mcp-server/node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "packages/mcp-server/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "18 || 20 || >=22" } }, "packages/mcp-server/node_modules/brace-expansion": { @@ -15085,16 +14660,6 @@ "node": "20 || >=22" } }, - "packages/mcp-server/node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, "packages/mcp-server/node_modules/eslint": { "version": "9.39.5", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", @@ -15171,15 +14736,17 @@ "url": "https://opencollective.com/eslint" } }, - "packages/mcp-server/node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "packages/mcp-server/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "packages/mcp-server/node_modules/eslint/node_modules/eslint-visitor-keys": { @@ -15195,19 +14762,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/mcp-server/node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "packages/mcp-server/node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -15262,22 +14816,6 @@ "node": ">=16" } }, - "packages/mcp-server/node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.8" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "packages/mcp-server/node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -15340,11 +14878,12 @@ "@types/ws": "^8.5.0", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitest/coverage-v8": "^1.0.0", + "@vitest/coverage-v8": "^4.1.12", "eslint": "^9.33.0", "globals": "^16.3.0", "tsx": "^4.6.0", - "vitest": "^1.0.0" + "vite": "^7.3.7", + "vitest": "^4.1.12" } }, "packages/server/node_modules/@eslint-community/eslint-utils": { @@ -15400,17 +14939,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/server/node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "packages/server/node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -15424,32 +14952,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/server/node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "packages/server/node_modules/@eslint/js": { - "version": "9.39.5", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", - "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, "packages/server/node_modules/@types/uuid": { "version": "10.0.0", "dev": true, @@ -15604,6 +15106,22 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "packages/server/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/server/node_modules/@typescript-eslint/utils": { "version": "8.72.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", @@ -15646,17 +15164,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/server/node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "packages/server/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "18 || 20 || >=22" } }, "packages/server/node_modules/brace-expansion": { @@ -15672,16 +15187,6 @@ "node": "20 || >=22" } }, - "packages/server/node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, "packages/server/node_modules/eslint": { "version": "9.39.5", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", @@ -15758,15 +15263,17 @@ "url": "https://opencollective.com/eslint" } }, - "packages/server/node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "packages/server/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "packages/server/node_modules/eslint/node_modules/eslint-visitor-keys": { @@ -15782,19 +15289,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/server/node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "packages/server/node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -15849,22 +15343,6 @@ "node": ">=16" } }, - "packages/server/node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.8" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "packages/server/node_modules/ts-api-utils": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", @@ -15909,8 +15387,8 @@ "@types/react-syntax-highlighter": "^15.5.13", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitejs/plugin-react": "^4.1.0", - "@vitest/coverage-v8": "^1.0.0", + "@vitejs/plugin-react": "^5.2.0", + "@vitest/coverage-v8": "^4.1.12", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", "autoprefixer": "^10.4.0", @@ -15921,8 +15399,8 @@ "jsdom": "^23.0.0", "mermaid": "^11.17.2", "postcss": "^8.4.0", - "vite": "^5.0.0", - "vitest": "^1.0.0" + "vite": "^7.3.7", + "vitest": "^4.1.12" } }, "packages/web/node_modules/@eslint-community/eslint-utils": { @@ -15995,17 +15473,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "packages/web/node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "packages/web/node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -16019,31 +15486,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/web/node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "packages/web/node_modules/@eslint/js": { - "version": "9.39.5", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", - "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "packages/web/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } + "license": "MIT" }, "packages/web/node_modules/@typescript-eslint/eslint-plugin": { "version": "8.72.0", @@ -16194,6 +15642,22 @@ "typescript": ">=4.8.4 <6.1.0" } }, + "packages/web/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "packages/web/node_modules/@typescript-eslint/utils": { "version": "8.72.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.0.tgz", @@ -16236,17 +15700,25 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "packages/web/node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "packages/web/node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node": "^20.19.0 || >=22.12.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "packages/web/node_modules/ajv": { @@ -16273,6 +15745,16 @@ "dev": true, "license": "MIT" }, + "packages/web/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, "packages/web/node_modules/brace-expansion": { "version": "5.0.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", @@ -16286,16 +15768,6 @@ "node": "20 || >=22" } }, - "packages/web/node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, "packages/web/node_modules/cookie": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", @@ -16385,6 +15857,19 @@ "url": "https://opencollective.com/eslint" } }, + "packages/web/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "packages/web/node_modules/eslint/node_modules/ajv": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", @@ -16402,17 +15887,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "packages/web/node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "packages/web/node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", @@ -16426,19 +15900,6 @@ "url": "https://opencollective.com/eslint" } }, - "packages/web/node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "packages/web/node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -16493,20 +15954,14 @@ "node": ">=16" } }, - "packages/web/node_modules/minimatch": { - "version": "10.2.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", - "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "packages/web/node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.8" - }, + "license": "MIT", "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, "packages/web/node_modules/react-router": { diff --git a/package.json b/package.json index aaccf83f..68339c18 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,8 @@ "qc:operations": "playwright test tests/e2e/quality/operations.spec.ts --project=GraphDone-Core/dev-neo4j/chromium --headed --workers=1 --reporter=line", "qc:operator-login": "playwright test tests/e2e/quality/operator-login.spec.ts --project=GraphDone-Core/dev-neo4j/chromium --headed --workers=1 --reporter=line", "test:operations": "tsx scripts/test-operations-local.mts && tsx scripts/test-admin-bootstrap.mts", - "qc:captcha": "playwright test --config playwright.captcha.config.ts --headed --workers=1 --retries=0" + "qc:captcha": "playwright test --config playwright.captcha.config.ts --headed --workers=1 --retries=0", + "test:toolchain": "node --test tests/toolchain/vite-contract.mjs" }, "devDependencies": { "@types/node": "^20.10.0", diff --git a/packages/core/package.json b/packages/core/package.json index 49be98b6..8754a867 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -21,10 +21,11 @@ "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitest/coverage-v8": "^1.0.0", + "@vitest/coverage-v8": "^4.1.12", "eslint": "^9.33.0", "globals": "^16.3.0", - "vitest": "^1.0.0" + "vitest": "^4.1.12", + "vite": "^7.3.7" }, "files": [ "dist", diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts index 2d918efb..ef741ec8 100644 --- a/packages/core/vitest.config.ts +++ b/packages/core/vitest.config.ts @@ -1,11 +1,13 @@ -import { defineConfig } from 'vitest/config'; +import { configDefaults, defineConfig } from 'vitest/config'; export default defineConfig({ test: { + exclude: [...configDefaults.exclude, '**/dist/**'], globals: true, environment: 'node', coverage: { provider: 'v8', + include: ['src/**/*.ts'], reporter: ['text', 'json', 'html'], exclude: [ 'node_modules/', diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 1ad00c4e..2170e8e9 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -30,12 +30,13 @@ "@types/node": "^20.10.0", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitest/coverage-v8": "^1.0.0", + "@vitest/coverage-v8": "^4.1.12", "eslint": "^9.33.0", "globals": "^16.3.0", "tsx": "^4.6.0", "typescript": "^5.3.0", - "vitest": "^1.0.0" + "vitest": "^4.1.12", + "vite": "^7.3.7" }, "files": [ "dist", diff --git a/packages/mcp-server/vitest.config.ts b/packages/mcp-server/vitest.config.ts index 9d507f38..02c27b0d 100644 --- a/packages/mcp-server/vitest.config.ts +++ b/packages/mcp-server/vitest.config.ts @@ -1,19 +1,17 @@ -import { defineConfig } from 'vitest/config'; +import { configDefaults, defineConfig } from 'vitest/config'; export default defineConfig({ test: { + exclude: [...configDefaults.exclude, '**/dist/**'], environment: 'node', testTimeout: 30000, pool: 'forks', // Use forked processes for better isolation - poolOptions: { - forks: { - // Keep database-backed functional suites isolated. - singleFork: true, - isolate: true, // Isolate each test file - }, - }, + maxWorkers: 1, + fileParallelism: false, + isolate: true, coverage: { provider: 'v8', + include: ['src/**/*.ts'], reporter: ['text', 'html'], exclude: [ 'node_modules/', diff --git a/packages/server/package.json b/packages/server/package.json index d740cb65..0bdb7271 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -63,11 +63,12 @@ "@types/ws": "^8.5.0", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitest/coverage-v8": "^1.0.0", + "@vitest/coverage-v8": "^4.1.12", "eslint": "^9.33.0", "globals": "^16.3.0", "tsx": "^4.6.0", - "vitest": "^1.0.0" + "vitest": "^4.1.12", + "vite": "^7.3.7" }, "files": [ "dist", diff --git a/packages/server/tests/captcha-auth.test.ts b/packages/server/tests/captcha-auth.test.ts index 7775f8d7..b6920055 100644 --- a/packages/server/tests/captcha-auth.test.ts +++ b/packages/server/tests/captcha-auth.test.ts @@ -4,7 +4,7 @@ import express from 'express'; import { createServer, type Server } from 'node:http'; import { ApolloServer } from '@apollo/server'; import { expressMiddleware } from '@as-integrations/express4'; -import { solveChallenge } from 'altcha-lib'; +import { createHash } from 'node:crypto'; import { sqliteAuthStore } from '../src/auth/sqlite-auth'; import { sqliteAuthResolvers } from '../src/resolvers/sqlite-auth'; import { authOnlyTypeDefs } from '../src/schema/auth-only-schema'; @@ -21,9 +21,14 @@ const store = sqliteAuthStore as unknown as { db: sqlite3.Database | null; initi async function proof(action: CaptchaAction) { const challenge = await createCaptchaChallenge(action); - const solution = await solveChallenge(challenge.challenge, challenge.salt, challenge.algorithm, challenge.maxnumber).promise; - if (!solution) throw new Error('Could not solve owned challenge'); - return Buffer.from(JSON.stringify({ ...challenge, number: solution.number })).toString('base64'); + expect(challenge.algorithm).toBe('SHA-256'); + expect(challenge.maxnumber).toBe(100000); + for (let number = 0; number <= challenge.maxnumber; number++) { + if (createHash('sha256').update(challenge.salt + number).digest('hex') === challenge.challenge) { + return Buffer.from(JSON.stringify({ ...challenge, number })).toString('base64'); + } + } + throw new Error('Could not solve owned challenge'); } async function request(operation: 'login' | 'signup', input: Record) { diff --git a/packages/server/vitest.config.ts b/packages/server/vitest.config.ts index 2c88c851..73b96e15 100644 --- a/packages/server/vitest.config.ts +++ b/packages/server/vitest.config.ts @@ -1,11 +1,14 @@ -import { defineConfig } from 'vitest/config'; +import { configDefaults, defineConfig } from 'vitest/config'; export default defineConfig({ test: { + maxWorkers: 2, + exclude: [...configDefaults.exclude, '**/dist/**'], globals: true, environment: 'node', coverage: { provider: 'v8', + include: ['src/**/*.ts'], reporter: ['text', 'json', 'html'], exclude: [ 'node_modules/', diff --git a/packages/web/package.json b/packages/web/package.json index d2e4e70d..1985c10c 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -42,8 +42,8 @@ "@types/react-syntax-highlighter": "^15.5.13", "@typescript-eslint/eslint-plugin": "^8.39.1", "@typescript-eslint/parser": "^8.39.1", - "@vitejs/plugin-react": "^4.1.0", - "@vitest/coverage-v8": "^1.0.0", + "@vitejs/plugin-react": "^5.2.0", + "@vitest/coverage-v8": "^4.1.12", "ajv": "^8.20.0", "ajv-formats": "^3.0.1", "autoprefixer": "^10.4.0", @@ -54,8 +54,8 @@ "jsdom": "^23.0.0", "mermaid": "^11.17.2", "postcss": "^8.4.0", - "vite": "^5.0.0", - "vitest": "^1.0.0" + "vite": "^7.3.7", + "vitest": "^4.1.12" }, "files": [ "dist", diff --git a/packages/web/src/components/WorkItemDetailsModal.test.tsx b/packages/web/src/components/WorkItemDetailsModal.test.tsx index 1e24434f..1c98f622 100644 --- a/packages/web/src/components/WorkItemDetailsModal.test.tsx +++ b/packages/web/src/components/WorkItemDetailsModal.test.tsx @@ -91,9 +91,13 @@ function editor() { }; } -const title = () => screen.getByRole('textbox', { name: 'Work item title' }); +const title = () => screen.getByLabelText('Work item title'); const dueDate = () => screen.getByLabelText('Due date'); -const save = () => screen.getByRole('button', { name: /Save changes to work item|No changes to save/ }); +const save = () => { + const button = screen.getByLabelText(/Save changes to work item|No changes to save/); + expect(button.tagName).toBe('BUTTON'); + return button; +}; beforeEach(() => { context.ownerId = 'owner-a'; @@ -108,7 +112,7 @@ afterEach(() => { vi.unstubAllGlobals(); }); describe('work item save completion', () => { it('preserves edits made after the mutation commits while its refetch is pending, then saves and undoes both snapshots', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(dueDate(), { target: { value: '2026-09-14' } }); fireEvent.click(save()); await view.acknowledgeMutation(); @@ -149,7 +153,7 @@ describe('work item save completion', () => { it('does not apply a late completion to a different item with a newer draft', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Saved first item' } }); fireEvent.click(save()); await view.acknowledgeMutation(); @@ -166,7 +170,7 @@ describe('work item save completion', () => { it('does not replace a draft from a later opening of the same item', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Submitted title' } }); fireEvent.click(save()); await view.acknowledgeMutation(); @@ -180,7 +184,7 @@ describe('work item save completion', () => { it('retains a deliberate return to the original value across the mutation cache write and refetch', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Submitted title' } }); fireEvent.click(save()); fireEvent.change(title(), { target: { value: 'First item' } }); @@ -193,14 +197,14 @@ describe('work item save completion', () => { it.each(['owner', 'graph'] as const)('ignores success from an earlier %s context', async scope => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Submitted in old context' } }); fireEvent.click(save()); await view.acknowledgeMutation(); if (scope === 'owner') context.ownerId = 'owner-b'; else context.graphId = 'graph-b'; view.navigate(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Current context draft' } }); await view.completeRefetch(); await waitFor(() => expect(save()).toBeEnabled()); @@ -210,7 +214,7 @@ describe('work item save completion', () => { it('retains a newer draft on failure and retries without registering failed undo history', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Failed title' } }); fireEvent.click(save()); fireEvent.change(title(), { target: { value: 'Retry this newer title' } }); @@ -228,7 +232,7 @@ describe('work item save completion', () => { it('does not report a stale failure in a different item session', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Failed title' } }); fireEvent.click(save()); view.navigate('item-b'); @@ -241,7 +245,7 @@ describe('work item save completion', () => { it('preserves unsaved fields before and during undo while updating the saved baseline', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Saved title' } }); fireEvent.click(save()); await view.acknowledgeMutation(); @@ -261,7 +265,7 @@ describe('work item save completion', () => { it.each(['mounted', 'unmounted'])('does not repopulate history cleared for another graph while a save is pending (%s)', async mode => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Saved in graph A' } }); fireEvent.click(save()); await view.acknowledgeMutation(); @@ -271,7 +275,7 @@ describe('work item save completion', () => { else { context.graphId = 'graph-b'; view.navigate('item-b'); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); } await view.completeRefetch(); expect(view.undoStack.size()).toBe(1); @@ -280,7 +284,7 @@ describe('work item save completion', () => { it('keeps a successful save undoable after normal modal unmount when history was not cleared', async () => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Saved before closing' } }); fireEvent.click(save()); await view.acknowledgeMutation(); @@ -298,7 +302,7 @@ describe('work item save completion', () => { it.each(['graphql', 'empty', 'wrong-item'] as const)('reports a %s save response and retains the newer draft for retry', async failure => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Submitted title' } }); fireEvent.click(save()); fireEvent.change(title(), { target: { value: 'Keep this newer draft' } }); @@ -317,7 +321,7 @@ describe('work item save completion', () => { it.each(['graphql', 'empty', 'wrong-item'] as const)('rejects a %s undo acknowledgement without changing the saved form', async failure => { const view = editor(); - await screen.findByRole('textbox', { name: 'Work item title' }); + await screen.findByLabelText('Work item title'); fireEvent.change(title(), { target: { value: 'Confirmed title' } }); fireEvent.click(save()); await view.acknowledgeMutation(); diff --git a/packages/web/src/test/setup.ts b/packages/web/src/test/setup.ts index 308bb61b..7dab6540 100644 --- a/packages/web/src/test/setup.ts +++ b/packages/web/src/test/setup.ts @@ -1,8 +1,6 @@ -import { expect, afterEach } from 'vitest'; +import { afterEach } from 'vitest'; import { cleanup } from '@testing-library/react'; -import * as matchers from '@testing-library/jest-dom/matchers'; - -expect.extend(matchers); +import '@testing-library/jest-dom/vitest'; afterEach(() => { cleanup(); diff --git a/packages/web/vite.config.ts b/packages/web/vite.config.ts index 15166ca7..43f33a31 100644 --- a/packages/web/vite.config.ts +++ b/packages/web/vite.config.ts @@ -1,5 +1,5 @@ import { offlineShell } from './offline-shell'; -import { defineConfig } from 'vite'; +import { configDefaults, defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; import { resolve } from 'path'; import { hostname } from 'os'; @@ -70,6 +70,7 @@ export default defineConfig({ }, build: { outDir: 'dist', + target: ['es2020', 'chrome87', 'edge88', 'firefox78', 'safari14'], // No production source maps — serving .js.map publicly leaks original source. // Caught by the live red-team (REDTEAM-SEC). Dev uses the Vite dev server // (its own maps), so debugging is unaffected. @@ -92,11 +93,14 @@ export default defineConfig({ } }, test: { + maxWorkers: 2, + exclude: [...configDefaults.exclude, '**/dist/**'], globals: true, environment: 'jsdom', setupFiles: ['./src/test/setup.ts'], coverage: { provider: 'v8', + include: ['src/**/*.{ts,tsx}', 'offline-shell.ts'], reporter: ['text', 'json', 'html'], exclude: [ 'node_modules/', diff --git a/tests/lib/dependencies/toolchain.test.mjs b/tests/lib/dependencies/toolchain.test.mjs new file mode 100644 index 00000000..c9d8fa62 --- /dev/null +++ b/tests/lib/dependencies/toolchain.test.mjs @@ -0,0 +1,60 @@ +import assert from 'node:assert/strict'; +import { readFile } from 'node:fs/promises'; +import { readFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { dirname, join, relative, sep } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import test from 'node:test'; + +const root = new URL('../../../', import.meta.url); +const require = createRequire(new URL('package.json', root)); +const semver = require('semver'); +const ranges = { vite: '^7.3.7', vitest: '^4.1.12', '@vitest/coverage-v8': '^4.1.12', '@vitejs/plugin-react': '^5.2.0', esbuild: '>=0.25.0' }; + +for (const [name, range] of Object.entries(ranges)) { + test(`all locked ${name} paths are on the reviewed patched line`, async () => { + const lock = JSON.parse(await readFile(new URL('package-lock.json', root), 'utf8')); + const paths = Object.entries(lock.packages).filter(([path]) => path.endsWith(`node_modules/${name}`)); + assert.ok(paths.length > 0, name); + for (const [path, entry] of paths) assert.ok(semver.satisfies(entry.version, range), `${path}: ${entry.version}`); + }); +} + +for (const workspace of ['core', 'server', 'mcp-server', 'web']) { + test(`${workspace} resolves matching Vitest/coverage and supported Vite from its lock`, async () => { + const local = createRequire(new URL(`packages/${workspace}/package.json`, root)); + const lock = JSON.parse(await readFile(new URL('package-lock.json', root), 'utf8')); + for (const name of ['vite', 'vitest', '@vitest/coverage-v8']) { + const pkg = local(`${name}/package.json`); + const path = relative(fileURLToPath(root), local.resolve(`${name}/package.json`)).split(sep).join('/').replace(/\/package\.json$/, ''); + assert.equal(pkg.version, lock.packages[path]?.version); + assert.ok(semver.satisfies(pkg.version, ranges[name]), `${workspace}/${name}: ${pkg.version}`); + if (name !== '@vitest/coverage-v8') { + assert.ok(pkg.engines?.node); + for (const node of ['22.18.0', '24.0.0']) assert.ok(semver.satisfies(node, pkg.engines.node), `${name} Node ${node}`); + } + } + const runner = local('vitest/package.json'); + const coverage = local('@vitest/coverage-v8/package.json'); + assert.equal(runner.version, coverage.version); + assert.ok(semver.satisfies(runner.version, coverage.peerDependencies.vitest)); + assert.ok(semver.satisfies(local('vite/package.json').version, runner.peerDependencies.vite)); + }); +} + +test('no legacy Vitest worker or vite-node remains installed or locked', async () => { + const lock = JSON.parse(await readFile(new URL('package-lock.json', root), 'utf8')); + assert.deepEqual(Object.keys(lock.packages).filter(path => /(^|\/)node_modules\/(tinypool|vite-node)$/.test(path)), []); + for (const workspace of ['core', 'server', 'mcp-server', 'web']) { + const local = createRequire(new URL(`packages/${workspace}/package.json`, root)); + for (const name of ['tinypool', 'vite-node']) assert.throws(() => local.resolve(name), { code: 'MODULE_NOT_FOUND' }); + } +}); + +test('the installed React transform supports the actual Vite consumer', () => { + const local = createRequire(new URL('packages/web/package.json', root)); + const plugin = JSON.parse(readFileSync(join(dirname(local.resolve('@vitejs/plugin-react')), '../package.json'), 'utf8')); + assert.equal(plugin.name, '@vitejs/plugin-react'); + assert.ok(semver.satisfies(local('vite/package.json').version, plugin.peerDependencies.vite)); + for (const node of ['22.18.0', '24.0.0']) assert.ok(semver.satisfies(node, plugin.engines.node)); +}); diff --git a/tests/toolchain/vite-contract.mjs b/tests/toolchain/vite-contract.mjs new file mode 100644 index 00000000..9dac36bb --- /dev/null +++ b/tests/toolchain/vite-contract.mjs @@ -0,0 +1,129 @@ +import assert from 'node:assert/strict'; +import { createServer as createHttpServer } from 'node:http'; +import { mkdtemp, mkdir, readFile, writeFile, rm } from 'node:fs/promises'; +import { dirname, join, resolve, extname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { once } from 'node:events'; +import test from 'node:test'; +import { createServer, build, resolveConfig } from 'vite'; +import { chromium, expect } from '@playwright/test'; +import { WebSocketServer } from 'ws'; + +const root = resolve(dirname(fileURLToPath(import.meta.url)), '../..'); + +test('installed Vite serves React HMR, forwards API routes, denies secrets and builds an offline shell', { timeout: 90000 }, async () => { + await mkdir(join(root, 'test-artifacts'), { recursive: true }); + const fixture = await mkdtemp(join(root, 'test-artifacts/toolchain-')); + const configFile = join(root, 'packages/web/vite.config.ts'); + const originalProxy = process.env.VITE_PROXY_TARGET; + const originalOffline = process.env.VITE_OFFLINE_SYNC; + let vite, browser, staticServer; + const backend = createHttpServer((req, res) => { + res.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' }); + res.end(JSON.stringify({ method: req.method, path: req.url, owned: true })); + }); + const sockets = new WebSocketServer({ server: backend }); + sockets.on('connection', (socket, request) => socket.send(JSON.stringify({ path: request.url, owned: true }))); + const closeHttp = async server => { + if (!server?.listening) return; + const closed = new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())); + server.closeAllConnections(); + await closed; + }; + try { + backend.listen(0, '127.0.0.1'); + await once(backend, 'listening'); + process.env.VITE_PROXY_TARGET = `http://127.0.0.1:${backend.address().port}`; + process.env.VITE_OFFLINE_SYNC = 'false'; + await writeFile(join(fixture, 'index.html'), '
'); + const component = label => `import React, {useState} from 'react'; export default function Probe(){const [count,setCount]=useState(0);return }`; + await writeFile(join(fixture, 'Probe.tsx'), component('Before')); + await writeFile(join(fixture, 'main.tsx'), "import React from 'react';import {createRoot} from 'react-dom/client';import Probe from './Probe';createRoot(document.getElementById('root')).render();"); + await writeFile(join(fixture, '.env'), 'OWNED_SECRET=toolchain-fixture-only\n'); + const config = await resolveConfig({ configFile, root: fixture }, 'serve'); + assert.deepEqual(config.build.target, ['es2020', 'chrome87', 'edge88', 'firefox78', 'safari14']); + vite = await createServer({ configFile, root: fixture, server: { host: '127.0.0.1', port: 0, strictPort: false } }); + await vite.listen(); + browser = await chromium.launch(process.env.QC_BROWSER_PORT ? { channel: 'chrome' } : {}); + const context = await browser.newContext(); + const page = await context.newPage(); + const errors = []; + page.on('pageerror', error => errors.push(error.message)); + const origin = `http://127.0.0.1:${vite.httpServer.address().port}`; + await page.goto(origin); + await page.getByRole('button', { name: 'Before 0' }).click(); + await expect(page.getByRole('button')).toHaveText('Before 1'); + await page.evaluate(() => { window.__toolchainDocument = 'same-document'; }); + await writeFile(join(fixture, 'Probe.tsx'), component('After')); + await expect(page.getByRole('button')).toHaveText('After 1', { timeout: 10000 }); + assert.equal(await page.evaluate(() => window.__toolchainDocument), 'same-document'); + for (const [path, method, forwarded] of [['/api/graphql?probe=1', 'POST', '/graphql?probe=1'], ['/config', 'GET', '/config'], ['/auth/login', 'POST', '/auth/login']]) { + const value = await page.evaluate(async ({ path, method }) => (await fetch(path, { method })).json(), { path, method }); + assert.deepEqual(value, { method, path: forwarded, owned: true }); + } + const subscription = await page.evaluate(() => new Promise((resolve, reject) => { + const socket = new WebSocket(`${location.origin.replace('http:', 'ws:')}/api/graphql?subscription=owned`); + const timeout = setTimeout(() => { socket.close(); reject(new Error('WebSocket proxy did not respond')); }, 5000); + socket.onmessage = event => { clearTimeout(timeout); socket.close(); resolve(JSON.parse(event.data)); }; + socket.onerror = () => { clearTimeout(timeout); socket.close(); reject(new Error('WebSocket proxy failed')); }; + })); + assert.deepEqual(subscription, { path: '/graphql?subscription=owned', owned: true }); + const denied = await context.request.get(`${origin}/.env`); + assert.equal(denied.status(), 403); + assert.ok(!(await denied.text()).includes('toolchain-fixture-only')); + assert.deepEqual(errors, []); + await context.close(); + await vite.close(); + vite = undefined; + process.env.VITE_OFFLINE_SYNC = 'true'; + const dist = join(fixture, 'dist'); + await build({ configFile, root: fixture, build: { outDir: dist, emptyOutDir: true, rollupOptions: { output: { manualChunks: () => undefined } } } }); + const worker = await readFile(join(dist, 'sw.js'), 'utf8'); + assert.match(worker, /graphdone-shell-/); + staticServer = createHttpServer(async (req, res) => { + try { + const pathname = new URL(req.url, 'http://localhost').pathname; + const file = resolve(dist, pathname === '/' ? 'index.html' : `.${pathname}`); + if (!file.startsWith(`${dist}/`)) { res.writeHead(403); res.end(); return; } + const body = await readFile(file); + res.writeHead(200, { 'content-type': ({ '.js': 'text/javascript', '.html': 'text/html', '.css': 'text/css' })[extname(file)] || 'application/octet-stream' }); + res.end(body); + } catch { res.writeHead(404); res.end(); } + }); + staticServer.listen(0, '127.0.0.1'); + await once(staticServer, 'listening'); + const offlineContext = await browser.newContext({ serviceWorkers: 'allow' }); + const offlinePage = await offlineContext.newPage(); + offlinePage.on('pageerror', error => errors.push(error.message)); + const offlineOrigin = `http://127.0.0.1:${staticServer.address().port}`; + await offlinePage.goto(offlineOrigin); + await expect(offlinePage.getByRole('button')).toHaveText('After 0'); + await offlinePage.evaluate(async () => { + await navigator.serviceWorker.register('/sw.js'); + await navigator.serviceWorker.ready; + if (!navigator.serviceWorker.controller) await new Promise(resolve => navigator.serviceWorker.addEventListener('controllerchange', resolve, { once: true })); + }); + const cached = await offlinePage.evaluate(async () => (await Promise.all((await caches.keys()).map(async key => (await (await caches.open(key)).keys()).map(request => new URL(request.url).pathname)))).flat()); + assert.ok(cached.includes('/')); + assert.ok(cached.some(path => path.endsWith('.js'))); + assert.ok(cached.every(path => !/^\/(api|auth|health|config|mcp)(\/|$)/.test(path))); + await offlineContext.setOffline(true); + await offlinePage.reload(); + await expect(offlinePage.getByRole('button')).toHaveText('After 0'); + await offlinePage.getByRole('button').click(); + await expect(offlinePage.getByRole('button')).toHaveText('After 1'); + assert.equal(await offlinePage.evaluate(async () => { try { await fetch('/api/graphql'); return false; } catch { return true; } }), true); + assert.deepEqual(errors, []); + await offlineContext.close(); + } finally { + await browser?.close(); + await vite?.close(); + await closeHttp(staticServer); + for (const socket of sockets.clients) socket.terminate(); + await new Promise(resolve => sockets.close(resolve)); + await closeHttp(backend); + if (originalProxy === undefined) delete process.env.VITE_PROXY_TARGET; else process.env.VITE_PROXY_TARGET = originalProxy; + if (originalOffline === undefined) delete process.env.VITE_OFFLINE_SYNC; else process.env.VITE_OFFLINE_SYNC = originalOffline; + await rm(fixture, { recursive: true, force: true }); + } +}); From a5b2593605b7b53bc8da8f13a9dd4da862a67bd9 Mon Sep 17 00:00:00 2001 From: Matthew Valancy Date: Tue, 27 Oct 2026 15:39:15 -0700 Subject: [PATCH 2/2] Preserve optional skip evidence with Vitest 4 reporters --- ...chain-upgrades-must-preserve-test-contracts.md | 10 +++++++++- docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md | 12 ++++++++++-- tests/lib/adapters/execution-evidence.test.mjs | 15 +++++++++++++++ tests/lib/adapters/vitest.mjs | 4 +++- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md b/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md index 0120ef78..e00e3bc5 100644 --- a/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md +++ b/.agents/inbox/2026-10-27-toolchain-upgrades-must-preserve-test-contracts.md @@ -25,12 +25,20 @@ A local CPU-protected database run failed six cases on the busy host; a separate CI-equivalent run passed all 136, without claiming production CPU acceptance. All earlier failures remain under the dated evidence directory on the test host. -Current harness: 190/190; actual unified web adapter: 353/353. An owned browser +Current harness: 192/192; actual unified web adapter: 353/353. An owned browser contract exercises real HMR/state, HTTP/WebSocket proxying, secret denial and compiled offline loading. Supported-Node coverage is a required CI matrix check. See [the migration evidence and limits](../../docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md) for commands, versions, authoritative references and remaining work. +`node --test tests/lib/adapters/execution-evidence.test.mjs` initially failed +the new optional-skip case: real Vitest 4 reports an explicitly skipped assertion +inside `numPendingTests`. The adapter now reconciles that count against actual +skipped assertions while still rejecting unfinished pending assertions, required +skips and counter contradictions. Real installed-runner controls separately +reported pass, failure, required-skip failure and optional skip, with zero +passes for either skip. The complete harness then passed 192/192. + ## Cause and corrective rule A successful install or lower audit count does not preserve runner behavior. diff --git a/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md b/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md index fa00adf8..748514ec 100644 --- a/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md +++ b/docs/quality/TOOLCHAIN_MIGRATION_2026-10-27.md @@ -68,9 +68,12 @@ Node 24 core/server/MCP coverage passed; current web coverage passed all 353 cases after correcting the fixture costs below. Final branch CI runs coverage for both supported Node versions and remains required before integration. -The current harness passes 190/190. The real unified web adapter passes 353 +The current harness passes 192/192. The real unified web adapter passes 353 with no skips or warnings. The installed runner's real pass/fail/skip JSON is -also checked through the adapter; required skips must fail. +also checked through the adapter. Vitest 4 includes explicitly skipped assertions +in `numPendingTests`; the adapter accepts that documented-by-output shape and +the prior zero-pending shape, while unfinished assertions and required skips +still fail. Optional skips remain skipped and never become passes. `npm run test:toolchain` uses an owned browser/backend/build fixture and proves React hot reload preserves state and document identity, HTTP and GraphQL @@ -99,6 +102,11 @@ Retained failures and corrections: exported React-plugin manifest. Corrected guards check the actual contracts; they do not weaken supported-runner or version checks. +7. Real Vitest 4 intentional-skip output initially produced a counter mismatch + for an optional sequence. Explicit skipped-assertion accounting corrected + it; the regression failed before the fix. Real pass/failure/required-skip/ + optional-skip controls now preserve all four outcomes. + Fresh isolated-cache audit: full inventory has three residual package entries (Turbo moderate, Mermaid/KaTeX low); production-only has zero. Historical counts remain dated evidence, not distinct exploit counts or a claim about why registry diff --git a/tests/lib/adapters/execution-evidence.test.mjs b/tests/lib/adapters/execution-evidence.test.mjs index 5eae4e31..5fed0be9 100644 --- a/tests/lib/adapters/execution-evidence.test.mjs +++ b/tests/lib/adapters/execution-evidence.test.mjs @@ -97,6 +97,21 @@ test('vitest: a still-pending execution fails even for an optional sequence', as const report = { ...vitestReport([{ title: 'unfinished', status: 'pending' }]), numPassedTests: 1, numFailedTests: 0, numPendingTests: 1, numTodoTests: 0 }; assert.equal((await execute(t, 'vitest', report, { blocking: false })).status, 'failed'); }); +for (const blocking of [true, false]) { + test(`vitest: version 4 intentional skip remains ${blocking ? 'required failure' : 'optional skip'}`, async t => { + const report = { + ...vitestReport([{ title: 'intentional skip', status: 'skipped' }]), + numPassedTests: 0, numFailedTests: 0, numPendingTests: 1, numTodoTests: 0, + numTotalTestSuites: 1, numPassedTestSuites: 1, numPendingTestSuites: 0, + }; + const result = await execute(t, 'vitest', report, { blocking }); + assert.equal(result.status, blocking ? 'failed' : 'skipped'); + assert.equal(result.counts.passed, 0); + assert.equal(result.counts.skipped, 1); + assert.equal(result.evidenceErrors.some(error => error.includes('numPendingTests')), false); + assert.equal(result.counts.failed, blocking ? 1 : 0); + }); +} for (const suites of [{ numTotalTestSuites: 0, numPassedTestSuites: 0 }, { numTotalTestSuites: 2, numPassedTestSuites: 1 }]) { test(`vitest: suite totals cannot contradict file evidence: ${JSON.stringify(suites)}`, async t => { assert.equal((await execute(t, 'vitest', { ...vitestReport(), ...suites })).status, 'failed'); diff --git a/tests/lib/adapters/vitest.mjs b/tests/lib/adapters/vitest.mjs index 54d85fb3..27ac2133 100644 --- a/tests/lib/adapters/vitest.mjs +++ b/tests/lib/adapters/vitest.mjs @@ -14,6 +14,7 @@ export async function runVitestSequence({ id, title, cwd, timeoutMs = 300000, bl const cases = []; const errors = []; let pending = 0; + let skipped = 0; let todo = 0; if (parsed && Array.isArray(parsed.testResults)) { for (const f of parsed.testResults) { @@ -22,6 +23,7 @@ export async function runVitestSequence({ id, title, cwd, timeoutMs = 300000, bl for (const a of f.assertionResults || []) { const st = a?.status === 'passed' ? 'passed' : ['pending', 'skipped', 'todo'].includes(a?.status) ? 'skipped' : 'failed'; if (a?.status === 'pending') pending++; + if (a?.status === 'skipped') skipped++; if (a?.status === 'todo') todo++; counts[st]++; if (st !== 'passed') cases.push({ title: [...(a?.ancestorTitles || []), a?.title || 'unnamed assertion'].join(' › '), status: st, error: (a?.failureMessages || []).join('\n').slice(-1500) }); @@ -33,7 +35,7 @@ export async function runVitestSequence({ id, title, cwd, timeoutMs = 300000, bl validateCounter(errors, parsed, 'numTotalTests', counts.passed + counts.failed + counts.skipped); validateCounter(errors, parsed, 'numPassedTests', [counts.passed, counts.passed + counts.skipped]); validateCounter(errors, parsed, 'numFailedTests', counts.failed); - validateCounter(errors, parsed, 'numPendingTests', pending); + validateCounter(errors, parsed, 'numPendingTests', [pending, pending + skipped]); validateCounter(errors, parsed, 'numTodoTests', todo); for (const key of ['numTotalTestSuites', 'numPassedTestSuites', 'numFailedTestSuites', 'numPendingTestSuites', 'numRuntimeErrorTestSuites']) validateCounter(errors, parsed, key); if (parsed.numTotalTestSuites < (parsed.testResults?.length || 0)) errors.push('Vitest suite total is smaller than its reported test files.');