diff --git a/.changeset/hot-ravens-roll.md b/.changeset/hot-ravens-roll.md new file mode 100644 index 000000000000..397229d9f188 --- /dev/null +++ b/.changeset/hot-ravens-roll.md @@ -0,0 +1,5 @@ +--- +"@cloudflare/vitest-pool-workers": minor +--- + +Support Vitest v3. While this drops testing for Vitest v2, we expect Vitest v2 will continue to work as well. diff --git a/fixtures/additional-modules/test/index.test.ts b/fixtures/additional-modules/test/index.test.ts index d2e06519e009..d31f18983387 100644 --- a/fixtures/additional-modules/test/index.test.ts +++ b/fixtures/additional-modules/test/index.test.ts @@ -6,33 +6,19 @@ import os from "node:os"; import path from "node:path"; import { setTimeout } from "node:timers/promises"; import { fetch } from "undici"; -import { afterAll, beforeAll, describe, expect, test } from "vitest"; -import { - runWranglerDev, - wranglerEntryPath, -} from "../../shared/src/run-wrangler-long-lived"; +import { afterAll, beforeAll, describe, expect, test, vi } from "vitest"; +import { unstable_startWorker } from "wrangler"; +import { wranglerEntryPath } from "../../shared/src/run-wrangler-long-lived"; async function getTmpDir() { return fs.mkdtemp(path.join(os.tmpdir(), "wrangler-modules-")); } -type WranglerDev = Awaited>; +type WranglerDev = Awaited>; function get(worker: WranglerDev, pathname: string) { - const url = `http://${worker.ip}:${worker.port}${pathname}`; + const url = `http://example.com${pathname}`; // Disable Miniflare's pretty error page, so we can parse errors as JSON - return fetch(url, { headers: { "MF-Disable-Pretty-Error": "true" } }); -} - -async function retry(closure: () => Promise, max = 30): Promise { - for (let attempt = 1; attempt <= max; attempt++) { - try { - return await closure(); - } catch (e) { - if (attempt === max) throw e; - } - await setTimeout(1_000); - } - assert.fail("Unreachable"); + return worker.fetch(url, { headers: { "MF-Disable-Pretty-Error": "true" } }); } describe("find_additional_modules dev", () => { @@ -52,10 +38,12 @@ describe("find_additional_modules dev", () => { path.join(tmpDir, "wrangler.toml") ); - worker = await runWranglerDev(tmpDir, ["--port=0", "--inspector-port=0"]); + worker = await unstable_startWorker({ + config: path.join(tmpDir, "wrangler.toml"), + }); }); afterAll(async () => { - await worker.stop(); + await worker.dispose(); try { await fs.rm(tmpDir, { recursive: true, force: true }); } catch (e) { @@ -102,20 +90,19 @@ describe("find_additional_modules dev", () => { path.join(srcDir, "dynamic.js"), 'export default "new dynamic";' ); - await retry(async () => { + await vi.waitFor(async () => { const res = await get(worker, "/dynamic"); assert.strictEqual(await res.text(), "new dynamic"); }); // Delete dynamically imported file await fs.rm(path.join(srcDir, "lang", "en.js")); - const res = await retry(async () => { - const res = await get(worker, "/lang/en"); - assert.strictEqual(res.status, 500); - return res; + + await vi.waitFor(async () => { + await expect(get(worker, "/lang/en")).rejects.toThrowError( + 'No such module "lang/en.js".' + ); }); - const error = (await res.json()) as { message?: string }; - expect(error.message).toBe('No such module "lang/en.js".'); // Create new dynamically imported file in new directory await fs.mkdir(path.join(srcDir, "lang", "en")); @@ -123,7 +110,7 @@ describe("find_additional_modules dev", () => { path.join(srcDir, "lang", "en", "us.js"), 'export default { hello: "hey" };' ); - await retry(async () => { + await vi.waitFor(async () => { const res = await get(worker, "/lang/en/us"); assert.strictEqual(await res.text(), "hey"); }); @@ -133,7 +120,7 @@ describe("find_additional_modules dev", () => { path.join(srcDir, "lang", "en", "us.js"), 'export default { hello: "bye" };' ); - await retry(async () => { + await vi.waitFor(async () => { const res = await get(worker, "/lang/en/us"); assert.strictEqual(await res.text(), "bye"); }); diff --git a/fixtures/asset-config/vitest.config.ts b/fixtures/asset-config/vitest.config.ts index 34e3cac98de2..1e8546a425c9 100644 --- a/fixtures/asset-config/vitest.config.ts +++ b/fixtures/asset-config/vitest.config.ts @@ -33,7 +33,7 @@ export default defineWorkersConfig({ server: { deps: { // Vitest automatically adds `/^(?!.*node_modules).*\.mjs$/` as an - // `inline` RegExp: https://github.com/vitest-dev/vitest/blob/v2.1.1/packages/vitest/src/constants.ts#L9 + // `inline` RegExp: https://github.com/vitest-dev/vitest/blob/v3.0.5/packages/vitest/src/constants.ts#L9 // We'd like `packages/vitest-pool-workers/dist/pool/index.mjs` to be // externalised though. Unfortunately, `inline`s are checked before // `external`s, so there's no nice way we can override this. Instead, diff --git a/fixtures/entrypoints-rpc-tests/tests/entrypoints.spec.ts b/fixtures/entrypoints-rpc-tests/tests/entrypoints.spec.ts index 96f7a4501e44..09793c4038a7 100644 --- a/fixtures/entrypoints-rpc-tests/tests/entrypoints.spec.ts +++ b/fixtures/entrypoints-rpc-tests/tests/entrypoints.spec.ts @@ -4,7 +4,7 @@ import os from "node:os"; import path from "node:path"; import dedent from "ts-dedent"; import { Agent, fetch, setGlobalDispatcher } from "undici"; -import { test as baseTest, expect, vi } from "vitest"; +import { test as baseTest, describe, expect, vi } from "vitest"; import { unstable_startWorkerRegistryServer } from "wrangler"; import { runWranglerDev, @@ -95,10 +95,10 @@ const test = baseTest.extend<{ await Promise.allSettled(cleanups.map((fn) => fn())); }, }); - -test("should support binding to the same worker", async ({ dev }) => { - const { url } = await dev({ - "wrangler.toml": dedent` +describe("entrypoints", () => { + test("should support binding to the same worker", async ({ dev }) => { + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -106,7 +106,7 @@ test("should support binding to the same worker", async ({ dev }) => { binding = "SERVICE" service = "entry" `, - "index.ts": dedent` + "index.ts": dedent` export default { fetch(request, env, ctx) { const { pathname } = new URL(request.url); @@ -122,32 +122,34 @@ test("should support binding to the same worker", async ({ dev }) => { } } `, - }); + }); - const response = await fetch(url); - // Check protocol, host, and cf preserved - expect(await response.text()).toBe( - 'POST https://placeholder:9999/loopback {"thing":true}' - ); -}); + const response = await fetch(url); + // Check protocol, host, and cf preserved + expect(await response.text()).toBe( + 'POST https://placeholder:9999/loopback {"thing":true}' + ); + }); -test("should support default ExportedHandler entrypoints", async ({ dev }) => { - await dev({ - "wrangler.toml": dedent` + test("should support default ExportedHandler entrypoints", async ({ + dev, + }) => { + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` export default { fetch(request, env, ctx) { return new Response(\`\${request.method} \${request.url} \${JSON.stringify(request.cf)}\`); } }; `, - }); + }); - const { url } = await dev({ - "wrangler.toml": dedent` + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -155,7 +157,7 @@ test("should support default ExportedHandler entrypoints", async ({ dev }) => { binding = "SERVICE" service = "bound" `, - "index.ts": dedent` + "index.ts": dedent` export default { fetch(request, env, ctx) { return env.SERVICE.fetch("https://placeholder:9999/", { @@ -165,23 +167,25 @@ test("should support default ExportedHandler entrypoints", async ({ dev }) => { } } `, - }); + }); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - // Check protocol, host, and cf preserved - expect(text).toBe('POST https://placeholder:9999/ {"thing":true}'); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + // Check protocol, host, and cf preserved + expect(text).toBe('POST https://placeholder:9999/ {"thing":true}'); + }); }); -}); -test("should support default WorkerEntrypoint entrypoints", async ({ dev }) => { - await dev({ - "wrangler.toml": dedent` + test("should support default WorkerEntrypoint entrypoints", async ({ + dev, + }) => { + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; // Check middleware is transparent to RPC export default class ThingEntrypoint extends WorkerEntrypoint { @@ -193,10 +197,10 @@ test("should support default WorkerEntrypoint entrypoints", async ({ dev }) => { } }; `, - }); + }); - const { url } = await dev({ - "wrangler.toml": dedent` + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -204,7 +208,7 @@ test("should support default WorkerEntrypoint entrypoints", async ({ dev }) => { binding = "SERVICE" service = "bound" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { const response = await env.SERVICE.fetch("https://placeholder:9999/", { @@ -217,21 +221,21 @@ test("should support default WorkerEntrypoint entrypoints", async ({ dev }) => { } } `, - }); + }); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - // Check protocol, host, and cf preserved - expect(text).toBe('POST https://placeholder:9999/ {"thing":true} pong'); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + // Check protocol, host, and cf preserved + expect(text).toBe('POST https://placeholder:9999/ {"thing":true} pong'); + }); }); -}); -test("should support middleware with default WorkerEntrypoint entrypoints", async ({ - dev, -}) => { - const files: Record = { - "wrangler.toml": dedent` + test("should support middleware with default WorkerEntrypoint entrypoints", async ({ + dev, + }) => { + const files: Record = { + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -239,7 +243,7 @@ test("should support middleware with default WorkerEntrypoint entrypoints", asyn binding = "SERVICE" service = "entry" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; let lastController; export default class TestEntrypoint extends WorkerEntrypoint { @@ -254,32 +258,32 @@ test("should support middleware with default WorkerEntrypoint entrypoints", asyn } } `, - }; - const { url } = await dev(files, ["--test-scheduled"]); - - let response = await fetch(url); - expect(await response.text()).toBe("GET /"); - - // Check other events can be dispatched - response = await fetch(new URL("/__scheduled?cron=* * * * 30", url)); - expect(response.status).toBe(200); - expect(await response.text()).toBe("Ran scheduled event"); - response = await fetch(new URL("/controller", url)); - expect(response.status).toBe(200); - expect(await response.text()).toBe("* * * * 30"); - - // Check multiple middleware can be registered - response = await fetch(new URL("/throw", url)); - expect(response.status).toBe(500); - expect(response.headers.get("Content-Type")).toMatch(/text\/html/); - expect(await response.text()).toMatch("Oops!"); -}); - -test("should support named ExportedHandler entrypoints to itself", async ({ - dev, -}) => { - const { url } = await dev({ - "wrangler.toml": dedent` + }; + const { url } = await dev(files, ["--test-scheduled"]); + + let response = await fetch(url); + expect(await response.text()).toBe("GET /"); + + // Check other events can be dispatched + response = await fetch(new URL("/__scheduled?cron=* * * * 30", url)); + expect(response.status).toBe(200); + expect(await response.text()).toBe("Ran scheduled event"); + response = await fetch(new URL("/controller", url)); + expect(response.status).toBe(200); + expect(await response.text()).toBe("* * * * 30"); + + // Check multiple middleware can be registered + response = await fetch(new URL("/throw", url)); + expect(response.status).toBe(500); + expect(response.headers.get("Content-Type")).toMatch(/text\/html/); + expect(await response.text()).toMatch("Oops!"); + }); + + test("should support named ExportedHandler entrypoints to itself", async ({ + dev, + }) => { + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -288,7 +292,7 @@ test("should support named ExportedHandler entrypoints to itself", async ({ service = "entry" entrypoint = "ThingEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; export class ThingEntrypoint extends WorkerEntrypoint { fetch(request) { @@ -307,22 +311,22 @@ test("should support named ExportedHandler entrypoints to itself", async ({ } } `, - }); + }); - const response = await fetch(url); - // Check protocol, host, and cf preserved - expect(await response.text()).toBe( - 'POST https://placeholder:9999/ {"thing":true}' - ); -}); + const response = await fetch(url); + // Check protocol, host, and cf preserved + expect(await response.text()).toBe( + 'POST https://placeholder:9999/ {"thing":true}' + ); + }); -test("should support named ExportedHandler entrypoints", async ({ dev }) => { - await dev({ - "wrangler.toml": dedent` + test("should support named ExportedHandler entrypoints", async ({ dev }) => { + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` export const thing = { fetch(request, env, ctx) { return new Response(\`\${request.method} \${request.url} \${JSON.stringify(request.cf)}\`); @@ -330,10 +334,10 @@ test("should support named ExportedHandler entrypoints", async ({ dev }) => { }; export default {}; // Required to treat as modules format worker `, - }); + }); - const { url } = await dev({ - "wrangler.toml": dedent` + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -342,7 +346,7 @@ test("should support named ExportedHandler entrypoints", async ({ dev }) => { service = "bound" entrypoint = "thing" `, - "index.ts": dedent` + "index.ts": dedent` export default { fetch(request, env, ctx) { return env.SERVICE.fetch("https://placeholder:9999/", { @@ -352,23 +356,23 @@ test("should support named ExportedHandler entrypoints", async ({ dev }) => { } } `, - }); + }); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - // Check protocol, host, and cf preserved - expect(text).toBe('POST https://placeholder:9999/ {"thing":true}'); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + // Check protocol, host, and cf preserved + expect(text).toBe('POST https://placeholder:9999/ {"thing":true}'); + }); }); -}); -test("should support named WorkerEntrypoint entrypoints", async ({ dev }) => { - await dev({ - "wrangler.toml": dedent` + test("should support named WorkerEntrypoint entrypoints", async ({ dev }) => { + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; export class ThingEntrypoint extends WorkerEntrypoint { fetch(request) { @@ -380,10 +384,10 @@ test("should support named WorkerEntrypoint entrypoints", async ({ dev }) => { }; export default {}; // Required to treat as modules format worker `, - }); + }); - const { url } = await dev({ - "wrangler.toml": dedent` + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -392,7 +396,7 @@ test("should support named WorkerEntrypoint entrypoints", async ({ dev }) => { service = "bound" entrypoint = "ThingEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { const response = await env.SERVICE.fetch("https://placeholder:9999/", { @@ -405,23 +409,23 @@ test("should support named WorkerEntrypoint entrypoints", async ({ dev }) => { } } `, - }); + }); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - // Check protocol, host, and cf preserved - expect(text).toBe('POST https://placeholder:9999/ {"thing":true} pong'); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + // Check protocol, host, and cf preserved + expect(text).toBe('POST https://placeholder:9999/ {"thing":true} pong'); + }); }); -}); -test("should support named entrypoints in pages dev", async ({ dev }) => { - await dev({ - "wrangler.toml": dedent` + test("should support named entrypoints in pages dev", async ({ dev }) => { + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; export class ThingEntrypoint extends WorkerEntrypoint { ping() { @@ -430,31 +434,31 @@ test("should support named entrypoints in pages dev", async ({ dev }) => { }; export default {}; // Required to treat as modules format worker `, - }); + }); - const files = { - "functions/index.ts": dedent` + const files = { + "functions/index.ts": dedent` export const onRequest = async ({ env }) => { return new Response(await env.SERVICE.ping()); }; `, - }; - const { url } = await dev( - files, - ["--service=SERVICE=bound#ThingEntrypoint"], - /* pagesPublicPath */ "dist" - ); + }; + const { url } = await dev( + files, + ["--service=SERVICE=bound#ThingEntrypoint"], + /* pagesPublicPath */ "dist" + ); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - expect(text).toBe("pong"); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + expect(text).toBe("pong"); + }); }); -}); -test("should support co-dependent services", async ({ dev }) => { - const { url } = await dev({ - "wrangler.toml": dedent` + test("should support co-dependent services", async ({ dev }) => { + const { url } = await dev({ + "wrangler.toml": dedent` name = "a" main = "index.ts" @@ -463,7 +467,7 @@ test("should support co-dependent services", async ({ dev }) => { service = "b" entrypoint = "BEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; export class AEntrypoint extends WorkerEntrypoint { ping() { @@ -476,10 +480,10 @@ test("should support co-dependent services", async ({ dev }) => { } }; `, - }); + }); - await dev({ - "wrangler.toml": dedent` + await dev({ + "wrangler.toml": dedent` name = "b" main = "index.ts" @@ -488,7 +492,7 @@ test("should support co-dependent services", async ({ dev }) => { service = "a" entrypoint = "AEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; export class BEntrypoint extends WorkerEntrypoint { async ping() { @@ -498,22 +502,22 @@ test("should support co-dependent services", async ({ dev }) => { }; export default {}; // Required to treat as modules format worker `, - }); + }); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - expect(text).toBe("b:a:pong"); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + expect(text).toBe("b:a:pong"); + }); }); -}); -test("should support binding to Durable Object in another worker", async ({ - dev, -}) => { - // RPC isn't supported in this case yet :( + test("should support binding to Durable Object in another worker", async ({ + dev, + }) => { + // RPC isn't supported in this case yet :( - await dev({ - "wrangler.toml": dedent` + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" @@ -522,7 +526,7 @@ test("should support binding to Durable Object in another worker", async ({ { name = "OBJECT", class_name = "ThingObject" } ] `, - "index.ts": dedent` + "index.ts": dedent` import { DurableObject } from "cloudflare:workers"; export class ThingObject extends DurableObject { fetch(request) { @@ -537,10 +541,10 @@ test("should support binding to Durable Object in another worker", async ({ }; export default {}; // Required to treat as modules format worker `, - }); + }); - const { url } = await dev({ - "wrangler.toml": dedent` + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -549,7 +553,7 @@ test("should support binding to Durable Object in another worker", async ({ { name = "OBJECT", class_name = "ThingObject", script_name = "bound" } ] `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { const id = env.OBJECT.newUniqueId(); @@ -570,32 +574,32 @@ test("should support binding to Durable Object in another worker", async ({ } } `, - }); + }); - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - // Check protocol, host, and cf preserved - expect(text).toBe('POST https://placeholder:9999/ {"thing":true}'); - }); + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + // Check protocol, host, and cf preserved + expect(text).toBe('POST https://placeholder:9999/ {"thing":true}'); + }); - const rpcResponse = await fetch(new URL("/rpc", url)); - const errors = await rpcResponse.json(); - expect(errors).toMatchInlineSnapshot(` + const rpcResponse = await fetch(new URL("/rpc", url)); + const errors = await rpcResponse.json(); + expect(errors).toMatchInlineSnapshot(` [ "Error: Cannot access \`ThingObject#property\` as Durable Object RPC is not yet supported between multiple \`wrangler dev\` sessions.", "Error: Cannot access \`ThingObject#method\` as Durable Object RPC is not yet supported between multiple \`wrangler dev\` sessions.", ] `); -}); + }); -test("should support binding to Durable Object in same worker", async ({ - dev, -}) => { - // RPC is supported here though :) + test("should support binding to Durable Object in same worker", async ({ + dev, + }) => { + // RPC is supported here though :) - const { url } = await dev({ - "wrangler.toml": dedent` + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -604,7 +608,7 @@ test("should support binding to Durable Object in same worker", async ({ { name = "OBJECT", class_name = "ThingObject" } ] `, - "index.ts": dedent` + "index.ts": dedent` import { DurableObject } from "cloudflare:workers"; export class ThingObject extends DurableObject { ping() { @@ -619,17 +623,17 @@ test("should support binding to Durable Object in same worker", async ({ } } `, - }); + }); - const response = await fetch(url); - expect(await response.text()).toBe("pong"); -}); + const response = await fetch(url); + expect(await response.text()).toBe("pong"); + }); -test("should support binding to Durable Object in same worker with explicit script_name", async ({ - dev, -}) => { - const { url } = await dev({ - "wrangler.toml": dedent` + test("should support binding to Durable Object in same worker with explicit script_name", async ({ + dev, + }) => { + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -638,7 +642,7 @@ test("should support binding to Durable Object in same worker with explicit scri { name = "OBJECT", class_name = "ThingObject", script_name = "entry" } ] `, - "index.ts": dedent` + "index.ts": dedent` import { DurableObject } from "cloudflare:workers"; export class ThingObject extends DurableObject { ping() { @@ -653,20 +657,20 @@ test("should support binding to Durable Object in same worker with explicit scri } } `, - }); + }); - const response = await fetch(url); - expect(await response.text()).toBe("pong"); -}); + const response = await fetch(url); + expect(await response.text()).toBe("pong"); + }); -test("should throw if binding to named entrypoint exported by version of wrangler without entrypoints support", async ({ - dev, - isolatedDevRegistryPath, -}) => { - // Start entry worker first, so the server starts with a stubbed service not - // found binding - const { url, session } = await dev({ - "wrangler.toml": dedent` + test("should throw if binding to named entrypoint exported by version of wrangler without entrypoints support", async ({ + dev, + isolatedDevRegistryPath, + }) => { + // Start entry worker first, so the server starts with a stubbed service not + // found binding + const { url, session } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -675,50 +679,50 @@ test("should throw if binding to named entrypoint exported by version of wrangle service = "bound" entrypoint = "ThingEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { return env.SERVICE.fetch("https://placeholder:9999/"); } } `, - }); - let response = await fetch(url); - expect(response.status).toBe(503); - expect(await response.text()).toBe( - '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' - ); - - await writeFile( - path.join(isolatedDevRegistryPath, "bound"), - JSON.stringify({ - protocol: "http", - mode: "local", - port: 0, - host: "localhost", - durableObjects: [], - durableObjectsHost: "localhost", - durableObjectsPort: 0, - // Intentionally omitting `entrypointAddresses` - }) - ); - - // Wait for error to be thrown - await waitFor(() => { - const output = session.getOutput(); - expect(output).toMatch( - 'The `wrangler dev` session for service "bound" does not support proxying entrypoints. Please upgrade "bound"\'s `wrangler` version.' + }); + let response = await fetch(url); + expect(response.status).toBe(503); + expect(await response.text()).toBe( + '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' ); - }); -}); -test("should throw if wrangler session doesn't export expected entrypoint", async ({ - dev, -}) => { - // Start entry worker first, so the server starts with a stubbed service not - // found binding - const { url, session } = await dev({ - "wrangler.toml": dedent` + await writeFile( + path.join(isolatedDevRegistryPath, "bound"), + JSON.stringify({ + protocol: "http", + mode: "local", + port: 0, + host: "localhost", + durableObjects: [], + durableObjectsHost: "localhost", + durableObjectsPort: 0, + // Intentionally omitting `entrypointAddresses` + }) + ); + + // Wait for error to be thrown + await waitFor(() => { + const output = session.getOutput(); + expect(output).toMatch( + 'The `wrangler dev` session for service "bound" does not support proxying entrypoints. Please upgrade "bound"\'s `wrangler` version.' + ); + }); + }); + + test("should throw if wrangler session doesn't export expected entrypoint", async ({ + dev, + }) => { + // Start entry worker first, so the server starts with a stubbed service not + // found binding + const { url, session } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -727,26 +731,26 @@ test("should throw if wrangler session doesn't export expected entrypoint", asyn service = "bound" entrypoint = "ThingEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { return env.SERVICE.fetch("https://placeholder:9999/"); } } `, - }); - let response = await fetch(url); - expect(await response.text()).toBe( - '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' - ); - - // Start up the bound worker without the expected entrypoint - await dev({ - "wrangler.toml": dedent` + }); + let response = await fetch(url); + expect(await response.text()).toBe( + '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' + ); + + // Start up the bound worker without the expected entrypoint + await dev({ + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` import { WorkerEntrypoint } from "cloudflare:workers"; export class BadEntrypoint extends WorkerEntrypoint { fetch(request) { @@ -755,24 +759,24 @@ test("should throw if wrangler session doesn't export expected entrypoint", asyn }; export default {}; // Required to treat as modules format worker `, - }); + }); - // Wait for error to be thrown - await waitFor(() => { - const output = session.getOutput(); - expect(output).toMatch( - 'The `wrangler dev` session for service "bound" does not export an entrypoint named "ThingEntrypoint"' - ); + // Wait for error to be thrown + await waitFor(() => { + const output = session.getOutput(); + expect(output).toMatch( + 'The `wrangler dev` session for service "bound" does not export an entrypoint named "ThingEntrypoint"' + ); + }); }); -}); -test("should support binding to wrangler session listening on HTTPS", async ({ - dev, -}) => { - // Start entry worker first, so the server starts with a stubbed service not - // found binding - const { url, session } = await dev({ - "wrangler.toml": dedent` + test("should support binding to wrangler session listening on HTTPS", async ({ + dev, + }) => { + // Start entry worker first, so the server starts with a stubbed service not + // found binding + const { url, session } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -780,50 +784,50 @@ test("should support binding to wrangler session listening on HTTPS", async ({ binding = "SERVICE" service = "bound" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { return env.SERVICE.fetch("http://placeholder/"); } } `, - }); - let response = await fetch(url); - expect(await response.text()).toBe( - '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' - ); - - // Start up the bound worker using HTTPS - const files: Record = { - "wrangler.toml": dedent` + }); + let response = await fetch(url); + expect(await response.text()).toBe( + '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' + ); + + // Start up the bound worker using HTTPS + const files: Record = { + "wrangler.toml": dedent` name = "bound" main = "index.ts" `, - "index.ts": dedent` + "index.ts": dedent` export default { fetch() { return new Response("secure"); } }; `, - }; - await dev(files, ["--local-protocol=https"]); - - await waitFor(async () => { - const response = await fetch(url); - const text = await response.text(); - expect(text).toBe("secure"); - }); -}); - -test("should throw if binding to version of wrangler without entrypoints support over HTTPS", async ({ - dev, - isolatedDevRegistryPath, -}) => { - // Start entry worker first, so the server starts with a stubbed service not - // found binding - const { url, session } = await dev({ - "wrangler.toml": dedent` + }; + await dev(files, ["--local-protocol=https"]); + + await waitFor(async () => { + const response = await fetch(url); + const text = await response.text(); + expect(text).toBe("secure"); + }); + }); + + test("should throw if binding to version of wrangler without entrypoints support over HTTPS", async ({ + dev, + isolatedDevRegistryPath, + }) => { + // Start entry worker first, so the server starts with a stubbed service not + // found binding + const { url, session } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -831,47 +835,47 @@ test("should throw if binding to version of wrangler without entrypoints support binding = "SERVICE" service = "bound" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { return env.SERVICE.fetch("http://placeholder/"); } } `, - }); - let response = await fetch(url); - expect(await response.text()).toBe( - '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' - ); - - await writeFile( - path.join(isolatedDevRegistryPath, "bound"), - JSON.stringify({ - protocol: "https", - mode: "local", - port: 0, - host: "localhost", - durableObjects: [], - durableObjectsHost: "localhost", - durableObjectsPort: 0, - // Intentionally omitting `entrypointAddresses` - }) - ); - - // Wait for error to be thrown - await waitFor(() => { - const output = session.getOutput(); - expect(output).toMatch( - 'Cannot proxy to `wrangler dev` session for service "bound" because it uses HTTPS. Please upgrade "bound"\'s `wrangler` version, or remove the `--local-protocol`/`dev.local_protocol` option.' + }); + let response = await fetch(url); + expect(await response.text()).toBe( + '[wrangler] Couldn\'t find `wrangler dev` session for service "bound" to proxy to' + ); + + await writeFile( + path.join(isolatedDevRegistryPath, "bound"), + JSON.stringify({ + protocol: "https", + mode: "local", + port: 0, + host: "localhost", + durableObjects: [], + durableObjectsHost: "localhost", + durableObjectsPort: 0, + // Intentionally omitting `entrypointAddresses` + }) ); + + // Wait for error to be thrown + await waitFor(() => { + const output = session.getOutput(); + expect(output).toMatch( + 'Cannot proxy to `wrangler dev` session for service "bound" because it uses HTTPS. Please upgrade "bound"\'s `wrangler` version, or remove the `--local-protocol`/`dev.local_protocol` option.' + ); + }); }); -}); -test("should throw if performing RPC with session that hasn't started", async ({ - dev, -}) => { - const { url } = await dev({ - "wrangler.toml": dedent` + test("should throw if performing RPC with session that hasn't started", async ({ + dev, + }) => { + const { url } = await dev({ + "wrangler.toml": dedent` name = "entry" main = "index.ts" @@ -880,7 +884,7 @@ test("should throw if performing RPC with session that hasn't started", async ({ service = "bound" entrypoint = "ThingEntrypoint" `, - "index.ts": dedent` + "index.ts": dedent` export default { async fetch(request, env, ctx) { const errors = []; @@ -890,14 +894,15 @@ test("should throw if performing RPC with session that hasn't started", async ({ } } `, - }); + }); - const response = await fetch(url); - const errors = await response.json(); - expect(errors).toMatchInlineSnapshot(` + const response = await fetch(url); + const errors = await response.json(); + expect(errors).toMatchInlineSnapshot(` [ "Error: Cannot access \`property\` as we couldn't find a \`wrangler dev\` session for service "bound" to proxy to.", "Error: Cannot access \`method\` as we couldn't find a \`wrangler dev\` session for service "bound" to proxy to.", ] `); + }); }); diff --git a/fixtures/pages-redirected-config/tests/index.test.ts b/fixtures/pages-redirected-config/tests/index.test.ts index e30c7fec1f73..36de5bb44274 100644 --- a/fixtures/pages-redirected-config/tests/index.test.ts +++ b/fixtures/pages-redirected-config/tests/index.test.ts @@ -1,5 +1,5 @@ import { rmSync, writeFileSync } from "fs"; -import { resolve } from "path"; +import path, { resolve } from "path"; import { fetch } from "undici"; import { describe, it } from "vitest"; import { runWranglerPagesDev } from "../../shared/src/run-wrangler-long-lived"; @@ -29,7 +29,7 @@ describe("wrangler pages dev", () => { onTestFinished, }) => { writeFileSync( - "wrangler.toml", + path.join(basePath, "wrangler.toml"), [ `name = "redirected-config-worker"`, `compatibility_date = "2024-12-01"`, @@ -41,7 +41,7 @@ describe("wrangler pages dev", () => { "--inspector-port=0", ]); onTestFinished(async () => { - rmSync("wrangler.toml", { force: true }); + rmSync(path.join(basePath, "wrangler.toml"), { force: true }); await stop?.(); }); diff --git a/fixtures/pages-workerjs-app/tests/index.test.ts b/fixtures/pages-workerjs-app/tests/index.test.ts index 34398e2b43be..92a2a09fa824 100644 --- a/fixtures/pages-workerjs-app/tests/index.test.ts +++ b/fixtures/pages-workerjs-app/tests/index.test.ts @@ -79,7 +79,7 @@ describe("Pages _worker.js", () => { "workerjs-test/_worker.js", "workerjs-test/XXX_worker.js" ); - await setTimeout(1000); + await setTimeout(200); // Expect no output since the deletion of the worker should be ignored expect(getOutput()).toBe(""); await tryRename( @@ -87,7 +87,7 @@ describe("Pages _worker.js", () => { "workerjs-test/XXX_worker.js", "workerjs-test/_worker.js" ); - await setTimeout(1000); + await setTimeout(200); // Expect replacing the worker to now trigger a success build. expect(getOutput()).toContain("Compiled Worker successfully"); } finally { @@ -116,7 +116,7 @@ describe("Pages _worker.js", () => { "workerjs-test/_routes.json", "workerjs-test/XXX_routes.json" ); - await setTimeout(1000); + await setTimeout(200); // Expect no output since the deletion of the routes file should be ignored expect(getOutput()).toBe(""); await tryRename( @@ -124,7 +124,7 @@ describe("Pages _worker.js", () => { "workerjs-test/XXX_routes.json", "workerjs-test/_routes.json" ); - await setTimeout(1000); + await setTimeout(200); // Expect replacing the routes file to trigger a build, although // the routes build does not provide any output feedback to compare against, // so we just check that nothing else is being printed. diff --git a/fixtures/ratelimit-app/tests/index.test.ts b/fixtures/ratelimit-app/tests/index.test.ts index fe5f46785343..0663de1b3e5e 100644 --- a/fixtures/ratelimit-app/tests/index.test.ts +++ b/fixtures/ratelimit-app/tests/index.test.ts @@ -1,35 +1,32 @@ -import { resolve } from "path"; -import { fetch } from "undici"; +import path, { resolve } from "path"; import { afterAll, beforeAll, describe, it } from "vitest"; -import { runWranglerDev } from "../../shared/src/run-wrangler-long-lived"; +import { unstable_startWorker } from "wrangler"; + +const basePath = resolve(__dirname, ".."); describe("'wrangler dev' correctly renders pages", () => { - let ip: string, - port: number, - stop: (() => Promise) | undefined, - getOutput: () => string; + let worker: Awaited>; beforeAll(async () => { - ({ ip, port, stop, getOutput } = await runWranglerDev( - resolve(__dirname, ".."), - ["--local", "--port=0", "--inspector-port=0"] - )); + worker = await unstable_startWorker({ + config: path.join(basePath, "wrangler.toml"), + }); }); afterAll(async () => { - await stop?.(); + await worker.dispose(); }); it("ratelimit binding is defined ", async ({ expect }) => { - let response = await fetch(`http://${ip}:${port}/`); + let response = await worker.fetch(`http://example.com`); let content = await response.text(); expect(content).toEqual("Success"); - response = await fetch(`http://${ip}:${port}/`); + response = await worker.fetch(`http://example.com`); content = await response.text(); expect(content).toEqual("Success"); - response = await fetch(`http://${ip}:${port}/`); + response = await worker.fetch(`http://example.com`); content = await response.text(); expect(content).toEqual("Slow down"); }); diff --git a/fixtures/shared/src/mock-console.ts b/fixtures/shared/src/mock-console.ts new file mode 100644 index 000000000000..85283e4b1450 --- /dev/null +++ b/fixtures/shared/src/mock-console.ts @@ -0,0 +1,60 @@ +import * as util from "node:util"; +import { afterEach, beforeEach, vi } from "vitest"; +import type { MockInstance } from "vitest"; + +/** + * We use this module to mock console methods, and optionally + * assert on the values they're called with in our tests. + */ + +let debugSpy: MockInstance, + logSpy: MockInstance, + infoSpy: MockInstance, + errorSpy: MockInstance, + warnSpy: MockInstance; + +const std = { + get debug() { + return normalizeOutput(debugSpy); + }, + get out() { + return normalizeOutput(logSpy); + }, + get info() { + return normalizeOutput(infoSpy); + }, + get err() { + return normalizeOutput(errorSpy); + }, + get warn() { + return normalizeOutput(warnSpy); + }, +}; + +function normalizeOutput(spy: MockInstance, join = "\n"): string { + return captureCalls(spy, join); +} + +function captureCalls(spy: MockInstance, join = "\n"): string { + return spy.mock.calls + .map((args: unknown[]) => util.format("%s", ...args)) + .join(join); +} + +export function mockConsoleMethods() { + beforeEach(() => { + debugSpy = vi.spyOn(console, "debug").mockImplementation(() => {}); + logSpy = vi.spyOn(console, "log").mockImplementation(() => {}); + infoSpy = vi.spyOn(console, "info").mockImplementation(() => {}); + errorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); + warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); + }); + afterEach(() => { + debugSpy.mockRestore(); + logSpy.mockRestore(); + infoSpy.mockRestore(); + errorSpy.mockRestore(); + warnSpy.mockRestore(); + }); + return std; +} diff --git a/fixtures/type-generation/vitest.config.mts b/fixtures/type-generation/vitest.config.mts index 74c6ea85d13a..a6fb54404864 100644 --- a/fixtures/type-generation/vitest.config.mts +++ b/fixtures/type-generation/vitest.config.mts @@ -2,9 +2,8 @@ import { defineConfig } from "vitest/config"; export default defineConfig({ test: { - testTimeout: 25_000, + testTimeout: 60_000, hookTimeout: 25_000, teardownTimeout: 25_000, - useAtomics: true, }, }); diff --git a/fixtures/worker-app/tests/env-vars.test.ts b/fixtures/worker-app/tests/env-vars.test.ts index afe88425e76a..14587af94153 100644 --- a/fixtures/worker-app/tests/env-vars.test.ts +++ b/fixtures/worker-app/tests/env-vars.test.ts @@ -5,6 +5,8 @@ import { join, resolve } from "path"; import { beforeEach, describe, it } from "vitest"; import { wranglerEntryPath } from "../../shared/src/run-wrangler-long-lived"; +const basePath = resolve(__dirname, ".."); + describe("'wrangler dev' with WRANGLER_BUILD_CONDITIONS", () => { let tempDir: string; @@ -23,6 +25,7 @@ describe("'wrangler dev' with WRANGLER_BUILD_CONDITIONS", () => { ...process.env, WRANGLER_BUILD_CONDITIONS: "other,node,browser", }, + cwd: basePath, } ); expect(readFileSync(resolve(tempDir, "index.js"), "utf8")).toContain( @@ -41,6 +44,7 @@ describe("'wrangler dev' with WRANGLER_BUILD_CONDITIONS", () => { ...process.env, WRANGLER_BUILD_CONDITIONS: "", }, + cwd: basePath, } ); expect(readFileSync(resolve(tempDir, "index.js"), "utf8")).toContain( @@ -61,6 +65,7 @@ describe("'wrangler build' with WRANGLER_BUILD_PLATFORM", () => { ...process.env, WRANGLER_BUILD_PLATFORM: "node", }, + cwd: basePath, } ); expect( @@ -79,6 +84,7 @@ describe("'wrangler build' with WRANGLER_BUILD_PLATFORM", () => { ...process.env, WRANGLER_BUILD_PLATFORM: "browser", }, + cwd: basePath, } ); expect( diff --git a/packages/create-cloudflare/e2e-tests/helpers.ts b/packages/create-cloudflare/e2e-tests/helpers.ts index 38935c546a00..0906625b819e 100644 --- a/packages/create-cloudflare/e2e-tests/helpers.ts +++ b/packages/create-cloudflare/e2e-tests/helpers.ts @@ -24,7 +24,7 @@ import type { SpawnOptionsWithoutStdio, } from "child_process"; import type { Writable } from "stream"; -import type { RunnerTestCase, Suite, Test } from "vitest"; +import type { RunnerTask, RunnerTestSuite } from "vitest"; export const C3_E2E_PREFIX = "tmp-e2e-c3"; @@ -333,7 +333,7 @@ export const waitForExit = async ( const createTestLogStream = ( opts: { experimental: boolean }, - task: RunnerTestCase, + task: RunnerTask, ) => { // The .ansi extension allows for editor extensions that format ansi terminal codes const fileName = `${normalizeTestName(task)}.ansi`; @@ -350,7 +350,7 @@ const createTestLogStream = ( export const recreateLogFolder = ( opts: { experimental: boolean }, - suite: Suite, + suite: RunnerTestSuite, ) => { // Clean the old folder if exists (useful for dev) rmSync(getLogPath(opts, suite), { @@ -361,7 +361,10 @@ export const recreateLogFolder = ( mkdirSync(getLogPath(opts, suite), { recursive: true }); }; -const getLogPath = (opts: { experimental: boolean }, suite: Suite) => { +const getLogPath = ( + opts: { experimental: boolean }, + suite: RunnerTestSuite, +) => { const { file } = suite; const suiteFilename = file @@ -375,7 +378,7 @@ const getLogPath = (opts: { experimental: boolean }, suite: Suite) => { ); }; -const normalizeTestName = (task: Test) => { +const normalizeTestName = (task: RunnerTask) => { const baseName = task.name .toLowerCase() .replace(/\s+/g, "_") // replace any whitespace with `_` diff --git a/packages/pages-shared/package.json b/packages/pages-shared/package.json index ca87b30a75e0..71a74bbcb893 100644 --- a/packages/pages-shared/package.json +++ b/packages/pages-shared/package.json @@ -29,7 +29,8 @@ "@miniflare/html-rewriter": "^2.14.4", "@miniflare/storage-memory": "^2.14.4", "concurrently": "^8.2.2", - "glob": "^10.4.5" + "glob": "^10.4.5", + "vitest": "~2.1.0" }, "volta": { "extends": "../../package.json" diff --git a/packages/vitest-pool-workers/package.json b/packages/vitest-pool-workers/package.json index ac841cd51c22..e3cfa0ab219e 100644 --- a/packages/vitest-pool-workers/package.json +++ b/packages/vitest-pool-workers/package.json @@ -77,9 +77,9 @@ "vitest": "catalog:default" }, "peerDependencies": { - "@vitest/runner": "2.0.x - 2.1.x", - "@vitest/snapshot": "2.0.x - 2.1.x", - "vitest": "2.0.x - 2.1.x" + "@vitest/runner": "2.0.x - 3.0.x", + "@vitest/snapshot": "2.0.x - 3.0.x", + "vitest": "2.0.x - 3.0.x" }, "volta": { "extends": "../../package.json" diff --git a/packages/vitest-pool-workers/src/config/index.ts b/packages/vitest-pool-workers/src/config/index.ts index 7d702c02c642..ba96be5e98c9 100644 --- a/packages/vitest-pool-workers/src/config/index.ts +++ b/packages/vitest-pool-workers/src/config/index.ts @@ -125,7 +125,7 @@ function createConfigPlugin(): Plugin { }, }, // Run after `vitest:project` plugin: - // https://github.com/vitest-dev/vitest/blob/v2.1.1/packages/vitest/src/node/plugins/workspace.ts#L34 + // https://github.com/vitest-dev/vitest/blob/v3.0.5/packages/vitest/src/node/plugins/workspace.ts#L37 config(config) { config.resolve ??= {}; config.resolve.conditions ??= []; @@ -142,7 +142,7 @@ function createConfigPlugin(): Plugin { ensureArrayIncludes(config.resolve.conditions, requiredConditions); // Vitest sets this to an empty array if unset, so restore Vite defaults: - // https://github.com/vitest-dev/vitest/blob/v2.1.1/packages/vitest/src/node/plugins/index.ts#L93 + // https://github.com/vitest-dev/vitest/blob/v3.0.5/packages/vitest/src/node/plugins/utils.ts#L156 ensureArrayIncludes(config.resolve.mainFields, requiredMainFields); // Apply `package.json` `browser` field remapping in SSR mode: diff --git a/packages/vitest-pool-workers/src/pool/index.ts b/packages/vitest-pool-workers/src/pool/index.ts index e594b408128b..f9ac2e324ec8 100644 --- a/packages/vitest-pool-workers/src/pool/index.ts +++ b/packages/vitest-pool-workers/src/pool/index.ts @@ -63,7 +63,12 @@ import type { SerializedConfig, WorkerContext, } from "vitest"; -import type { ProcessPool, Vitest, WorkspaceProject } from "vitest/node"; +import type { + ProcessPool, + TestSpecification, + Vitest, + WorkspaceProject, +} from "vitest/node"; interface SerializedOptions { main?: string; @@ -532,6 +537,7 @@ function getModuleFallbackService(ctx: Vitest): ModuleFallbackService { if (service !== undefined) { return service; } + // @ts-expect-error ctx.vitenode is marked as internal service = handleModuleFallbackRequest.bind(undefined, ctx.vitenode.server); moduleFallbackServices.set(ctx, service); return service; @@ -648,7 +654,8 @@ async function runTests( project: Project, config: SerializedConfig, files: string[], - invalidates: string[] = [] + invalidates: string[] = [], + method: "run" | "collect" ) { let workerPath = path.join(ctx.distPath, "worker.js"); let threadsWorkerPath = path.join(ctx.distPath, "workers", "threads.js"); @@ -699,7 +706,7 @@ async function runTests( Upgrade: "websocket", "MF-Vitest-Worker-Data": structuredSerializableStringify({ filePath: workerPath, - name: "run", + name: method, data, cwd: process.cwd(), }), @@ -864,179 +871,191 @@ function assertCompatibleVitestVersion(ctx: Vitest) { log.warn(message); } } +async function executeMethod( + ctx: Vitest, + specs: TestSpecification[], + invalidates: string[] | undefined, + method: "run" | "collect" +) { + // Vitest waits for the previous `runTests()` to complete before calling + // `runTests()` again: + // https://github.com/vitest-dev/vitest/blob/v1.0.4/packages/vitest/src/node/core.ts#L458-L459 + // This behaviour is required for stacked storage to work correctly. + // If we had concurrent runs, stack pushes/pops would interfere. We should + // always have an empty, fully-popped stacked at the end of a run. + + // 1. Collect new specs + const parsedProjectOptions = new Set(); + for (const [project, testFile] of specs) { + // Vitest validates all project names are unique + const projectName = project.getName(); + let workersProject = allProjects.get(projectName); + // Parse project options once per project per re-run + if (workersProject === undefined) { + workersProject = { + project, + options: await parseProjectOptions(project), + testFiles: new Set(), + relativePath: getRelativeProjectPath(project), + }; + allProjects.set(projectName, workersProject); + } else if (!parsedProjectOptions.has(project)) { + workersProject.project = project; + workersProject.options = await parseProjectOptions(project); + workersProject.relativePath = getRelativeProjectPath(project); + } + workersProject.testFiles.add(testFile); -export default function (ctx: Vitest): ProcessPool { - // This function is called when config changes and may be called on re-runs - assertCompatibleVitestVersion(ctx); + parsedProjectOptions.add(project); + } - return { - name: "vitest-pool-workers", - async runTests(specs, invalidates) { - // Vitest waits for the previous `runTests()` to complete before calling - // `runTests()` again: - // https://github.com/vitest-dev/vitest/blob/v1.0.4/packages/vitest/src/node/core.ts#L458-L459 - // This behaviour is required for stacked storage to work correctly. - // If we had concurrent runs, stack pushes/pops would interfere. We should - // always have an empty, fully-popped stacked at the end of a run. - - // 1. Collect new specs - const parsedProjectOptions = new Set(); - for (const [project, testFile] of specs) { - // Vitest validates all project names are unique - const projectName = project.getName(); - let workersProject = allProjects.get(projectName); - // Parse project options once per project per re-run - if (workersProject === undefined) { - workersProject = { - project, - options: await parseProjectOptions(project), - testFiles: new Set(), - relativePath: getRelativeProjectPath(project), - }; - allProjects.set(projectName, workersProject); - } else if (!parsedProjectOptions.has(project)) { - workersProject.project = project; - workersProject.options = await parseProjectOptions(project); - workersProject.relativePath = getRelativeProjectPath(project); - } - workersProject.testFiles.add(testFile); + // 2. Run just the required tests + const resultPromises: Promise[] = []; + const filesByProject = new Map(); + for (const [project, file] of specs) { + let group = filesByProject.get(project); + if (group === undefined) { + filesByProject.set(project, (group = [])); + } + group.push(file); + } + for (const [workspaceProject, files] of filesByProject) { + const project = allProjects.get(workspaceProject.getName()); + assert(project !== undefined); // Defined earlier in this function + const options = project.options; + + const config = workspaceProject.getSerializableConfig(); + + // Use our custom test runner. We don't currently support custom + // runners, since we need our own for isolated storage/fetch mock resets + // to work properly. There aren't many use cases where a user would need + // to control this. + config.runner = "cloudflare:test-runner"; + + // Make sure `setImmediate` and `clearImmediate` are never faked as they + // don't exist on the workers global scope + config.fakeTimers.toFake = config.fakeTimers.toFake?.filter( + (timerMethod) => + timerMethod !== "setImmediate" && timerMethod !== "clearImmediate" + ); - parsedProjectOptions.add(project); - } + // We don't need all pool options from the config at runtime. + // Additionally, users may set symbols in the config which aren't + // serialisable. `getSerializableConfig()` may also return references to + // the same objects, so override it with a new object. + config.poolOptions = { + // @ts-expect-error Vitest provides no way to extend this type + threads: { + // Allow workers to be re-used by removing the isolation requirement + isolate: false, + }, + workers: { + // Include resolved `main` if defined, and the names of Durable Object + // bindings that point to classes in the current isolate in the + // serialized config + main: maybeGetResolvedMainPath(project), + // Include designators of all Durable Object namespaces bound in the + // runner worker. We'll use this to list IDs in a namespace. We'll + // also use this to check Durable Object test runner helpers are + // only used with classes defined in the current worker, as these + // helpers rely on wrapping the object. + durableObjectBindingDesignators: getDurableObjectDesignators( + project.options + ), + // Include whether isolated storage has been enabled for this + // project, so we know whether to call out to the loopback service + // to push/pop the storage stack between tests. + isolatedStorage: project.options.isolatedStorage, + } satisfies SerializedOptions, + }; - // 2. Run just the required tests - const resultPromises: Promise[] = []; - const filesByProject = new Map(); - for (const [project, file] of specs) { - let group = filesByProject.get(project); - if (group === undefined) { - filesByProject.set(project, (group = [])); - } - group.push(file); + const mf = await getProjectMiniflare(ctx, project); + if (options.singleWorker) { + // Single Worker, Isolated or Shared Storage + // --> single instance with single runner worker + assert(mf instanceof Miniflare, "Expected single instance"); + const name = getRunnerName(workspaceProject); + resultPromises.push( + runTests(ctx, mf, name, project, config, files, invalidates, method) + ); + } else if (options.isolatedStorage) { + // Multiple Workers, Isolated Storage: + // --> multiple instances each with single runner worker + assert(mf instanceof Map, "Expected multiple isolated instances"); + const name = getRunnerName(workspaceProject); + for (const file of files) { + const fileMf = mf.get(file); + assert(fileMf !== undefined); + resultPromises.push( + runTests( + ctx, + fileMf, + name, + project, + config, + [file], + invalidates, + method + ) + ); } - for (const [workspaceProject, files] of filesByProject) { - const project = allProjects.get(workspaceProject.getName()); - assert(project !== undefined); // Defined earlier in this function - const options = project.options; - - const config = workspaceProject.getSerializableConfig(); - - // Use our custom test runner. We don't currently support custom - // runners, since we need our own for isolated storage/fetch mock resets - // to work properly. There aren't many use cases where a user would need - // to control this. - config.runner = "cloudflare:test-runner"; - - // Make sure `setImmediate` and `clearImmediate` are never faked as they - // don't exist on the workers global scope - config.fakeTimers.toFake = config.fakeTimers.toFake?.filter( - (method) => method !== "setImmediate" && method !== "clearImmediate" + } else { + // Multiple Workers, Shared Storage: + // --> single instance with multiple runner workers + assert(mf instanceof Miniflare, "Expected single instance"); + for (const file of files) { + const name = getRunnerName(workspaceProject, file); + resultPromises.push( + runTests(ctx, mf, name, project, config, [file], invalidates, method) ); - - // We don't need all pool options from the config at runtime. - // Additionally, users may set symbols in the config which aren't - // serialisable. `getSerializableConfig()` may also return references to - // the same objects, so override it with a new object. - config.poolOptions = { - // @ts-expect-error Vitest provides no way to extend this type - threads: { - // Allow workers to be re-used by removing the isolation requirement - isolate: false, - }, - workers: { - // Include resolved `main` if defined, and the names of Durable Object - // bindings that point to classes in the current isolate in the - // serialized config - main: maybeGetResolvedMainPath(project), - // Include designators of all Durable Object namespaces bound in the - // runner worker. We'll use this to list IDs in a namespace. We'll - // also use this to check Durable Object test runner helpers are - // only used with classes defined in the current worker, as these - // helpers rely on wrapping the object. - durableObjectBindingDesignators: getDurableObjectDesignators( - project.options - ), - // Include whether isolated storage has been enabled for this - // project, so we know whether to call out to the loopback service - // to push/pop the storage stack between tests. - isolatedStorage: project.options.isolatedStorage, - } satisfies SerializedOptions, - }; - - const mf = await getProjectMiniflare(ctx, project); - if (options.singleWorker) { - // Single Worker, Isolated or Shared Storage - // --> single instance with single runner worker - assert(mf instanceof Miniflare, "Expected single instance"); - const name = getRunnerName(workspaceProject); - resultPromises.push( - runTests(ctx, mf, name, project, config, files, invalidates) - ); - } else if (options.isolatedStorage) { - // Multiple Workers, Isolated Storage: - // --> multiple instances each with single runner worker - assert(mf instanceof Map, "Expected multiple isolated instances"); - const name = getRunnerName(workspaceProject); - for (const file of files) { - const fileMf = mf.get(file); - assert(fileMf !== undefined); - resultPromises.push( - runTests(ctx, fileMf, name, project, config, [file], invalidates) - ); - } - } else { - // Multiple Workers, Shared Storage: - // --> single instance with multiple runner workers - assert(mf instanceof Miniflare, "Expected single instance"); - for (const file of files) { - const name = getRunnerName(workspaceProject, file); - resultPromises.push( - runTests(ctx, mf, name, project, config, [file], invalidates) - ); - } - } } + } + } - // 3. Wait for all tests to complete, and throw if any failed - const results = await Promise.allSettled(resultPromises); - const errors = results - .filter((r): r is PromiseRejectedResult => r.status === "rejected") - .map((r) => r.reason); + // 3. Wait for all tests to complete, and throw if any failed + const results = await Promise.allSettled(resultPromises); + const errors = results + .filter((r): r is PromiseRejectedResult => r.status === "rejected") + .map((r) => r.reason); + + // 4. Clean up persistence directories. Note we do this in the background + // at the end of tests as opposed to before tests start, so re-runs + // start quickly, and results are displayed as soon as they're ready. + for (const project of allProjects.values()) { + if (project.mf !== undefined) { + void forEachMiniflare(project.mf, async (mf) => scheduleStorageReset(mf)); + } + } - // 4. Clean up persistence directories. Note we do this in the background - // at the end of tests as opposed to before tests start, so re-runs - // start quickly, and results are displayed as soon as they're ready. - for (const project of allProjects.values()) { - if (project.mf !== undefined) { - void forEachMiniflare(project.mf, async (mf) => - scheduleStorageReset(mf) - ); - } - } + if (errors.length > 0) { + throw new AggregateError( + errors, + "Errors occurred while running tests. For more information, see serialized error." + ); + } - if (errors.length > 0) { - throw new AggregateError( - errors, - "Errors occurred while running tests. For more information, see serialized error." - ); - } + // TODO(soon): something like this is required for watching non-statically imported deps, + // `vitest/dist/vendor/node.c-kzGvOB.js:handleFileChanged` is interesting, + // could also use `forceRerunTriggers` + // (Vite statically analyses imports here: https://github.com/vitejs/vite/blob/2649f40733bad131bc94b06d370bedc8f57853e2/packages/vite/src/node/plugins/importAnalysis.ts#L770) + // const project = specs[0][0]; + // const moduleGraph = project.server.moduleGraph; + // const testModule = moduleGraph.getModuleById(".../packages/vitest-pool-workers/test/kv/store.test.ts"); + // const thingModule = moduleGraph.getModuleById(".../packages/vitest-pool-workers/test/kv/thing.ts"); + // assert(testModule && thingModule); + // thingModule.importers.add(testModule); +} +export default function (ctx: Vitest): ProcessPool { + // This function is called when config changes and may be called on re-runs + assertCompatibleVitestVersion(ctx); - // TODO(soon): something like this is required for watching non-statically imported deps, - // `vitest/dist/vendor/node.c-kzGvOB.js:handleFileChanged` is interesting, - // could also use `forceRerunTriggers` - // (Vite statically analyses imports here: https://github.com/vitejs/vite/blob/2649f40733bad131bc94b06d370bedc8f57853e2/packages/vite/src/node/plugins/importAnalysis.ts#L770) - // const project = specs[0][0]; - // const moduleGraph = project.server.moduleGraph; - // const testModule = moduleGraph.getModuleById(".../packages/vitest-pool-workers/test/kv/store.test.ts"); - // const thingModule = moduleGraph.getModuleById(".../packages/vitest-pool-workers/test/kv/thing.ts"); - // assert(testModule && thingModule); - // thingModule.importers.add(testModule); + return { + name: "vitest-pool-workers", + async runTests(specs, invalidates) { + await executeMethod(ctx, specs, invalidates, "run"); }, - async collectTests(_specs, _invalidates) { - // TODO: This is a new API introduced in Vitest v2+ which we should consider supporting at some point - throw new Error( - "The Cloudflare Workers Vitest integration does not support the `.collect()` or `vitest list` APIs" - ); + async collectTests(specs, invalidates) { + await executeMethod(ctx, specs, invalidates, "collect"); }, async close() { // `close()` will be called when shutting down Vitest or updating config diff --git a/packages/vitest-pool-workers/src/worker/lib/cloudflare/test-runner.ts b/packages/vitest-pool-workers/src/worker/lib/cloudflare/test-runner.ts index d6f62cc6c215..5bed71ff0023 100644 --- a/packages/vitest-pool-workers/src/worker/lib/cloudflare/test-runner.ts +++ b/packages/vitest-pool-workers/src/worker/lib/cloudflare/test-runner.ts @@ -216,8 +216,13 @@ export default class WorkersTestRunner extends VitestTestRunner { } resetMockAgent(fetchMock); - return super.onBeforeRunFiles(); + // @ts-expect-error Support Vitest v2 + if (super.onBeforeRunFiles) { + // @ts-expect-error Support Vitest v2 + return super.onBeforeRunFiles(); + } } + async onAfterRunFiles() { if (DEBUG) { __console.log("onAfterRunFiles"); diff --git a/packages/vitest-pool-workers/test/console.test.ts b/packages/vitest-pool-workers/test/console.test.ts index 3a7a8199e865..14094adb5dcb 100644 --- a/packages/vitest-pool-workers/test/console.test.ts +++ b/packages/vitest-pool-workers/test/console.test.ts @@ -19,7 +19,8 @@ test.skipIf(process.platform === "win32")( }); const result = vitestDev(); await waitFor(() => { - expect(result.stdout).toMatch("stdout | index.test.ts\nglobal\ndescribe"); + expect(result.stdout).toMatch("stdout | index.test.ts\nglobal"); + expect(result.stdout).toMatch("stdout | index.test.ts\ndescribe"); expect(result.stdout).toMatch( "stdout | index.test.ts > thing > does something\ntest" ); @@ -41,9 +42,8 @@ test.skipIf(process.platform === "win32")( `, }); await waitFor(() => { - expect(result.stdout).toMatch( - "stdout | index.test.ts\nnew global\nnew describe" - ); + expect(result.stdout).toMatch("stdout | index.test.ts\nnew global"); + expect(result.stdout).toMatch("stdout | index.test.ts\nnew describe"); expect(result.stdout).toMatch( "stdout | index.test.ts > new thing > does something else\nnew test" @@ -116,6 +116,6 @@ test("console.logs() inside `export default`ed handlers with SELF", async ({ }); const result = await vitestRun(); expect(result.stdout).toMatch( - "stdout | index.test.ts > sends request\none\ntwo\n" + "stdout | index.test.ts > sends request\none\ntwo" ); }); diff --git a/packages/vitest-pool-workers/test/global-setup.ts b/packages/vitest-pool-workers/test/global-setup.ts index c08e364875ba..7fe465e559e4 100644 --- a/packages/vitest-pool-workers/test/global-setup.ts +++ b/packages/vitest-pool-workers/test/global-setup.ts @@ -26,7 +26,10 @@ export default async function ({ provide }: GlobalSetupContext) { await stop(); console.log("Cleaning up temporary directory..."); - await fs.rm(projectPath, { recursive: true, maxRetries: 10 }); + try { + await fs.rm(projectPath, { recursive: true, maxRetries: 10 }); + // This sometimes fails on Windows with EBUSY + } catch {} }; } diff --git a/packages/workers-shared/package.json b/packages/workers-shared/package.json index b131d51dbb2b..31a864f4cad0 100644 --- a/packages/workers-shared/package.json +++ b/packages/workers-shared/package.json @@ -67,7 +67,7 @@ "rimraf": "catalog:default", "toucan-js": "4.0.0", "typescript": "catalog:default", - "vitest": "catalog:default" + "vitest": "~2.1.0" }, "engines": { "node": ">=16.7.0" diff --git a/packages/wrangler/src/__tests__/access.test.ts b/packages/wrangler/src/__tests__/access.test.ts index 01b77923dff8..f4c595c84ac4 100644 --- a/packages/wrangler/src/__tests__/access.test.ts +++ b/packages/wrangler/src/__tests__/access.test.ts @@ -1,3 +1,4 @@ +import { UserError } from "../errors"; import { domainUsesAccess, getAccessToken } from "../user/access"; import { msw, mswAccessHandlers } from "./helpers/msw"; @@ -16,7 +17,7 @@ describe("access", () => { }); it("should error without cloudflared installed on an access protected domain", async () => { await expect(getAccessToken("access-protected.com")).rejects.toEqual( - new Error( + new UserError( "To use Wrangler with Cloudflare Access, please install `cloudflared` from https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation" ) ); diff --git a/packages/wrangler/src/__tests__/d1/convert-timestamp-to-iso.test.ts b/packages/wrangler/src/__tests__/d1/convert-timestamp-to-iso.test.ts index 03b914331e35..a5b58628602a 100644 --- a/packages/wrangler/src/__tests__/d1/convert-timestamp-to-iso.test.ts +++ b/packages/wrangler/src/__tests__/d1/convert-timestamp-to-iso.test.ts @@ -3,7 +3,7 @@ import { convertTimestampToISO } from "../../d1/timeTravel/utils"; describe("convertTimestampToISO", () => { beforeAll(() => { - vi.useFakeTimers(); + vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "Date"] }); //lock time to 2023-08-01 UTC vi.setSystemTime(new Date(2023, 7, 1)); }); diff --git a/packages/wrangler/src/__tests__/d1/insights.test.ts b/packages/wrangler/src/__tests__/d1/insights.test.ts index 59ea81c06dae..7390fd0a4575 100644 --- a/packages/wrangler/src/__tests__/d1/insights.test.ts +++ b/packages/wrangler/src/__tests__/d1/insights.test.ts @@ -12,7 +12,7 @@ import { writeWranglerConfig } from "../helpers/write-wrangler-config"; describe("getDurationDates()", () => { beforeAll(() => { - vi.useFakeTimers(); + vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "Date"] }); //lock time to 2023-08-01 UTC vi.setSystemTime(new Date(2023, 7, 1)); }); diff --git a/packages/wrangler/src/__tests__/deploy.test.ts b/packages/wrangler/src/__tests__/deploy.test.ts index df7037ebac99..a7698f881926 100644 --- a/packages/wrangler/src/__tests__/deploy.test.ts +++ b/packages/wrangler/src/__tests__/deploy.test.ts @@ -4072,7 +4072,7 @@ addEventListener('fetch', event => {});` `); expect(std.warn).toMatchInlineSnapshot(`""`); expect(std.err).toMatchInlineSnapshot(`""`); - }); + }, 30_000); it("should error if the asset key is over 512 characters", async () => { const longFilePathAsset = { diff --git a/packages/wrangler/src/__tests__/deprecated-usage-model.test.ts b/packages/wrangler/src/__tests__/deprecated-usage-model.test.ts index c2b37372b274..0633a4e275c8 100644 --- a/packages/wrangler/src/__tests__/deprecated-usage-model.test.ts +++ b/packages/wrangler/src/__tests__/deprecated-usage-model.test.ts @@ -1,4 +1,3 @@ -import { vi } from "vitest"; import { mockAccountId, mockApiToken } from "./helpers/mock-account-id"; import { mockConsoleMethods } from "./helpers/mock-console"; import { mockUploadWorkerRequest } from "./helpers/mock-upload-worker"; @@ -16,16 +15,6 @@ describe("deprecated-usage-model", () => { runInTempDir(); const std = mockConsoleMethods(); - // TODO: remove the fake timers and irrelevant tests after March 1st - beforeAll(() => { - vi.useFakeTimers(); - vi.setSystemTime(new Date(2024, 2, 2)); - }); - - afterAll(() => { - vi.useRealTimers(); - }); - it("should warn user about ignored usage model if usage_model specified", async () => { msw.use( ...mswSuccessDeploymentScriptMetadata, diff --git a/packages/wrangler/src/__tests__/metrics.test.ts b/packages/wrangler/src/__tests__/metrics.test.ts index 7c093c23c3ce..cd33ff8001f6 100644 --- a/packages/wrangler/src/__tests__/metrics.test.ts +++ b/packages/wrangler/src/__tests__/metrics.test.ts @@ -68,6 +68,7 @@ describe("metrics", () => { vi.mocked(getPlatform).mockReturnValue("mock platform"); vi.mocked(sniffUserAgent).mockReturnValue("npm"); vi.useFakeTimers({ + toFake: ["setTimeout", "clearTimeout", "Date"], now: new Date(2024, 11, 12), }); writeMetricsConfig({ @@ -671,7 +672,9 @@ describe("metrics", () => { }); it("should print a message if the permission date is older than the current metrics date", async () => { - vi.useFakeTimers(); + vi.useFakeTimers({ + toFake: ["setTimeout", "clearTimeout", "Date"], + }); vi.setSystemTime(new Date(2024, 11, 12)); const OLD_DATE = new Date(2000); writeMetricsConfig({ @@ -721,7 +724,9 @@ describe("metrics", () => { describe.each(["metrics", "telemetry"])("%s commands", (cmd) => { beforeEach(() => { - vi.useFakeTimers(); + vi.useFakeTimers({ + toFake: ["setTimeout", "clearTimeout", "Date"], + }); vi.setSystemTime(new Date(2024, 11, 12)); }); afterEach(() => { diff --git a/packages/wrangler/src/__tests__/pages/project-upload.test.ts b/packages/wrangler/src/__tests__/pages/project-upload.test.ts index ace38279b415..924328f1d14e 100644 --- a/packages/wrangler/src/__tests__/pages/project-upload.test.ts +++ b/packages/wrangler/src/__tests__/pages/project-upload.test.ts @@ -572,7 +572,7 @@ describe("pages project upload", () => { await runWrangler("pages project upload ."); expect(uploadedAssets).toEqual(assets); - }); + }, 60_000); it("should not error when directory names contain periods and houses a extensionless file", async () => { mkdirSync(".well-known"); diff --git a/packages/wrangler/src/api/startDevWorker/DevEnv.ts b/packages/wrangler/src/api/startDevWorker/DevEnv.ts index 6168a233e04a..811f3d4f12d9 100644 --- a/packages/wrangler/src/api/startDevWorker/DevEnv.ts +++ b/packages/wrangler/src/api/startDevWorker/DevEnv.ts @@ -181,5 +181,6 @@ function createWorkerObject(devEnv: DevEnv): Worker { async dispose() { await devEnv.teardown(); }, + raw: devEnv, }; } diff --git a/packages/wrangler/src/api/startDevWorker/types.ts b/packages/wrangler/src/api/startDevWorker/types.ts index ca071300d943..cf83b560ed1e 100644 --- a/packages/wrangler/src/api/startDevWorker/types.ts +++ b/packages/wrangler/src/api/startDevWorker/types.ts @@ -31,6 +31,7 @@ import type { WorkerRegistry } from "../../dev-registry"; import type { CfAccount } from "../../dev/create-worker-preview"; import type { EsbuildBundle } from "../../dev/use-esbuild"; import type { ConfigController } from "./ConfigController"; +import type { DevEnv } from "./DevEnv"; import type { DispatchFetch, Json, @@ -53,6 +54,7 @@ export interface Worker { scheduled: MiniflareWorker["scheduled"]; queue: MiniflareWorker["queue"]; dispose(): Promise; + raw: DevEnv; } export interface StartDevWorkerInput { diff --git a/packages/wrangler/src/dev/miniflare.ts b/packages/wrangler/src/dev/miniflare.ts index a4fe5df8dfa0..4a9c936bab11 100644 --- a/packages/wrangler/src/dev/miniflare.ts +++ b/packages/wrangler/src/dev/miniflare.ts @@ -447,6 +447,7 @@ export function buildMiniflareBindingOptions(config: MiniflareBindingsConfig): { } const target = config.workerDefinitions?.[service.service]; + if (target?.host === undefined || target.port === undefined) { // If the target isn't in the registry, always return an error response notFoundServices.add(service.service); diff --git a/packages/wrangler/src/index.ts b/packages/wrangler/src/index.ts index b16e6ba24b94..6dea08b67e73 100644 --- a/packages/wrangler/src/index.ts +++ b/packages/wrangler/src/index.ts @@ -1185,10 +1185,12 @@ export async function main(argv: string[]): Promise { } await closeSentry(); + const controller = new AbortController(); + await Promise.race([ - await Promise.allSettled(dispatcher?.requests ?? []), - setTimeout(1000), // Ensure we don't hang indefinitely - ]); + Promise.allSettled(dispatcher?.requests ?? []), + setTimeout(1000, undefined, controller), // Ensure we don't hang indefinitely + ]).then(() => controller.abort()); // Ensure the Wrangler process doesn't hang waiting for setTimeout(1000) to complete } catch (e) { logger.error(e); // Only re-throw if we haven't already re-thrown an exception from a diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b2d9a30a14a..025c6f746c75 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,14 +7,14 @@ settings: catalogs: default: '@vitest/runner': - specifier: ~2.1.9 - version: 2.1.9 + specifier: ~3.0.5 + version: 3.0.5 '@vitest/snapshot': - specifier: ~2.1.9 - version: 2.1.9 + specifier: ~3.0.5 + version: 3.0.5 '@vitest/ui': - specifier: ~2.1.9 - version: 2.1.9 + specifier: ~3.0.5 + version: 3.0.5 rimraf: specifier: ^5.0.10 version: 5.0.10 @@ -28,8 +28,8 @@ catalogs: specifier: ^5.4.14 version: 5.4.14 vitest: - specifier: ~2.1.9 - version: 2.1.9 + specifier: ~3.0.5 + version: 3.0.5 vite-plugin: vite: specifier: ^6.1.0 @@ -129,7 +129,7 @@ importers: version: 5.4.14(@types/node@18.19.74) vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) fixtures/additional-modules: devDependencies: @@ -147,7 +147,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -165,7 +165,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -192,7 +192,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -213,7 +213,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -231,7 +231,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -252,7 +252,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -276,7 +276,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -300,7 +300,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) fixtures/isomorphic-random-example: {} @@ -325,7 +325,7 @@ importers: version: 5.7.3 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -337,7 +337,7 @@ importers: version: 7.0.0 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -362,7 +362,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -380,7 +380,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -407,7 +407,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -425,7 +425,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -446,7 +446,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -474,7 +474,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -492,7 +492,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -510,7 +510,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -528,7 +528,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -549,7 +549,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -567,7 +567,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -604,7 +604,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -625,7 +625,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -640,7 +640,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -661,7 +661,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -679,7 +679,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -697,7 +697,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -715,7 +715,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -733,7 +733,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -751,7 +751,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -769,7 +769,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -787,7 +787,7 @@ importers: version: 5.7.3 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -808,7 +808,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -823,7 +823,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -848,7 +848,7 @@ importers: devDependencies: vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -899,7 +899,7 @@ importers: version: 5.4.14(@types/node@18.19.74) vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -926,7 +926,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -958,7 +958,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -979,7 +979,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -1000,7 +1000,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -1018,7 +1018,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -1036,7 +1036,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../../packages/wrangler @@ -1258,7 +1258,7 @@ importers: version: 4.2.0(typescript@5.7.3)(vite@5.4.14(@types/node@18.19.74)) vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) which-pm-runs: specifier: ^1.1.0 version: 1.1.0 @@ -1599,6 +1599,9 @@ importers: glob: specifier: ^10.4.5 version: 10.4.5 + vitest: + specifier: ~2.1.0 + version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9) packages/playground-preview-worker: dependencies: @@ -1734,7 +1737,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../wrangler @@ -1795,7 +1798,7 @@ importers: version: 6.1.0(@types/node@18.19.74)(jiti@2.4.2) vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../wrangler @@ -2317,10 +2320,10 @@ importers: version: 7.5.1 '@vitest/runner': specifier: catalog:default - version: 2.1.9 + version: 3.0.5 '@vitest/snapshot': specifier: catalog:default - version: 2.1.9 + version: 3.0.5 capnp-es: specifier: ^0.0.7 version: 0.0.7(typescript@5.7.3) @@ -2335,7 +2338,7 @@ importers: version: 5.28.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) packages/workers-editor-shared: dependencies: @@ -2518,7 +2521,7 @@ importers: version: link:../eslint-config-worker '@cloudflare/vitest-pool-workers': specifier: ^0.5.31 - version: 0.5.31(@cloudflare/workers-types@4.20250204.0)(@vitest/runner@2.1.9)(@vitest/snapshot@2.1.9)(vitest@2.1.9) + version: 0.5.31(@cloudflare/workers-types@4.20250204.0)(@vitest/runner@3.0.5)(@vitest/snapshot@3.0.5)(vitest@2.1.9) '@cloudflare/workers-tsconfig': specifier: workspace:* version: link:../workers-tsconfig @@ -2547,8 +2550,8 @@ importers: specifier: catalog:default version: 5.7.3 vitest: - specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + specifier: ~2.1.0 + version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9) packages/workers-tsconfig: {} @@ -2571,7 +2574,7 @@ importers: version: 5.7.3 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) wrangler: specifier: workspace:* version: link:../wrangler @@ -2614,7 +2617,7 @@ importers: version: 5.7.3 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) packages/wrangler: dependencies: @@ -2742,7 +2745,7 @@ importers: version: 17.0.24 '@vitest/ui': specifier: catalog:default - version: 2.1.9(vitest@2.1.9) + version: 3.0.5(vitest@3.0.5) '@webcontainer/env': specifier: ^1.1.0 version: 1.1.0 @@ -2880,10 +2883,10 @@ importers: version: 1.5.4 vitest: specifier: catalog:default - version: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + version: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) vitest-websocket-mock: specifier: ^0.4.0 - version: 0.4.0(vitest@2.1.9) + version: 0.4.0(vitest@3.0.5) ws: specifier: ^8.18.0 version: 8.18.0 @@ -3495,121 +3498,121 @@ packages: vitest: 2.0.x - 2.1.x '@cloudflare/workerd-darwin-64@1.20241106.1': - resolution: {integrity: sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241106.1.tgz} + resolution: {integrity: sha512-zxvaToi1m0qzAScrxFt7UvFVqU8DxrCO2CinM1yQkv5no7pA1HolpIrwZ0xOhR3ny64Is2s/J6BrRjpO5dM9Zw==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-64@1.20241230.0': - resolution: {integrity: sha512-BZHLg4bbhNQoaY1Uan81O3FV/zcmWueC55juhnaI7NAobiQth9RppadPNpxNAmS9fK2mR5z8xrwMQSQrHmztyQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241230.0.tgz} + resolution: {integrity: sha512-BZHLg4bbhNQoaY1Uan81O3FV/zcmWueC55juhnaI7NAobiQth9RppadPNpxNAmS9fK2mR5z8xrwMQSQrHmztyQ==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-64@1.20250124.0': - resolution: {integrity: sha512-P5Z5KfVAuoCidIc0o2JPQZFLNTXDjtxN8vhtreCUr6V+xF5pqDNwQqeBDnDDF0gcszFQOYi2OZAB9e1MwssTwA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250124.0.tgz} + resolution: {integrity: sha512-P5Z5KfVAuoCidIc0o2JPQZFLNTXDjtxN8vhtreCUr6V+xF5pqDNwQqeBDnDDF0gcszFQOYi2OZAB9e1MwssTwA==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-64@1.20250204.0': - resolution: {integrity: sha512-HpsgbWEfvdcwuZ8WAZhi1TlSCyyHC3tbghpKsOqGDaQNltyAFAWqa278TPNfcitYf/FmV4961v3eqUE+RFdHNQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250204.0.tgz} + resolution: {integrity: sha512-HpsgbWEfvdcwuZ8WAZhi1TlSCyyHC3tbghpKsOqGDaQNltyAFAWqa278TPNfcitYf/FmV4961v3eqUE+RFdHNQ==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20241106.1': - resolution: {integrity: sha512-j3dg/42D/bPgfNP3cRUBxF+4waCKO/5YKwXNj+lnVOwHxDu+ne5pFw9TIkKYcWTcwn0ZUkbNZNM5rhJqRn4xbg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241106.1.tgz} + resolution: {integrity: sha512-j3dg/42D/bPgfNP3cRUBxF+4waCKO/5YKwXNj+lnVOwHxDu+ne5pFw9TIkKYcWTcwn0ZUkbNZNM5rhJqRn4xbg==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20241230.0': - resolution: {integrity: sha512-lllxycj7EzYoJ0VOJh8M3palUgoonVrILnzGrgsworgWlIpgjfXGS7b41tEGCw6AxSxL9prmTIGtfSPUvn/rjg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241230.0.tgz} + resolution: {integrity: sha512-lllxycj7EzYoJ0VOJh8M3palUgoonVrILnzGrgsworgWlIpgjfXGS7b41tEGCw6AxSxL9prmTIGtfSPUvn/rjg==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20250124.0': - resolution: {integrity: sha512-lVxf6qIfmJ5rS6rmGKV7lt6ApY6nhD4kAQTK4vKYm/npk2sXod6LASIY0U4WBCwy4N+S75a8hP2QtmQf+KV3Iw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250124.0.tgz} + resolution: {integrity: sha512-lVxf6qIfmJ5rS6rmGKV7lt6ApY6nhD4kAQTK4vKYm/npk2sXod6LASIY0U4WBCwy4N+S75a8hP2QtmQf+KV3Iw==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20250204.0': - resolution: {integrity: sha512-AJ8Tk7KMJqePlch3SH8oL41ROtsrb07hKRHD6M+FvGC3tLtf26rpteAAMNYKMDYKzFNFUIKZNijYDFZjBFndXQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250204.0.tgz} + resolution: {integrity: sha512-AJ8Tk7KMJqePlch3SH8oL41ROtsrb07hKRHD6M+FvGC3tLtf26rpteAAMNYKMDYKzFNFUIKZNijYDFZjBFndXQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-linux-64@1.20241106.1': - resolution: {integrity: sha512-Ih+Ye8E1DMBXcKrJktGfGztFqHKaX1CeByqshmTbODnWKHt6O65ax3oTecUwyC0+abuyraOpAtdhHNpFMhUkmw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241106.1.tgz} + resolution: {integrity: sha512-Ih+Ye8E1DMBXcKrJktGfGztFqHKaX1CeByqshmTbODnWKHt6O65ax3oTecUwyC0+abuyraOpAtdhHNpFMhUkmw==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-64@1.20241230.0': - resolution: {integrity: sha512-Y3mHcW0KghOmWdNZyHYpEOG4Ba/ga8tht5vj1a+WXfagEjMO8Y98XhZUlCaYa9yB7Wh5jVcK5LM2jlO/BLgqpA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241230.0.tgz} + resolution: {integrity: sha512-Y3mHcW0KghOmWdNZyHYpEOG4Ba/ga8tht5vj1a+WXfagEjMO8Y98XhZUlCaYa9yB7Wh5jVcK5LM2jlO/BLgqpA==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-64@1.20250124.0': - resolution: {integrity: sha512-5S4GzN08vW/CfzaM1rVAkRhPPSDX1O1t7u0pj+xdbGl4GcazBzE4ZLre+y9OMplZ9PBCkxXkRWqHXzabWA1x4A==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250124.0.tgz} + resolution: {integrity: sha512-5S4GzN08vW/CfzaM1rVAkRhPPSDX1O1t7u0pj+xdbGl4GcazBzE4ZLre+y9OMplZ9PBCkxXkRWqHXzabWA1x4A==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-64@1.20250204.0': - resolution: {integrity: sha512-RIUfUSnDC8h73zAa+u1K2Frc7nc+eeQoBBP7SaqsRe6JdX8jfIv/GtWjQWCoj8xQFgLvhpJKZ4sTTTV+AilQbw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250204.0.tgz} + resolution: {integrity: sha512-RIUfUSnDC8h73zAa+u1K2Frc7nc+eeQoBBP7SaqsRe6JdX8jfIv/GtWjQWCoj8xQFgLvhpJKZ4sTTTV+AilQbw==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20241106.1': - resolution: {integrity: sha512-mdQFPk4+14Yywn7n1xIzI+6olWM8Ybz10R7H3h+rk0XulMumCWUCy1CzIDauOx6GyIcSgKIibYMssVHZR30ObA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241106.1.tgz} + resolution: {integrity: sha512-mdQFPk4+14Yywn7n1xIzI+6olWM8Ybz10R7H3h+rk0XulMumCWUCy1CzIDauOx6GyIcSgKIibYMssVHZR30ObA==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20241230.0': - resolution: {integrity: sha512-IAjhsWPlHzhhkJ6I49sDG6XfMnhPvv0szKGXxTWQK/IWMrbGdHm4RSfNKBSoLQm67jGMIzbmcrX9UIkms27Y1g==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241230.0.tgz} + resolution: {integrity: sha512-IAjhsWPlHzhhkJ6I49sDG6XfMnhPvv0szKGXxTWQK/IWMrbGdHm4RSfNKBSoLQm67jGMIzbmcrX9UIkms27Y1g==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20250124.0': - resolution: {integrity: sha512-CHSYnutDfXgUWL9WcP0GbzIb5OyC9RZVCJGhKbDTQy6/uH7AivNcLzXtOhNdqetKjERmOxUbL9Us7vcMQLztog==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250124.0.tgz} + resolution: {integrity: sha512-CHSYnutDfXgUWL9WcP0GbzIb5OyC9RZVCJGhKbDTQy6/uH7AivNcLzXtOhNdqetKjERmOxUbL9Us7vcMQLztog==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20250204.0': - resolution: {integrity: sha512-8Ql8jDjoIgr2J7oBD01kd9kduUz60njofrBpAOkjCPed15He8e8XHkYaYow3g0xpae4S2ryrPOeoD3M64sRxeg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250204.0.tgz} + resolution: {integrity: sha512-8Ql8jDjoIgr2J7oBD01kd9kduUz60njofrBpAOkjCPed15He8e8XHkYaYow3g0xpae4S2ryrPOeoD3M64sRxeg==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-windows-64@1.20241106.1': - resolution: {integrity: sha512-4rtcss31E/Rb/PeFocZfr+B9i1MdrkhsTBWizh8siNR4KMmkslU2xs2wPaH1z8+ErxkOsHrKRa5EPLh5rIiFeg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241106.1.tgz} + resolution: {integrity: sha512-4rtcss31E/Rb/PeFocZfr+B9i1MdrkhsTBWizh8siNR4KMmkslU2xs2wPaH1z8+ErxkOsHrKRa5EPLh5rIiFeg==} engines: {node: '>=16'} cpu: [x64] os: [win32] '@cloudflare/workerd-windows-64@1.20241230.0': - resolution: {integrity: sha512-y5SPIk9iOb2gz+yWtHxoeMnjPnkYQswiCJ480oHC6zexnJLlKTpcmBCjDH1nWCT4pQi8F25gaH8thgElf4NvXQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241230.0.tgz} + resolution: {integrity: sha512-y5SPIk9iOb2gz+yWtHxoeMnjPnkYQswiCJ480oHC6zexnJLlKTpcmBCjDH1nWCT4pQi8F25gaH8thgElf4NvXQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] '@cloudflare/workerd-windows-64@1.20250124.0': - resolution: {integrity: sha512-5TunEy5x4pNUQ10Z47qP5iF6m3X9uB2ZScKDLkNaWtbQ7EcMCapOWzuynVkTKIMBgDeKw6DAB8nbbkybPyMS9w==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250124.0.tgz} + resolution: {integrity: sha512-5TunEy5x4pNUQ10Z47qP5iF6m3X9uB2ZScKDLkNaWtbQ7EcMCapOWzuynVkTKIMBgDeKw6DAB8nbbkybPyMS9w==} engines: {node: '>=16'} cpu: [x64] os: [win32] '@cloudflare/workerd-windows-64@1.20250204.0': - resolution: {integrity: sha512-RpDJO3+to+e17X3EWfRCagboZYwBz2fowc+jL53+fd7uD19v3F59H48lw2BDpHJMRyhg6ouWcpM94OhsHv8ecA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250204.0.tgz} + resolution: {integrity: sha512-RpDJO3+to+e17X3EWfRCagboZYwBz2fowc+jL53+fd7uD19v3F59H48lw2BDpHJMRyhg6ouWcpM94OhsHv8ecA==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -6106,6 +6109,9 @@ packages: '@vitest/expect@2.1.9': resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + '@vitest/expect@3.0.5': + resolution: {integrity: sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==} + '@vitest/mocker@2.1.9': resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} peerDependencies: @@ -6117,32 +6123,63 @@ packages: vite: optional: true + '@vitest/mocker@3.0.5': + resolution: {integrity: sha512-CLPNBFBIE7x6aEGbIjaQAX03ZZlBMaWwAjBdMkIf/cAn6xzLTiM3zYqO/WAbieEjsAZir6tO71mzeHZoodThvw==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@2.1.8': resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==} '@vitest/pretty-format@2.1.9': resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + '@vitest/pretty-format@3.0.5': + resolution: {integrity: sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==} + '@vitest/runner@2.1.9': resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + '@vitest/runner@3.0.5': + resolution: {integrity: sha512-BAiZFityFexZQi2yN4OX3OkJC6scwRo8EhRB0Z5HIGGgd2q+Nq29LgHU/+ovCtd0fOfXj5ZI6pwdlUmC5bpi8A==} + '@vitest/snapshot@2.1.9': resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + '@vitest/snapshot@3.0.5': + resolution: {integrity: sha512-GJPZYcd7v8QNUJ7vRvLDmRwl+a1fGg4T/54lZXe+UOGy47F9yUfE18hRCtXL5aHN/AONu29NGzIXSVFh9K0feA==} + '@vitest/spy@2.1.9': resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + '@vitest/spy@3.0.5': + resolution: {integrity: sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==} + '@vitest/ui@2.1.9': resolution: {integrity: sha512-izzd2zmnk8Nl5ECYkW27328RbQ1nKvkm6Bb5DAaz1Gk59EbLkiCMa6OLT0NoaAYTjOFS6N+SMYW1nh4/9ljPiw==} peerDependencies: vitest: 2.1.9 + '@vitest/ui@3.0.5': + resolution: {integrity: sha512-gw2noso6WI+2PeMVCZFntdATS6xl9qhQcbhkPQ9sOmx/Xn0f4Bx4KDSbD90jpJPF0l5wOzSoGCmKyVR3W612mg==} + peerDependencies: + vitest: 3.0.5 + '@vitest/utils@2.1.8': resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} '@vitest/utils@2.1.9': resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + '@vitest/utils@3.0.5': + resolution: {integrity: sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==} + '@volar/language-core@2.3.4': resolution: {integrity: sha512-wXBhY11qG6pCDAqDnbBRFIDSIwbqkWI7no+lj5+L7IlA7HRIjRP7YQLGzT0LF4lS6eHkMSsclXqy9DwYJasZTQ==} @@ -7531,6 +7568,9 @@ packages: es-module-lexer@1.5.4: resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + es-object-atoms@1.0.0: resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} engines: {node: '>= 0.4'} @@ -7986,6 +8026,9 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + flatted@3.3.2: + resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -9790,6 +9833,9 @@ packages: pathe@2.0.1: resolution: {integrity: sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.0: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} @@ -11201,6 +11247,9 @@ packages: tinyexec@0.3.1: resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyglobby@0.2.10: resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} @@ -11212,10 +11261,18 @@ packages: resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} engines: {node: ^18.0.0 || >=20.0.0} + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + tinyrainbow@1.2.0: resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} engines: {node: '>=14.0.0'} + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + tinyspy@3.0.2: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} @@ -11716,6 +11773,11 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true + vite-node@3.0.5: + resolution: {integrity: sha512-02JEJl7SbtwSDJdYS537nU6l+ktdvcREfLksk/NDAqtdKWGqHl+joXzEubHROmS3E6pip+Xgu2tFezMu75jH7A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + vite-plugin-dts@4.0.1: resolution: {integrity: sha512-JFbAKMjJdJbeXJVwQNoi8M26lP+5Ene4/ryv9w0Z7Ca5N0DdxYEak9V3C0tqwHO7WZ9JLbwMsuUZOqYIyBRwSQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -11835,6 +11897,34 @@ packages: jsdom: optional: true + vitest@3.0.5: + resolution: {integrity: sha512-4dof+HvqONw9bvsYxtkfUp2uHsTN9bV2CZIi1pWgoFpL1Lld8LA1ka9q/ONSsoScAKG7NVGf2stJTI7XRkXb2Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.19.71 + '@vitest/browser': 3.0.5 + '@vitest/ui': 3.0.5 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vsce@2.15.0: resolution: {integrity: sha512-P8E9LAZvBCQnoGoizw65JfGvyMqNGlHdlUXD1VAuxtvYAaHBKLBdKPnpy60XKVDAkQCfmMu53g+gq9FM+ydepw==} engines: {node: '>= 14'} @@ -13318,17 +13408,17 @@ snapshots: lodash.memoize: 4.1.2 marked: 0.3.19 - '@cloudflare/vitest-pool-workers@0.5.31(@cloudflare/workers-types@4.20250204.0)(@vitest/runner@2.1.9)(@vitest/snapshot@2.1.9)(vitest@2.1.9)': + '@cloudflare/vitest-pool-workers@0.5.31(@cloudflare/workers-types@4.20250204.0)(@vitest/runner@3.0.5)(@vitest/snapshot@3.0.5)(vitest@2.1.9)': dependencies: - '@vitest/runner': 2.1.9 - '@vitest/snapshot': 2.1.9 + '@vitest/runner': 3.0.5 + '@vitest/snapshot': 3.0.5 birpc: 0.2.14 cjs-module-lexer: 1.2.3 devalue: 4.3.2 esbuild: 0.17.19 miniflare: 3.20241106.1 semver: 7.6.3 - vitest: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + vitest: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9) wrangler: 3.90.0(@cloudflare/workers-types@4.20250204.0) zod: 3.22.3 transitivePeerDependencies: @@ -13822,7 +13912,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -13869,7 +13959,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -15616,7 +15706,7 @@ snapshots: '@typescript-eslint/type-utils': 6.10.0(eslint@8.57.0)(typescript@5.7.3) '@typescript-eslint/utils': 6.10.0(eslint@8.57.0)(typescript@5.7.3) '@typescript-eslint/visitor-keys': 6.10.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -15652,7 +15742,7 @@ snapshots: '@typescript-eslint/types': 6.10.0 '@typescript-eslint/typescript-estree': 6.10.0(typescript@5.7.3) '@typescript-eslint/visitor-keys': 6.10.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) eslint: 8.57.0 optionalDependencies: typescript: 5.7.3 @@ -15665,7 +15755,7 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.3) '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) eslint: 8.57.0 optionalDependencies: typescript: 5.6.3 @@ -15686,7 +15776,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 6.10.0(typescript@5.7.3) '@typescript-eslint/utils': 6.10.0(eslint@8.57.0)(typescript@5.7.3) - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) eslint: 8.57.0 ts-api-utils: 1.4.3(typescript@5.7.3) optionalDependencies: @@ -15698,7 +15788,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.6.3) '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.6.3) - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) eslint: 8.57.0 ts-api-utils: 1.4.3(typescript@5.6.3) optionalDependencies: @@ -15714,7 +15804,7 @@ snapshots: dependencies: '@typescript-eslint/types': 6.10.0 '@typescript-eslint/visitor-keys': 6.10.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 @@ -15728,7 +15818,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -15851,7 +15941,7 @@ snapshots: '@verdaccio/loaders@8.0.0-next-8.4': dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) lodash: 4.17.21 transitivePeerDependencies: - supports-color @@ -15912,7 +16002,7 @@ snapshots: '@verdaccio/signature@8.0.0-next-8.1': dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) jsonwebtoken: 9.0.2 transitivePeerDependencies: - supports-color @@ -15987,11 +16077,26 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.9(msw@2.4.3(typescript@5.7.3))(vite@5.4.14(@types/node@18.19.74))': + '@vitest/expect@3.0.5': + dependencies: + '@vitest/spy': 3.0.5 + '@vitest/utils': 3.0.5 + chai: 5.1.2 + tinyrainbow: 2.0.0 + + '@vitest/mocker@2.1.9(vite@5.4.14(@types/node@18.19.74))': dependencies: '@vitest/spy': 2.1.9 estree-walker: 3.0.3 magic-string: 0.30.17 + optionalDependencies: + vite: 5.4.14(@types/node@18.19.74) + + '@vitest/mocker@3.0.5(msw@2.4.3(typescript@5.7.3))(vite@5.4.14(@types/node@18.19.74))': + dependencies: + '@vitest/spy': 3.0.5 + estree-walker: 3.0.3 + magic-string: 0.30.17 optionalDependencies: msw: 2.4.3(typescript@5.7.3) vite: 5.4.14(@types/node@18.19.74) @@ -16004,31 +16109,62 @@ snapshots: dependencies: tinyrainbow: 1.2.0 + '@vitest/pretty-format@3.0.5': + dependencies: + tinyrainbow: 2.0.0 + '@vitest/runner@2.1.9': dependencies: '@vitest/utils': 2.1.9 pathe: 1.1.2 + '@vitest/runner@3.0.5': + dependencies: + '@vitest/utils': 3.0.5 + pathe: 2.0.3 + '@vitest/snapshot@2.1.9': dependencies: '@vitest/pretty-format': 2.1.9 magic-string: 0.30.17 pathe: 1.1.2 + '@vitest/snapshot@3.0.5': + dependencies: + '@vitest/pretty-format': 3.0.5 + magic-string: 0.30.17 + pathe: 2.0.3 + '@vitest/spy@2.1.9': dependencies: tinyspy: 3.0.2 + '@vitest/spy@3.0.5': + dependencies: + tinyspy: 3.0.2 + '@vitest/ui@2.1.9(vitest@2.1.9)': dependencies: '@vitest/utils': 2.1.9 fflate: 0.8.2 - flatted: 3.3.1 + flatted: 3.3.2 pathe: 1.1.2 sirv: 3.0.0 tinyglobby: 0.2.10 tinyrainbow: 1.2.0 - vitest: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + vitest: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9) + optional: true + + '@vitest/ui@3.0.5(vitest@3.0.5)': + dependencies: + '@vitest/utils': 3.0.5 + fflate: 0.8.2 + flatted: 3.3.2 + pathe: 2.0.3 + sirv: 3.0.0 + tinyglobby: 0.2.10 + tinyrainbow: 2.0.0 + vitest: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) '@vitest/utils@2.1.8': dependencies: @@ -16042,6 +16178,12 @@ snapshots: loupe: 3.1.2 tinyrainbow: 1.2.0 + '@vitest/utils@3.0.5': + dependencies: + '@vitest/pretty-format': 3.0.5 + loupe: 3.1.2 + tinyrainbow: 2.0.0 + '@volar/language-core@2.3.4': dependencies: '@volar/source-map': 2.3.4 @@ -16469,7 +16611,7 @@ snapshots: common-path-prefix: 3.0.0 concordance: 5.0.4 currently-unhandled: 0.4.1 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) emittery: 1.0.1 figures: 6.0.1 globby: 14.0.1 @@ -17626,6 +17768,8 @@ snapshots: es-module-lexer@1.5.4: {} + es-module-lexer@1.6.0: {} + es-object-atoms@1.0.0: dependencies: es-errors: 1.3.0 @@ -17650,7 +17794,7 @@ snapshots: esbuild-register@3.5.0(esbuild@0.17.19): dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) esbuild: 0.17.19 transitivePeerDependencies: - supports-color @@ -17939,7 +18083,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -18290,6 +18434,8 @@ snapshots: flatted@3.3.1: {} + flatted@3.3.2: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -18664,7 +18810,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) transitivePeerDependencies: - supports-color @@ -18690,13 +18836,6 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.3 - debug: 4.3.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - https-proxy-agent@7.0.2(supports-color@9.2.2): dependencies: agent-base: 7.1.3 @@ -18707,7 +18846,7 @@ snapshots: https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) transitivePeerDependencies: - supports-color @@ -20007,7 +20146,7 @@ snapshots: debug: 4.4.0(supports-color@9.2.2) get-uri: 6.0.1 http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.2(supports-color@9.2.2) pac-resolver: 7.0.0 socks-proxy-agent: 8.0.2 transitivePeerDependencies: @@ -20156,6 +20295,8 @@ snapshots: pathe@2.0.1: {} + pathe@2.0.3: {} + pathval@2.0.0: {} peek-stream@1.1.3: @@ -20616,7 +20757,7 @@ snapshots: agent-base: 7.1.3 debug: 4.4.0(supports-color@9.2.2) http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.2(supports-color@9.2.2) lru-cache: 7.18.3 pac-proxy-agent: 7.0.1 proxy-from-env: 1.1.0 @@ -21695,6 +21836,8 @@ snapshots: tinyexec@0.3.1: {} + tinyexec@0.3.2: {} + tinyglobby@0.2.10: dependencies: fdir: 6.4.2(picomatch@4.0.2) @@ -21707,8 +21850,12 @@ snapshots: tinypool@1.0.1: {} + tinypool@1.0.2: {} + tinyrainbow@1.2.0: {} + tinyrainbow@2.0.0: {} + tinyspy@3.0.2: {} title-case@2.1.1: @@ -21854,7 +22001,7 @@ snapshots: cac: 6.7.14 chokidar: 3.6.0 consola: 3.3.3 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) esbuild: 0.23.1 execa: 5.1.1 joycon: 3.1.1 @@ -22289,7 +22436,7 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@2.1.9(@types/node@18.19.74)(supports-color@9.2.2): + vite-node@2.1.9(@types/node@18.19.74): dependencies: cac: 6.7.14 debug: 4.4.0(supports-color@9.2.2) @@ -22307,6 +22454,24 @@ snapshots: - supports-color - terser + vite-node@3.0.5(@types/node@18.19.74)(supports-color@9.2.2): + dependencies: + cac: 6.7.14 + debug: 4.4.0(supports-color@9.2.2) + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 5.4.14(@types/node@18.19.74) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-plugin-dts@4.0.1(@types/node@18.19.74)(rollup@4.30.1)(typescript@5.7.3)(vite@5.4.14(@types/node@18.19.74)): dependencies: '@microsoft/api-extractor': 7.47.4(@types/node@18.19.74) @@ -22314,7 +22479,7 @@ snapshots: '@volar/typescript': 2.3.4 '@vue/language-core': 2.0.29(typescript@5.7.3) compare-versions: 6.1.1 - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) kolorist: 1.8.0 local-pkg: 0.5.0 magic-string: 0.30.17 @@ -22329,7 +22494,7 @@ snapshots: vite-tsconfig-paths@4.2.0(typescript@5.7.3)(vite@5.4.14(@types/node@18.19.74)): dependencies: - debug: 4.3.7(supports-color@8.1.1) + debug: 4.3.7(supports-color@9.2.2) globrex: 0.1.2 tsconfck: 2.1.1(typescript@5.7.3) optionalDependencies: @@ -22357,16 +22522,16 @@ snapshots: fsevents: 2.3.3 jiti: 2.4.2 - vitest-websocket-mock@0.4.0(vitest@2.1.9): + vitest-websocket-mock@0.4.0(vitest@3.0.5): dependencies: '@vitest/utils': 2.1.8 mock-socket: 9.3.1 - vitest: 2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) + vitest: 3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2) - vitest@2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2): + vitest@2.1.9(@types/node@18.19.74)(@vitest/ui@2.1.9): dependencies: '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(msw@2.4.3(typescript@5.7.3))(vite@5.4.14(@types/node@18.19.74)) + '@vitest/mocker': 2.1.9(vite@5.4.14(@types/node@18.19.74)) '@vitest/pretty-format': 2.1.9 '@vitest/runner': 2.1.9 '@vitest/snapshot': 2.1.9 @@ -22383,7 +22548,7 @@ snapshots: tinypool: 1.0.1 tinyrainbow: 1.2.0 vite: 5.4.14(@types/node@18.19.74) - vite-node: 2.1.9(@types/node@18.19.74)(supports-color@9.2.2) + vite-node: 2.1.9(@types/node@18.19.74) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 18.19.74 @@ -22399,6 +22564,42 @@ snapshots: - supports-color - terser + vitest@3.0.5(@types/node@18.19.74)(@vitest/ui@3.0.5)(msw@2.4.3(typescript@5.7.3))(supports-color@9.2.2): + dependencies: + '@vitest/expect': 3.0.5 + '@vitest/mocker': 3.0.5(msw@2.4.3(typescript@5.7.3))(vite@5.4.14(@types/node@18.19.74)) + '@vitest/pretty-format': 3.0.5 + '@vitest/runner': 3.0.5 + '@vitest/snapshot': 3.0.5 + '@vitest/spy': 3.0.5 + '@vitest/utils': 3.0.5 + chai: 5.1.2 + debug: 4.4.0(supports-color@9.2.2) + expect-type: 1.1.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 5.4.14(@types/node@18.19.74) + vite-node: 3.0.5(@types/node@18.19.74)(supports-color@9.2.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 18.19.74 + '@vitest/ui': 3.0.5(vitest@3.0.5) + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vsce@2.15.0: dependencies: azure-devops-node-api: 11.2.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6d1a201722ca..55bee1fb3306 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -7,14 +7,14 @@ packages: catalog: "@types/node": "^18.19.71" - "@vitest/runner": "~2.1.9" - "@vitest/snapshot": "~2.1.9" - "@vitest/ui": "~2.1.9" + "@vitest/runner": ~3.0.5 + "@vitest/snapshot": ~3.0.5 + "@vitest/ui": ~3.0.5 # rimraf@6 requires node 20 or >=22 rimraf: "^5.0.10" typescript: "^5.7.2" undici: "^5.28.4" - vitest: "~2.1.9" + vitest: "~3.0.5" vite: "^5.4.14" catalogs: