From ae20eaf01f1e0a230cd244d6e1922b326f208b01 Mon Sep 17 00:00:00 2001 From: suyx Date: Mon, 27 Jul 2026 17:13:01 +0800 Subject: [PATCH] feat: complete TASK-WP0-01 toolchain skeleton --- NuGet.Config | 9 + apps/api/package.json | 23 + apps/api/src/app.ts | 17 + apps/api/src/main.ts | 8 + apps/api/tsconfig.json | 12 + apps/web/index.html | 12 + apps/web/package.json | 24 + apps/web/src/main.tsx | 16 + apps/web/src/toolchain-probe.tsx | 21 + apps/web/tsconfig.json | 11 + apps/web/vite.config.ts | 6 + apps/worker/package.json | 19 + apps/worker/src/worker.ts | 13 + apps/worker/tsconfig.json | 12 + package.json | 37 + packages/shared-contracts/package.json | 20 + packages/shared-contracts/src/index.ts | 1 + packages/shared-contracts/tsconfig.json | 12 + pnpm-lock.yaml | 2424 +++++++++++++++++ pnpm-workspace.yaml | 7 + scripts/frozen-versions.mjs | 61 + scripts/lib/tdd-trace.mjs | 259 ++ scripts/native-smoke.mjs | 23 + scripts/package-smoke.mjs | 77 + scripts/redaction-scan.mjs | 32 + scripts/run-wp0-01-validation.mjs | 79 + scripts/validate-external.mjs | 23 + scripts/validate-layer-scope.mjs | 24 + scripts/validate-tdd-trace.mjs | 5 + scripts/verify-frozen-dependencies.mjs | 89 + scripts/worker-smoke.mjs | 23 + .../Dada.Supervisor/Dada.Supervisor.csproj | 9 + supervisor/Dada.Supervisor/Program.cs | 11 + supervisor/Dada.Supervisor/SupervisorForm.cs | 13 + tests/api/app.test.ts | 12 + tests/integration/native-database.test.ts | 15 + tests/toolchain/frozen-toolchain.test.mjs | 59 + tests/unit/toolchain-smoke.test.ts | 57 + tsconfig.base.json | 13 + 39 files changed, 3588 insertions(+) create mode 100644 NuGet.Config create mode 100644 apps/api/package.json create mode 100644 apps/api/src/app.ts create mode 100644 apps/api/src/main.ts create mode 100644 apps/api/tsconfig.json create mode 100644 apps/web/index.html create mode 100644 apps/web/package.json create mode 100644 apps/web/src/main.tsx create mode 100644 apps/web/src/toolchain-probe.tsx create mode 100644 apps/web/tsconfig.json create mode 100644 apps/web/vite.config.ts create mode 100644 apps/worker/package.json create mode 100644 apps/worker/src/worker.ts create mode 100644 apps/worker/tsconfig.json create mode 100644 package.json create mode 100644 packages/shared-contracts/package.json create mode 100644 packages/shared-contracts/src/index.ts create mode 100644 packages/shared-contracts/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 scripts/frozen-versions.mjs create mode 100644 scripts/lib/tdd-trace.mjs create mode 100644 scripts/native-smoke.mjs create mode 100644 scripts/package-smoke.mjs create mode 100644 scripts/redaction-scan.mjs create mode 100644 scripts/run-wp0-01-validation.mjs create mode 100644 scripts/validate-external.mjs create mode 100644 scripts/validate-layer-scope.mjs create mode 100644 scripts/validate-tdd-trace.mjs create mode 100644 scripts/verify-frozen-dependencies.mjs create mode 100644 scripts/worker-smoke.mjs create mode 100644 supervisor/Dada.Supervisor/Dada.Supervisor.csproj create mode 100644 supervisor/Dada.Supervisor/Program.cs create mode 100644 supervisor/Dada.Supervisor/SupervisorForm.cs create mode 100644 tests/api/app.test.ts create mode 100644 tests/integration/native-database.test.ts create mode 100644 tests/toolchain/frozen-toolchain.test.mjs create mode 100644 tests/unit/toolchain-smoke.test.ts create mode 100644 tsconfig.base.json diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..c848225 --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 0000000..e9121d1 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,23 @@ +{ + "name": "@dada/api", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc -p tsconfig.json", + "start": "node dist/main.js", + "typecheck": "tsc --noEmit -p tsconfig.json" + }, + "dependencies": { + "@fastify/swagger": "9.8.1", + "@sinclair/typebox": "0.34.52", + "better-sqlite3": "13.0.1", + "drizzle-orm": "0.45.2", + "fastify": "5.10.0" + }, + "devDependencies": { + "@types/better-sqlite3": "7.6.13", + "@types/node": "24.13.3", + "typescript": "7.0.2" + } +} diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts new file mode 100644 index 0000000..d183983 --- /dev/null +++ b/apps/api/src/app.ts @@ -0,0 +1,17 @@ +import swagger from "@fastify/swagger"; +import Fastify from "fastify"; + +export function createApp() { + const app = Fastify({ logger: false }); + + void app.register(swagger, { + openapi: { + info: { + title: "Dada P0-A", + version: "0.0.0", + }, + }, + }); + + return app; +} diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts new file mode 100644 index 0000000..0e1f657 --- /dev/null +++ b/apps/api/src/main.ts @@ -0,0 +1,8 @@ +import { createApp } from "./app.js"; + +const app = createApp(); + +await app.listen({ + host: "127.0.0.1", + port: 43121, +}); diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 0000000..5425508 --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2024"], + "types": ["node"], + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/apps/web/index.html b/apps/web/index.html new file mode 100644 index 0000000..940c05e --- /dev/null +++ b/apps/web/index.html @@ -0,0 +1,12 @@ + + + + + + Dada + + +
+ + + diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 0000000..069680e --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,24 @@ +{ + "name": "@dada/web", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "typecheck": "tsc --noEmit -p tsconfig.json" + }, + "dependencies": { + "@vibrant/core": "4.0.4", + "@vibrant/quantizer-mmcq": "4.0.4", + "fabric": "7.4.0", + "react": "19.2.8", + "react-dom": "19.2.8" + }, + "devDependencies": { + "@types/react": "19.2.17", + "@types/react-dom": "19.2.3", + "@vitejs/plugin-react": "6.0.4", + "typescript": "7.0.2", + "vite": "8.1.5" + } +} diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx new file mode 100644 index 0000000..c43edd8 --- /dev/null +++ b/apps/web/src/main.tsx @@ -0,0 +1,16 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; + +import { ToolchainProbe } from "./toolchain-probe.js"; + +const root = document.getElementById("root"); + +if (!root) { + throw new Error("Dada web root element is missing."); +} + +createRoot(root).render( + + + , +); diff --git a/apps/web/src/toolchain-probe.tsx b/apps/web/src/toolchain-probe.tsx new file mode 100644 index 0000000..830aa4d --- /dev/null +++ b/apps/web/src/toolchain-probe.tsx @@ -0,0 +1,21 @@ +import { Rect, version as fabricVersion } from "fabric"; +import { renderToStaticMarkup } from "react-dom/server"; + +export function ToolchainProbe() { + return ; +} + +export function renderToolchainProbe() { + const reactMarkup = renderToStaticMarkup(); + const fabricSvg = new Rect({ + fill: "#111111", + height: 16, + width: 16, + }).toSVG(); + + return { + fabricSvg, + fabricVersion, + reactMarkup, + }; +} diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json new file mode 100644 index 0000000..35f22c6 --- /dev/null +++ b/apps/web/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Bundler", + "jsx": "react-jsx", + "lib": ["ES2024", "DOM", "DOM.Iterable"], + "types": ["vite/client"] + }, + "include": ["src", "vite.config.ts"] +} diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts new file mode 100644 index 0000000..58676f7 --- /dev/null +++ b/apps/web/vite.config.ts @@ -0,0 +1,6 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/apps/worker/package.json b/apps/worker/package.json new file mode 100644 index 0000000..9281266 --- /dev/null +++ b/apps/worker/package.json @@ -0,0 +1,19 @@ +{ + "name": "@dada/worker", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "tsc -p tsconfig.json", + "typecheck": "tsc --noEmit -p tsconfig.json" + }, + "dependencies": { + "better-sqlite3": "13.0.1", + "drizzle-orm": "0.45.2" + }, + "devDependencies": { + "@types/better-sqlite3": "7.6.13", + "@types/node": "24.13.3", + "typescript": "7.0.2" + } +} diff --git a/apps/worker/src/worker.ts b/apps/worker/src/worker.ts new file mode 100644 index 0000000..7088a88 --- /dev/null +++ b/apps/worker/src/worker.ts @@ -0,0 +1,13 @@ +import { parentPort } from "node:worker_threads"; + +export function handleWorkerProbe(message: unknown) { + return message === "ping" ? "pong" : null; +} + +const workerPort = parentPort; + +if (workerPort) { + workerPort.on("message", (message: unknown) => { + workerPort.postMessage(handleWorkerProbe(message)); + }); +} diff --git a/apps/worker/tsconfig.json b/apps/worker/tsconfig.json new file mode 100644 index 0000000..5425508 --- /dev/null +++ b/apps/worker/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2024"], + "types": ["node"], + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8995e5b --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "dada-p0a", + "version": "0.0.0", + "private": true, + "packageManager": "pnpm@10.28.2", + "engines": { + "node": "24.13.0" + }, + "scripts": { + "build": "pnpm -r --if-present build && dotnet build supervisor/Dada.Supervisor/Dada.Supervisor.csproj --configuration Release", + "typecheck": "pnpm -r --if-present typecheck", + "test:unit:contract": "node --test tests/toolchain/frozen-toolchain.test.mjs", + "test:unit": "pnpm run test:unit:contract && vitest run tests/unit", + "test:integration": "vitest run tests/integration", + "test:api": "vitest run tests/api", + "test:worker": "pnpm --filter @dada/worker build && node scripts/worker-smoke.mjs", + "test:e2e": "node scripts/validate-layer-scope.mjs E2E", + "test:visual": "node scripts/validate-layer-scope.mjs VISUAL", + "test:performance": "node scripts/validate-layer-scope.mjs PERFORMANCE", + "test:security": "node scripts/verify-frozen-dependencies.mjs && node scripts/redaction-scan.mjs", + "test:package": "pnpm run typecheck && pnpm --filter @dada/web build && pnpm --filter @dada/api build && pnpm --filter @dada/worker build && node scripts/package-smoke.mjs", + "validate:tdd-trace": "node scripts/validate-tdd-trace.mjs", + "validate:external": "node scripts/validate-external.mjs", + "test:all": "pnpm test:unit && pnpm test:integration && pnpm test:api && pnpm test:worker && pnpm test:e2e && pnpm test:visual && pnpm test:performance && pnpm test:security && pnpm test:package && pnpm validate:tdd-trace", + "test:wp0-01": "node scripts/run-wp0-01-validation.mjs" + }, + "devDependencies": { + "@playwright/test": "1.62.0", + "@types/better-sqlite3": "7.6.13", + "@types/node": "24.13.3", + "@types/react": "19.2.17", + "@types/react-dom": "19.2.3", + "typescript": "7.0.2", + "vite": "8.1.5", + "vitest": "4.1.10" + } +} diff --git a/packages/shared-contracts/package.json b/packages/shared-contracts/package.json new file mode 100644 index 0000000..5688fb4 --- /dev/null +++ b/packages/shared-contracts/package.json @@ -0,0 +1,20 @@ +{ + "name": "@dada/shared-contracts", + "version": "0.0.0", + "private": true, + "type": "module", + "exports": { + ".": "./dist/index.js" + }, + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "typecheck": "tsc --noEmit -p tsconfig.json" + }, + "dependencies": { + "@sinclair/typebox": "0.34.52" + }, + "devDependencies": { + "typescript": "7.0.2" + } +} diff --git a/packages/shared-contracts/src/index.ts b/packages/shared-contracts/src/index.ts new file mode 100644 index 0000000..14a9f90 --- /dev/null +++ b/packages/shared-contracts/src/index.ts @@ -0,0 +1 @@ +export { Type } from "@sinclair/typebox"; diff --git a/packages/shared-contracts/tsconfig.json b/packages/shared-contracts/tsconfig.json new file mode 100644 index 0000000..5bb4903 --- /dev/null +++ b/packages/shared-contracts/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2024"], + "declaration": true, + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..e1cd060 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2424 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@playwright/test': + specifier: 1.62.0 + version: 1.62.0 + '@types/better-sqlite3': + specifier: 7.6.13 + version: 7.6.13 + '@types/node': + specifier: 24.13.3 + version: 24.13.3 + '@types/react': + specifier: 19.2.17 + version: 19.2.17 + '@types/react-dom': + specifier: 19.2.3 + version: 19.2.3(@types/react@19.2.17) + typescript: + specifier: 7.0.2 + version: 7.0.2 + vite: + specifier: 8.1.5 + version: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + vitest: + specifier: 4.1.10 + version: 4.1.10(@types/node@24.13.3)(jsdom@26.1.0(canvas@3.2.3))(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + + apps/api: + dependencies: + '@fastify/swagger': + specifier: 9.8.1 + version: 9.8.1 + '@sinclair/typebox': + specifier: 0.34.52 + version: 0.34.52 + better-sqlite3: + specifier: 13.0.1 + version: 13.0.1 + drizzle-orm: + specifier: 0.45.2 + version: 0.45.2(@types/better-sqlite3@7.6.13)(better-sqlite3@13.0.1) + fastify: + specifier: 5.10.0 + version: 5.10.0 + devDependencies: + '@types/better-sqlite3': + specifier: 7.6.13 + version: 7.6.13 + '@types/node': + specifier: 24.13.3 + version: 24.13.3 + typescript: + specifier: 7.0.2 + version: 7.0.2 + + apps/web: + dependencies: + '@vibrant/core': + specifier: 4.0.4 + version: 4.0.4 + '@vibrant/quantizer-mmcq': + specifier: 4.0.4 + version: 4.0.4 + fabric: + specifier: 7.4.0 + version: 7.4.0 + react: + specifier: 19.2.8 + version: 19.2.8 + react-dom: + specifier: 19.2.8 + version: 19.2.8(react@19.2.8) + devDependencies: + '@types/react': + specifier: 19.2.17 + version: 19.2.17 + '@types/react-dom': + specifier: 19.2.3 + version: 19.2.3(@types/react@19.2.17) + '@vitejs/plugin-react': + specifier: 6.0.4 + version: 6.0.4(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + typescript: + specifier: 7.0.2 + version: 7.0.2 + vite: + specifier: 8.1.5 + version: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + + apps/worker: + dependencies: + better-sqlite3: + specifier: 13.0.1 + version: 13.0.1 + drizzle-orm: + specifier: 0.45.2 + version: 0.45.2(@types/better-sqlite3@7.6.13)(better-sqlite3@13.0.1) + devDependencies: + '@types/better-sqlite3': + specifier: 7.6.13 + version: 7.6.13 + '@types/node': + specifier: 24.13.3 + version: 24.13.3 + typescript: + specifier: 7.0.2 + version: 7.0.2 + + packages/shared-contracts: + dependencies: + '@sinclair/typebox': + specifier: 0.34.52 + version: 0.34.52 + devDependencies: + typescript: + specifier: 7.0.2 + version: 7.0.2 + +packages: + + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@fastify/ajv-compiler@4.0.5': + resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} + + '@fastify/error@4.2.0': + resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} + + '@fastify/fast-json-stringify-compiler@5.1.0': + resolution: {integrity: sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==} + + '@fastify/forwarded@3.0.1': + resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==} + + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} + + '@fastify/proxy-addr@5.1.0': + resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==} + + '@fastify/swagger@9.8.1': + resolution: {integrity: sha512-VpHMnqZTY8iBZYJE8WWkbKPrXIYWy2rDfIf5qLr6DzZSpQYZ+KxQVcJFiq/AMlvNwI4gCBd66++iUlxXXGT0IQ==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@playwright/test@1.62.0': + resolution: {integrity: sha512-9zOJ6ZQRAena31MpOH9VSzIz8Ou3YJ/wtY/eQm5T2uhfhG7/U3COrMS8xOtUrZrp9OgdmzEnIYODye3nY1VqzA==} + engines: {node: '>=20'} + hasBin: true + + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.1.5': + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@sinclair/typebox@0.34.52': + resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/better-sqlite3@7.6.13': + resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/node@24.13.3': + resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.17': + resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + + '@typescript/typescript-aix-ppc64@7.0.2': + resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [aix] + + '@typescript/typescript-darwin-arm64@7.0.2': + resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [darwin] + + '@typescript/typescript-darwin-x64@7.0.2': + resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [darwin] + + '@typescript/typescript-freebsd-arm64@7.0.2': + resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [freebsd] + + '@typescript/typescript-freebsd-x64@7.0.2': + resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [freebsd] + + '@typescript/typescript-linux-arm64@7.0.2': + resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [linux] + + '@typescript/typescript-linux-arm@7.0.2': + resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} + engines: {node: '>=16.20.0'} + cpu: [arm] + os: [linux] + + '@typescript/typescript-linux-loong64@7.0.2': + resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} + engines: {node: '>=16.20.0'} + cpu: [loong64] + os: [linux] + + '@typescript/typescript-linux-mips64el@7.0.2': + resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} + engines: {node: '>=16.20.0'} + cpu: [mips64el] + os: [linux] + + '@typescript/typescript-linux-ppc64@7.0.2': + resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [linux] + + '@typescript/typescript-linux-riscv64@7.0.2': + resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} + engines: {node: '>=16.20.0'} + cpu: [riscv64] + os: [linux] + + '@typescript/typescript-linux-s390x@7.0.2': + resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} + engines: {node: '>=16.20.0'} + cpu: [s390x] + os: [linux] + + '@typescript/typescript-linux-x64@7.0.2': + resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [linux] + + '@typescript/typescript-netbsd-arm64@7.0.2': + resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [netbsd] + + '@typescript/typescript-netbsd-x64@7.0.2': + resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [netbsd] + + '@typescript/typescript-openbsd-arm64@7.0.2': + resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [openbsd] + + '@typescript/typescript-openbsd-x64@7.0.2': + resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [openbsd] + + '@typescript/typescript-sunos-x64@7.0.2': + resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [sunos] + + '@typescript/typescript-win32-arm64@7.0.2': + resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [win32] + + '@typescript/typescript-win32-x64@7.0.2': + resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [win32] + + '@vibrant/color@4.0.4': + resolution: {integrity: sha512-Fq2tAszz4QOPWfHZ+KuEAchXUD8i594BM2fOJt8dI/fvYbiVoBycBF/BlNH6F4IWBubxXoPqD4JmmAHvFYbNew==} + + '@vibrant/core@4.0.4': + resolution: {integrity: sha512-yZ0XSpW2biKyaJPpBC31AVYgn7NseKSO2q3KNMmDrkL2qC6TEWsBMnSQ28n0m///chZELXpQLx1CCOsWg5pj8w==} + + '@vibrant/generator@4.0.4': + resolution: {integrity: sha512-rwq8PnlpKdch4YqaA1FAwdm71gKE2cMrUsbu72TqRFGa8rpP1roaZlQCVXIIwElXVc3r9axZyAcqyTLaMjhrTg==} + + '@vibrant/image@4.0.4': + resolution: {integrity: sha512-NBIJj7umfDRVpFjJHQo1AFSCWCzQyjfil+Yxu7W62PEL72GPCif0CDiglPkvVF8QhDLmnx/x1k3LIBb9jWF2sw==} + + '@vibrant/quantizer-mmcq@4.0.4': + resolution: {integrity: sha512-/1CNnM96J8K+OBCWNUzywo6VdnmdFJyiKO+ty/nkfe8H0NseOEHIL7PrVtWGgtsb0rh2uTAq2rjXv65TfgPy8g==} + + '@vibrant/quantizer@4.0.4': + resolution: {integrity: sha512-722CooC2W4mlBiv+zyAsIrIvARnMCN/P2Muo8bnWd0SQlVWFtQnFxJWGOUPOPS4DGe3pGoqmNfvS0let4dICZQ==} + + '@vibrant/types@4.0.4': + resolution: {integrity: sha512-Qq3mVTJamn7yD4OBgBEUKaxfDlm3sxBK55N7dH3XzI9Ey7KR00R06uwtqOcEJMsziWTEXdYN3VUlYaj2Tkt7hw==} + + '@vibrant/worker@4.0.4': + resolution: {integrity: sha512-Q/R6PYhSMWCXEk/IcXbWIzIu7Z4b58ABkGvcdF8Y+q/7g+KnpxKW5x/jfQ/6ciyYSby13wZZoEdNr3QQVgsdBQ==} + + '@vitejs/plugin-react@6.0.4': + resolution: {integrity: sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} + + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} + + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} + + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} + + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} + + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} + + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + avvio@9.3.0: + resolution: {integrity: sha512-g2tQ7LE7oOSqDfwEm3M+ZCMTJc7KiZCdJ4UwyZJb5ckTKyYu50OYmvv0mCFXPuYXoM4zkSt8zM9XQ9KCvxA74A==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + better-sqlite3@13.0.1: + resolution: {integrity: sha512-LYpmOXdkpQYf4wmlxkdzW01XGlOXNIbjLg45yNkh0FQ4814VbK9PdOFmhZpYbej+EZtR/i3FDdhEG98HqZdgnA==} + engines: {node: '>=22'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + canvas@3.2.3: + resolution: {integrity: sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw==} + engines: {node: ^18.12.0 || >= 20.9.0} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + drizzle-orm@0.45.2: + resolution: {integrity: sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=4' + '@electric-sql/pglite': '>=0.2.0' + '@libsql/client': '>=0.10.0' + '@libsql/client-wasm': '>=0.10.0' + '@neondatabase/serverless': '>=0.10.0' + '@op-engineering/op-sqlite': '>=2' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1.13' + '@prisma/client': '*' + '@tidbcloud/serverless': '*' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@upstash/redis': '>=1.34.7' + '@vercel/postgres': '>=0.8.0' + '@xata.io/client': '*' + better-sqlite3: '>=7' + bun-types: '*' + expo-sqlite: '>=14.0.0' + gel: '>=2' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + prisma: '*' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@electric-sql/pglite': + optional: true + '@libsql/client': + optional: true + '@libsql/client-wasm': + optional: true + '@neondatabase/serverless': + optional: true + '@op-engineering/op-sqlite': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@prisma/client': + optional: true + '@tidbcloud/serverless': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@upstash/redis': + optional: true + '@vercel/postgres': + optional: true + '@xata.io/client': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + expo-sqlite: + optional: true + gel: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + prisma: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + es-module-lexer@2.3.1: + resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + fabric@7.4.0: + resolution: {integrity: sha512-NalYDc3eifTl1C33zryQwpH6+XA/2ClxQrH9vkASkZw3tbkRmorpikhYMmxhUTmi7O3e9ODz0vOT8qfaCh9IVA==} + engines: {node: '>=20.0.0'} + + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stringify@7.0.1: + resolution: {integrity: sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==} + + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-uri@3.1.4: + resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + + fast-uri@4.1.1: + resolution: {integrity: sha512-YPOs1zD5TG2+EZt+r88LwF6mclA7TPkpwMP7ZN3TO2HiHS8TXvq7QA/17iJsV9dubcLo/f8eEYqMBruyQV21hQ==} + + fastify-plugin@6.0.0: + resolution: {integrity: sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==} + + fastify@5.10.0: + resolution: {integrity: sha512-A9L0ziuWGQHgEEVgF3davQ9vbD93IuX+lo2IsxapQmu5b/Y/ynn9m9K5JHt9dvyJXOFc5iN0Zk5GHEOqnzhWjg==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + find-my-way@9.7.0: + resolution: {integrity: sha512-f2JHn75x2JlwUwLenZypgczR7YWMb/uO9BvUXtus+JMgkbIkLADd38cI4EiV+OQqrGo1Zlq6V8wnqMJ8e62wUQ==} + engines: {node: '>=20'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ipaddr.js@2.4.0: + resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} + engines: {node: '>= 10'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + json-schema-ref-resolver@3.0.0: + resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} + + json-schema-resolver@3.0.0: + resolution: {integrity: sha512-HqMnbz0tz2DaEJ3ntsqtx3ezzZyDE7G56A/pPY/NGmrPu76UzsWquOpHFRAf5beTNXoH2LU5cQePVvRli1nchA==} + engines: {node: '>=20'} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + light-my-request@6.6.0: + resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + + node-abi@3.94.0: + resolution: {integrity: sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==} + engines: {node: '>=10'} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-addon-api@8.9.0: + resolution: {integrity: sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q==} + engines: {node: ^18 || ^20 || >= 21} + + nwsapi@2.2.24: + resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==} + + obug@2.1.4: + resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} + engines: {node: '>=12.20.0'} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@10.3.1: + resolution: {integrity: sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==} + hasBin: true + + playwright-core@1.62.0: + resolution: {integrity: sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==} + engines: {node: '>=20'} + hasBin: true + + playwright@1.62.0: + resolution: {integrity: sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==} + engines: {node: '>=20'} + hasBin: true + + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + engines: {node: ^10 || ^12 || >=14} + + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. + hasBin: true + + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + react-dom@19.2.8: + resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} + peerDependencies: + react: ^19.2.8 + + react@19.2.8: + resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + real-require@1.0.0: + resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} + engines: {node: '>=10'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex2@5.1.1: + resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==} + hasBin: true + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tar-fs@2.1.5: + resolution: {integrity: sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + thread-stream@4.2.0: + resolution: {integrity: sha512-e2zZ96wSChazBsbENf/Pcm/4swHt2cEKQ92rhUjkL9GCKiTDJIaTBenjE/m9DXi0QBmTMDkFDdOomUy20A1tDQ==} + engines: {node: '>=20'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + + toad-cache@3.7.4: + resolution: {integrity: sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==} + engines: {node: '>=20'} + + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + typescript@7.0.2: + resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} + engines: {node: '>=16.20.0'} + hasBin: true + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite@8.1.5: + resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.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 + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 + happy-dom: '*' + 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-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': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.21.1: + resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + +snapshots: + + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + optional: true + + '@csstools/color-helpers@5.1.0': + optional: true + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + optional: true + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + optional: true + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + optional: true + + '@csstools/css-tokenizer@3.0.4': + optional: true + + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@fastify/ajv-compiler@4.0.5': + dependencies: + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.4 + + '@fastify/error@4.2.0': {} + + '@fastify/fast-json-stringify-compiler@5.1.0': + dependencies: + fast-json-stringify: 7.0.1 + + '@fastify/forwarded@3.0.1': {} + + '@fastify/merge-json-schemas@0.2.1': + dependencies: + dequal: 2.0.3 + + '@fastify/proxy-addr@5.1.0': + dependencies: + '@fastify/forwarded': 3.0.1 + ipaddr.js: 2.4.0 + + '@fastify/swagger@9.8.1': + dependencies: + fastify-plugin: 6.0.0 + json-schema-resolver: 3.0.0 + openapi-types: 12.1.3 + rfdc: 1.4.1 + yaml: 2.9.0 + transitivePeerDependencies: + - supports-color + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@oxc-project/types@0.139.0': {} + + '@pinojs/redact@0.4.0': {} + + '@playwright/test@1.62.0': + dependencies: + playwright: 1.62.0 + + '@rolldown/binding-android-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-arm64@1.1.5': + optional: true + + '@rolldown/binding-darwin-x64@1.1.5': + optional: true + + '@rolldown/binding-freebsd-x64@1.1.5': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.1.5': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.1.5': + optional: true + + '@rolldown/binding-linux-x64-musl@1.1.5': + optional: true + + '@rolldown/binding-openharmony-arm64@1.1.5': + optional: true + + '@rolldown/binding-wasm32-wasi@1.1.5': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.1.5': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@sinclair/typebox@0.34.52': {} + + '@standard-schema/spec@1.1.0': {} + + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/better-sqlite3@7.6.13': + dependencies: + '@types/node': 24.13.3 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/node@24.13.3': + dependencies: + undici-types: 7.18.2 + + '@types/react-dom@19.2.3(@types/react@19.2.17)': + dependencies: + '@types/react': 19.2.17 + + '@types/react@19.2.17': + dependencies: + csstype: 3.2.3 + + '@typescript/typescript-aix-ppc64@7.0.2': + optional: true + + '@typescript/typescript-darwin-arm64@7.0.2': + optional: true + + '@typescript/typescript-darwin-x64@7.0.2': + optional: true + + '@typescript/typescript-freebsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-freebsd-x64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm64@7.0.2': + optional: true + + '@typescript/typescript-linux-arm@7.0.2': + optional: true + + '@typescript/typescript-linux-loong64@7.0.2': + optional: true + + '@typescript/typescript-linux-mips64el@7.0.2': + optional: true + + '@typescript/typescript-linux-ppc64@7.0.2': + optional: true + + '@typescript/typescript-linux-riscv64@7.0.2': + optional: true + + '@typescript/typescript-linux-s390x@7.0.2': + optional: true + + '@typescript/typescript-linux-x64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-netbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-arm64@7.0.2': + optional: true + + '@typescript/typescript-openbsd-x64@7.0.2': + optional: true + + '@typescript/typescript-sunos-x64@7.0.2': + optional: true + + '@typescript/typescript-win32-arm64@7.0.2': + optional: true + + '@typescript/typescript-win32-x64@7.0.2': + optional: true + + '@vibrant/color@4.0.4': {} + + '@vibrant/core@4.0.4': + dependencies: + '@vibrant/color': 4.0.4 + '@vibrant/generator': 4.0.4 + '@vibrant/image': 4.0.4 + '@vibrant/quantizer': 4.0.4 + '@vibrant/worker': 4.0.4 + + '@vibrant/generator@4.0.4': + dependencies: + '@vibrant/color': 4.0.4 + '@vibrant/types': 4.0.4 + + '@vibrant/image@4.0.4': + dependencies: + '@vibrant/color': 4.0.4 + + '@vibrant/quantizer-mmcq@4.0.4': + dependencies: + '@vibrant/color': 4.0.4 + '@vibrant/image': 4.0.4 + '@vibrant/quantizer': 4.0.4 + + '@vibrant/quantizer@4.0.4': + dependencies: + '@vibrant/color': 4.0.4 + '@vibrant/image': 4.0.4 + '@vibrant/types': 4.0.4 + + '@vibrant/types@4.0.4': {} + + '@vibrant/worker@4.0.4': + dependencies: + '@vibrant/types': 4.0.4 + + '@vitejs/plugin-react@6.0.4(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + + '@vitest/expect@4.1.10': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + '@vitest/mocker@4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 4.1.10 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + + '@vitest/pretty-format@4.1.10': + dependencies: + tinyrainbow: 3.1.0 + + '@vitest/runner@4.1.10': + dependencies: + '@vitest/utils': 4.1.10 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.10': {} + + '@vitest/utils@4.1.10': + dependencies: + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + abstract-logging@2.0.1: {} + + agent-base@7.1.4: + optional: true + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + assertion-error@2.0.1: {} + + atomic-sleep@1.0.0: {} + + avvio@9.3.0: + dependencies: + '@fastify/error': 4.2.0 + fastq: 1.20.1 + + base64-js@1.5.1: + optional: true + + better-sqlite3@13.0.1: + dependencies: + node-addon-api: 8.9.0 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + optional: true + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + optional: true + + canvas@3.2.3: + dependencies: + node-addon-api: 7.1.1 + prebuild-install: 7.1.3 + optional: true + + chai@6.2.2: {} + + chownr@1.1.4: + optional: true + + convert-source-map@2.0.0: {} + + cookie@1.1.1: {} + + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + optional: true + + csstype@3.2.3: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + optional: true + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: + optional: true + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + optional: true + + deep-extend@0.6.0: + optional: true + + dequal@2.0.3: {} + + detect-libc@2.1.2: {} + + drizzle-orm@0.45.2(@types/better-sqlite3@7.6.13)(better-sqlite3@13.0.1): + optionalDependencies: + '@types/better-sqlite3': 7.6.13 + better-sqlite3: 13.0.1 + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + optional: true + + entities@6.0.1: + optional: true + + es-module-lexer@2.3.1: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + expand-template@2.0.3: + optional: true + + expect-type@1.4.0: {} + + fabric@7.4.0: + optionalDependencies: + canvas: 3.2.3 + jsdom: 26.1.0(canvas@3.2.3) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + fast-decode-uri-component@1.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stringify@7.0.1: + dependencies: + '@fastify/merge-json-schemas': 0.2.1 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 4.1.1 + json-schema-ref-resolver: 3.0.0 + rfdc: 1.4.1 + + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-uri@3.1.4: {} + + fast-uri@4.1.1: {} + + fastify-plugin@6.0.0: {} + + fastify@5.10.0: + dependencies: + '@fastify/ajv-compiler': 4.0.5 + '@fastify/error': 4.2.0 + '@fastify/fast-json-stringify-compiler': 5.1.0 + '@fastify/proxy-addr': 5.1.0 + abstract-logging: 2.0.1 + avvio: 9.3.0 + fast-json-stringify: 7.0.1 + find-my-way: 9.7.0 + light-my-request: 6.6.0 + pino: 10.3.1 + process-warning: 5.0.0 + rfdc: 1.4.1 + secure-json-parse: 4.1.0 + semver: 7.8.5 + toad-cache: 3.7.4 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + find-my-way@9.7.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 5.1.1 + + fs-constants@1.0.0: + optional: true + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + github-from-package@0.0.0: + optional: true + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + optional: true + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + optional: true + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + optional: true + + ieee754@1.2.1: + optional: true + + inherits@2.0.4: + optional: true + + ini@1.3.8: + optional: true + + ipaddr.js@2.4.0: {} + + is-potential-custom-element-name@1.0.1: + optional: true + + jsdom@26.1.0(canvas@3.2.3): + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.24 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.21.1 + xml-name-validator: 5.0.0 + optionalDependencies: + canvas: 3.2.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + optional: true + + json-schema-ref-resolver@3.0.0: + dependencies: + dequal: 2.0.3 + + json-schema-resolver@3.0.0: + dependencies: + debug: 4.4.3 + fast-uri: 3.1.4 + rfdc: 1.4.1 + transitivePeerDependencies: + - supports-color + + json-schema-traverse@1.0.0: {} + + light-my-request@6.6.0: + dependencies: + cookie: 1.1.1 + process-warning: 4.0.1 + set-cookie-parser: 2.7.2 + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + lru-cache@10.4.3: + optional: true + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + mimic-response@3.1.0: + optional: true + + minimist@1.2.8: + optional: true + + mkdirp-classic@0.5.3: + optional: true + + ms@2.1.3: {} + + nanoid@3.3.16: {} + + napi-build-utils@2.0.0: + optional: true + + node-abi@3.94.0: + dependencies: + semver: 7.8.5 + optional: true + + node-addon-api@7.1.1: + optional: true + + node-addon-api@8.9.0: {} + + nwsapi@2.2.24: + optional: true + + obug@2.1.4: {} + + on-exit-leak-free@2.1.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + optional: true + + openapi-types@12.1.3: {} + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + optional: true + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.5: {} + + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.1.0: {} + + pino@10.3.1: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 4.2.0 + + playwright-core@1.62.0: {} + + playwright@1.62.0: + dependencies: + playwright-core: 1.62.0 + optionalDependencies: + fsevents: 2.3.2 + + postcss@8.5.23: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.1.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.94.0 + pump: 3.0.4 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.5 + tunnel-agent: 0.6.0 + optional: true + + process-warning@4.0.1: {} + + process-warning@5.0.0: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + optional: true + + punycode@2.3.1: + optional: true + + quick-format-unescaped@4.0.4: {} + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + optional: true + + react-dom@19.2.8(react@19.2.8): + dependencies: + react: 19.2.8 + scheduler: 0.27.0 + + react@19.2.8: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + optional: true + + real-require@0.2.0: {} + + real-require@1.0.0: {} + + require-from-string@2.0.2: {} + + ret@0.5.0: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rolldown@1.1.5: + dependencies: + '@oxc-project/types': 0.139.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.5 + '@rolldown/binding-darwin-arm64': 1.1.5 + '@rolldown/binding-darwin-x64': 1.1.5 + '@rolldown/binding-freebsd-x64': 1.1.5 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 + '@rolldown/binding-linux-arm64-gnu': 1.1.5 + '@rolldown/binding-linux-arm64-musl': 1.1.5 + '@rolldown/binding-linux-ppc64-gnu': 1.1.5 + '@rolldown/binding-linux-s390x-gnu': 1.1.5 + '@rolldown/binding-linux-x64-gnu': 1.1.5 + '@rolldown/binding-linux-x64-musl': 1.1.5 + '@rolldown/binding-openharmony-arm64': 1.1.5 + '@rolldown/binding-wasm32-wasi': 1.1.5 + '@rolldown/binding-win32-arm64-msvc': 1.1.5 + '@rolldown/binding-win32-x64-msvc': 1.1.5 + + rrweb-cssom@0.8.0: + optional: true + + safe-buffer@5.2.1: + optional: true + + safe-regex2@5.1.1: + dependencies: + ret: 0.5.0 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: + optional: true + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + optional: true + + scheduler@0.27.0: {} + + secure-json-parse@4.1.0: {} + + semver@7.8.5: {} + + set-cookie-parser@2.7.2: {} + + siginfo@2.0.0: {} + + simple-concat@1.0.1: + optional: true + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + optional: true + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + split2@4.2.0: {} + + stackback@0.0.2: {} + + std-env@4.2.0: {} + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + + strip-json-comments@2.0.1: + optional: true + + symbol-tree@3.2.4: + optional: true + + tar-fs@2.1.5: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.4 + tar-stream: 2.2.0 + optional: true + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + optional: true + + thread-stream@4.2.0: + dependencies: + real-require: 1.0.0 + + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinyrainbow@3.1.0: {} + + tldts-core@6.1.86: + optional: true + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + optional: true + + toad-cache@3.7.4: {} + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + optional: true + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + optional: true + + tslib@2.8.1: + optional: true + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + + typescript@7.0.2: + optionalDependencies: + '@typescript/typescript-aix-ppc64': 7.0.2 + '@typescript/typescript-darwin-arm64': 7.0.2 + '@typescript/typescript-darwin-x64': 7.0.2 + '@typescript/typescript-freebsd-arm64': 7.0.2 + '@typescript/typescript-freebsd-x64': 7.0.2 + '@typescript/typescript-linux-arm': 7.0.2 + '@typescript/typescript-linux-arm64': 7.0.2 + '@typescript/typescript-linux-loong64': 7.0.2 + '@typescript/typescript-linux-mips64el': 7.0.2 + '@typescript/typescript-linux-ppc64': 7.0.2 + '@typescript/typescript-linux-riscv64': 7.0.2 + '@typescript/typescript-linux-s390x': 7.0.2 + '@typescript/typescript-linux-x64': 7.0.2 + '@typescript/typescript-netbsd-arm64': 7.0.2 + '@typescript/typescript-netbsd-x64': 7.0.2 + '@typescript/typescript-openbsd-arm64': 7.0.2 + '@typescript/typescript-openbsd-x64': 7.0.2 + '@typescript/typescript-sunos-x64': 7.0.2 + '@typescript/typescript-win32-arm64': 7.0.2 + '@typescript/typescript-win32-x64': 7.0.2 + + undici-types@7.18.2: {} + + util-deprecate@1.0.2: + optional: true + + vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.23 + rolldown: 1.1.5 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.3 + fsevents: 2.3.3 + yaml: 2.9.0 + + vitest@4.1.10(@types/node@24.13.3)(jsdom@26.1.0(canvas@3.2.3))(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.1.5(@types/node@24.13.3)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.1 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.4 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.2.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.1.5(@types/node@24.13.3)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.13.3 + jsdom: 26.1.0(canvas@3.2.3) + transitivePeerDependencies: + - msw + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + optional: true + + webidl-conversions@7.0.0: + optional: true + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + optional: true + + whatwg-mimetype@4.0.0: + optional: true + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + optional: true + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wrappy@1.0.2: + optional: true + + ws@8.21.1: + optional: true + + xml-name-validator@5.0.0: + optional: true + + xmlchars@2.2.0: + optional: true + + yaml@2.9.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..bfe29af --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,7 @@ +packages: + - apps/* + - packages/* + +onlyBuiltDependencies: + - better-sqlite3 + - esbuild diff --git a/scripts/frozen-versions.mjs b/scripts/frozen-versions.mjs new file mode 100644 index 0000000..1f5cd20 --- /dev/null +++ b/scripts/frozen-versions.mjs @@ -0,0 +1,61 @@ +export const frozenPackages = { + "package.json": { + devDependencies: { + "@playwright/test": "1.62.0", + typescript: "7.0.2", + vite: "8.1.5", + vitest: "4.1.10", + }, + }, + "apps/web/package.json": { + dependencies: { + "@vibrant/core": "4.0.4", + "@vibrant/quantizer-mmcq": "4.0.4", + fabric: "7.4.0", + react: "19.2.8", + "react-dom": "19.2.8", + }, + devDependencies: { + "@vitejs/plugin-react": "6.0.4", + typescript: "7.0.2", + vite: "8.1.5", + }, + }, + "apps/api/package.json": { + dependencies: { + "@fastify/swagger": "9.8.1", + "@sinclair/typebox": "0.34.52", + "better-sqlite3": "13.0.1", + "drizzle-orm": "0.45.2", + fastify: "5.10.0", + }, + devDependencies: { + typescript: "7.0.2", + }, + }, + "apps/worker/package.json": { + dependencies: { + "better-sqlite3": "13.0.1", + "drizzle-orm": "0.45.2", + }, + devDependencies: { + typescript: "7.0.2", + }, + }, + "packages/shared-contracts/package.json": { + dependencies: { + "@sinclair/typebox": "0.34.52", + }, + devDependencies: { + typescript: "7.0.2", + }, + }, +}; + +export const frozenRuntime = { + arch: "x64", + dotnetTarget: "net8.0-windows", + node: "24.13.0", + os: "win32", + pnpm: "10.28.2", +}; diff --git a/scripts/lib/tdd-trace.mjs b/scripts/lib/tdd-trace.mjs new file mode 100644 index 0000000..7204723 --- /dev/null +++ b/scripts/lib/tdd-trace.mjs @@ -0,0 +1,259 @@ +import { createHash } from "node:crypto"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const expectedCounts = { + acceptanceCriteria: 52, + errorCategories: 9, + featureModules: 13, + parentFamilies: 89, + productContracts: 19, + requirements: 109, + tasks: 52, + testCases: 117, + uiPages: 22, +}; + +function readText(root, path) { + return readFileSync(resolve(root, path), "utf8"); +} + +function sha256(root, path) { + return createHash("sha256").update(readFileSync(resolve(root, path))).digest("hex").toUpperCase(); +} + +function duplicates(values) { + const counts = new Map(); + for (const value of values) counts.set(value, (counts.get(value) ?? 0) + 1); + return [...counts.entries()].filter(([, count]) => count > 1).map(([value]) => value); +} + +function markdownTable(markdown, headingPattern) { + const lines = markdown.split(/\r?\n/); + const headingIndex = lines.findIndex((line) => headingPattern.test(line)); + if (headingIndex < 0) return []; + + const tableIndex = lines.findIndex((line, index) => index > headingIndex && line.trim().startsWith("|")); + if (tableIndex < 0) return []; + + const rows = []; + for (let index = tableIndex + 2; index < lines.length; index += 1) { + const line = lines[index].trim(); + if (!line.startsWith("|")) break; + rows.push(line.split("|").slice(1, -1).map((cell) => cell.trim())); + } + return rows; +} + +function collectPenIds(node, ids, duplicateIds) { + if (node.id) { + if (ids.has(node.id)) duplicateIds.push(node.id); + ids.add(node.id); + } + for (const child of node.children ?? []) collectPenIds(child, ids, duplicateIds); +} + +function uiFrameIds(scope) { + if (!scope.frames) return []; + const frames = Array.isArray(scope.frames) ? scope.frames : [scope.frames]; + return frames.map((frame) => frame.frame_id).filter((id) => id && id !== "UIDesign-only"); +} + +export function validateTddTrace({ root = process.cwd(), manifestOverride } = {}) { + const errors = []; + const manifest = manifestOverride ?? JSON.parse(readText(root, "tasks.manifest.json")); + const prd = readText(root, "PRD.md"); + const featureSummary = readText(root, "FeatureSummary.md"); + const tdd = readText(root, "tdd.md"); + const tasksMarkdown = readText(root, "tasks.md"); + const pen = JSON.parse(readText(root, "Dada-P0A-LowFi.pen")); + + for (const [path, expectedHash] of Object.entries(manifest.source_hashes ?? {})) { + const actualHash = sha256(root, path); + if (actualHash !== expectedHash.toUpperCase()) { + errors.push(`${path} SHA-256 mismatch: ${actualHash}`); + } + } + + if (manifest.tasks.length !== expectedCounts.tasks || manifest.task_count !== expectedCounts.tasks) { + errors.push(`task count must be ${expectedCounts.tasks}`); + } + if ( + manifest.case_catalog.length !== expectedCounts.testCases || + manifest.normative_case_count !== expectedCounts.testCases + ) { + errors.push(`normative case count must be ${expectedCounts.testCases}`); + } + + const taskIds = manifest.tasks.map((task) => task.task_id); + const familyAssignments = manifest.tasks.flatMap((task) => task.parent_families); + const caseAssignments = manifest.tasks.flatMap((task) => task.case_ids); + const catalogCaseIds = manifest.case_catalog.map((testCase) => testCase.case_id); + const catalogFamilies = [...new Set(manifest.case_catalog.map((testCase) => testCase.parent_family))]; + + for (const [label, values] of [ + ["task", taskIds], + ["family assignment", familyAssignments], + ["case assignment", caseAssignments], + ["case catalog", catalogCaseIds], + ]) { + const repeated = duplicates(values); + if (repeated.length > 0) errors.push(`duplicate ${label} IDs: ${repeated.join(", ")}`); + } + + if (familyAssignments.length !== expectedCounts.parentFamilies || new Set(familyAssignments).size !== expectedCounts.parentFamilies) { + errors.push(`parent family assignments must be unique and total ${expectedCounts.parentFamilies}`); + } + if (manifest.parent_family_count !== expectedCounts.parentFamilies || catalogFamilies.length !== expectedCounts.parentFamilies) { + errors.push(`parent family catalog count must be ${expectedCounts.parentFamilies}`); + } + if (caseAssignments.length !== expectedCounts.testCases || new Set(caseAssignments).size !== expectedCounts.testCases) { + errors.push(`case assignments must be unique and total ${expectedCounts.testCases}`); + } + + const assignedFamilySet = new Set(familyAssignments); + const assignedCaseSet = new Set(caseAssignments); + for (const family of catalogFamilies) { + if (!assignedFamilySet.has(family)) errors.push(`unassigned parent family: ${family}`); + if (!tdd.includes(family)) errors.push(`parent family missing from tdd.md: ${family}`); + } + for (const caseId of catalogCaseIds) { + if (!assignedCaseSet.has(caseId)) errors.push(`unassigned normative case: ${caseId}`); + if (!tdd.includes(caseId)) errors.push(`normative case missing from tdd.md: ${caseId}`); + } + for (const assignedCase of assignedCaseSet) { + if (!catalogCaseIds.includes(assignedCase)) errors.push(`assigned case missing from catalog: ${assignedCase}`); + } + + const taskIndex = new Map(taskIds.map((id, index) => [id, index])); + const knownWorkPackages = new Set(manifest.tasks.map((task) => task.work_package)); + manifest.tasks.forEach((task, index) => { + if (!/^TASK-(?:WP\d+|FINAL)-\d{2}$/.test(task.task_id)) { + errors.push(`invalid task ID: ${task.task_id}`); + } + if (!tasksMarkdown.includes(task.task_id)) errors.push(`task missing from tasks.md: ${task.task_id}`); + + for (const dependency of task.dependencies.task_ids) { + const dependencyIndex = taskIndex.get(dependency); + if (dependencyIndex === undefined) errors.push(`${task.task_id} has unknown dependency ${dependency}`); + else if (dependencyIndex >= index) errors.push(`${task.task_id} dependency is not earlier: ${dependency}`); + } + + for (const dependency of task.dependencies.work_packages) { + if (!knownWorkPackages.has(dependency)) errors.push(`${task.task_id} has unknown work-package dependency ${dependency}`); + } + + if (task.validation_commands.length === 0) errors.push(`${task.task_id} has no validation command`); + if (task.evidence_directories.length === 0) errors.push(`${task.task_id} has no evidence directory`); + if (task.automation.length === 0) errors.push(`${task.task_id} has no automation classification`); + if (task.release_gate.length === 0) errors.push(`${task.task_id} has no release gate`); + }); + + for (const testCase of manifest.case_catalog) { + if (!/^TDD-[A-Z0-9-]+-[a-z0-9-]+$/.test(testCase.case_id)) { + errors.push(`invalid case ID: ${testCase.case_id}`); + } + if (!testCase.case_id.startsWith(`${testCase.parent_family}-`)) { + errors.push(`${testCase.case_id} does not belong to ${testCase.parent_family}`); + } + for (const field of [ + "requirement_ac_source", + "fixture_and_preconditions", + "numbered_steps", + "expected_response_ui", + "expected_db_files", + "forbidden_side_effects", + "evidence_files", + ]) { + if (!testCase[field]?.trim()) errors.push(`${testCase.case_id} has an empty ${field}`); + } + } + + const requirementIds = [...new Set(manifest.tasks.flatMap((task) => task.requirements))]; + if (requirementIds.length !== expectedCounts.requirements) { + errors.push(`requirement coverage must total ${expectedCounts.requirements}`); + } + for (const id of requirementIds) { + if (!prd.includes(id)) errors.push(`requirement missing from PRD.md: ${id}`); + } + + const acceptanceCriteria = [...new Set(manifest.tasks.flatMap((task) => task.acceptance_criteria))]; + const expectedAcceptanceCriteria = Array.from({ length: 56 }, (_, index) => index + 1) + .filter((number) => ![8, 26, 37, 54].includes(number)) + .map((number) => `AC-${String(number).padStart(2, "0")}`); + if ( + acceptanceCriteria.length !== expectedCounts.acceptanceCriteria || + expectedAcceptanceCriteria.some((id) => !acceptanceCriteria.includes(id)) + ) { + errors.push(`current P0-A AC coverage must be the frozen ${expectedCounts.acceptanceCriteria}-item set`); + } + + const featureModules = markdownTable(featureSummary, /^## 5\./); + const errorCategories = markdownTable(featureSummary, /^### 6\.1\b/); + const productContracts = markdownTable(featureSummary, /^## 7\./); + for (const [label, rows, count] of [ + ["feature modules", featureModules, expectedCounts.featureModules], + ["error categories", errorCategories, expectedCounts.errorCategories], + ["product contracts", productContracts, expectedCounts.productContracts], + ]) { + if (rows.length !== count) errors.push(`${label} table must contain ${count} rows`); + if (duplicates(rows.map((row) => row[0])).length > 0) errors.push(`${label} table has duplicate keys`); + } + + const uiScopes = manifest.tasks.flatMap((task) => task.ui_scope); + const pageIds = [...new Set(uiScopes.map((scope) => scope.page_id))]; + if (pageIds.length !== expectedCounts.uiPages) errors.push(`UI page coverage must total ${expectedCounts.uiPages}`); + const uiRoleKeys = uiScopes.map((scope) => `${scope.page_id}:${scope.role}`); + for (const pageId of pageIds) { + for (const role of ["implementation", "final_evidence"]) { + if (!uiRoleKeys.includes(`${pageId}:${role}`)) errors.push(`${pageId} is missing UI role ${role}`); + } + } + + const penIds = new Set(); + const duplicatePenIds = []; + collectPenIds(pen, penIds, duplicatePenIds); + if (duplicatePenIds.length > 0) errors.push(`duplicate .pen IDs: ${duplicatePenIds.join(", ")}`); + if (pen.children.length !== 19 || pen.children.filter((frame) => frame.id !== "Z8p3I").length !== 18) { + errors.push("Dada-P0A-LowFi.pen must contain one index and 18 product frames"); + } + for (const frameId of new Set(uiScopes.flatMap(uiFrameIds))) { + if (!penIds.has(frameId)) errors.push(`UI scope references an unknown .pen frame: ${frameId}`); + } + + const requiredScripts = [ + "test:unit", + "test:integration", + "test:api", + "test:worker", + "test:e2e", + "test:visual", + "test:performance", + "test:security", + "test:package", + "validate:tdd-trace", + "test:all", + "validate:external", + ]; + const packageJson = JSON.parse(readText(root, "package.json")); + for (const script of requiredScripts) { + if (!packageJson.scripts?.[script]) errors.push(`package.json is missing script ${script}`); + } + + return { + errors, + status: errors.length === 0 ? "passed" : "failed", + summary: { + acceptanceCriteria: acceptanceCriteria.length, + errorCategories: errorCategories.length, + featureModules: featureModules.length, + parentFamilies: catalogFamilies.length, + penProductFrames: pen.children.filter((frame) => frame.id !== "Z8p3I").length, + productContracts: productContracts.length, + requirements: requirementIds.length, + tasks: manifest.tasks.length, + testCases: manifest.case_catalog.length, + uiPages: pageIds.length, + }, + }; +} diff --git a/scripts/native-smoke.mjs b/scripts/native-smoke.mjs new file mode 100644 index 0000000..e7b6bcb --- /dev/null +++ b/scripts/native-smoke.mjs @@ -0,0 +1,23 @@ +import { createRequire } from "node:module"; +import { resolve } from "node:path"; +import { pathToFileURL } from "node:url"; + +const requireFromApi = createRequire(pathToFileURL(resolve("apps/api/package.json"))); +const Database = requireFromApi("better-sqlite3"); +const sqlitePackage = requireFromApi("better-sqlite3/package.json"); + +const database = new Database(":memory:"); +const row = database.prepare("select 1 as value").get(); +database.close(); + +const result = { + arch: process.arch, + betterSqlite3: sqlitePackage.version, + node: process.version.slice(1), + os: process.platform, + selectValue: row.value, + status: row.value === 1 ? "passed" : "failed", +}; + +console.log(JSON.stringify(result)); +if (result.status !== "passed") process.exit(1); diff --git a/scripts/package-smoke.mjs b/scripts/package-smoke.mjs new file mode 100644 index 0000000..c060a80 --- /dev/null +++ b/scripts/package-smoke.mjs @@ -0,0 +1,77 @@ +import { execFileSync } from "node:child_process"; +import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { frozenRuntime } from "./frozen-versions.mjs"; + +if ( + process.platform !== frozenRuntime.os || + process.arch !== frozenRuntime.arch || + process.version.slice(1) !== frozenRuntime.node +) { + throw new Error("The package smoke must run on the frozen win-x64 Node 24.13.0 runtime."); +} + +const runtimeDirectory = resolve(".build/runtime"); +const runtimeNode = resolve(runtimeDirectory, "node.exe"); +mkdirSync(runtimeDirectory, { recursive: true }); +copyFileSync(process.execPath, runtimeNode); + +const nativeSmoke = JSON.parse( + execFileSync(runtimeNode, ["scripts/native-smoke.mjs"], { encoding: "utf8" }).trim(), +); +const workerSmoke = JSON.parse( + execFileSync(runtimeNode, ["scripts/worker-smoke.mjs"], { encoding: "utf8" }).trim(), +); + +execFileSync( + "dotnet", + [ + "restore", + "supervisor/Dada.Supervisor/Dada.Supervisor.csproj", + "--configfile", + "NuGet.Config", + ], + { stdio: "inherit" }, +); +execFileSync( + "dotnet", + [ + "build", + "supervisor/Dada.Supervisor/Dada.Supervisor.csproj", + "--configuration", + "Release", + "--no-restore", + ], + { stdio: "inherit" }, +); + +const supervisorExecutable = resolve( + "supervisor/Dada.Supervisor/bin/Release/net8.0-windows/Dada.Supervisor.exe", +); +if (!existsSync(supervisorExecutable)) { + throw new Error("The .NET 8 WinForms supervisor executable was not produced."); +} + +const result = { + schema_version: "1.0", + native: nativeSmoke, + packagedNodeCandidate: { + path: ".build/runtime/node.exe", + version: frozenRuntime.node, + }, + status: "passed", + supervisor: { + build: "passed", + target: frozenRuntime.dotnetTarget, + }, + worker: workerSmoke, +}; + +const evidenceDirectory = process.env.DADA_EVIDENCE_DIR; +if (evidenceDirectory) { + mkdirSync(evidenceDirectory, { recursive: true }); + writeFileSync(resolve(evidenceDirectory, "native-smoke.json"), `${JSON.stringify(result, null, 2)}\n`); +} + +console.log(JSON.stringify(result, null, 2)); diff --git a/scripts/redaction-scan.mjs b/scripts/redaction-scan.mjs new file mode 100644 index 0000000..f2e9dc6 --- /dev/null +++ b/scripts/redaction-scan.mjs @@ -0,0 +1,32 @@ +import { readdirSync, readFileSync, statSync } from "node:fs"; +import { extname, join, relative } from "node:path"; + +const scanRoots = ["apps", "packages", "scripts", "supervisor", "tests"]; +const textExtensions = new Set([".cs", ".json", ".mjs", ".ts", ".tsx", ".yaml", ".yml"]); +const findings = []; + +function visit(path) { + for (const name of readdirSync(path)) { + const child = join(path, name); + const relativePath = relative(process.cwd(), child).replaceAll("\\", "/"); + if (["bin", "dist", "node_modules", "obj"].includes(name)) continue; + if (statSync(child).isDirectory()) { + visit(child); + continue; + } + if (!textExtensions.has(extname(name)) || relativePath === "scripts/redaction-scan.mjs") continue; + + const content = readFileSync(child, "utf8"); + const prohibited = [ + /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/, + /[A-Za-z]:\\Users\\[^\\\s]+/, + /(?:api[_-]?key|password|secret)\s*[:=]\s*["'][^"']{8,}["']/i, + ]; + if (prohibited.some((pattern) => pattern.test(content))) findings.push(relativePath); + } +} + +for (const root of scanRoots) visit(root); + +console.log(JSON.stringify({ findings, status: findings.length === 0 ? "passed" : "failed" }, null, 2)); +if (findings.length > 0) process.exit(1); diff --git a/scripts/run-wp0-01-validation.mjs b/scripts/run-wp0-01-validation.mjs new file mode 100644 index 0000000..b6383d9 --- /dev/null +++ b/scripts/run-wp0-01-validation.mjs @@ -0,0 +1,79 @@ +import { createHash } from "node:crypto"; +import { spawnSync } from "node:child_process"; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const runId = process.env.DADA_TDD_RUN_ID ?? `wp0-01-green-${new Date().toISOString().replace(/[^0-9]/g, "")}`; +const caseId = "TDD-WP0-DEP-001-frozen-toolchain"; +const evidenceDirectory = resolve("artifacts", "tdd", runId, "cases", caseId); + +if (existsSync(evidenceDirectory)) { + throw new Error(`Evidence run already exists: ${runId}`); +} +mkdirSync(evidenceDirectory, { recursive: true }); + +const commandDefinitions = [ + { command: "pnpm install --frozen-lockfile --offline", args: ["install", "--frozen-lockfile", "--offline"] }, + { command: "pnpm test:unit", args: ["test:unit"] }, + { command: "pnpm test:security", args: ["test:security"] }, + { command: "pnpm test:package", args: ["test:package"] }, + { command: "pnpm validate:tdd-trace", args: ["validate:tdd-trace"] }, +]; + +const startedAt = new Date().toISOString(); +const commands = []; +for (const definition of commandDefinitions) { + const commandStartedAt = new Date().toISOString(); + const executable = process.platform === "win32" ? (process.env.ComSpec ?? "cmd.exe") : "pnpm"; + const args = process.platform === "win32" + ? ["/d", "/s", "/c", `pnpm ${definition.args.join(" ")}`] + : definition.args; + const result = spawnSync(executable, args, { + env: { ...process.env, DADA_EVIDENCE_DIR: evidenceDirectory }, + stdio: "inherit", + }); + commands.push({ + command: definition.command, + exit_code: result.status ?? 1, + finished_at: new Date().toISOString(), + started_at: commandStartedAt, + }); +} + +const allPassed = commands.every((command) => command.exit_code === 0); +const requiredEvidence = ["dependency-tree.json", "native-smoke.json"]; +const missingEvidence = requiredEvidence.filter((path) => !existsSync(resolve(evidenceDirectory, path))); +const passed = allPassed && missingEvidence.length === 0; + +writeFileSync( + resolve(evidenceDirectory, "commands.json"), + `${JSON.stringify({ schema_version: "1.0", run_id: runId, phase: "green", commands }, null, 2)}\n`, +); + +const manifestBytes = readFileSync("tasks.manifest.json"); +const result = { + schema_version: "1.0", + run_id: runId, + task_id: "TASK-WP0-01", + case_id: caseId, + parent_family: "TDD-WP0-DEP-001", + phase: "green", + status: passed ? "passed" : "failed", + manifest: { + path: "tasks.manifest.json", + sha256: createHash("sha256").update(manifestBytes).digest("hex").toUpperCase(), + }, + environment: { + arch: process.arch, + node: process.version.slice(1), + os: process.platform, + }, + evidence_files: ["commands.json", ...requiredEvidence], + missing_evidence: missingEvidence, + started_at: startedAt, + finished_at: new Date().toISOString(), +}; +writeFileSync(resolve(evidenceDirectory, "result.json"), `${JSON.stringify(result, null, 2)}\n`); + +console.log(JSON.stringify(result, null, 2)); +if (!passed) process.exit(1); diff --git a/scripts/validate-external.mjs b/scripts/validate-external.mjs new file mode 100644 index 0000000..e2b7444 --- /dev/null +++ b/scripts/validate-external.mjs @@ -0,0 +1,23 @@ +const allowedServices = new Set(["ai", "resend", "amap"]); + +function argument(name) { + const index = process.argv.indexOf(name); + return index >= 0 ? process.argv[index + 1] : undefined; +} + +const service = argument("--service"); +const runId = argument("--run-id"); + +if (!allowedServices.has(service) || !runId) { + console.error("Usage: pnpm validate:external -- --service --run-id "); + process.exit(2); +} + +console.log( + JSON.stringify({ + mode: "mock", + run_id: runId, + service, + status: "not_applicable_for_TASK-WP0-01", + }), +); diff --git a/scripts/validate-layer-scope.mjs b/scripts/validate-layer-scope.mjs new file mode 100644 index 0000000..9f54c67 --- /dev/null +++ b/scripts/validate-layer-scope.mjs @@ -0,0 +1,24 @@ +import { readFileSync } from "node:fs"; + +const layer = process.argv[2]; +if (!layer) { + console.error("A test layer is required."); + process.exit(2); +} + +const manifest = JSON.parse(readFileSync("tasks.manifest.json", "utf8")); +const task = manifest.tasks.find((item) => item.task_id === "TASK-WP0-01"); +const applicable = task.layers.includes(layer); + +if (applicable) { + console.error(`TASK-WP0-01 assigns ${layer}; a real layer runner is required.`); + process.exit(1); +} + +console.log( + JSON.stringify({ + layer, + status: "not_applicable", + task_id: task.task_id, + }), +); diff --git a/scripts/validate-tdd-trace.mjs b/scripts/validate-tdd-trace.mjs new file mode 100644 index 0000000..924df64 --- /dev/null +++ b/scripts/validate-tdd-trace.mjs @@ -0,0 +1,5 @@ +import { validateTddTrace } from "./lib/tdd-trace.mjs"; + +const result = validateTddTrace(); +console.log(JSON.stringify(result, null, 2)); +if (result.errors.length > 0) process.exit(1); diff --git a/scripts/verify-frozen-dependencies.mjs b/scripts/verify-frozen-dependencies.mjs new file mode 100644 index 0000000..88831d1 --- /dev/null +++ b/scripts/verify-frozen-dependencies.mjs @@ -0,0 +1,89 @@ +import { execFileSync } from "node:child_process"; +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; + +import { frozenPackages, frozenRuntime } from "./frozen-versions.mjs"; + +function readJson(path) { + return JSON.parse(readFileSync(path, "utf8")); +} + +function installedPackageVersion(manifestPath, packageName) { + const packagePath = resolve( + dirname(manifestPath), + "node_modules", + ...packageName.split("/"), + "package.json", + ); + return readJson(packagePath).version; +} + +export function verifyFrozenDependencies() { + const problems = []; + const packages = {}; + + for (const [manifestPath, sections] of Object.entries(frozenPackages)) { + const manifest = readJson(manifestPath); + packages[manifest.name] = {}; + + for (const [section, expected] of Object.entries(sections)) { + for (const [name, version] of Object.entries(expected)) { + const declared = manifest[section]?.[name]; + if (declared !== version) { + problems.push(`${manifestPath} ${section}.${name}: declared ${declared ?? "missing"}, expected ${version}`); + continue; + } + + const installed = installedPackageVersion(manifestPath, name); + packages[manifest.name][name] = installed; + if (installed !== version) { + problems.push(`${manifestPath} ${name}: installed ${installed}, expected ${version}`); + } + } + } + } + + const packageManager = readJson("package.json").packageManager; + const pnpmVersion = process.platform === "win32" + ? execFileSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", "pnpm --version"], { + encoding: "utf8", + }).trim() + : execFileSync("pnpm", ["--version"], { encoding: "utf8" }).trim(); + const runtimeChecks = { + arch: process.arch, + node: process.version.slice(1), + os: process.platform, + packageManager, + pnpm: pnpmVersion, + }; + + for (const key of ["arch", "node", "os", "pnpm"]) { + if (runtimeChecks[key] !== frozenRuntime[key]) { + problems.push(`${key}: running ${runtimeChecks[key]}, expected ${frozenRuntime[key]}`); + } + } + if (packageManager !== `pnpm@${frozenRuntime.pnpm}`) { + problems.push(`packageManager: declared ${packageManager}, expected pnpm@${frozenRuntime.pnpm}`); + } + + return { + packages, + problems, + runtime: runtimeChecks, + status: problems.length === 0 ? "passed" : "failed", + }; +} + +const snapshot = verifyFrozenDependencies(); +const evidenceDirectory = process.env.DADA_EVIDENCE_DIR; + +if (evidenceDirectory) { + mkdirSync(evidenceDirectory, { recursive: true }); + writeFileSync( + resolve(evidenceDirectory, "dependency-tree.json"), + `${JSON.stringify({ schema_version: "1.0", ...snapshot }, null, 2)}\n`, + ); +} + +console.log(JSON.stringify(snapshot, null, 2)); +if (snapshot.problems.length > 0) process.exit(1); diff --git a/scripts/worker-smoke.mjs b/scripts/worker-smoke.mjs new file mode 100644 index 0000000..2f3cebb --- /dev/null +++ b/scripts/worker-smoke.mjs @@ -0,0 +1,23 @@ +import { resolve } from "node:path"; +import { Worker } from "node:worker_threads"; + +const worker = new Worker(resolve("apps/worker/dist/worker.js")); +const timeout = setTimeout(() => { + void worker.terminate(); + throw new Error("Worker probe timed out."); +}, 5_000); + +const reply = await new Promise((resolveReply, reject) => { + worker.once("error", reject); + worker.once("message", resolveReply); + worker.postMessage("ping"); +}); + +clearTimeout(timeout); +await worker.terminate(); + +if (reply !== "pong") { + throw new Error(`Unexpected Worker probe reply: ${String(reply)}`); +} + +console.log(JSON.stringify({ reply, status: "passed" })); diff --git a/supervisor/Dada.Supervisor/Dada.Supervisor.csproj b/supervisor/Dada.Supervisor/Dada.Supervisor.csproj new file mode 100644 index 0000000..0590777 --- /dev/null +++ b/supervisor/Dada.Supervisor/Dada.Supervisor.csproj @@ -0,0 +1,9 @@ + + + WinExe + net8.0-windows + true + enable + enable + + diff --git a/supervisor/Dada.Supervisor/Program.cs b/supervisor/Dada.Supervisor/Program.cs new file mode 100644 index 0000000..9e3e282 --- /dev/null +++ b/supervisor/Dada.Supervisor/Program.cs @@ -0,0 +1,11 @@ +namespace Dada.Supervisor; + +internal static class Program +{ + [STAThread] + private static void Main() + { + ApplicationConfiguration.Initialize(); + Application.Run(new SupervisorForm()); + } +} diff --git a/supervisor/Dada.Supervisor/SupervisorForm.cs b/supervisor/Dada.Supervisor/SupervisorForm.cs new file mode 100644 index 0000000..609b155 --- /dev/null +++ b/supervisor/Dada.Supervisor/SupervisorForm.cs @@ -0,0 +1,13 @@ +namespace Dada.Supervisor; + +internal sealed class SupervisorForm : Form +{ + public SupervisorForm() + { + ClientSize = new Size(420, 160); + FormBorderStyle = FormBorderStyle.FixedDialog; + MaximizeBox = false; + StartPosition = FormStartPosition.CenterScreen; + Text = "Dada"; + } +} diff --git a/tests/api/app.test.ts b/tests/api/app.test.ts new file mode 100644 index 0000000..6d131de --- /dev/null +++ b/tests/api/app.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; + +import { createApp } from "../../apps/api/src/app.js"; + +describe("Fastify skeleton", () => { + it("becomes ready without adding a product route", async () => { + const app = createApp(); + await app.ready(); + expect(app.printRoutes()).not.toContain("health"); + await app.close(); + }); +}); diff --git a/tests/integration/native-database.test.ts b/tests/integration/native-database.test.ts new file mode 100644 index 0000000..c18713c --- /dev/null +++ b/tests/integration/native-database.test.ts @@ -0,0 +1,15 @@ +import { createRequire } from "node:module"; + +import { describe, expect, it } from "vitest"; + +const requireFromApi = createRequire(new URL("../../apps/api/package.json", import.meta.url)); +const Database = requireFromApi("better-sqlite3"); + +describe("better-sqlite3 native module", () => { + it("executes an in-memory query without creating business data", () => { + const database = new Database(":memory:"); + const row = database.prepare("select 1 as value").get(); + database.close(); + expect(row.value).toBe(1); + }); +}); diff --git a/tests/toolchain/frozen-toolchain.test.mjs b/tests/toolchain/frozen-toolchain.test.mjs new file mode 100644 index 0000000..74fc700 --- /dev/null +++ b/tests/toolchain/frozen-toolchain.test.mjs @@ -0,0 +1,59 @@ +import assert from "node:assert/strict"; +import { existsSync, readFileSync } from "node:fs"; +import test from "node:test"; + +import { frozenPackages } from "../../scripts/frozen-versions.mjs"; + +const expectedFiles = [ + "NuGet.Config", + "pnpm-lock.yaml", + "pnpm-workspace.yaml", + "tsconfig.base.json", + "apps/web/package.json", + "apps/web/src/toolchain-probe.tsx", + "apps/api/package.json", + "apps/api/src/app.ts", + "apps/worker/package.json", + "apps/worker/src/worker.ts", + "packages/shared-contracts/package.json", + "packages/shared-contracts/src/index.ts", + "scripts/validate-tdd-trace.mjs", + "scripts/native-smoke.mjs", + "supervisor/Dada.Supervisor/Dada.Supervisor.csproj", +]; + +function readJson(path) { + return JSON.parse(readFileSync(path, "utf8")); +} + +test("TASK-WP0-01 has no unresolved task dependency", () => { + const manifest = readJson("tasks.manifest.json"); + const task = manifest.tasks.find((item) => item.task_id === "TASK-WP0-01"); + assert.ok(task, "TASK-WP0-01 must exist in tasks.manifest.json"); + assert.deepEqual(task.dependencies.task_ids, []); + assert.deepEqual(task.dependencies.work_packages, []); + assert.equal(task.dependencies.source_text, "无"); +}); + +test("TDD-WP0-DEP-001 frozen toolchain contract is implemented", () => { + const problems = []; + + for (const path of expectedFiles) { + if (!existsSync(path)) problems.push(`missing file: ${path}`); + } + + for (const [path, sections] of Object.entries(frozenPackages)) { + if (!existsSync(path)) continue; + const packageJson = readJson(path); + for (const [section, packages] of Object.entries(sections)) { + for (const [name, version] of Object.entries(packages)) { + const actual = packageJson[section]?.[name]; + if (actual !== version) { + problems.push(`${path} ${section}.${name}: expected ${version}, got ${actual ?? "missing"}`); + } + } + } + } + + assert.deepEqual(problems, []); +}); diff --git a/tests/unit/toolchain-smoke.test.ts b/tests/unit/toolchain-smoke.test.ts new file mode 100644 index 0000000..59d55de --- /dev/null +++ b/tests/unit/toolchain-smoke.test.ts @@ -0,0 +1,57 @@ +import { readFileSync } from "node:fs"; + +import { describe, expect, it } from "vitest"; + +import { createApp } from "../../apps/api/src/app.js"; +import { renderToolchainProbe } from "../../apps/web/src/toolchain-probe.js"; +import { validateTddTrace } from "../../scripts/lib/tdd-trace.mjs"; + +function readManifest() { + return JSON.parse(readFileSync(new URL("../../tasks.manifest.json", import.meta.url), "utf8")); +} + +describe("TASK-WP0-01 minimum toolchain", () => { + it("renders through React and Fabric at the frozen versions", () => { + const probe = renderToolchainProbe(); + + expect(probe.reactMarkup).toContain("Dada toolchain probe"); + expect(probe.fabricSvg).toContain(" { + const app = createApp(); + await app.ready(); + expect(app.hasPlugin("@fastify/swagger")).toBe(true); + await app.close(); + }); + + it("validates the frozen TDD trace", () => { + const result = validateTddTrace(); + expect(result.errors).toEqual([]); + expect(result.summary).toMatchObject({ + acceptanceCriteria: 52, + parentFamilies: 89, + requirements: 109, + tasks: 52, + testCases: 117, + uiPages: 22, + }); + }); + + it("rejects a missing normative case", () => { + const manifest = readManifest(); + manifest.case_catalog.pop(); + const result = validateTddTrace({ manifestOverride: manifest }); + expect(result.status).toBe("failed"); + expect(result.errors.some((error) => error.includes("normative case count"))).toBe(true); + }); + + it("rejects a duplicated case assignment", () => { + const manifest = readManifest(); + manifest.tasks[1].case_ids.push(manifest.tasks[0].case_ids[0]); + const result = validateTddTrace({ manifestOverride: manifest }); + expect(result.status).toBe("failed"); + expect(result.errors.some((error) => error.includes("duplicate case assignment"))).toBe(true); + }); +}); diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..9ee6ae1 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2024", + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "verbatimModuleSyntax": true, + "isolatedModules": true, + "resolveJsonModule": true + } +}