Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/dependabot-update-13111.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"miniflare": patch
"wrangler": patch
---

Update dependencies of "miniflare", "wrangler"

The following dependency versions have been updated:

| Dependency | From | To |
| ---------- | ------------ | ------------ |
| workerd | 1.20260317.1 | 1.20260329.1 |
7 changes: 7 additions & 0 deletions .changeset/vite-plugin-cloudflare-connect-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@cloudflare/vite-plugin": patch
---

Add missing `connect` key to `WorkerEntrypoint` and `DurableObject` key lists in the runner worker

The `connect` method was added to the `WorkerEntrypoint` and `DurableObject` types in workerd 1.20260329.1 but was missing from the `WORKER_ENTRYPOINT_KEYS` and `DURABLE_OBJECT_KEYS` arrays used for RPC property access in the Vite plugin runner worker. This caused the compile-time exhaustiveness check to fail with the updated workers-types.
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ This is the **Cloudflare Workers SDK** monorepo containing tools and libraries f
- E2E tests require real Cloudflare account credentials
- Use `vitest-pool-workers` for testing actual Workers runtime behavior
- Shared vitest config (`vitest.shared.ts`): 50s timeouts, `retry: 2`, `restoreMocks: true`
- Vitest 4 pool config: use `maxWorkers: 1` instead of the removed `poolOptions.forks.singleFork: true` when tests must run sequentially

