diff --git a/.gitignore b/.gitignore index 5a892f3aba..d8edd6458a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ packages/cli-*/bin/ # Transient render dir created by packages/api/scripts/generated-output-sync.unit.test.ts packages/api/.generated-output-sync-*/ + +# Vitest 5 artifact directory (blob reports, attachments, html/json output) +.vitest/ diff --git a/AGENTS.md b/AGENTS.md index fa33c3d460..03348ca725 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,6 +47,17 @@ Expected exceptions: } ``` +**vitest.config.ts:** + +Package configs build on the repo-root `vitest.shared.ts` preset. `definePackageConfig` merges the +shared defaults (bun export-condition resolution for workspace packages, v8 coverage, +`passWithNoTests`, console output only from failing tests), and `testProject("unit" | "integration" | +"e2e" | "live", overrides)` declares one inline project per test kind with the repo's file-suffix +convention baked in. Package-specific settings such as timeouts, setup files, serial execution, or +Vite plugins go in the overrides. The root `vitest.config.mts` loads every package config as a nested +project group, so `bun --bun vitest run --project '*(unit)'` from the repo root runs one kind across +all workspaces while `pnpm test:unit` inside a package still works standalone. + ## Config Naming Vocabulary `@supabase/config` and its CLI consumer use three settled names: diff --git a/apps/cli-e2e/vitest.config.ts b/apps/cli-e2e/vitest.config.ts index bb87f884aa..337992723e 100644 --- a/apps/cli-e2e/vitest.config.ts +++ b/apps/cli-e2e/vitest.config.ts @@ -1,16 +1,12 @@ -import { defineConfig } from "vitest/config"; import { BaseSequencer, type TestSpecification } from "vitest/node"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; -export default defineConfig({ +export default definePackageConfig({ test: { - passWithNoTests: true, - include: ["**/*.e2e.test.ts"], - exclude: ["**/node_modules/**"], - fileParallelism: false, - maxWorkers: 1, - globalSetup: ["tests/setup.ts"], - testTimeout: 60_000, - hookTimeout: 30_000, + // Replay fixtures are shared across files, so run them in a deterministic + // lexicographic order. `sequence.sequencer` is a run-level option: it + // applies to standalone runs of this package, not when the repo root loads + // this config as a project. sequence: { sequencer: class extends BaseSequencer { override async sort(files: TestSpecification[]) { @@ -18,5 +14,16 @@ export default defineConfig({ } }, }, + projects: [ + testProject("e2e", { + test: { + fileParallelism: false, + maxWorkers: 1, + globalSetup: ["tests/setup.ts"], + testTimeout: 60_000, + hookTimeout: 30_000, + }, + }), + ], }, }); diff --git a/apps/cli/src/shared/issue/issue-template-contract.unit.test.ts b/apps/cli/src/shared/issue/issue-template-contract.unit.test.ts index 8a1c82ce78..d227e3b71a 100644 --- a/apps/cli/src/shared/issue/issue-template-contract.unit.test.ts +++ b/apps/cli/src/shared/issue/issue-template-contract.unit.test.ts @@ -35,7 +35,7 @@ function isBodyItem(value: unknown): value is IssueFormBodyItem { } function issueTemplateDir() { - return resolve(process.cwd(), "../../.github/ISSUE_TEMPLATE"); + return resolve(import.meta.dirname, "../../../../../.github/ISSUE_TEMPLATE"); } function readTemplate(template: string): ReadonlyArray { diff --git a/apps/cli/vitest.config.ts b/apps/cli/vitest.config.ts index 13c4fb42bb..ed76c3a096 100644 --- a/apps/cli/vitest.config.ts +++ b/apps/cli/vitest.config.ts @@ -1,7 +1,8 @@ import { readFileSync } from "node:fs"; -import { defaultClientConditions, defaultServerConditions } from "vite"; -import { defineConfig } from "vitest/config"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; +// `src/shared/services/dockerfile-images.ts` imports the Go CLI's Dockerfile +// with Bun's `{ type: "text" }` import attribute; Vite needs a loader for it. function dockerfileTextPlugin() { return { name: "dockerfile-text-loader", @@ -16,31 +17,17 @@ function dockerfileTextPlugin() { }; } -// Workspace packages such as @supabase/config publish a `bun` export -// condition pointing at their TypeScript source (see -// packages/config/package.json's `exports` map); without it, Vite's resolver -// falls through to the `default` condition and loads the built `dist/*.js` -// output instead — which is stale, or missing entirely on a fresh clone -// before the package has been built. Extending (not replacing) Vite's -// default condition lists keeps every other package's exports resolution -// unchanged. Required on every inline `test.projects` entry below too: -// Vitest builds a separate Vite config per project and does not inherit -// these from the root config (see PR #6366 finding 0). -const workspacePackageResolve = { conditions: [...defaultClientConditions, "bun"] }; -const workspacePackageSsrResolve = { conditions: [...defaultServerConditions, "bun"] }; +const e2eRuntime = { + globalSetup: ["tests/e2e-global-setup.ts"], + setupFiles: ["tests/e2e-setup.ts"], + testTimeout: 120_000, + hookTimeout: 120_000, +}; -export default defineConfig({ - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, +export default definePackageConfig({ plugins: [dockerfileTextPlugin()], test: { - passWithNoTests: true, coverage: { - enabled: false, - provider: "v8", - include: ["src/**/*.ts"], - reporter: ["text", "lcov"], - reportsDirectory: "coverage", exclude: [ "tests/**", "scripts/**", @@ -56,79 +43,26 @@ export default defineConfig({ ], }, projects: [ - { - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - plugins: [dockerfileTextPlugin()], + testProject("unit", { test: { env: { FORCE_COLOR: "1" } } }), + testProject("integration"), + // Stackless e2e: black-box CLI subprocesses against an isolated temporary + // home, safe under file-level parallelism. + testProject("e2e", { test: e2eRuntime }), + // Stack-backed e2e: `*.stack.e2e.test.ts` files start a local stack or + // run Docker containers and run one at a time (ADR 0024). + testProject("e2e-stack", { test: e2eRuntime }), + // Live tests run against one provisioned project on the configured + // platform. They are never part of the default unit/integration/e2e + // loop; an explicit run fails fast when required configuration is absent. + testProject("live", { test: { - name: "unit", - include: ["**/*.unit.test.ts"], - env: { FORCE_COLOR: "1" }, - }, - }, - { - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - plugins: [dockerfileTextPlugin()], - test: { - name: "integration", - include: ["**/*.integration.test.ts"], - }, - }, - { - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - plugins: [dockerfileTextPlugin()], - test: { - // Stackless e2e: black-box CLI subprocesses against an isolated - // temporary home. Safe under file-level parallelism (see the flake - // policy in AGENTS.md), so Vitest's default parallelism applies. - name: "e2e", - include: ["**/*.e2e.test.ts"], - exclude: ["**/*.stack.e2e.test.ts", "**/node_modules/**"], - globalSetup: ["tests/e2e-global-setup.ts"], - setupFiles: ["tests/e2e-setup.ts"], - testTimeout: 120_000, - hookTimeout: 120_000, - }, - }, - { - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - plugins: [dockerfileTextPlugin()], - test: { - // Stack-backed e2e: files that start a local Supabase stack or run - // Docker containers claim machine-level resources, so they run one - // file at a time. Vitest schedules this serial group after the - // parallel projects finish. Opt in with the `*.stack.e2e.test.ts` - // suffix (ADR 0024). - name: "e2e-stack", - include: ["**/*.stack.e2e.test.ts"], - fileParallelism: false, - maxWorkers: 1, - globalSetup: ["tests/e2e-global-setup.ts"], - setupFiles: ["tests/e2e-setup.ts"], - testTimeout: 120_000, - hookTimeout: 120_000, - }, - }, - { - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - plugins: [dockerfileTextPlugin()], - test: { - // Live tests run against one provisioned project on the configured - // platform. They are never part of the default unit/integration/e2e - // loop; an explicit run fails fast when required configuration is absent. - name: "live", - include: ["**/*.live.test.ts"], fileParallelism: false, maxWorkers: 1, globalSetup: ["tests/live-global-setup.ts"], testTimeout: 300_000, hookTimeout: 300_000, }, - }, + }), ], }, }); diff --git a/knip.json b/knip.json index 4fb19c9c2a..8e54b25dd3 100644 --- a/knip.json +++ b/knip.json @@ -3,10 +3,11 @@ "exclude": ["catalogReferences"], "workspaces": { ".": { - "entry": [".github/scripts/**/*.ts", "tools/*.ts", "tools/release/*.ts"], + "entry": [".github/scripts/**/*.ts", "tools/*.ts", "tools/release/*.ts", "vitest.config.mts"], "ignore": [".repos/**", "apps/cli-go/**"], "ignoreBinaries": ["go"], - "ignoreDependencies": ["verdaccio"] + "ignoreDependencies": ["verdaccio"], + "vitest": false }, "apps/cli": { "entry": [ diff --git a/package.json b/package.json index 6aef9409f4..88822d379d 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "test:unit": "pnpm exec turbo run test:unit:run --filter=!@supabase/cli-go --", "test:integration": "pnpm exec turbo run test:integration:run --", "test:e2e": "pnpm exec turbo run supabase#build && pnpm exec turbo run test:e2e:run --only --concurrency=1 --", + "test:vitest": "bun --bun vitest run --project '!supabase (live)'", "check:all": "pnpm exec turbo run types:check lint:check fmt:check knip:check lint:effect:check", "fix:all": "pnpm exec turbo run lint:fix fmt:fix knip:fix && pnpm run lint:effect:fix", "lint:check": "oxlint --config .oxlintrc.json", @@ -40,7 +41,8 @@ "turbo": "catalog:", "typescript": "catalog:", "verdaccio": "^6.10.0", - "vite": "^8.2.2" + "vite": "^8.2.2", + "vitest": "catalog:" }, "devEngines": { "packageManager": { diff --git a/packages/api/vitest.config.ts b/packages/api/vitest.config.ts index e3ecd5dcab..62fffebcfa 100644 --- a/packages/api/vitest.config.ts +++ b/packages/api/vitest.config.ts @@ -1,23 +1,5 @@ -import { defineConfig } from "vitest/config"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; -export default defineConfig({ - test: { - passWithNoTests: true, - coverage: { - enabled: false, - provider: "v8", - clean: false, - include: ["src/**/*.ts"], - reporter: ["text", "lcov"], - reportsDirectory: "coverage", - }, - projects: [ - { - test: { - name: "unit", - include: ["**/*.unit.test.ts"], - }, - }, - ], - }, +export default definePackageConfig({ + test: { projects: [testProject("unit")] }, }); diff --git a/packages/cli-test-helpers/vitest.config.ts b/packages/cli-test-helpers/vitest.config.ts index e3ecd5dcab..62fffebcfa 100644 --- a/packages/cli-test-helpers/vitest.config.ts +++ b/packages/cli-test-helpers/vitest.config.ts @@ -1,23 +1,5 @@ -import { defineConfig } from "vitest/config"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; -export default defineConfig({ - test: { - passWithNoTests: true, - coverage: { - enabled: false, - provider: "v8", - clean: false, - include: ["src/**/*.ts"], - reporter: ["text", "lcov"], - reportsDirectory: "coverage", - }, - projects: [ - { - test: { - name: "unit", - include: ["**/*.unit.test.ts"], - }, - }, - ], - }, +export default definePackageConfig({ + test: { projects: [testProject("unit")] }, }); diff --git a/packages/config/vitest.config.ts b/packages/config/vitest.config.ts index 14e1c86d76..62fffebcfa 100644 --- a/packages/config/vitest.config.ts +++ b/packages/config/vitest.config.ts @@ -1,40 +1,5 @@ -import { defaultClientConditions, defaultServerConditions } from "vite"; -import { defineConfig } from "vitest/config"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; -// This package publishes a `bun` export condition pointing at its -// TypeScript source (see package.json's `exports` map); without it, Vite's -// resolver falls through to the `default` condition and loads the built -// `dist/*.js` output instead — stale, or missing entirely on a fresh clone -// before the package has been built. Extending (not replacing) Vite's -// default condition lists keeps every other package's exports resolution -// unchanged. Required on every inline `test.projects` entry too: Vitest -// builds a separate Vite config per project and does not inherit these from -// the root config (see PR #6366 finding 0). -const workspacePackageResolve = { conditions: [...defaultClientConditions, "bun"] }; -const workspacePackageSsrResolve = { conditions: [...defaultServerConditions, "bun"] }; - -export default defineConfig({ - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - test: { - passWithNoTests: true, - coverage: { - enabled: false, - provider: "v8", - clean: false, - include: ["src/**/*.ts"], - reporter: ["text", "lcov"], - reportsDirectory: "coverage", - }, - projects: [ - { - resolve: workspacePackageResolve, - ssr: { resolve: workspacePackageSsrResolve }, - test: { - name: "unit", - include: ["**/*.unit.test.ts"], - }, - }, - ], - }, +export default definePackageConfig({ + test: { projects: [testProject("unit")] }, }); diff --git a/packages/process-compose/vitest.config.ts b/packages/process-compose/vitest.config.ts index 16ccdf3fc6..aefedecbd3 100644 --- a/packages/process-compose/vitest.config.ts +++ b/packages/process-compose/vitest.config.ts @@ -1,29 +1,5 @@ -import { defineConfig } from "vitest/config"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; -export default defineConfig({ - test: { - passWithNoTests: true, - coverage: { - enabled: false, - provider: "v8", - clean: false, - include: ["src/**/*.ts"], - reporter: ["text", "lcov"], - reportsDirectory: "coverage", - }, - projects: [ - { - test: { - name: "unit", - include: ["**/*.unit.test.ts"], - }, - }, - { - test: { - name: "integration", - include: ["**/*.integration.test.ts"], - }, - }, - ], - }, +export default definePackageConfig({ + test: { projects: [testProject("unit"), testProject("integration")] }, }); diff --git a/packages/stack/src/ApiProxy.ts b/packages/stack/src/ApiProxy.ts index 08e49149cc..612ce8f3ad 100644 --- a/packages/stack/src/ApiProxy.ts +++ b/packages/stack/src/ApiProxy.ts @@ -172,8 +172,11 @@ function makeProxyHandler( const noBodyMethods = new Set(["GET", "HEAD", "OPTIONS", "TRACE"]); const contentType = Option.getOrUndefined(Headers.get(req.headers, "content-type")); + const hasBody = + Option.isSome(Headers.get(req.headers, "transfer-encoding")) || + Option.getOrElse(Headers.get(req.headers, "content-length"), () => "0") !== "0"; let body: HttpBody.HttpBody; - if (noBodyMethods.has(req.method)) { + if (noBodyMethods.has(req.method) || !hasBody) { body = HttpBody.empty; } else if (opts.retryColdStart === true) { // Buffer the body so the request can be safely re-sent if we retry. diff --git a/packages/stack/src/ApiProxy.unit.test.ts b/packages/stack/src/ApiProxy.unit.test.ts index cf031ba0cd..96de19b487 100644 --- a/packages/stack/src/ApiProxy.unit.test.ts +++ b/packages/stack/src/ApiProxy.unit.test.ts @@ -203,6 +203,18 @@ describe("ApiProxy", () => { expect(res.status).toBe(200); }); + // A DELETE from supabase-js carries no body. Forwarding it as a streamed + // (chunked) body made PostgREST drop the connection under the Bun HTTP + // client, surfacing as "Bad gateway: Transport error" on every native + // delete; the proxy must send an empty body instead. + test("forwards a body-less DELETE without a chunked body", async () => { + const res = await fetch(`${proxyUrl}/rest/v1/todos?id=eq.3`, { method: "DELETE" }); + expect(res.status).toBe(200); + const echoed = (await res.json()) as { method: string; headers: Record }; + expect(echoed.method).toBe("DELETE"); + expect(echoed.headers["transfer-encoding"]).toBeUndefined(); + }); + // --------------------------------------------------------------------------- // CORS // --------------------------------------------------------------------------- diff --git a/packages/stack/vitest.config.ts b/packages/stack/vitest.config.ts index d251303904..3079bd4956 100644 --- a/packages/stack/vitest.config.ts +++ b/packages/stack/vitest.config.ts @@ -1,41 +1,13 @@ -import { defineConfig } from "vitest/config"; +import { definePackageConfig, testProject } from "../../vitest.shared.ts"; -export default defineConfig({ +export default definePackageConfig({ test: { - passWithNoTests: true, - coverage: { - enabled: false, - provider: "v8", - clean: false, - include: ["src/**/*.ts"], - reporter: ["text", "lcov"], - reportsDirectory: "coverage", - }, projects: [ - { - test: { - name: "unit", - include: ["**/*.unit.test.ts"], - }, - }, - { - test: { - name: "integration", - include: ["**/*.integration.test.ts"], - testTimeout: 60_000, - }, - }, - { - test: { - // Every e2e file here starts a local stack, so the whole kind is - // stack-backed and serial. See ADR 0024 for the `*.stack.e2e.test.ts` - // convention. - name: "e2e-stack", - include: ["**/*.stack.e2e.test.ts"], - fileParallelism: false, - globalSetup: ["./tests/global-setup.ts"], - }, - }, + testProject("unit"), + testProject("integration", { test: { testTimeout: 60_000 } }), + // Every e2e file here starts a local stack, so the whole kind is + // stack-backed (ADR 0024). + testProject("e2e-stack", { test: { globalSetup: ["./tests/global-setup.ts"] } }), ], }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38c9053ad7..ce1e3d4ab3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -129,8 +129,8 @@ catalogs: specifier: ^1.4.0 version: 1.4.0 '@vitest/coverage-v8': - specifier: ^4.1.11 - version: 4.1.11 + specifier: ^5.0.0 + version: 5.0.0 effect: specifier: 4.0.0-rc.112 version: 4.0.0-rc.112 @@ -159,8 +159,8 @@ catalogs: specifier: ^7.0.2 version: 7.0.2 vitest: - specifier: ^4.1.11 - version: 4.1.11 + specifier: ^5.0.0 + version: 5.0.0 overrides: '@launchql/protobufjs>@types/node': 24.10.4 @@ -209,7 +209,10 @@ importers: version: 6.10.0(supports-color@7.2.0)(typanion@3.14.0) vite: specifier: ^8.2.2 - version: 8.2.2 + version: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) + vitest: + specifier: 'catalog:' + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) apps/cli: dependencies: @@ -237,7 +240,7 @@ importers: version: 4.0.0-rc.112(effect@4.0.0-rc.112) '@effect/vitest': specifier: 'catalog:' - version: 4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11) + version: 4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) '@modelcontextprotocol/sdk': specifier: ^1.30.0 version: 1.30.0(supports-color@7.2.0)(zod@4.4.3) @@ -276,7 +279,7 @@ importers: version: 1.2.5 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.11(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11) + version: 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) dotenv: specifier: ^17.4.2 version: 17.4.2 @@ -315,7 +318,7 @@ importers: version: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) yaml: specifier: ^2.9.0 version: 2.9.0 @@ -362,7 +365,7 @@ importers: version: 7.0.2 vitest: specifier: 'catalog:' - version: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) apps/cli-go: {} @@ -426,13 +429,13 @@ importers: version: 1.4.0 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.11(vite@8.2.2(@types/node@26.3.0))(vitest@4.1.11) + version: 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) typescript: specifier: 'catalog:' version: 7.0.2 vitest: specifier: 'catalog:' - version: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) packages/cli-darwin-arm64: {} @@ -456,13 +459,13 @@ importers: version: 1.4.0 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.11(vite@8.2.2)(vitest@4.1.11) + version: 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) typescript: specifier: 'catalog:' version: 7.0.2 vitest: specifier: 'catalog:' - version: 4.1.11(@vitest/coverage-v8@4.1.11)(vite@8.2.2) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) packages/cli-windows-arm64: {} @@ -500,7 +503,7 @@ importers: version: 1.4.0 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.11(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11) + version: 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) effect: specifier: 'catalog:' version: 4.0.0-rc.112 @@ -515,7 +518,7 @@ importers: version: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) vitest: specifier: 'catalog:' - version: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) packages/process-compose: dependencies: @@ -528,7 +531,7 @@ importers: version: 4.0.0-rc.112(effect@4.0.0-rc.112) '@effect/vitest': specifier: 'catalog:' - version: 4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2)(vitest@4.1.11) + version: 4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) '@tsconfig/bun': specifier: 'catalog:' version: 1.0.11 @@ -537,13 +540,13 @@ importers: version: 1.4.0 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.11(vite@8.2.2)(vitest@4.1.11) + version: 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) typescript: specifier: 'catalog:' version: 7.0.2 vitest: specifier: 'catalog:' - version: 4.1.11(@vitest/coverage-v8@4.1.11)(vite@8.2.2) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) packages/stack: dependencies: @@ -562,7 +565,7 @@ importers: devDependencies: '@effect/vitest': specifier: 'catalog:' - version: 4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11) + version: 4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) '@supabase/supabase-js': specifier: ^2.112.4 version: 2.112.4 @@ -574,13 +577,13 @@ importers: version: 1.4.0 '@vitest/coverage-v8': specifier: 'catalog:' - version: 4.1.11(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11) + version: 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) typescript: specifier: 'catalog:' version: 7.0.2 vitest: specifier: 'catalog:' - version: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) + version: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) packages: @@ -2984,21 +2987,26 @@ packages: resolution: {integrity: sha512-RWS2h1yXeaF7txXD7jK/v1aecMrTCGFGRMDH3qjcvM0FMXYs5rleGo/MooiXHuOGFC4D7xNqt3hERXQweNlf2Q==} engines: {node: '>=22'} - '@vitest/coverage-v8@4.1.11': - resolution: {integrity: sha512-8MVGEFnJIcdGjcbfKmeq8z0pZHH0JlVtoVZH9Q/qwUp6wyFnEJUBMrw9DCaj+ra3vShGmhavjalMIhPNxZAUcw==} + '@vitest/coverage-v8@5.0.0': + resolution: {integrity: sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==} peerDependencies: - '@vitest/browser': 4.1.11 + '@vitest/browser': 5.0.0 vite: '*' - vitest: 4.1.11 + vitest: 5.0.0 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@4.1.11': - resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + '@vitest/istanbul-lib-coverage@1.0.0': + resolution: {integrity: sha512-BScRXlnT3d8tN39mDZuZgS6OmczgyLNO55FGka+CO0LO5458m7hBnEvDm/Dc12f07R4ChdDst66YfKtCr2T8mg==} + engines: {node: '>=22'} - '@vitest/mocker@4.1.11': - resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + '@vitest/istanbul-lib-report@1.0.0': + resolution: {integrity: sha512-NYqaFIc2vKd069hB+oRPf2ckkEq/lYg1W+12l4t0M0c3LYrGgMz8Sj7v+fgONanDsZMBqxQySQkChcwN/ajUBw==} + engines: {node: '>=22'} + + '@vitest/mocker@5.0.0': + resolution: {integrity: sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3008,20 +3016,8 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.11': - resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} - - '@vitest/runner@4.1.11': - resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} - - '@vitest/snapshot@4.1.11': - resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} - - '@vitest/spy@4.1.11': - resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} - - '@vitest/utils@4.1.11': - resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + '@vitest/spy@5.0.0': + resolution: {integrity: sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==} '@yuku-analyzer/binding-android-arm64@0.8.7': resolution: {integrity: sha512-pzJ++UMCZEV4s6SP3Ryvj+snWP8s7aTXFkSXRyeBF4RSALftPzfqYssHdGOmOH2QnRAtyOhhg64tdjeSGJvYRg==} @@ -4261,9 +4257,6 @@ packages: resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} engines: {node: ^20.17.0 || >=22.9.0} - html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -4440,18 +4433,6 @@ packages: resolution: {integrity: sha512-7atWPjhGEIX3JEtMrOYd8TKzboYlq+5sNbdl9POiLYOI14G5HZiQbZP0Xj5EZdrufQVXfJlpTV0hys0CuxwxZw==} engines: {node: ^18.17 || >=20.6.1} - 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'} - java-properties@1.0.2: resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==} engines: {node: '>= 0.6.0'} @@ -4705,9 +4686,6 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magic-string@1.2.3: resolution: {integrity: sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==} @@ -4718,10 +4696,6 @@ packages: resolution: {integrity: sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==} engines: {node: '>=18'} - make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - markdown-extensions@2.0.0: resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} engines: {node: '>=16'} @@ -5365,9 +5339,6 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - peek-stream@1.1.3: resolution: {integrity: sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==} @@ -6105,8 +6076,9 @@ packages: resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} engines: {node: '>=12'} - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinybench@6.1.4: + resolution: {integrity: sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==} + engines: {node: '>=20.0.0'} tinyexec@1.3.0: resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} @@ -6427,23 +6399,23 @@ packages: yaml: optional: true - vitest@4.1.11: - resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + vitest@5.0.0: + resolution: {integrity: sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==} + engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.11 - '@vitest/browser-preview': 4.1.11 - '@vitest/browser-webdriverio': 4.1.11 - '@vitest/coverage-istanbul': 4.1.11 - '@vitest/coverage-v8': 4.1.11 - '@vitest/ui': 4.1.11 + '@types/node': ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 5.0.0 + '@vitest/browser-preview': 5.0.0 + '@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0 + '@vitest/coverage-istanbul': 5.0.0 + '@vitest/coverage-v8': 5.0.0 + '@vitest/ui': 5.0.0 happy-dom: '*' jsdom: '*' - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite: ^6.4.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -6879,17 +6851,11 @@ snapshots: '@effect/tsgo-win32-arm64': 0.37.0 '@effect/tsgo-win32-x64': 0.37.0 - '@effect/vitest@4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11)': + '@effect/vitest@4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0)': dependencies: effect: 4.0.0-rc.112 vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - vitest: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) - - '@effect/vitest@4.0.0-rc.112(effect@4.0.0-rc.112)(vite@8.2.2)(vitest@4.1.11)': - dependencies: - effect: 4.0.0-rc.112 - vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - vitest: 4.1.11(@vitest/coverage-v8@4.1.11)(vite@8.2.2) + vitest: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) '@emnapi/core@1.11.2': dependencies: @@ -8671,91 +8637,35 @@ snapshots: lodash: 4.18.1 minimatch: 10.2.6 - '@vitest/coverage-v8@4.1.11(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11)': - dependencies: - '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.11 - 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.1 - vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - vitest: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) - - '@vitest/coverage-v8@4.1.11(vite@8.2.2(@types/node@26.3.0))(vitest@4.1.11)': + '@vitest/coverage-v8@5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.11 + '@vitest/istanbul-lib-coverage': 1.0.0 + '@vitest/istanbul-lib-report': 1.0.0 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.1 vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - vitest: 4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)) + vitest: 5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) - '@vitest/coverage-v8@4.1.11(vite@8.2.2)(vitest@4.1.11)': - dependencies: - '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.11 - 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.1 - vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - vitest: 4.1.11(@vitest/coverage-v8@4.1.11)(vite@8.2.2) + '@vitest/istanbul-lib-coverage@1.0.0': {} - '@vitest/expect@4.1.11': + '@vitest/istanbul-lib-report@1.0.0': dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - chai: 6.2.2 - tinyrainbow: 3.1.1 + '@vitest/istanbul-lib-coverage': 1.0.0 - '@vitest/mocker@4.1.11(vite@8.2.2)': + '@vitest/mocker@5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.11 + '@jridgewell/trace-mapping': 0.3.31 + '@vitest/spy': 5.0.0 estree-walker: 3.0.3 - magic-string: 0.30.21 + magic-string: 1.2.3 optionalDependencies: vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - '@vitest/pretty-format@4.1.11': - dependencies: - tinyrainbow: 3.1.1 - - '@vitest/runner@4.1.11': - dependencies: - '@vitest/utils': 4.1.11 - pathe: 2.0.3 - - '@vitest/snapshot@4.1.11': - dependencies: - '@vitest/pretty-format': 4.1.11 - '@vitest/utils': 4.1.11 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.1.11': {} - - '@vitest/utils@4.1.11': - dependencies: - '@vitest/pretty-format': 4.1.11 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.1 + '@vitest/spy@5.0.0': {} '@yuku-analyzer/binding-android-arm64@0.8.7': optional: true @@ -9218,7 +9128,8 @@ snapshots: convert-hrtime@5.0.0: {} - convert-source-map@2.0.0: {} + convert-source-map@2.0.0: + optional: true cookie-signature@1.0.7: {} @@ -10099,8 +10010,6 @@ snapshots: dependencies: lru-cache: 11.5.2 - html-escaper@2.0.2: {} - html-void-elements@3.0.0: {} http-cache-semantics@4.2.0: {} @@ -10254,19 +10163,6 @@ snapshots: lodash.isstring: 4.0.1 lodash.uniqby: 4.7.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 - java-properties@1.0.2: {} jiti@2.7.0: {} @@ -10492,10 +10388,6 @@ snapshots: dependencies: react: 19.2.8 - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - magic-string@1.2.3: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -10512,10 +10404,6 @@ snapshots: type-fest: 4.41.0 web-worker: 1.5.0 - make-dir@4.0.0: - dependencies: - semver: 7.8.5 - markdown-extensions@2.0.0: {} markdown-table@3.0.4: {} @@ -11371,8 +11259,6 @@ snapshots: path-type@4.0.0: {} - pathe@2.0.3: {} - peek-stream@1.1.3: dependencies: buffer-from: 1.1.2 @@ -12317,7 +12203,7 @@ snapshots: dependencies: convert-hrtime: 5.0.0 - tinybench@2.9.0: {} + tinybench@6.1.4: {} tinyexec@1.3.0: {} @@ -12648,86 +12534,25 @@ snapshots: jiti: 2.7.0 yaml: 2.9.0 - vitest@4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)): - dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.2.2) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - es-module-lexer: 2.3.2 - expect-type: 1.4.0 - magic-string: 0.30.21 - obug: 2.1.4 - pathe: 2.0.3 - picomatch: 4.0.7 - std-env: 4.2.0 - tinybench: 2.9.0 - tinyexec: 1.3.0 - tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 - vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - why-is-node-running: 2.3.0 - optionalDependencies: - '@types/node': 26.3.0 - '@vitest/coverage-v8': 4.1.11(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@4.1.11) - transitivePeerDependencies: - - msw - - vitest@4.1.11(@types/node@26.3.0)(@vitest/coverage-v8@4.1.11)(vite@8.2.2(@types/node@26.3.0)): + vitest@5.0.0(@types/node@26.3.0)(@vitest/coverage-v8@5.0.0)(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.2.2) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 + '@types/chai': 5.2.3 + '@vitest/mocker': 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0)) + chai: 6.2.2 es-module-lexer: 2.3.2 expect-type: 1.4.0 - magic-string: 0.30.21 + magic-string: 1.2.3 obug: 2.1.4 - pathe: 2.0.3 picomatch: 4.0.7 std-env: 4.2.0 - tinybench: 2.9.0 + tinybench: 6.1.4 tinyexec: 1.3.0 tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 26.3.0 - '@vitest/coverage-v8': 4.1.11(vite@8.2.2(@types/node@26.3.0))(vitest@4.1.11) - transitivePeerDependencies: - - msw - - vitest@4.1.11(@vitest/coverage-v8@4.1.11)(vite@8.2.2): - dependencies: - '@vitest/expect': 4.1.11 - '@vitest/mocker': 4.1.11(vite@8.2.2) - '@vitest/pretty-format': 4.1.11 - '@vitest/runner': 4.1.11 - '@vitest/snapshot': 4.1.11 - '@vitest/spy': 4.1.11 - '@vitest/utils': 4.1.11 - es-module-lexer: 2.3.2 - expect-type: 1.4.0 - magic-string: 0.30.21 - obug: 2.1.4 - pathe: 2.0.3 - picomatch: 4.0.7 - std-env: 4.2.0 - tinybench: 2.9.0 - tinyexec: 1.3.0 - tinyglobby: 0.2.17 - tinyrainbow: 3.1.1 - vite: 8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0) - why-is-node-running: 2.3.0 - optionalDependencies: - '@vitest/coverage-v8': 4.1.11(vite@8.2.2)(vitest@4.1.11) + '@vitest/coverage-v8': 5.0.0(vite@8.2.2(@types/node@26.3.0)(esbuild@0.28.2)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0) transitivePeerDependencies: - msw diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9cc38e0ec7..7b27e6b0aa 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -20,7 +20,7 @@ catalog: "@tsconfig/bun": "^1.0.11" "@types/bun": "^1.4.0" "typescript": "^7.0.2" - "@vitest/coverage-v8": "^4.1.11" + "@vitest/coverage-v8": "^5.0.0" "effect": "4.0.0-rc.112" "knip": "^6.32.2" "oxfmt": "^0.65.0" @@ -29,7 +29,7 @@ catalog: "semantic-release": "^25.0.9" "tldts": "^7.4.11" "turbo": "2.10.12" - "vitest": "^4.1.11" + "vitest": ^5.0.0 blockExoticSubdeps: true @@ -89,6 +89,15 @@ packageExtensions: "@oxlint-tsgolint/win32-arm64": *effect-tsgo-patched "@oxlint-tsgolint/win32-x64": *effect-tsgo-patched +# @effect/vitest 4.0.0-rc.x declares a `vitest >=4.1.0 <5.0.0` peer, but it only +# uses the stable `vitest` entrypoint and runs cleanly against Vitest 5 (the +# whole unit/integration suite passes). Upstream has not widened the range yet; +# accept Vitest 5 here so every install stops warning about a known-good pair. +# Drop this rule once @effect/vitest ships a vitest@5-compatible peer range. +peerDependencyRules: + allowedVersions: + "@effect/vitest>vitest": "5" + minimumReleaseAge: 10200 minimumReleaseAgeExclude: - "@turbo/darwin-64@2.10.11" @@ -107,7 +116,12 @@ minimumReleaseAgeExclude: - "@types/bun@1.4.0" - "bun-types@1.4.0" - "effect@4.0.0-rc.111" + - tinybench@6.1.4 - "turbo@2.10.11" + - "@vitest/coverage-v8@5.0.0" + - "@vitest/mocker@5.0.0" + - "@vitest/spy@5.0.0" + - vitest@5.0.0 supportedArchitectures: cpu: diff --git a/vitest.config.mts b/vitest.config.mts new file mode 100644 index 0000000000..5e36ef95a6 --- /dev/null +++ b/vitest.config.mts @@ -0,0 +1,15 @@ +import { defineConfig } from "vitest/config"; +import { runDefaults } from "./vitest.shared.ts"; + +// Every package config becomes a nested project group named after the package, +// so `vitest --project 'supabase (unit)'` or `--project '*(integration)'` selects +// slices of the whole repo from one process. Root-only options such as `silent` +// are not inherited by these file-referenced projects; they come from +// `vitest.shared.ts` through each package config for standalone runs and are +// repeated here for root runs. +export default defineConfig({ + test: { + ...runDefaults, + projects: ["apps/*/vitest.config.ts", "packages/*/vitest.config.ts"], + }, +}); diff --git a/vitest.shared.ts b/vitest.shared.ts new file mode 100644 index 0000000000..ba6b4a20c7 --- /dev/null +++ b/vitest.shared.ts @@ -0,0 +1,107 @@ +import { defaultClientConditions, defaultServerConditions } from "vite"; +import { + defaultExclude, + defineConfig, + mergeConfig, + type TestProjectInlineConfiguration, + type TestUserConfig, + type ViteUserConfig, +} from "vitest/config"; + +/** + * Shared Vitest preset for every TypeScript workspace. + * + * Package configs play two roles: `bun --bun vitest` inside a package treats the + * package config as the root, while the repo-root `vitest.config.mts` loads the + * same file as a nested project group. Vitest only inherits options into + * *inline* projects, never into config files referenced by glob, so anything + * shared across packages has to be merged in here rather than declared once at + * the root. + */ + +const STACK_E2E_GLOB = "**/*.stack.e2e.test.ts"; + +/** + * Test kinds and the colocated file suffix each one owns (see AGENTS.md, + * "Testing"). `e2e-stack` is the sub-kind for e2e files that start a local + * stack or run Docker containers; the plain `e2e` kind excludes them so the two + * projects partition the e2e files (ADR 0024). + */ +export type TestKind = "unit" | "integration" | "e2e" | "e2e-stack" | "live"; + +const testKinds: Record = { + unit: { include: "**/*.unit.test.ts" }, + integration: { include: "**/*.integration.test.ts" }, + e2e: { include: "**/*.e2e.test.ts", exclude: [STACK_E2E_GLOB, ...defaultExclude] }, + "e2e-stack": { include: STACK_E2E_GLOB }, + live: { include: "**/*.live.test.ts" }, +}; + +/** + * One inline project per test kind. Nested under a package config, Vitest names + * it ` ()`, so `vitest --project '*(unit)'` from the root + * selects that kind across the whole repo. Project-level overrides (timeouts, + * setup files) layer on top. + * + * Stack-backed e2e files claim machine-level resources, so `e2e-stack` runs one + * file at a time by default. Vitest schedules that serial group after the + * parallel projects finish. + */ +export function testProject( + kind: TestKind, + overrides: TestProjectInlineConfiguration = {}, +): TestProjectInlineConfiguration { + const spec = testKinds[kind]; + const serial = kind === "e2e-stack" ? { fileParallelism: false, maxWorkers: 1 } : {}; + return { + ...overrides, + test: { + ...serial, + ...overrides.test, + name: kind, + include: [spec.include], + ...(spec.exclude ? { exclude: spec.exclude } : {}), + }, + }; +} + +/** + * Run-level options that Vitest applies only from the root config of a run. + * Set on the repo-root config and on every package config (for standalone runs). + */ +export const runDefaults = { + passWithNoTests: true, + // Console output from passing tests is noise; failing tests still print theirs. + silent: "passed-only", +} as const satisfies TestUserConfig; + +const packageDefaults: ViteUserConfig = defineConfig({ + // Workspace packages such as @supabase/config, @supabase/stack, and + // @supabase/api publish a `bun` export condition pointing at their TypeScript + // source. Without it Vite falls through to the `default` condition and loads + // built `dist/*.js` output, which is stale or missing on a fresh clone. + // Extending (not replacing) Vite's default condition lists leaves every other + // package's exports resolution unchanged. Vitest 5 inherits these into the + // inline projects declared below each package config. + resolve: { conditions: [...defaultClientConditions, "bun"] }, + ssr: { resolve: { conditions: [...defaultServerConditions, "bun"] } }, + test: { + ...runDefaults, + // Coverage is a run-level option too, so this only applies to standalone + // package runs (`pnpm test:unit --coverage.enabled`). Each package's + // `test:*:run` script points `reportsDirectory` at a per-kind subdirectory. + coverage: { + enabled: false, + provider: "v8", + clean: false, + include: ["src/**/*.ts"], + reporter: ["text", "lcov"], + reportsDirectory: "coverage", + }, + }, +}); + +/** A package's Vitest config: the shared preset with package-specific options merged on top. */ +export function definePackageConfig(config: ViteUserConfig): ViteUserConfig { + return mergeConfig(packageDefaults, config); +}