From 6b886307a1f35d354fa3477bc62e855244e4977e Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Wed, 12 Aug 2026 10:15:53 +0530 Subject: [PATCH 1/3] chore: adopt mixed code-health baseline --- .github/workflows/ci.yml | 16 +- AGENTS.md | 2 +- PROJECT_STATUS.md | 9 + ios/README.md | 4 + knip.jsonc | 9 + package.json | 24 +- pnpm-lock.yaml | 1058 +++++++++++++++++++++----- scripts/check-code-health.mjs | 275 +++++++ scripts/check-native-code-health.mjs | 113 +++ src/components/charts/chart-utils.ts | 8 - src/lib/actionable-insights.ts | 2 +- src/lib/api.ts | 16 +- src/lib/cycle-sessions.ts | 2 +- src/lib/demo.ts | 3 - src/lib/food-library.ts | 2 +- src/lib/local-store.ts | 3 - src/lib/macro-completion.ts | 2 +- src/lib/nutrient-density.ts | 4 +- src/lib/offline.ts | 2 +- src/lib/recommendations.ts | 2 +- vite.config.ts | 2 +- vitest.config.ts | 9 +- 22 files changed, 1340 insertions(+), 227 deletions(-) create mode 100644 knip.jsonc create mode 100644 scripts/check-code-health.mjs create mode 100644 scripts/check-native-code-health.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f28c5a..4ffb3d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,10 +11,24 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 2 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - - run: pnpm check + - uses: astral-sh/setup-uv@v7 + - run: pnpm quality + + native-quality: + runs-on: macos-15 + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: command -v xcodegen >/dev/null || brew install xcodegen + - run: pnpm quality:native diff --git a/AGENTS.md b/AGENTS.md index fcbcd21..53a112a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ migrations, or credential changes. - **Stack:** Vite + React + TypeScript, Cloudflare Worker, D1, Better Auth with Google - **Package manager:** pnpm - **Local dev:** `pnpm dev` -- **Checks:** `pnpm check` +- **Checks:** `pnpm quality` (alias: `pnpm check`); `pnpm quality:native` on macOS - **Deploy:** `pnpm deploy` (manual only) ## Product rules diff --git a/PROJECT_STATUS.md b/PROJECT_STATUS.md index b8d4e89..db65911 100644 --- a/PROJECT_STATUS.md +++ b/PROJECT_STATUS.md @@ -34,6 +34,12 @@ full sets/reps workout-programming system. ## Timeline +- 2026-08-12 — adopted the Fleet code-health contract as the single CI gate: + whole-source web and native coverage, unused code, cross-language complexity, + exact duplication, import/target cycles, severe advisories, suppression + markers, web/native builds, and repository hygiene now have explicit + non-regression floors or ceilings; removed unused exports and duplicate + aliases, and targeted tool updates reduced high advisories from two to zero - 2026-08-11 — released native Sign in with Apple, explicit linking to an existing Google-owned journal, deterministic iPhone/cloud reconciliation, durable offline sync intents, and single-use Google-to-native handoffs; D1 @@ -100,6 +106,9 @@ full sets/reps workout-programming system. ## Features (shipped) +- CI-enforced mixed web/native Fleet code-health ratchets across whole-source + coverage, dead code, complexity, duplication, cycles, dependency advisories, + suppression markers, builds, and repository hygiene - Native iPhone and iPad journal with local onboarding, food/water/weight/routine capture, transparent calculations and guidance, progress/history, food management, data transfer, appearance and accessibility support, simulator diff --git a/ios/README.md b/ios/README.md index d756fb6..b55df90 100644 --- a/ios/README.md +++ b/ios/README.md @@ -8,6 +8,10 @@ A native SwiftUI nutrition journal for iOS 17 and later. It uses Apple framework ./scripts/check.sh ``` +From the repository root, `pnpm quality:native` selects an available iPhone +simulator, runs the same tests and Release build, and enforces the checked-in +production Swift coverage floor. CI runs this command on macOS. + ## Personal-team archive ```bash diff --git a/knip.jsonc b/knip.jsonc new file mode 100644 index 0000000..0e5cb3d --- /dev/null +++ b/knip.jsonc @@ -0,0 +1,9 @@ +{ + "$schema": "https://unpkg.com/knip@6/schema.json", + "entry": ["public/sw.js"], + "project": ["src/**/*.{ts,tsx,mjs}", "*.config.ts"], + "ignoreDependencies": ["jscpd", "lightningcss"], + "ignoreIssues": { + "src/agent-edge.mjs": ["exports"] + } +} diff --git a/package.json b/package.json index 8814335..f29fa70 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,21 @@ "typecheck": "tsc --noEmit -p tsconfig.app.json && tsc --noEmit -p tsconfig.worker.json", "lint": "biome check .", "format": "biome format --write .", + "format:check": "biome format .", "test": "vitest run", - "check": "pnpm lint && pnpm typecheck && pnpm test && pnpm build" + "test:coverage": "vitest run --coverage", + "knip": "knip --no-exit-code --reporter symbols", + "knip:strict": "knip --reporter symbols", + "quality:unused": "node scripts/check-code-health.mjs unused", + "quality:complexity": "node scripts/check-code-health.mjs complexity", + "quality:duplication": "node scripts/check-code-health.mjs duplication", + "quality:cycles": "node scripts/check-code-health.mjs cycles", + "quality:dependencies": "node scripts/check-code-health.mjs dependencies", + "quality:suppressions": "node scripts/check-code-health.mjs suppressions", + "quality:hygiene": "node scripts/check-code-health.mjs hygiene", + "quality:native": "node scripts/check-native-code-health.mjs", + "quality": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test:coverage && pnpm quality:unused && pnpm quality:complexity && pnpm quality:duplication && pnpm quality:cycles && pnpm quality:dependencies && pnpm quality:suppressions && pnpm build && pnpm quality:hygiene", + "check": "pnpm quality" }, "dependencies": { "better-auth": "1.6.25", @@ -34,17 +47,20 @@ }, "devDependencies": { "@biomejs/biome": "2.5.5", - "@cloudflare/workers-types": "5.20260727.1", + "@cloudflare/workers-types": "5.20260812.1", "@types/react": "19.2.17", "@types/react-dom": "19.2.3", "@vitejs/plugin-react-swc": "4.3.2", + "@vitest/coverage-v8": "4.1.10", "concurrently": "9.2.1", + "jscpd": "5.0.14", + "knip": "6.29.0", "lightningcss": "1.33.0", "typescript": "6.0.3", "ultracite": "7.10.2", - "vite": "8.1.5", + "vite": "8.2.1", "vitest": "4.1.10", - "wrangler": "4.114.0" + "wrangler": "4.121.0" }, "pnpm": { "overrides": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf361c3..b46f843 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,10 +13,10 @@ importers: dependencies: better-auth: specifier: 1.6.25 - version: 1.6.25(@cloudflare/workers-types@5.20260727.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0))) + version: 1.6.25(@cloudflare/workers-types@5.20260812.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10) drizzle-orm: specifier: 0.45.2 - version: 0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4) + version: 0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4) hono: specifier: 4.12.32 version: 4.12.32 @@ -37,8 +37,8 @@ importers: specifier: 2.5.5 version: 2.5.5 '@cloudflare/workers-types': - specifier: 5.20260727.1 - version: 5.20260727.1 + specifier: 5.20260812.1 + version: 5.20260812.1 '@types/react': specifier: 19.2.17 version: 19.2.17 @@ -47,10 +47,19 @@ importers: version: 19.2.3(@types/react@19.2.17) '@vitejs/plugin-react-swc': specifier: 4.3.2 - version: 4.3.2(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0)) + version: 4.3.2(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/coverage-v8': + specifier: 4.1.10 + version: 4.1.10(vitest@4.1.10) concurrently: specifier: 9.2.1 version: 9.2.1 + jscpd: + specifier: 5.0.14 + version: 5.0.14 + knip: + specifier: 6.29.0 + version: 6.29.0 lightningcss: specifier: 1.33.0 version: 1.33.0 @@ -61,17 +70,38 @@ importers: specifier: 7.10.2 version: 7.10.2 vite: - specifier: 8.1.5 - version: 8.1.5(esbuild@0.28.1)(yaml@2.9.0) + specifier: 8.2.1 + version: 8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) vitest: specifier: 4.1.10 - version: 4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0)) + version: 4.1.10(@vitest/coverage-v8@4.1.10)(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) wrangler: - specifier: 4.114.0 - version: 4.114.0(@cloudflare/workers-types@5.20260727.1) + specifier: 4.121.0 + version: 4.121.0(@cloudflare/workers-types@5.20260812.1) packages: + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + '@better-auth/core@1.6.25': resolution: {integrity: sha512-lMTlhtwyK4NpY9kPF+2rQCRKYpg136d3gM2xl8esxT1PjJx5Nh5YwZvxcYCIjDuO759sx6TCloJTuwcZGG6ZBw==} peerDependencies: @@ -229,48 +259,48 @@ packages: workerd: optional: true - '@cloudflare/workerd-darwin-64@1.20260722.1': - resolution: {integrity: sha512-vZOP8vIS3NwnuaO+gz0FZ7kIGeiO3bZmxV35Ph9zOXKSREhDFlH7wQ7mkCdhW3O4jnXsew+XT7b+DNEI2CcJGQ==} + '@cloudflare/workerd-darwin-64@1.20260804.1': + resolution: {integrity: sha512-191/PPEFicRK2wK69eXzSjnLgHL79k7zR2VUpyIr8rhFgGns1b5bTHgnBuUrgU2LPbEtwbE5eL2hJ0uhLAFEow==} engines: {node: '>=16'} cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20260722.1': - resolution: {integrity: sha512-EmIQymihDq6WNdER4+LF8Qn80yqayBUpJ+tkOO7wmY8pmgfyXjIUFNXotl21AHovTeu2seR7HdVUgeN/BilCWw==} + '@cloudflare/workerd-darwin-arm64@1.20260804.1': + resolution: {integrity: sha512-aI2cAFLsrNkSz3kLSQrgrO9ICTfY7jb2h0jgaWDE9mQLQQDfpXeYrKWt07tTgMmeNP79o9w3NZe3aqtt8mTGHQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] - '@cloudflare/workerd-linux-64@1.20260722.1': - resolution: {integrity: sha512-jvZ3k9fxcnEn04s80CgIYxQfpOyAiz/8qC42DP8EBa9tR27qWyg9wmm31zIobVlrgBZn/+8NfdP73avRGcQOjQ==} + '@cloudflare/workerd-linux-64@1.20260804.1': + resolution: {integrity: sha512-KBCjxBIlN2jucfQGaTK4EgmPsWzQgYR/zYhPfi3mkWwdoTyG1dgrt2aizKps/SYse85ci/SOxojKk0/K7vstPw==} engines: {node: '>=16'} cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20260722.1': - resolution: {integrity: sha512-BOSB55SMNdy+DA5uj2WirgiNanpHGis5PVvXH1wSfvjRKr4JGgWK+EZzxz0RFUo6QjjQQC/NimEzNZ7va7jmKg==} + '@cloudflare/workerd-linux-arm64@1.20260804.1': + resolution: {integrity: sha512-7lswfarBZ7xkHpTFrNb74ExwOltIalVaASc+GOYfCNtnwFxK/JZSVByfm/hnZEBtrHU7fMY2z7dYT64rwS0pHg==} engines: {node: '>=16'} cpu: [arm64] os: [linux] - '@cloudflare/workerd-windows-64@1.20260722.1': - resolution: {integrity: sha512-sYM8YgUpKnRz2xjvdJLX1Ojzoi4MlA4gk8WTTExhGydjYB2UTs5NIbv0ZmpKgMoK9io3ixgmiW56ZnTbcWOdiA==} + '@cloudflare/workerd-windows-64@1.20260804.1': + resolution: {integrity: sha512-GOgRWYtxISN5rAWfx3K7zubt3xEn0/ZPFrbcLL+GwT4ouCKyNoHqfT1cPNB6Nx7t8BHEjnuTG7gkHO4Wd5ORdg==} engines: {node: '>=16'} cpu: [x64] os: [win32] - '@cloudflare/workers-types@5.20260727.1': - resolution: {integrity: sha512-b/wT+LMZz0oELzxibww0ujFz5BD8NRz9WJ+xd+JNZJUMXgh8IHjpibKdGDvtkbotmihWUknP5tBPUU8KluLxxA==} + '@cloudflare/workers-types@5.20260812.1': + resolution: {integrity: sha512-eG2aQdUWH8RYEubpBjUE98L2G57JYzGEcI8PgROTjt9YjunbEnPBHP4371Usj8v8pTWcXtbOmI+LRCXF4KhJgQ==} '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@emnapi/core@1.11.1': - resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} - '@emnapi/runtime@1.11.1': - resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} '@emnapi/runtime@1.11.3': resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} @@ -603,6 +633,9 @@ packages: '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -624,8 +657,241 @@ packages: resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==} engines: {node: '>=14'} - '@oxc-project/types@0.139.0': - resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + '@oxc-parser/binding-android-arm-eabi@0.140.0': + resolution: {integrity: sha512-ZfjDZ422mo7eo3b3VltqNsV9kmv1qt/sPEAMSl64iOSwhVfd0eIZ9LB79Mbs1xYXJnk7WSROwzBCKDIiVxPTvQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.140.0': + resolution: {integrity: sha512-Ia8jSvikUX6Sf+Ht+KOCUF/k1HpR0VlmqIYymubmWDebOEGtsyliHDR6JxsZ4IX3/c/GbrB1uh09aVGQv/LQmQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.140.0': + resolution: {integrity: sha512-G6VK0nK61pH0d0mBjUqSZbVxGqqO5uzeginLDQj+gOO6ObfJjXRwgkD/ol0w1INcnFeAb6YGGO7qc3ueGHaycQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.140.0': + resolution: {integrity: sha512-HazBOuZzd2pO1C2uMmp8Gv7mhzMHqKSKDS1OZfcLEvpIcgA+48J92HEtNanVHDIzRD9PRPCV6aS6fkZIWOVl8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.140.0': + resolution: {integrity: sha512-9hSUU+HmTUyOe4JzMHxNGgLWNY7rrO+6ShicZwImNJacEAACDMIkuEQQkvXSL+WJN50jaNtLYJv8s4OcBdpyUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + resolution: {integrity: sha512-RAEuQsYtS0KcDFqN0ABTjyyNlokS91JeuDuoW9tEbG0JTbRNXnpQUdbYc/16JoA6Z/2ALbNrE3KmxtqDiuIjCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + resolution: {integrity: sha512-c4CkHvPvqfojouredJ0w3e6+jiBq0SbFyhH61kr/zPb/7XsaYTNKQ54vmlSsopfdQbNDX40ZeK9Abs2Qet6wcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + resolution: {integrity: sha512-yrjmLj8ixPB25yqvPGr28meGjb+keed7m1GqqY/0uqkhZIoT4t9zmfwUgFEtC33C7dtE+UQ7TU0IaVxf97SWJg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.140.0': + resolution: {integrity: sha512-ggGMQTN8Agwxp2WiLMpdY671dt0qTDJWiWlJeig3HnUwTnerRl0J2JdGVghWBeDcss2D9S2V2Js6dZHEiVabVA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + resolution: {integrity: sha512-IgTs8xYAFgAUGNmR65tIqjlJ8vKgrfXzC515e9goSdfMyKQV4aJpd2pUUudU4u51G64H0/DSEJEXKOraxm9ZCA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + resolution: {integrity: sha512-A1x+PMWZmSGaFVOx2YeNTFau8uD+QO14/vLP4GrcuvUPs3+nBkUOjy9Lus86ftHsDojjYMbvBelmKc3F7Rv08g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + resolution: {integrity: sha512-zBqpfRo2myWPrPo5xUjeZqlnPXPXsX8BcWtWff66/eGRQdbPjhzPgXa/F+AtxT2afUViPxbuDlwscMKzQ5tg+g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + resolution: {integrity: sha512-2M1DPm/8w9I//YzFlFC9qXw+r2tJFh5CYwRlYTq2vUJQS7qoQftEDeCZ8EnN7KHtvSiXvYj8mZI5pR7DpXmcEw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.140.0': + resolution: {integrity: sha512-8aRDbZ/U/jO8N7go1MO72jtbpb4uswV8d7vOkMvt/BPgZiyEYvl1VIWK4ESxZZhnJ4tqwVldgX7dNiP/eB1Jdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.140.0': + resolution: {integrity: sha512-xRqpeI8U2sQQS1W5BMWRyMTxtagkuLG2dEWruet5lFsWHTvBth11/TpSaJatHdqVVwHN0q3uuoS9zRsGinq8hg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.140.0': + resolution: {integrity: sha512-GbGRe26MqAKciFRvXeHNQJ6VAHYs9R4miP89sEAncysM3n+f4lnyLWgsa9kklJNpfnxdq2yRoNYHFqwBckVimw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-wasm32-wasi@0.140.0': + resolution: {integrity: sha512-vFiC1hqys+hkX1GnQkIoiTQJNiUm43Z0lO35ETKXTw0YtpW7+cN58YRRXFAQQ+TgpkIi3lrhcxdlnqz+Oi3ptQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + resolution: {integrity: sha512-fGSQldwEYKhM+H8uLt76Op8hh5+FYaR6lvvQ1Txw3Mhn86DyQXLcI0fi1EkFlTK7F+46OCk/j0AJMzZQm6g5Xg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + resolution: {integrity: sha512-sDS2Bai+g3ZWYwfZqmosiSuFDBcVnZ3Ta6pszzsiJoLMqsJEWKcxXXbGa7b7yXr++W2lQNPb3ZRJ8czseqL7RA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.140.0': + resolution: {integrity: sha512-kHbE1zWyb5OQgJA6/5P4WjiuB01sYdQwtZnSSyE58FQEXDAMnyeeq4vj7KgN75i5SlBzOs8A5MrtlD3gOlDKqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.140.0': + resolution: {integrity: sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==} + + '@oxc-project/types@0.143.0': + resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} + + '@oxc-resolver/binding-android-arm-eabi@11.24.2': + resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} + cpu: [arm] + os: [android] + + '@oxc-resolver/binding-android-arm64@11.24.2': + resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==} + cpu: [arm64] + os: [android] + + '@oxc-resolver/binding-darwin-arm64@11.24.2': + resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==} + cpu: [arm64] + os: [darwin] + + '@oxc-resolver/binding-darwin-x64@11.24.2': + resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==} + cpu: [x64] + os: [darwin] + + '@oxc-resolver/binding-freebsd-x64@11.24.2': + resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==} + cpu: [x64] + os: [freebsd] + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==} + cpu: [arm] + os: [linux] + + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-resolver/binding-linux-x64-musl@11.24.2': + resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-resolver/binding-openharmony-arm64@11.24.2': + resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==} + cpu: [arm64] + os: [openharmony] + + '@oxc-resolver/binding-wasm32-wasi@11.24.2': + resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==} + cpu: [arm64] + os: [win32] + + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==} + cpu: [x64] + os: [win32] '@poppinss/colors@4.1.6': resolution: {integrity: sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==} @@ -636,97 +902,92 @@ packages: '@poppinss/exception@1.2.3': resolution: {integrity: sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==} - '@rolldown/binding-android-arm64@1.1.5': - resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + '@rolldown/binding-android-arm64@1.2.3': + resolution: {integrity: sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.5': - resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + '@rolldown/binding-darwin-arm64@1.2.3': + resolution: {integrity: sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==} 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==} + '@rolldown/binding-darwin-x64@1.2.3': + resolution: {integrity: sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==} 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==} + '@rolldown/binding-freebsd-x64@1.2.3': + resolution: {integrity: sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==} 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==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.3': + resolution: {integrity: sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==} 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==} + '@rolldown/binding-linux-arm64-gnu@1.2.3': + resolution: {integrity: sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==} 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==} + '@rolldown/binding-linux-arm64-musl@1.2.3': + resolution: {integrity: sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==} 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==} + '@rolldown/binding-linux-ppc64-gnu@1.2.3': + resolution: {integrity: sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==} 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==} + '@rolldown/binding-linux-s390x-gnu@1.2.3': + resolution: {integrity: sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==} 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==} + '@rolldown/binding-linux-x64-gnu@1.2.3': + resolution: {integrity: sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==} 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==} + '@rolldown/binding-linux-x64-musl@1.2.3': + resolution: {integrity: sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==} 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==} + '@rolldown/binding-openharmony-arm64@1.2.3': + resolution: {integrity: sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==} 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==} + '@rolldown/binding-win32-arm64-msvc@1.2.3': + resolution: {integrity: sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==} 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==} + '@rolldown/binding-win32-x64-msvc@1.2.3': + resolution: {integrity: sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -863,6 +1124,15 @@ packages: peerDependencies: vite: ^4 || ^5 || ^6 || ^7 || ^8 + '@vitest/coverage-v8@4.1.10': + resolution: {integrity: sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==} + peerDependencies: + '@vitest/browser': 4.1.10 + vitest: 4.1.10 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/expect@4.1.10': resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} @@ -904,6 +1174,9 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-v8-to-istanbul@1.0.5: + resolution: {integrity: sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==} + balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} @@ -1167,6 +1440,9 @@ packages: fast-wrap-ansi@0.2.2: resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + fd-package-json@2.0.0: + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -1176,6 +1452,11 @@ packages: picomatch: optional: true + formatly@0.3.0: + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} + hasBin: true + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1185,6 +1466,9 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-tsconfig@4.14.0: + resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} + glob@13.0.6: resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} engines: {node: 18 || 20 || >=22} @@ -1197,6 +1481,9 @@ packages: resolution: {integrity: sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg==} engines: {node: '>=16.9.0'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + idb@8.0.3: resolution: {integrity: sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==} @@ -1207,9 +1494,66 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + jose@6.2.4: resolution: {integrity: sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + + jscpd-darwin-arm64@5.0.14: + resolution: {integrity: sha512-Ojjl79SBuj9tEW6WbjZ1a/1ZOR89dneH9yLQYQu8WyWaQownttnx7RYFEHU6aGhS4jIvwUEbr+1wxzFTb37cwg==} + cpu: [arm64] + os: [darwin] + + jscpd-darwin-x64@5.0.14: + resolution: {integrity: sha512-DxFg5XvjMZ81iVeqillnM5apqcGCfNTbroNF+mPLr7RkHLGH6mudLgtO+ILL/hfpZXy1bF9oIY5BSudPmN/k9A==} + cpu: [x64] + os: [darwin] + + jscpd-linux-arm64-gnu@5.0.14: + resolution: {integrity: sha512-1uw+XBHEt9pONXNICSp5HpaVWPjG6mQ6deDXaq9Yb0xCNJkX4/8gmn0vhzekIyZD2DspRYKPUolbDsqm/HEdYg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + jscpd-linux-x64-gnu@5.0.14: + resolution: {integrity: sha512-dFTbyyrm+Z9pcXIVzJQCw8QAgiNqIiO69sm4AfA7/wFdPoizoVzjhaXsYXcSV4bs0aoPiWbNazg0J0HgslT/5A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + jscpd-linux-x64-musl@5.0.14: + resolution: {integrity: sha512-SayS7qQJvixyy9eR0+UjepkTsUUwqvlsiuSxfIdHgG2qzqoh/thnkgiu4By8fsiiDpQONsQrRrZDwHRQ3GDrBQ==} + cpu: [x64] + os: [linux] + libc: [musl] + + jscpd-windows-x64-msvc@5.0.14: + resolution: {integrity: sha512-DqjxlVkUanlahGgY2lY7Zkrau4BUTI+AwWky+bPGK4kSK2AIOaUziY9Q19u8b58idXmJA9FKK98Fuu4ajNXVjQ==} + cpu: [x64] + os: [win32] + + jscpd@5.0.14: + resolution: {integrity: sha512-zge+FPZZAymt2Do5Z0+QHyIn4/XcUhrO/W7of9HcHZfx2AK8++dYhLA1uWtwXj47ml3Of8PbcUW4wUWvYMCc3w==} + engines: {node: '>=18'} + hasBin: true + jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} @@ -1217,6 +1561,11 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + knip@6.29.0: + resolution: {integrity: sha512-A3kXqSBky1tWBAqiU9srdtu0Larhzkuyor0aD/gg+ToiqyBncCCs2Q60sLsxmcKhV0OsKss9LV0hMPpwLv711Q==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + kysely@0.29.4: resolution: {integrity: sha512-y5mVgQNkMbs1eK9Xyc0pmNdabN2wHhRYY/5r4W5HrUT1rYCEPeVNSj1RUJeSDKT3U0p+mXCvLgkrFuIafYI6BA==} engines: {node: '>=22.0.0'} @@ -1307,10 +1656,16 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - miniflare@4.20260722.0: - resolution: {integrity: sha512-LW6ABMhCx/yIEFBLC/DO4yAhdm2T/G7jp7pr5T2kj895+CCIaHZqpMXdW9O6YE48LcYcCJChwWc8aEs1vpbTXw==} + magicast@0.5.4: + resolution: {integrity: sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + miniflare@5.20260804.1-alpha: + resolution: {integrity: sha512-J0QBHEj+d75TyFE9VhH+2dXgvdYt/pfyDlm+9IiYUFocQvqYy9iuW1DIqNawh1N7Kr6iMrDzVkgDSdt6pA75uA==} engines: {node: '>=22.0.0'} - hasBin: true minimatch@10.2.6: resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} @@ -1320,8 +1675,8 @@ packages: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -1338,6 +1693,13 @@ packages: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} + oxc-parser@0.140.0: + resolution: {integrity: sha512-h6QFWd6lBMfjESqgQ27GjzrSDb0qbznp7VDQqp2zvgsrWut4vcchyMIzOVXvGQ2GMZgKw9RWrFNWv9WqGL0p7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-resolver@11.24.2: + resolution: {integrity: sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1359,8 +1721,8 @@ packages: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} - postcss@8.5.23: - resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + postcss@8.5.26: + resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} engines: {node: ^10 || ^12 || >=14} react-dom@19.2.8: @@ -1376,8 +1738,11 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - rolldown@1.1.5: - resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + rolldown@1.2.3: + resolution: {integrity: sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1420,6 +1785,10 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + smol-toml@1.8.0: + resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} + engines: {node: '>= 18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -1438,6 +1807,10 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + supports-color@10.2.2: resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} engines: {node: '>=18'} @@ -1489,20 +1862,24 @@ packages: oxlint: optional: true - undici@7.28.0: - resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + unbash@4.0.10: + resolution: {integrity: sha512-b7zoBQvpWp0vuN5q2vK2RRBR2SvuruQAs50DApdDveBSn3eSYd84IaHodFqQIMlvY9K2VnyBUEXgwOBuGU9GBg==} + engines: {node: '>=14'} + + undici@7.29.0: + resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} unenv@2.0.0-rc.24: resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} - vite@8.1.5: - resolution: {integrity: sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==} + vite@8.2.1: + resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@types/node': ^20.19.0 || >=22.12.0 - '@vitejs/devtools': ^0.3.0 + '@vitejs/devtools': ^0.4.0 esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' less: ^4.0.0 @@ -1580,6 +1957,10 @@ packages: jsdom: optional: true + walk-up-path@4.0.0: + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1590,17 +1971,17 @@ packages: engines: {node: '>=8'} hasBin: true - workerd@1.20260722.1: - resolution: {integrity: sha512-NycKuc1x2onvsRfGGpM093vRlLFU2zHDAM0+APpccfg4+gZxDGCH27RmdDvkeBuoZyYqgLo3oAfF6re4mvC3vQ==} + workerd@1.20260804.1: + resolution: {integrity: sha512-b0P38g5/ssemwWxd/mafNYggEZ0ere7PCiUH6RCHkgqjRhhXTP45nDiL2L3iIvi8uF2IjNrGpVgMXEunCaeY/w==} engines: {node: '>=16'} hasBin: true - wrangler@4.114.0: - resolution: {integrity: sha512-M65P25t5UHA1TIJfgZXDcj+YzVobgKdRguM2QPz0xnxLFuOcuE3ErgllDht0iaho7MS4o0g/Bb4YK2+GT+bibg==} + wrangler@4.121.0: + resolution: {integrity: sha512-dcARWk6CyaD0vJBSLjJn4K2yo+mYko73hzryq+t/9DXnyAq877RWIMl7uOMcDKs5dDXdoickNhZTKxBYT9XKsA==} engines: {node: '>=22.0.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^5.20260722.1 + '@cloudflare/workers-types': ^5.20260804.1 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -1649,7 +2030,22 @@ packages: snapshots: - '@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1)': + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@bcoe/v8-coverage@1.0.2': {} + + '@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1)': dependencies: '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 @@ -1661,40 +2057,40 @@ snapshots: nanostores: 1.4.1 zod: 4.4.3 optionalDependencies: - '@cloudflare/workers-types': 5.20260727.1 + '@cloudflare/workers-types': 5.20260812.1 - '@better-auth/drizzle-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4))': + '@better-auth/drizzle-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4))': dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) '@better-auth/utils': 0.4.2 optionalDependencies: - drizzle-orm: 0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4) + drizzle-orm: 0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4) - '@better-auth/kysely-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(kysely@0.29.4)': + '@better-auth/kysely-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(kysely@0.29.4)': dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) '@better-auth/utils': 0.4.2 optionalDependencies: kysely: 0.29.4 - '@better-auth/memory-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)': + '@better-auth/memory-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)': dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) '@better-auth/utils': 0.4.2 - '@better-auth/mongo-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)': + '@better-auth/mongo-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)': dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) '@better-auth/utils': 0.4.2 - '@better-auth/prisma-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)': + '@better-auth/prisma-adapter@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)': dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) '@better-auth/utils': 0.4.2 - '@better-auth/telemetry@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': + '@better-auth/telemetry@1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 @@ -1753,40 +2149,40 @@ snapshots: '@cloudflare/kv-asset-handler@0.5.0': {} - '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260722.1)': + '@cloudflare/unenv-preset@2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260804.1)': dependencies: unenv: 2.0.0-rc.24 optionalDependencies: - workerd: 1.20260722.1 + workerd: 1.20260804.1 - '@cloudflare/workerd-darwin-64@1.20260722.1': + '@cloudflare/workerd-darwin-64@1.20260804.1': optional: true - '@cloudflare/workerd-darwin-arm64@1.20260722.1': + '@cloudflare/workerd-darwin-arm64@1.20260804.1': optional: true - '@cloudflare/workerd-linux-64@1.20260722.1': + '@cloudflare/workerd-linux-64@1.20260804.1': optional: true - '@cloudflare/workerd-linux-arm64@1.20260722.1': + '@cloudflare/workerd-linux-arm64@1.20260804.1': optional: true - '@cloudflare/workerd-windows-64@1.20260722.1': + '@cloudflare/workerd-windows-64@1.20260804.1': optional: true - '@cloudflare/workers-types@5.20260727.1': {} + '@cloudflare/workers-types@5.20260812.1': {} '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@emnapi/core@1.11.1': + '@emnapi/core@1.11.2': dependencies: '@emnapi/wasi-threads': 1.2.2 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.1': + '@emnapi/runtime@1.11.2': dependencies: tslib: 2.8.1 optional: true @@ -1989,15 +2385,20 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 '@tybys/wasm-util': 0.10.3 optional: true @@ -2007,7 +2408,134 @@ snapshots: '@opentelemetry/semantic-conventions@1.43.0': {} - '@oxc-project/types@0.139.0': {} + '@oxc-parser/binding-android-arm-eabi@0.140.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.140.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.140.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.140.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.140.0': + optional: true + + '@oxc-parser/binding-wasm32-wasi@0.140.0': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.140.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.140.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.140.0': + optional: true + + '@oxc-project/types@0.140.0': {} + + '@oxc-project/types@0.143.0': {} + + '@oxc-resolver/binding-android-arm-eabi@11.24.2': + optional: true + + '@oxc-resolver/binding-android-arm64@11.24.2': + optional: true + + '@oxc-resolver/binding-darwin-arm64@11.24.2': + optional: true + + '@oxc-resolver/binding-darwin-x64@11.24.2': + optional: true + + '@oxc-resolver/binding-freebsd-x64@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + optional: true + + '@oxc-resolver/binding-linux-x64-musl@11.24.2': + optional: true + + '@oxc-resolver/binding-openharmony-arm64@11.24.2': + optional: true + + '@oxc-resolver/binding-wasm32-wasi@11.24.2': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + + '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + optional: true + + '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + optional: true '@poppinss/colors@4.1.6': dependencies: @@ -2021,53 +2549,46 @@ snapshots: '@poppinss/exception@1.2.3': {} - '@rolldown/binding-android-arm64@1.1.5': - optional: true - - '@rolldown/binding-darwin-arm64@1.1.5': + '@rolldown/binding-android-arm64@1.2.3': optional: true - '@rolldown/binding-darwin-x64@1.1.5': + '@rolldown/binding-darwin-arm64@1.2.3': optional: true - '@rolldown/binding-freebsd-x64@1.1.5': + '@rolldown/binding-darwin-x64@1.2.3': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + '@rolldown/binding-freebsd-x64@1.2.3': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.5': + '@rolldown/binding-linux-arm-gnueabihf@1.2.3': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.5': + '@rolldown/binding-linux-arm64-gnu@1.2.3': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.5': + '@rolldown/binding-linux-arm64-musl@1.2.3': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.5': + '@rolldown/binding-linux-ppc64-gnu@1.2.3': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.5': + '@rolldown/binding-linux-s390x-gnu@1.2.3': optional: true - '@rolldown/binding-linux-x64-musl@1.1.5': + '@rolldown/binding-linux-x64-gnu@1.2.3': optional: true - '@rolldown/binding-openharmony-arm64@1.1.5': + '@rolldown/binding-linux-x64-musl@1.2.3': 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) + '@rolldown/binding-openharmony-arm64@1.2.3': optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.5': + '@rolldown/binding-win32-arm64-msvc@1.2.3': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.5': + '@rolldown/binding-win32-x64-msvc@1.2.3': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -2160,14 +2681,28 @@ snapshots: dependencies: csstype: 3.2.3 - '@vitejs/plugin-react-swc@4.3.2(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0))': + '@vitejs/plugin-react-swc@4.3.2(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@rolldown/pluginutils': 1.0.1 '@swc/core': 1.15.46 - vite: 8.1.5(esbuild@0.28.1)(yaml@2.9.0) + vite: 8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) transitivePeerDependencies: - '@swc/helpers' + '@vitest/coverage-v8@4.1.10(vitest@4.1.10)': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.10 + ast-v8-to-istanbul: 1.0.5 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.2.0 + magicast: 0.5.4 + obug: 2.1.4 + std-env: 4.2.0 + tinyrainbow: 3.1.0 + vitest: 4.1.10(@vitest/coverage-v8@4.1.10)(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) + '@vitest/expect@4.1.10': dependencies: '@standard-schema/spec': 1.1.0 @@ -2177,13 +2712,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0))': + '@vitest/mocker@4.1.10(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(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(esbuild@0.28.1)(yaml@2.9.0) + vite: 8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -2217,17 +2752,23 @@ snapshots: assertion-error@2.0.1: {} + ast-v8-to-istanbul@1.0.5: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + balanced-match@4.0.4: {} - better-auth@1.6.25(@cloudflare/workers-types@5.20260727.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0))): + better-auth@1.6.25(@cloudflare/workers-types@5.20260812.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@4.1.10): dependencies: - '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) - '@better-auth/drizzle-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4)) - '@better-auth/kysely-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(kysely@0.29.4) - '@better-auth/memory-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2) - '@better-auth/mongo-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2) - '@better-auth/prisma-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2) - '@better-auth/telemetry': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260727.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) + '@better-auth/core': 1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1) + '@better-auth/drizzle-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4)) + '@better-auth/kysely-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(kysely@0.29.4) + '@better-auth/memory-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2) + '@better-auth/mongo-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2) + '@better-auth/prisma-adapter': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2) + '@better-auth/telemetry': 1.6.25(@better-auth/core@1.6.25(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@cloudflare/workers-types@5.20260812.1)(better-call@1.3.7(zod@4.4.3))(jose@6.2.4)(kysely@0.29.4)(nanostores@1.4.1))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 '@noble/ciphers': 2.2.0 @@ -2239,10 +2780,10 @@ snapshots: nanostores: 1.4.1 zod: 4.4.3 optionalDependencies: - drizzle-orm: 0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4) + drizzle-orm: 0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4) react: 19.2.8 react-dom: 19.2.8(react@19.2.8) - vitest: 4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0)) + vitest: 4.1.10(@vitest/coverage-v8@4.1.10)(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) transitivePeerDependencies: - '@cloudflare/workers-types' - '@opentelemetry/api' @@ -2312,9 +2853,9 @@ snapshots: detect-libc@2.1.2: {} - drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260727.1)(kysely@0.29.4): + drizzle-orm@0.45.2(@cloudflare/workers-types@5.20260812.1)(kysely@0.29.4): optionalDependencies: - '@cloudflare/workers-types': 5.20260727.1 + '@cloudflare/workers-types': 5.20260812.1 kysely: 0.29.4 emoji-regex@8.0.0: {} @@ -2370,15 +2911,27 @@ snapshots: dependencies: fast-string-width: 3.0.2 + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + fdir@6.5.0(picomatch@4.0.5): optionalDependencies: picomatch: 4.0.5 + formatly@0.3.0: + dependencies: + fd-package-json: 2.0.0 + fsevents@2.3.3: optional: true get-caller-file@2.0.5: {} + get-tsconfig@4.14.0: + dependencies: + resolve-pkg-maps: 1.0.0 + glob@13.0.6: dependencies: minimatch: 10.2.6 @@ -2389,18 +2942,80 @@ snapshots: hono@4.12.32: {} + html-escaper@2.0.2: {} + idb@8.0.3: {} is-fullwidth-code-point@3.0.0: {} isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jiti@2.7.0: {} + jose@6.2.4: {} + js-tokens@10.0.0: {} + + jscpd-darwin-arm64@5.0.14: + optional: true + + jscpd-darwin-x64@5.0.14: + optional: true + + jscpd-linux-arm64-gnu@5.0.14: + optional: true + + jscpd-linux-x64-gnu@5.0.14: + optional: true + + jscpd-linux-x64-musl@5.0.14: + optional: true + + jscpd-windows-x64-msvc@5.0.14: + optional: true + + jscpd@5.0.14: + optionalDependencies: + jscpd-darwin-arm64: 5.0.14 + jscpd-darwin-x64: 5.0.14 + jscpd-linux-arm64-gnu: 5.0.14 + jscpd-linux-x64-gnu: 5.0.14 + jscpd-linux-x64-musl: 5.0.14 + jscpd-windows-x64-msvc: 5.0.14 + jsonc-parser@3.3.1: {} kleur@4.1.5: {} + knip@6.29.0: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + formatly: 0.3.0 + get-tsconfig: 4.14.0 + jiti: 2.7.0 + oxc-parser: 0.140.0 + oxc-resolver: 11.24.2 + picomatch: 4.0.5 + smol-toml: 1.8.0 + strip-json-comments: 5.0.3 + tinyglobby: 0.2.17 + unbash: 4.0.10 + yaml: 2.9.0 + zod: 4.4.3 + kysely@0.29.4: {} lightningcss-android-arm64@1.33.0: @@ -2462,12 +3077,22 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - miniflare@4.20260722.0: + magicast@0.5.4: + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.8.5 + + miniflare@5.20260804.1-alpha: dependencies: '@cspotcode/source-map-support': 0.8.1 sharp: 0.35.2 - undici: 7.28.0 - workerd: 1.20260722.1 + undici: 7.29.0 + workerd: 1.20260804.1 ws: 8.21.0 youch: 4.1.0-beta.10 transitivePeerDependencies: @@ -2480,7 +3105,7 @@ snapshots: minipass@7.1.3: {} - nanoid@3.3.16: {} + nanoid@3.3.18: {} nanostores@1.4.1: {} @@ -2492,6 +3117,53 @@ snapshots: obug@2.1.4: {} + oxc-parser@0.140.0: + dependencies: + '@oxc-project/types': 0.140.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.140.0 + '@oxc-parser/binding-android-arm64': 0.140.0 + '@oxc-parser/binding-darwin-arm64': 0.140.0 + '@oxc-parser/binding-darwin-x64': 0.140.0 + '@oxc-parser/binding-freebsd-x64': 0.140.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.140.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.140.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.140.0 + '@oxc-parser/binding-linux-arm64-musl': 0.140.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.140.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.140.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.140.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.140.0 + '@oxc-parser/binding-linux-x64-gnu': 0.140.0 + '@oxc-parser/binding-linux-x64-musl': 0.140.0 + '@oxc-parser/binding-openharmony-arm64': 0.140.0 + '@oxc-parser/binding-wasm32-wasi': 0.140.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.140.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.140.0 + '@oxc-parser/binding-win32-x64-msvc': 0.140.0 + + oxc-resolver@11.24.2: + optionalDependencies: + '@oxc-resolver/binding-android-arm-eabi': 11.24.2 + '@oxc-resolver/binding-android-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-arm64': 11.24.2 + '@oxc-resolver/binding-darwin-x64': 11.24.2 + '@oxc-resolver/binding-freebsd-x64': 11.24.2 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.24.2 + '@oxc-resolver/binding-linux-arm64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-arm64-musl': 11.24.2 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-riscv64-musl': 11.24.2 + '@oxc-resolver/binding-linux-s390x-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-gnu': 11.24.2 + '@oxc-resolver/binding-linux-x64-musl': 11.24.2 + '@oxc-resolver/binding-openharmony-arm64': 11.24.2 + '@oxc-resolver/binding-wasm32-wasi': 11.24.2 + '@oxc-resolver/binding-win32-arm64-msvc': 11.24.2 + '@oxc-resolver/binding-win32-x64-msvc': 11.24.2 + path-key@3.1.1: {} path-scurry@2.0.2: @@ -2507,9 +3179,9 @@ snapshots: picomatch@4.0.5: {} - postcss@8.5.23: + postcss@8.5.26: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.18 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -2522,26 +3194,27 @@ snapshots: require-directory@2.1.1: {} - rolldown@1.1.5: + resolve-pkg-maps@1.0.0: {} + + rolldown@1.2.3: dependencies: - '@oxc-project/types': 0.139.0 + '@oxc-project/types': 0.143.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 + '@rolldown/binding-android-arm64': 1.2.3 + '@rolldown/binding-darwin-arm64': 1.2.3 + '@rolldown/binding-darwin-x64': 1.2.3 + '@rolldown/binding-freebsd-x64': 1.2.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.3 + '@rolldown/binding-linux-arm64-gnu': 1.2.3 + '@rolldown/binding-linux-arm64-musl': 1.2.3 + '@rolldown/binding-linux-ppc64-gnu': 1.2.3 + '@rolldown/binding-linux-s390x-gnu': 1.2.3 + '@rolldown/binding-linux-x64-gnu': 1.2.3 + '@rolldown/binding-linux-x64-musl': 1.2.3 + '@rolldown/binding-openharmony-arm64': 1.2.3 + '@rolldown/binding-win32-arm64-msvc': 1.2.3 + '@rolldown/binding-win32-x64-msvc': 1.2.3 rou3@0.7.12: {} @@ -2599,6 +3272,8 @@ snapshots: sisteransi@1.0.5: {} + smol-toml@1.8.0: {} + source-map-js@1.2.1: {} stackback@0.0.2: {} @@ -2615,6 +3290,8 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-json-comments@5.0.3: {} + supports-color@10.2.2: {} supports-color@7.2.0: @@ -2654,28 +3331,31 @@ snapshots: yaml: 2.9.0 zod: 4.4.3 - undici@7.28.0: {} + unbash@4.0.10: {} + + undici@7.29.0: {} unenv@2.0.0-rc.24: dependencies: pathe: 2.0.3 - vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0): + vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 - postcss: 8.5.23 - rolldown: 1.1.5 + postcss: 8.5.26 + rolldown: 1.2.3 tinyglobby: 0.2.17 optionalDependencies: esbuild: 0.28.1 fsevents: 2.3.3 + jiti: 2.7.0 yaml: 2.9.0 - vitest@4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0)): + vitest@4.1.10(@vitest/coverage-v8@4.1.10)(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.1.5(esbuild@0.28.1)(yaml@2.9.0)) + '@vitest/mocker': 4.1.10(vite@8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -2692,11 +3372,15 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.1.5(esbuild@0.28.1)(yaml@2.9.0) + vite: 8.2.1(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 + optionalDependencies: + '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) transitivePeerDependencies: - msw + walk-up-path@4.0.0: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -2706,26 +3390,26 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - workerd@1.20260722.1: + workerd@1.20260804.1: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20260722.1 - '@cloudflare/workerd-darwin-arm64': 1.20260722.1 - '@cloudflare/workerd-linux-64': 1.20260722.1 - '@cloudflare/workerd-linux-arm64': 1.20260722.1 - '@cloudflare/workerd-windows-64': 1.20260722.1 + '@cloudflare/workerd-darwin-64': 1.20260804.1 + '@cloudflare/workerd-darwin-arm64': 1.20260804.1 + '@cloudflare/workerd-linux-64': 1.20260804.1 + '@cloudflare/workerd-linux-arm64': 1.20260804.1 + '@cloudflare/workerd-windows-64': 1.20260804.1 - wrangler@4.114.0(@cloudflare/workers-types@5.20260727.1): + wrangler@4.121.0(@cloudflare/workers-types@5.20260812.1): dependencies: '@cloudflare/kv-asset-handler': 0.5.0 - '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260722.1) + '@cloudflare/unenv-preset': 2.16.1(unenv@2.0.0-rc.24)(workerd@1.20260804.1) blake3-wasm: 2.1.5 esbuild: 0.28.1 - miniflare: 4.20260722.0 + miniflare: 5.20260804.1-alpha path-to-regexp: 6.3.0 unenv: 2.0.0-rc.24 - workerd: 1.20260722.1 + workerd: 1.20260804.1 optionalDependencies: - '@cloudflare/workers-types': 5.20260727.1 + '@cloudflare/workers-types': 5.20260812.1 fsevents: 2.3.3 transitivePeerDependencies: - bufferutil diff --git a/scripts/check-code-health.mjs b/scripts/check-code-health.mjs new file mode 100644 index 0000000..f742088 --- /dev/null +++ b/scripts/check-code-health.mjs @@ -0,0 +1,275 @@ +#!/usr/bin/env node + +import { spawnSync } from 'node:child_process'; +import { mkdtempSync, readFileSync, readdirSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, extname, join, resolve } from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +const currentFile = fileURLToPath(import.meta.url); +const projectRoot = resolve(dirname(currentFile), '..'); +const productionPaths = [ + 'src', + 'ios/Sources', + 'public/sw.js', + 'vite.config.ts', + 'vitest.config.ts', +]; +const sourceExtensions = new Set(['.js', '.jsx', '.mjs', '.mts', '.swift', '.ts', '.tsx']); +const baselines = { + complexity: { violations: 32, maxCcn: 98, maxLength: 616, maxParams: 19 }, + duplication: { clones: 18, duplicatedLines: 234 }, + unused: { + files: 0, + exports: 0, + types: 0, + dependencies: 0, + devDependencies: 0, + unlisted: 0, + unresolved: 0, + }, + suppressions: 1, +}; + +function run(command, args, options = {}) { + const result = spawnSync(command, args, { + cwd: projectRoot, + encoding: 'utf8', + env: { ...process.env, ...(options.env ?? {}) }, + maxBuffer: 64 * 1024 * 1024, + }); + if (result.error) throw result.error; + if (result.status !== 0 && !options.allowFailure) { + process.stdout.write(result.stdout ?? ''); + process.stderr.write(result.stderr ?? ''); + throw new Error(`${command} exited with status ${result.status}`); + } + return { status: result.status ?? 1, stdout: result.stdout ?? '', stderr: result.stderr ?? '' }; +} + +function parseJson(result, label) { + try { + return JSON.parse(result.stdout); + } catch (error) { + process.stderr.write(result.stderr); + throw new Error(`${label} did not return valid JSON`, { cause: error }); + } +} + +function commandWithUvx(command, uvxArgs) { + const probe = spawnSync(command, ['--version'], { encoding: 'utf8' }); + return probe.status === 0 ? { command, prefix: [] } : { command: 'uvx', prefix: uvxArgs }; +} + +function issueCount(issues, key) { + return issues.reduce((sum, issue) => sum + (issue[key]?.length ?? 0), 0); +} + +function failRegressions(label, observed, baseline) { + const regressions = Object.entries(baseline).filter(([key, maximum]) => observed[key] > maximum); + if (regressions.length > 0) { + throw new Error( + regressions + .map(([key, maximum]) => `${label} ${key} regressed: ${observed[key]} > ${maximum}`) + .join('\n') + ); + } + if (Object.entries(baseline).some(([key, maximum]) => observed[key] < maximum)) { + console.log(`${label} improved; lower the checked-in baseline intentionally.`); + } +} + +function checkUnused() { + const report = parseJson( + run('pnpm', ['exec', 'knip', '--reporter', 'json', '--no-exit-code', '--no-progress'], { + allowFailure: true, + }), + 'Knip' + ); + const issues = report.issues ?? []; + const observed = Object.fromEntries( + Object.keys(baselines.unused).map((key) => [key, issueCount(issues, key)]) + ); + console.log( + `Unused: files=${observed.files}, exports=${observed.exports}, types=${observed.types}, ` + + `dependencies=${observed.dependencies}, devDependencies=${observed.devDependencies}, ` + + `unlisted=${observed.unlisted}, unresolved=${observed.unresolved}.` + ); + failRegressions('Unused', observed, baselines.unused); +} + +function checkComplexity() { + const lizard = commandWithUvx('lizard', ['--from', 'lizard==1.23.0', 'lizard']); + const result = run(lizard.command, [ + ...lizard.prefix, + ...productionPaths, + '-x', + '**/*.test.*', + '-x', + 'src/agent-edge.mjs', + '--csv', + ]); + const rows = result.stdout + .trim() + .split('\n') + .map((line) => line.match(/^(\d+),(\d+),(\d+),(\d+),(\d+),/u)) + .filter(Boolean) + .map((match) => match.slice(1).map(Number)); + const observed = { + functions: rows.length, + nloc: rows.reduce((sum, row) => sum + row[0], 0), + violations: rows.filter((row) => row[1] > 15 || row[4] > 100 || row[3] > 7).length, + maxCcn: Math.max(...rows.map((row) => row[1])), + maxLength: Math.max(...rows.map((row) => row[4])), + maxParams: Math.max(...rows.map((row) => row[3])), + }; + console.log( + `Complexity: ${observed.functions} functions, ${observed.nloc} NLOC, ` + + `${observed.violations} violations; max CCN ${observed.maxCcn}, ` + + `max length ${observed.maxLength}, max params ${observed.maxParams}.` + ); + failRegressions('Complexity', observed, baselines.complexity); +} + +function checkDuplication() { + const outputDirectory = mkdtempSync(join(tmpdir(), 'calorie-jscpd-')); + run('pnpm', [ + 'exec', + 'jscpd', + ...productionPaths, + '--min-lines', + '8', + '--min-tokens', + '60', + '--mode', + 'strict', + '--ignore', + '**/*.test.*,src/agent-edge.mjs,**/*.d.ts,**/*.d.mts,**/node_modules/**,**/dist/**,**/coverage/**', + '--reporters', + 'json', + '--output', + outputDirectory, + '--silent', + '--no-tips', + ]); + const observed = JSON.parse(readFileSync(join(outputDirectory, 'jscpd-report.json'), 'utf8')) + .statistics.total; + console.log( + `Duplication: ${observed.clones} groups, ${observed.duplicatedLines}/${observed.lines} lines ` + + `(${observed.percentage.toFixed(4)}%) across ${observed.sources} web/native files.` + ); + failRegressions('Duplication', observed, baselines.duplication); +} + +function checkCycles() { + const report = parseJson( + run( + 'pnpm', + ['exec', 'knip', '--cycles', '--reporter', 'json', '--no-exit-code', '--no-progress'], + { allowFailure: true } + ), + 'Knip cycle analysis' + ); + const cycles = (report.issues ?? []).flatMap((issue) => issue.cycles ?? []); + if (cycles.length > 0) throw new Error(`TypeScript dependency cycles detected: ${cycles.length}`); + console.log('Cycles: zero TypeScript import cycles; native CI resolves the Swift target graph.'); +} + +function checkDependencies() { + const report = parseJson(run('pnpm', ['audit', '--json'], { allowFailure: true }), 'pnpm audit'); + const severe = Object.values(report.advisories ?? {}).filter((advisory) => + ['critical', 'high'].includes(advisory.severity) + ); + const critical = severe.filter((advisory) => advisory.severity === 'critical').length; + const high = severe.filter((advisory) => advisory.severity === 'high').length; + console.log(`Dependencies: ${critical} critical, ${high} high advisories.`); + if (severe.length > 0) { + throw new Error( + `Critical/high advisories detected: ${severe + .map((advisory) => advisory.github_advisory_id) + .join(', ')}` + ); + } +} + +const suppressionPattern = + /swiftlint:disable|swiftformat:disable|biome-ignore|eslint-disable|@ts-ignore|@ts-expect-error|istanbul ignore|c8 ignore|(?:test|base)\.skip\(|\bTODO\b|\bFIXME\b/u; + +function sourceFiles(root) { + const files = []; + for (const entry of readdirSync(root, { withFileTypes: true })) { + const path = join(root, entry.name); + if (entry.isDirectory()) files.push(...sourceFiles(path)); + else if (entry.isFile() && sourceExtensions.has(extname(entry.name))) files.push(path); + } + return files; +} + +function checkSuppressions() { + const files = ['src', 'ios/Sources', 'ios/Tests', 'public'].flatMap((root) => + sourceFiles(resolve(projectRoot, root)) + ); + const matches = files + .filter((file) => file !== currentFile && !file.endsWith('/src/agent-edge.mjs')) + .flatMap((file) => + readFileSync(file, 'utf8') + .split('\n') + .filter((line) => suppressionPattern.test(line)) + ); + console.log(`Suppressions: ${matches.length} justified web/native source or test markers.`); + if (matches.length > baselines.suppressions) { + throw new Error(`Suppressions regressed: ${matches.length} > ${baselines.suppressions}.`); + } + if (matches.length < baselines.suppressions) { + console.log('Suppressions improved; lower the checked-in baseline intentionally.'); + } +} + +function checkHygiene() { + const parent = run('git', ['rev-parse', '--verify', 'HEAD^'], { allowFailure: true }); + if (parent.status === 0) run('git', ['diff', '--check', 'HEAD^', 'HEAD']); + else run('git', ['diff-tree', '--check', '--root', '-r', 'HEAD']); + run('git', ['diff', '--check', 'HEAD', '--', '.']); + const conflicts = run('git', ['grep', '-nE', '^(<<<<<<< |=======$|>>>>>>> )', '--', '.'], { + allowFailure: true, + }); + if (conflicts.status === 0) throw new Error(`Conflict markers found:\n${conflicts.stdout}`); + if (conflicts.status > 1) throw new Error(`git grep failed with status ${conflicts.status}`); + const generated = run('git', ['ls-files', '--others', '--exclude-standard']) + .stdout.trim() + .split('\n') + .filter(Boolean) + .filter((file) => + /(^|\/)(?:coverage|dist|build|\.next|\.open-next|\.wrangler)(?:\/|$)|(?:^|\/)\.DS_Store$|\.tsbuildinfo$/u.test( + file + ) + ); + if (generated.length > 0) { + throw new Error(`Untracked generated artifacts found: ${generated.join(', ')}`); + } + console.log('Repository hygiene: whitespace, conflicts, and generated outputs pass.'); +} + +const checks = { + unused: checkUnused, + complexity: checkComplexity, + duplication: checkDuplication, + cycles: checkCycles, + dependencies: checkDependencies, + suppressions: checkSuppressions, + hygiene: checkHygiene, +}; +const selected = process.argv[2]; + +if (!Object.hasOwn(checks, selected)) { + console.error(`Usage: check-code-health.mjs <${Object.keys(checks).join('|')}>`); + process.exit(2); +} + +try { + checks[selected](); +} catch (error) { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); +} diff --git a/scripts/check-native-code-health.mjs b/scripts/check-native-code-health.mjs new file mode 100644 index 0000000..e024e8d --- /dev/null +++ b/scripts/check-native-code-health.mjs @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +import { spawnSync } from 'node:child_process'; +import { readdirSync, statSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join, resolve } from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +const projectRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const minimumProductionCoverage = 0.543; + +function capture(command, args) { + const result = spawnSync(command, args, { + cwd: projectRoot, + encoding: 'utf8', + maxBuffer: 64 * 1024 * 1024, + }); + if (result.error) throw result.error; + if (result.status !== 0) { + process.stdout.write(result.stdout ?? ''); + process.stderr.write(result.stderr ?? ''); + throw new Error(`${command} exited with status ${result.status}`); + } + return result.stdout ?? ''; +} + +function simulatorDestination() { + if (process.env.CALORIE_SIMULATOR_DESTINATION) { + return process.env.CALORIE_SIMULATOR_DESTINATION; + } + const report = JSON.parse(capture('xcrun', ['simctl', 'list', 'devices', 'available', '-j'])); + const candidates = Object.entries(report.devices) + .filter(([runtime]) => runtime.includes('iOS')) + .flatMap(([runtime, devices]) => + devices + .filter((device) => device.isAvailable && device.name.startsWith('iPhone')) + .map((device) => ({ ...device, runtime })) + ) + .sort((left, right) => { + if (left.state === 'Booted' && right.state !== 'Booted') return -1; + if (right.state === 'Booted' && left.state !== 'Booted') return 1; + return right.runtime.localeCompare(left.runtime, undefined, { numeric: true }); + }); + if (candidates.length === 0) throw new Error('No available iPhone simulator was found.'); + return `platform=iOS Simulator,id=${candidates[0].udid}`; +} + +function latestResultBundle(derivedData) { + const logDirectory = join(derivedData, 'Logs', 'Test'); + const bundles = readdirSync(logDirectory) + .filter((name) => name.endsWith('.xcresult')) + .map((name) => ({ + path: join(logDirectory, name), + modified: statSync(join(logDirectory, name)).mtimeMs, + })) + .sort((left, right) => right.modified - left.modified); + if (bundles.length === 0) throw new Error(`No xcresult bundle found under ${logDirectory}.`); + return bundles[0].path; +} + +function productionCoverage(resultBundle) { + const report = JSON.parse( + capture('xcrun', ['xccov', 'view', '--report', '--json', resultBundle]) + ); + const productionTargets = report.targets.filter((target) => + ['Calorie.app', 'CalorieCore.framework'].includes(target.name) + ); + if (productionTargets.length !== 2) { + throw new Error('The native coverage report did not contain both production targets.'); + } + const coveredLines = productionTargets.reduce((sum, target) => sum + target.coveredLines, 0); + const executableLines = productionTargets.reduce( + (sum, target) => sum + target.executableLines, + 0 + ); + return { coveredLines, executableLines, ratio: coveredLines / executableLines }; +} + +try { + const derivedData = + process.env.CALORIE_DERIVED_DATA ?? join(tmpdir(), 'calorie-code-health-ios-derived'); + const destination = simulatorDestination(); + console.log(`Native gate: ${destination}`); + const result = spawnSync('zsh', ['ios/scripts/check.sh'], { + cwd: projectRoot, + env: { + ...process.env, + CALORIE_DERIVED_DATA: derivedData, + CALORIE_SIMULATOR_DESTINATION: destination, + }, + stdio: 'inherit', + }); + if (result.error) throw result.error; + if (result.status !== 0) + throw new Error(`Native tests/build exited with status ${result.status}`); + + const coverage = productionCoverage(latestResultBundle(derivedData)); + console.log( + `Native coverage: ${coverage.coveredLines}/${coverage.executableLines} production lines ` + + `(${(coverage.ratio * 100).toFixed(4)}%).` + ); + if (coverage.ratio < minimumProductionCoverage) { + throw new Error( + `Native production coverage regressed: ${(coverage.ratio * 100).toFixed(4)}% < ` + + `${(minimumProductionCoverage * 100).toFixed(2)}%` + ); + } + console.log('Native gate: 16 unit tests, 3 UI tests, release build, and coverage pass.'); +} catch (error) { + console.error(error instanceof Error ? error.message : String(error)); + process.exit(1); +} diff --git a/src/components/charts/chart-utils.ts b/src/components/charts/chart-utils.ts index 27ea23c..628dbb6 100644 --- a/src/components/charts/chart-utils.ts +++ b/src/components/charts/chart-utils.ts @@ -48,11 +48,3 @@ export function xPositions(count: number, width: number, pad: number): number[] } export type SeriesKey = 'calories' | 'protein' | 'carbs' | 'fibre' | 'water'; - -export const SERIES_LABELS: Record = { - calories: 'Calories', - protein: 'Protein', - carbs: 'Carbs', - fibre: 'Fibre', - water: 'Water', -}; diff --git a/src/lib/actionable-insights.ts b/src/lib/actionable-insights.ts index 182a532..3960714 100644 --- a/src/lib/actionable-insights.ts +++ b/src/lib/actionable-insights.ts @@ -2,7 +2,7 @@ import { localDateKey } from './calendar'; import { analyzeFoodAnalytics } from './food-analytics'; import type { FoodEntry, HistoryDay, NutritionTarget } from './types'; -export type InsightCoverageKey = 'calories' | 'protein' | 'fibre' | 'water'; +type InsightCoverageKey = 'calories' | 'protein' | 'fibre' | 'water'; export type ActionableInsights = { confidence: { loggedDays: number; windowDays: number; isSparse: boolean }; diff --git a/src/lib/api.ts b/src/lib/api.ts index 8297e84..2067f33 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -22,8 +22,6 @@ import { demoSaveProfile, demoSetFoodArchived, demoUpdateCycleStart, - demoUpdateWater, - demoUpdateWeight, } from './demo'; import { type FoodLifecycle, @@ -54,8 +52,6 @@ import { localSaveProfile, localSetFoodArchived, localUpdateCycleStart, - localUpdateWater, - localUpdateWeight, } from './local-store'; import { cacheDashboard, @@ -221,7 +217,7 @@ export async function getBootstrap(): Promise { } } -export async function getProfile(): Promise { +async function getProfile(): Promise { if (isDemo()) return normalizeProfile(demoDashboard().profile); if (isLocalMode()) return normalizeProfile(localProfile()); try { @@ -251,7 +247,7 @@ export async function saveProfile( return saved; } -export function localDayRange(date = new Date()) { +function localDayRange(date = new Date()) { const start = new Date(date); start.setHours(0, 0, 0, 0); const end = new Date(start); @@ -406,8 +402,8 @@ export async function addWater(input: WaterEntry) { } export async function updateWater(input: WaterEntry) { - if (isDemo()) return demoUpdateWater(input); - if (isLocalMode()) return localUpdateWater(input); + if (isDemo()) return demoAddWater(input); + if (isLocalMode()) return localAddWater(input); const saved = await writeOffline({ id: `update-water:${input.id}:${Date.now()}`, path: `/api/app/water/${input.id}`, @@ -507,8 +503,8 @@ export async function addWeight(input: WeightEntry) { } export async function updateWeight(input: WeightEntry) { - if (isDemo()) return demoUpdateWeight(input); - if (isLocalMode()) return localUpdateWeight(input); + if (isDemo()) return demoAddWeight(input); + if (isLocalMode()) return localAddWeight(input); const saved = await writeOffline({ id: `update-weight:${input.id}:${Date.now()}`, path: `/api/app/weights/${input.id}`, diff --git a/src/lib/cycle-sessions.ts b/src/lib/cycle-sessions.ts index 0c752fd..fcdf836 100644 --- a/src/lib/cycle-sessions.ts +++ b/src/lib/cycle-sessions.ts @@ -78,7 +78,7 @@ export function transitionCycleSessions(input: { ]; } -export function validateCycleStartDate( +function validateCycleStartDate( startOn: string, today: string, previousEndOn: string | null diff --git a/src/lib/demo.ts b/src/lib/demo.ts index da7a262..b9f8aa8 100644 --- a/src/lib/demo.ts +++ b/src/lib/demo.ts @@ -383,9 +383,6 @@ export function demoAddWeight(input: WeightEntry) { return input; } -export const demoUpdateWater = demoAddWater; -export const demoUpdateWeight = demoAddWeight; - export function demoDeleteWeight(id: string) { weights = weights.filter((entry) => entry.id !== id); } diff --git a/src/lib/food-library.ts b/src/lib/food-library.ts index 3b38f06..0763f3f 100644 --- a/src/lib/food-library.ts +++ b/src/lib/food-library.ts @@ -35,7 +35,7 @@ export function detachFoodDefinition(entries: FoodEntry[], foodId: string): Food return entries.map((entry) => (entry.foodId === foodId ? { ...entry, foodId: null } : entry)); } -export function isArchivedFood(food: Food): boolean { +function isArchivedFood(food: Food): boolean { return food.archivedAt !== null; } diff --git a/src/lib/local-store.ts b/src/lib/local-store.ts index cbe8a1f..da3ac27 100644 --- a/src/lib/local-store.ts +++ b/src/lib/local-store.ts @@ -305,9 +305,6 @@ export function localAddWeight(input: WeightEntry) { return input; } -export const localUpdateWater = localAddWater; -export const localUpdateWeight = localAddWeight; - export function localDeleteWeight(id: string) { const state = readState(); state.weights = state.weights.filter((entry) => entry.id !== id); diff --git a/src/lib/macro-completion.ts b/src/lib/macro-completion.ts index c30cc6c..3a5e46d 100644 --- a/src/lib/macro-completion.ts +++ b/src/lib/macro-completion.ts @@ -1,7 +1,7 @@ import { round, scaleNutrients } from './recommendations'; import type { Food, NutritionTarget } from './types'; -export type MacroCompletionSuggestion = { +type MacroCompletionSuggestion = { food: Food; calories: number; proteinG: number; diff --git a/src/lib/nutrient-density.ts b/src/lib/nutrient-density.ts index 31cda62..2f6eab7 100644 --- a/src/lib/nutrient-density.ts +++ b/src/lib/nutrient-density.ts @@ -1,6 +1,6 @@ import type { Nutrients } from './types'; -export type NutrientDensityLevel = 'high' | 'medium' | 'low' | 'unavailable'; +type NutrientDensityLevel = 'high' | 'medium' | 'low' | 'unavailable'; export type NutrientDensity = { level: NutrientDensityLevel; @@ -10,7 +10,7 @@ export type NutrientDensity = { explanation: string; }; -export const NUTRIENT_DENSITY_CAVEAT = +const NUTRIENT_DENSITY_CAVEAT = 'Based only on tracked protein and fibre per 100 kcal. It does not assess vitamins, minerals, ingredients, or overall health quality.'; function rounded(value: number) { diff --git a/src/lib/offline.ts b/src/lib/offline.ts index 2f2f819..e51a391 100644 --- a/src/lib/offline.ts +++ b/src/lib/offline.ts @@ -32,7 +32,7 @@ export async function readCachedDashboard(userId: string): Promise { +async function readStaleDashboard(userId: string): Promise { return readCachedDashboard(userId); } diff --git a/src/lib/recommendations.ts b/src/lib/recommendations.ts index b63e75c..00b3d6a 100644 --- a/src/lib/recommendations.ts +++ b/src/lib/recommendations.ts @@ -301,7 +301,7 @@ export function calculateGymGuidance(entries: FoodEntry[], now = Date.now()): Gy }; } -export function timeToMinutes(time: string): number { +function timeToMinutes(time: string): number { const [hours, minutes] = time.split(':').map(Number); return hours * 60 + minutes; } diff --git a/vite.config.ts b/vite.config.ts index 59a50c0..8309ba0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -6,7 +6,7 @@ export default defineConfig({ plugins: [react()], resolve: { alias: { - '@': path.resolve(__dirname, './src'), + '@': path.resolve(import.meta.dirname, './src'), }, }, server: { diff --git a/vitest.config.ts b/vitest.config.ts index ed69615..4d0e35c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,7 +4,14 @@ export default defineConfig({ test: { include: ['src/**/*.test.ts'], coverage: { - include: ['src/lib/recommendations.ts'], + include: ['src/**/*.{ts,tsx,mjs}'], + exclude: ['src/**/*.test.*', 'src/**/*.d.*'], + thresholds: { + lines: 22, + functions: 22, + branches: 17, + statements: 21, + }, }, }, }); From 35290700aec6ded3c0d40cf56f0f52b0fa5e9217 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Wed, 12 Aug 2026 10:18:48 +0530 Subject: [PATCH 2/3] ci: modernize quality workflow actions --- .github/workflows/ci.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ffb3d5..85c2123 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,25 +10,26 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 2 - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: 22 - cache: pnpm + - run: corepack enable && corepack install - run: pnpm install --frozen-lockfile - uses: astral-sh/setup-uv@v7 + with: + enable-cache: false - run: pnpm quality native-quality: runs-on: macos-15 steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 with: node-version: 22 + - run: corepack enable && corepack install - run: command -v xcodegen >/dev/null || brew install xcodegen - run: pnpm quality:native From 25b642c374c4fdcf547a843f4b4bc045f763eb28 Mon Sep 17 00:00:00 2001 From: Sarthak Agrawal Date: Wed, 12 Aug 2026 10:31:16 +0530 Subject: [PATCH 3/3] test: make cloud meal mapping deterministic --- ios/Sources/CalorieCore/CloudJournal.swift | 21 +++++++++++++------ .../CalorieCoreTests/CalorieCoreTests.swift | 9 ++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ios/Sources/CalorieCore/CloudJournal.swift b/ios/Sources/CalorieCore/CloudJournal.swift index 678c16b..d7e73e7 100644 --- a/ios/Sources/CalorieCore/CloudJournal.swift +++ b/ios/Sources/CalorieCore/CloudJournal.swift @@ -36,7 +36,10 @@ public enum JournalReconciliationChoice: Equatable, Sendable { } public enum CloudJournalMapper { - public static func decode(_ data: Data) throws -> CloudJournalSnapshot { + public static func decode( + _ data: Data, + calendar: Calendar = .current + ) throws -> CloudJournalSnapshot { let export = try JSONDecoder().decode(CloudExport.self, from: data) guard export.schema == "calorie-journal-backup", export.version == 2 else { throw CalorieError.unsupportedSchema(export.version) @@ -52,7 +55,9 @@ public enum CloudJournalMapper { let document = CalorieDocument( profile: profile, foods: foods, - foodEntries: export.entries.map { mapEntry($0, food: $0.foodId.flatMap { foodByID[$0] }) }, + foodEntries: export.entries.map { + mapEntry($0, food: $0.foodId.flatMap { foodByID[$0] }, calendar: calendar) + }, waterEntries: export.waterEntries.map { WaterEntry(id: stableUUID($0.id), timestamp: date($0.drankAt), millilitres: $0.amountMl) }, @@ -201,7 +206,11 @@ public enum CloudJournalMapper { ) } - private static func mapEntry(_ entry: CloudEntry, food: CloudFood?) -> FoodEntry { + private static func mapEntry( + _ entry: CloudEntry, + food: CloudFood?, + calendar: Calendar + ) -> FoodEntry { let servings: Double if let food, food.servingMode == "per_100g", food.defaultAmount > 0 { servings = entry.amount / food.defaultAmount @@ -213,7 +222,7 @@ public enum CloudJournalMapper { id: stableUUID(entry.id), foodID: stableUUID(entry.foodId ?? "direct:\(entry.id)"), foodName: entry.foodName, - meal: meal(for: timestamp), + meal: meal(for: timestamp, calendar: calendar), timestamp: timestamp, servings: max(0.01, servings), nutrients: Nutrients( @@ -226,8 +235,8 @@ public enum CloudJournalMapper { ) } - private static func meal(for date: Date) -> Meal { - switch Calendar.current.component(.hour, from: date) { + private static func meal(for date: Date, calendar: Calendar) -> Meal { + switch calendar.component(.hour, from: date) { case 0..<11: .breakfast case 11..<16: .lunch case 16..<21: .dinner diff --git a/ios/Tests/CalorieCoreTests/CalorieCoreTests.swift b/ios/Tests/CalorieCoreTests/CalorieCoreTests.swift index 2471915..e26bb98 100644 --- a/ios/Tests/CalorieCoreTests/CalorieCoreTests.swift +++ b/ios/Tests/CalorieCoreTests/CalorieCoreTests.swift @@ -121,12 +121,17 @@ final class CalorieCoreTests: XCTestCase { } func testCloudExportMapsCurrentJournalWithoutInventingFat() throws { - let snapshot = try CloudJournalMapper.decode(Data(Self.cloudExport.utf8)) + var calendar = Calendar(identifier: .gregorian) + calendar.timeZone = try XCTUnwrap(TimeZone(secondsFromGMT: 0)) + let snapshot = try CloudJournalMapper.decode( + Data(Self.cloudExport.utf8), + calendar: calendar + ) XCTAssertEqual(snapshot.document.profile.name, "Sarthak") XCTAssertEqual(snapshot.counts.foodEntries, 1) XCTAssertEqual(snapshot.document.foodEntries.first?.foodName, "Greek yoghurt") - XCTAssertEqual(snapshot.document.foodEntries.first?.meal, .breakfast) + XCTAssertEqual(snapshot.document.foodEntries.first?.meal, .snack) XCTAssertEqual(snapshot.document.foodEntries.first?.nutrients.fat, 0) XCTAssertEqual(snapshot.document.weightEntries.first?.kilograms, 72.4) XCTAssertEqual(snapshot.document.profile.weightKilograms, 72.4)