**Git Workflow:**

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"extends": "../../tsconfig.workerd.json",
"compilerOptions": {
// @cloudflare/containers@0.0.25 has an alarm() signature incompatible
// with the updated DurableObject base type in @cloudflare/workers-types.
// Remove when https://github.com/cloudflare/containers/issues/167 is resolved.
"skipLibCheck": true
},
"include": ["./**/*.ts"]
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"extends": "../tsconfig.node.json",
"compilerOptions": {
// @cloudflare/containers@0.0.25 has an alarm() signature incompatible
// with the updated DurableObject base type in @cloudflare/workers-types.
// Remove when https://github.com/cloudflare/containers/issues/167 is resolved.
"skipLibCheck": true
},
"include": ["./*.ts"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ it("produces queue message with mocked send", async ({ expect }) => {
// Intercept calls to `QUEUE_PRODUCER.send()`
const sendSpy = vi
.spyOn(env.QUEUE_PRODUCER, "send")
.mockImplementation(async () => {});
.mockImplementation(async () => ({
metadata: {
metrics: {
backlogCount: 0,
backlogBytes: 0,
oldestMessageTimestamp: 0,
},
},
}));

// Enqueue job on queue
const request = new IncomingRequest("https://example.com/key", {
Expand Down
2 changes: 1 addition & 1 deletion packages/miniflare/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Local dev simulator for Cloudflare Workers, powered by workerd runtime. Main cla
## Testing

- Test files use `.spec.ts` (NOT `.test.ts`)
- `pool: "forks"`, `singleFork: true`
- `pool: "forks"`, `maxWorkers: 1` (Vitest 4 equivalent of the old `singleFork: true`)
- Does NOT extend `vitest.shared.ts` — own full vitest config
- Timeouts: 30s test, 30s hook
- `globals: true`
Expand Down
2 changes: 1 addition & 1 deletion packages/miniflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"@cspotcode/source-map-support": "0.8.1",
"sharp": "^0.34.5",
"undici": "catalog:default",
"workerd": "1.20260317.1",
"workerd": "1.20260329.1",
"ws": "catalog:default",
"youch": "4.1.0-beta.10"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,11 @@ describe("Same ID across multiple instances with same persistence directories",
},
});

// Wait for instanceA to be ready before starting instanceB to avoid
// SQLite "database is locked" errors when both instances race to open
// the same persistence file simultaneously.
await instanceA.ready;

instanceB = new Miniflare({
name: "worker-b",
inspectorPort: 0,
Expand All @@ -689,7 +694,6 @@ describe("Same ID across multiple instances with same persistence directories",
},
});

await instanceA.ready;
await instanceB.ready;

await waitForWorkersInRegistry(registryPath, ["worker-a", "worker-b"]);
Expand Down
6 changes: 1 addition & 5 deletions packages/miniflare/vitest.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ export default defineConfig({
testTimeout: 30_000,
hookTimeout: 30_000,
pool: "forks",
poolOptions: {
forks: {
singleFork: true,
},
},
maxWorkers: 1,
include: ["test/**/*.spec.ts"],
setupFiles: [path.resolve(__dirname, "test/setup.mjs")],
globals: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/vite-plugin-cloudflare/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"test:ci:build": "cross-env VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts",
"test:ci:serve": "vitest run -c vitest.config.e2e.ts",
"pretest:serve": "pnpm playwright:install",
"test:serve": "pnpm test:ci:serve --poolOptions.forks.singleFork=false"
"test:serve": "pnpm test:ci:serve"
},
"devDependencies": {
"@cloudflare/vite-plugin": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const IGNORED_KEYS = ["self"] as const;

/** Available methods for `WorkerEntrypoint` class */
export const WORKER_ENTRYPOINT_KEYS = [
"connect",
"email",
"fetch",
"queue",
Expand All @@ -22,6 +23,7 @@ export const WORKER_ENTRYPOINT_KEYS = [
/** Available methods for `DurableObject` class */
export const DURABLE_OBJECT_KEYS = [
"alarm",
"connect",
"fetch",
"webSocketClose",
"webSocketError",
Expand Down
5 changes: 4 additions & 1 deletion packages/vitest-pool-workers/src/pool/loopback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ export async function listDurableObjectIds(
try {
const names = await fs.readdir(namespacePath);
for (const name of names) {
if (name.endsWith(".sqlite")) {
// Exclude metadata.sqlite, added by newer workerd versions for
// per-namespace metadata. Only include files whose stem is a
// valid 64-hex-digit Durable Object ID.
if (name.endsWith(".sqlite") && name !== "metadata.sqlite") {
ids.push(name.substring(0, name.length - 7 /* ".sqlite".length */));
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/vitest-pool-workers/src/worker/entrypoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ function getEntrypointState(
}

const WORKER_ENTRYPOINT_KEYS = [
"connect",
"tailStream",
"fetch",
"tail",
Expand All @@ -186,6 +187,7 @@ const WORKER_ENTRYPOINT_KEYS = [
"email",
] as const;
const DURABLE_OBJECT_KEYS = [
"connect",
"fetch",
"alarm",
"webSocketMessage",
Expand Down
9 changes: 9 additions & 0 deletions packages/vitest-pool-workers/src/worker/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class QueueController<Body = unknown> /* MessageBatch */ {
// https://github.com/cloudflare/workerd/blob/v1.20231218.0/src/workerd/api/queue.h#L198
readonly queue!: string;
readonly messages!: QueueMessage<Body>[];
readonly metadata!: MessageBatchMetadata;
[kRetryAll] = false;
[kAckAll] = false;

Expand All @@ -263,6 +264,9 @@ class QueueController<Body = unknown> /* MessageBatch */ {
const messages = messagesOption.map(
(message) => new QueueMessage(kConstructFlag, this, message)
);
const metadata: MessageBatchMetadata = {
metrics: { backlogCount: 0, backlogBytes: 0, oldestMessageTimestamp: 0 },
};

// Match `JSG_READONLY_INSTANCE_PROPERTY` behaviour
Object.defineProperties(this, {
Expand All @@ -276,6 +280,11 @@ class QueueController<Body = unknown> /* MessageBatch */ {
return messages;
},
},
metadata: {
get() {
return metadata;
},
},
});
}

Expand Down
132 changes: 66 additions & 66 deletions packages/wrangler/e2e/versions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,39 +104,39 @@ describe.skipIf(!CLOUDFLARE_ACCOUNT_ID)(
);

expect(normalize(deploy.stdout)).toMatchInlineSnapshot(`
"╭ Deploy Worker Versions by splitting traffic between multiple versions
├ Fetching latest deployment
├ Your current deployment has 1 version(s):
│ (100%) 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: -
│ Message: -
├ Fetching deployable versions
├ Which version(s) do you want to deploy?
├ 1 Worker Version(s) selected
├ Worker Version 1: 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: e2e-upload
│ Message: Upload via e2e test
├ What percentage of traffic should Worker Version 1 receive?
├ 100% of traffic
├ Add a deployment message
│ Deployment message Deploy via e2e test
├ Deploying 1 version(s)
│ No non-versioned settings to sync. Skipping...
╰ SUCCESS Deployed tmp-e2e-worker-00000000-0000-0000-0000-000000000000 version 00000000-0000-0000-0000-000000000000 at 100% (TIMINGS)"
`);
"╭ Deploy Worker Versions by splitting traffic between multiple versions
├ Fetching latest deployment
├ Your current deployment has 1 version(s):
│ (100%) 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: -
│ Message: -
├ Fetching versions
├ Which version(s) do you want to deploy?
├ 1 Worker Version(s) selected
├ Worker Version 1: 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: e2e-upload
│ Message: Upload via e2e test
├ What percentage of traffic should Worker Version 1 receive?
├ 100% of traffic
├ Add a deployment message
│ Deployment message Deploy via e2e test
├ Deploying 1 version(s)
│ No non-versioned settings to sync. Skipping...
╰ SUCCESS Deployed tmp-e2e-worker-00000000-0000-0000-0000-000000000000 version 00000000-0000-0000-0000-000000000000 at 100% (TIMINGS)"
`);
});

it("should list 1 deployment", async ({ expect }) => {
Expand Down Expand Up @@ -228,39 +228,39 @@ describe.skipIf(!CLOUDFLARE_ACCOUNT_ID)(
const deploymentsList = await helper.run(`wrangler deployments list`);

expect(normalize(deploy.stdout)).toMatchInlineSnapshot(`
"╭ Deploy Worker Versions by splitting traffic between multiple versions
├ Fetching latest deployment
├ Your current deployment has 1 version(s):
│ (100%) 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: e2e-upload
│ Message: Upload via e2e test
├ Fetching deployable versions
├ Which version(s) do you want to deploy?
├ 1 Worker Version(s) selected
├ Worker Version 1: 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: e2e-upload-AGAIN
│ Message: Upload AGAIN via e2e test
├ What percentage of traffic should Worker Version 1 receive?
├ 100% of traffic
├ Add a deployment message
│ Deployment message Deploy AGAIN via e2e test
├ Deploying 1 version(s)
│ No non-versioned settings to sync. Skipping...
╰ SUCCESS Deployed tmp-e2e-worker-00000000-0000-0000-0000-000000000000 version 00000000-0000-0000-0000-000000000000 at 100% (TIMINGS)"
`);
"╭ Deploy Worker Versions by splitting traffic between multiple versions
├ Fetching latest deployment
├ Your current deployment has 1 version(s):
│ (100%) 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: e2e-upload
│ Message: Upload via e2e test
├ Fetching versions
├ Which version(s) do you want to deploy?
├ 1 Worker Version(s) selected
├ Worker Version 1: 00000000-0000-0000-0000-000000000000
│ Created: TIMESTAMP
│ Tag: e2e-upload-AGAIN
│ Message: Upload AGAIN via e2e test
├ What percentage of traffic should Worker Version 1 receive?
├ 100% of traffic
├ Add a deployment message
│ Deployment message Deploy AGAIN via e2e test
├ Deploying 1 version(s)
│ No non-versioned settings to sync. Skipping...
╰ SUCCESS Deployed tmp-e2e-worker-00000000-0000-0000-0000-000000000000 version 00000000-0000-0000-0000-000000000000 at 100% (TIMINGS)"
`);

// list 2 deployments (+ old deployment)
expect(normalize(deploymentsList.stdout)).toMatchInlineSnapshot(`
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"miniflare": "workspace:*",
"path-to-regexp": "6.3.0",
"unenv": "2.0.0-rc.24",
"workerd": "1.20260317.1"
"workerd": "1.20260329.1"
},
"devDependencies": {
"@aws-sdk/client-s3": "^3.721.0",
Expand Down
7 changes: 6 additions & 1 deletion packages/wrangler/src/dev/use-esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,12 @@ export function runBuild(
const watching = [path.resolve(entry.moduleRoot)];
const watcher = watch(watching, {
persistent: true,
ignored: [".git", "node_modules"],
// Ignore VCS dirs, dependencies, and the .wrangler dir (which
// contains miniflare state/cache files written by workerd at
// runtime — watching them causes an infinite reload loop).
// chokidar v4 normalises paths to forward slashes before
// matching, so a regex on path segments works cross-platform.
ignored: /[/\\](\.git|node_modules|\.wrangler)([/\\]|$)/,
}).on("change", async (_event) => {
await updateBundle();
});
Expand Down
Loading
Loading