Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: cloudflare/workers-sdk
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: @cloudflare/vitest-pool-workers@0.7.6
Choose a base ref
...
head repository: cloudflare/workers-sdk
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: @cloudflare/vitest-pool-workers@0.7.7
Choose a head ref
  • 9 commits
  • 68 files changed
  • 7 contributors

Commits on Mar 6, 2025

  1. feat(fixtures): Add new fixtures for Workers + Assets with service bi…

    …ndings (#7980)
    
    * feat(fixtures): Add new fixtures Workers + Assets with service bindings
    
    * feedback fixes
    
    * fix tests
    CarmenPopoviciu authored Mar 6, 2025

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    grahamc Graham Christensen
    Copy the full SHA
    187d887 View commit details
  2. Add type gen command to react + vite + assets template (#8349)

    * rename to jsonc
    
    * add type gen
    
    * changeset
    
    * fix tsconfig
    emily-shen authored Mar 6, 2025
    Copy the full SHA
    ca60010 View commit details
  3. graduate C3 React (Workers) template (#8371)

    Resolves DEVX-1697
    petebacondarwin authored Mar 6, 2025
    Copy the full SHA
    b24497d View commit details
  4. Version Packages (#8370)

    Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
    workers-devprod and github-actions[bot] authored Mar 6, 2025
    Copy the full SHA
    2138fef View commit details
  5. chore(create-cloudflare): bump template vitest packages version (#8291)

    edmundhung authored Mar 6, 2025
    Copy the full SHA
    8461f9b View commit details
  6. add vite + worker to vue experimental template (#8358)

    * add worker to vue template
    
    * add flags
    
    * changeset
    
    * fix js template
    
    * Update tangy-parts-dig.md
    
    * fix tests
    
    * pr feedback
    
    * fix test
    emily-shen authored Mar 6, 2025
    Copy the full SHA
    5875adb View commit details
  7. Change id parameter to name for both bucket lifecycle and r2 bucket l…

    …ock commands (#8367)
    
    * Change id parameter to name for both bucket lifecycle and r2 bucket lock commands
    
    * Added tests for id alias
    
    * Apply suggestions from code review
    
    Co-authored-by: Edmund Hung <edmund@cloudflare.com>
    
    ---------
    
    Co-authored-by: Edmund Hung <edmund@cloudflare.com>
    jonesphillip and edmundhung authored Mar 6, 2025
    Copy the full SHA
    7b6b0c2 View commit details
  8. chore: update changeset (#8381)

    * chore: update changeset
    
    * Update .changeset/whole-dots-smile.md
    
    Co-authored-by: Pete Bacon Darwin <pete@bacondarwin.com>
    
    ---------
    
    Co-authored-by: Pete Bacon Darwin <pete@bacondarwin.com>
    edmundhung and petebacondarwin authored Mar 6, 2025
    Copy the full SHA
    d96fd53 View commit details
  9. Version Packages (#8378)

    Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
    workers-devprod and github-actions[bot] authored Mar 6, 2025
    Copy the full SHA
    56c4ba9 View commit details
Showing with 1,403 additions and 185 deletions.
  1. +65 −0 fixtures/workers-with-assets-and-service-bindings/README.md
  2. +21 −0 fixtures/workers-with-assets-and-service-bindings/package.json
  3. +247 −0 fixtures/workers-with-assets-and-service-bindings/tests/index.test.ts
  4. +7 −0 fixtures/workers-with-assets-and-service-bindings/tests/tsconfig.json
  5. +13 −0 fixtures/workers-with-assets-and-service-bindings/tsconfig.json
  6. +30 −0 fixtures/workers-with-assets-and-service-bindings/workerA/src/index.ts
  7. +27 −0 fixtures/workers-with-assets-and-service-bindings/workerA/src/workerB.util.ts
  8. +23 −0 fixtures/workers-with-assets-and-service-bindings/workerA/src/workerC.util.ts
  9. +22 −0 fixtures/workers-with-assets-and-service-bindings/workerA/src/workerD.util.ts
  10. +19 −0 fixtures/workers-with-assets-and-service-bindings/workerA/wrangler.toml
  11. +1 −0 fixtures/workers-with-assets-and-service-bindings/workerB-with-default-export/public/busy-bee.html
  12. +1 −0 fixtures/workers-with-assets-and-service-bindings/workerB-with-default-export/public/index.html
  13. +36 −0 fixtures/workers-with-assets-and-service-bindings/workerB-with-default-export/src/index.ts
  14. +7 −0 fixtures/workers-with-assets-and-service-bindings/workerB-with-default-export/wrangler.toml
  15. +1 −0 ...res/workers-with-assets-and-service-bindings/workerC-with-default-entrypoint/public/busy-bee.html
  16. +1 −0 fixtures/workers-with-assets-and-service-bindings/workerC-with-default-entrypoint/public/index.html
  17. +41 −0 fixtures/workers-with-assets-and-service-bindings/workerC-with-default-entrypoint/src/index.ts
  18. +7 −0 fixtures/workers-with-assets-and-service-bindings/workerC-with-default-entrypoint/wrangler.toml
  19. +1 −0 fixtures/workers-with-assets-and-service-bindings/workerD-with-named-entrypoint/public/busy-bee.html
  20. +1 −0 fixtures/workers-with-assets-and-service-bindings/workerD-with-named-entrypoint/public/index.html
  21. +35 −0 fixtures/workers-with-assets-and-service-bindings/workerD-with-named-entrypoint/src/index.ts
  22. +7 −0 fixtures/workers-with-assets-and-service-bindings/workerD-with-named-entrypoint/wrangler.toml
  23. +1 −1 fixtures/workers-with-assets/README.md
  24. +16 −0 packages/create-cloudflare/CHANGELOG.md
  25. +2 −26 packages/create-cloudflare/e2e-tests/frameworks/framework-test-config-experimental.ts
  26. +32 −3 packages/create-cloudflare/e2e-tests/frameworks/framework-test-config.ts
  27. +1 −1 packages/create-cloudflare/package.json
  28. +0 −2 packages/create-cloudflare/src/templates.ts
  29. +2 −2 packages/create-cloudflare/templates-experimental/hello-world-with-assets/js/package.json
  30. +2 −2 packages/create-cloudflare/templates-experimental/hello-world-with-assets/ts/package.json
  31. +69 −4 packages/create-cloudflare/templates-experimental/vue/c3.ts
  32. +13 −0 packages/create-cloudflare/templates-experimental/vue/js/server/index.js
  33. +107 −0 packages/create-cloudflare/templates-experimental/vue/js/src/App.vue
  34. +47 −0 packages/create-cloudflare/templates-experimental/vue/js/src/components/HelloWorld.vue
  35. +21 −0 packages/create-cloudflare/templates-experimental/vue/js/vite.config.js
  36. +12 −0 packages/create-cloudflare/templates-experimental/vue/js/wrangler.jsonc
  37. +0 −10 packages/create-cloudflare/templates-experimental/vue/templates/wrangler.jsonc
  38. +13 −0 packages/create-cloudflare/templates-experimental/vue/ts/server/index.ts
  39. +107 −0 packages/create-cloudflare/templates-experimental/vue/ts/src/App.vue
  40. +44 −0 packages/create-cloudflare/templates-experimental/vue/ts/src/components/HelloWorld.vue
  41. +8 −0 packages/create-cloudflare/templates-experimental/vue/ts/tsconfig.worker.json
  42. +21 −0 packages/create-cloudflare/templates-experimental/vue/ts/vite.config.ts
  43. +6 −0 packages/create-cloudflare/templates-experimental/vue/ts/worker-configuration.d.ts
  44. +12 −0 packages/create-cloudflare/templates-experimental/vue/ts/wrangler.jsonc
  45. +2 −2 packages/create-cloudflare/templates/hello-world/js/package.json
  46. +2 −2 packages/create-cloudflare/templates/hello-world/ts/package.json
  47. +5 −57 packages/create-cloudflare/templates/react/c3.ts
  48. +62 −0 packages/create-cloudflare/templates/react/pages/c3.ts
  49. +4 −3 packages/create-cloudflare/{templates-experimental/react → templates/react/workers}/c3.ts
  50. 0 packages/create-cloudflare/{templates-experimental/react → templates/react/workers}/js/api/index.js
  51. 0 packages/create-cloudflare/{templates-experimental/react → templates/react/workers}/js/src/App.jsx
  52. 0 ...dflare/{templates-experimental/react → templates/react/workers}/js/src/assets/Cloudflare_Logo.svg
  53. 0 ...flare/{templates-experimental/react/js/wrangler.json → templates/react/workers/js/wrangler.jsonc}
  54. +0 −4 packages/create-cloudflare/{templates-experimental/react → templates/react/workers}/ts/api/index.ts
  55. 0 packages/create-cloudflare/{templates-experimental/react → templates/react/workers}/ts/src/App.tsx
  56. 0 ...dflare/{templates-experimental/react → templates/react/workers}/ts/src/assets/Cloudflare_Logo.svg
  57. +1 −1 ...reate-cloudflare/{templates-experimental/react → templates/react/workers}/ts/tsconfig.worker.json
  58. +5 −0 packages/create-cloudflare/templates/react/workers/ts/worker-configuration.d.ts
  59. 0 ...flare/{templates-experimental/react/ts/wrangler.json → templates/react/workers/ts/wrangler.jsonc}
  60. +7 −0 packages/vitest-pool-workers/CHANGELOG.md
  61. +1 −1 packages/vitest-pool-workers/package.json
  62. +6 −0 packages/wrangler/CHANGELOG.md
  63. +1 −1 packages/wrangler/package.json
  64. +87 −19 packages/wrangler/src/__tests__/r2.test.ts
  65. +4 −4 packages/wrangler/src/r2/helpers.ts
  66. +22 −19 packages/wrangler/src/r2/lifecycle.ts
  67. +24 −21 packages/wrangler/src/r2/lock.ts
  68. +21 −0 pnpm-lock.yaml
65 changes: 65 additions & 0 deletions fixtures/workers-with-assets-and-service-bindings/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# workers-with-assets-and-service-bindings

`workers-with-assets-and-service-bindings` is a test fixture that showcases [Service Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) between a Worker and a [Worker with assets](https://developers.cloudflare.com/workers/static-assets/).

The fixture sets up multiple Workers:

- `worker-A` ➔ a regular Worker without assets
- `worker-B` ➔ a Worker with assets, that exports a default object

```
export default {
async fetch() {}
}
```

- `worker-C` ➔ a Worker with assets, that exports a default entrypoint

```
export default class extends WorkerEntrypoint {
async fetch(){}
}
```

- `worker-D` ➔ a Worker with assets, that exports a named entrypoint

```
export class EntrypointD extends WokrerEntrypoint {}
```

and configures service bindings between `worker-A` and all other Workers:

```
## workerA/wrangler.toml
# service binding to Worker that exports a default object
[[services]]
binding = "DEFAULT_EXPORT"
service = "worker-b"
# service binding to Worker that exports a default entrypoint
[[services]]
binding = "DEFAULT_ENTRYPOINT"
service = "worker-c"
# service binding to Worker that exports a named entrypoint
[[services]]
binding = "NAMED_ENTRYPOINT"
service = "worker-d"
entrypoint = "EntrypointD"
```

## dev

To start a dev session for each Worker individually, run:

```
cd <worker_directory>
wrangler dev
```

## Run tests

```
npm run test:ci
```
21 changes: 21 additions & 0 deletions fixtures/workers-with-assets-and-service-bindings/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "workers-with-assets-and-service-bindings",
"private": true,
"scripts": {
"dev": "wrangler dev",
"test:ci": "vitest run",
"test:watch": "vitest",
"type:tests": "tsc -p ./tests/tsconfig.json"
},
"devDependencies": {
"@cloudflare/workers-tsconfig": "workspace:*",
"@cloudflare/workers-types": "^4.20250121.0",
"typescript": "catalog:default",
"undici": "catalog:default",
"vitest": "catalog:default",
"wrangler": "workspace:*"
},
"volta": {
"extends": "../../package.json"
}
}
247 changes: 247 additions & 0 deletions fixtures/workers-with-assets-and-service-bindings/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
import { resolve } from "node:path";
import { setTimeout } from "timers/promises";
import { fetch } from "undici";
import { afterAll, beforeAll, describe, it } from "vitest";
import { runWranglerDev } from "../../shared/src/run-wrangler-long-lived";

const devCmds = [{ args: [] }, { args: ["--x-assets-rpc"] }];

describe.each(devCmds)(
"[wrangler dev $args][Workers + Assets] Service bindings to Worker with assets",
({ args }) => {
let ipWorkerA: string,
portWorkerA: number,
stopWorkerA: (() => Promise<unknown>) | undefined;
let stopWorkerB: (() => Promise<unknown>) | undefined,
getOutputWorkerB: () => string;
let stopWorkerC: (() => Promise<unknown>) | undefined,
getOutputWorkerC: () => string;
let stopWorkerD: (() => Promise<unknown>) | undefined;

beforeAll(async () => {
({ getOutput: getOutputWorkerB } = await runWranglerDev(
resolve(__dirname, "..", "workerB-with-default-export"),
["--port=0", "--inspector-port=0", ...args]
));

({ getOutput: getOutputWorkerC } = await runWranglerDev(
resolve(__dirname, "..", "workerC-with-default-entrypoint"),
["--port=0", "--inspector-port=0", ...args]
));

({ stop: stopWorkerD } = await runWranglerDev(
resolve(__dirname, "..", "workerD-with-named-entrypoint"),
["--port=0", "--inspector-port=0", ...args]
));

({
ip: ipWorkerA,
port: portWorkerA,
stop: stopWorkerA,
} = await runWranglerDev(resolve(__dirname, "..", "workerA"), [
"--port=0",
"--inspector-port=0",
]));
});

afterAll(async () => {
await stopWorkerA?.();
await stopWorkerB?.();
await stopWorkerC?.();
await stopWorkerD?.();
});

describe("Workers running in separate wrangler dev sessions", () => {
describe("Service binding to default export", () => {
// this currently incorrectly returns the User Worker response
// instead of the Asset Worker response
it.fails(
"should return Asset Worker response for routes that serve static content",
async ({ expect }) => {
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
`env.DEFAULT_EXPORT.fetch() response: This is an asset of "worker-b"`
);

response = await fetch(
`http://${ipWorkerA}:${portWorkerA}/busy-bee`
);
text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
`env.DEFAULT_EXPORT.fetch() response: All "worker-b" 🐝🐝🐝 are 🐝sy. Please come back later`
);
}
);

it("should return User Worker response for routes that don't serve static content", async ({
expect,
}) => {
let response = await fetch(
`http://${ipWorkerA}:${portWorkerA}/no-assets-at-this-path`
);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.DEFAULT_EXPORT.fetch() response: Hello from worker-b fetch()"
);
});

it("should return User Worker response for named functions", async ({
expect,
}) => {
// fetch URL is irrelevant here. workerA will internally call
// the appropriate fns on the service binding instead
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.DEFAULT_EXPORT.bee() response: Workers in non-class based syntax do not support RPC functions with zero or variable number of arguments. They only support RPC functions with strictly one argument."
);
expect(text).toContain(
'env.DEFAULT_EXPORT.busyBee("🐝") response: Hello busy 🐝s from worker-b busyBee(bee)'
);
});

it("should return cron trigger responses", async ({ expect }) => {
// fetch URL is irrelevant here. workerA will internally call
// env.DEFAULT_EXPORT.scheduled({cron: "* * * * *"}) instead
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.DEFAULT_EXPORT.scheduled() response: undefined"
);

// add a timeout to allow stdout to update
await setTimeout(500);
console.log(getOutputWorkerB());
expect(getOutputWorkerB()).toContain(
"Hello from worker-b scheduled()"
);
});
});

describe("Service binding to default entrypoint", () => {
// this currently incorrectly returns the User Worker response
// instead of the Asset Worker response
it.fails(
"should return Asset Worker response for fetch requestsfor routes that serve static content",
async ({ expect }) => {
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
`env.DEFAULT_ENTRYPOINT.fetch() response: This is an asset of "worker-c"`
);

response = await fetch(
`http://${ipWorkerA}:${portWorkerA}/busy-bee`
);
text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
`env.DEFAULT_ENTRYPOINT.fetch() response: All "worker-c" 🐝🐝🐝 are 🐝sy. Please come back later`
);
}
);

it("should return User Worker response for routes that don't serve static content", async ({
expect,
}) => {
let response = await fetch(
`http://${ipWorkerA}:${portWorkerA}/no-assets-at-this-path`
);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.DEFAULT_ENTRYPOINT.fetch() response: Hello from worker-c fetch()"
);
});

it("should return User Worker response for named functions", async ({
expect,
}) => {
// fetch URL is irrelevant here. workerA will internally call
// the appropriate fns on the service binding instead
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.DEFAULT_ENTRYPOINT.bee() response: Hello from worker-c bee()"
);
expect(text).toContain(
'env.DEFAULT_ENTRYPOINT.busyBee("🐝") response: Hello busy 🐝s from worker-c busyBee(bee)'
);
});

it("should return cron trigger responses", async ({ expect }) => {
// fetch URL is irrelevant here. workerA will internally call
// env.DEFAULT_ENTRYPOINT.scheduled({cron: "* * * * *"}) instead
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.DEFAULT_ENTRYPOINT.scheduled() response: undefined"
);

// add a timeout to allow stdout to update
await setTimeout(500);
expect(getOutputWorkerC()).toContain(
"Hello from worker-c scheduled()"
);
});
});

describe("Service binding to named entrypoint", () => {
it("should return User Worker response for fetch requests", async ({
expect,
}) => {
// static asset route
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
`env.NAMED_ENTRYPOINT.fetch() response: Hello from worker-d fetch()`
);

// static asset route
response = await fetch(`http://${ipWorkerA}:${portWorkerA}/busy-bee`);
text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
`env.NAMED_ENTRYPOINT.fetch() response: Hello from worker-d fetch()`
);

// User Worker route
response = await fetch(
`http://${ipWorkerA}:${portWorkerA}/no-assets-at-this-path`
);
text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.NAMED_ENTRYPOINT.fetch() response: Hello from worker-d fetch()"
);
});

it("should return User Worker response for named functions", async ({
expect,
}) => {
// fetch URL is irrelevant here. workerA will internally call
// the appropriate fns on the service binding instead
let response = await fetch(`http://${ipWorkerA}:${portWorkerA}`);
let text = await response.text();
expect(response.status).toBe(200);
expect(text).toContain(
"env.NAMED_ENTRYPOINT.bee() response: Hello from worker-d bee()"
);
expect(text).toContain(
'env.NAMED_ENTRYPOINT.busyBee("🐝") response: Hello busy 🐝s from worker-d busyBee(bee)'
);
});
});
});
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@cloudflare/workers-tsconfig/tsconfig.json",
"compilerOptions": {
"types": ["node"]
},
"include": ["**/*.ts", "../../../node-types.d.ts"]
}
13 changes: 13 additions & 0 deletions fixtures/workers-with-assets-and-service-bindings/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"lib": ["ES2020"],
"types": ["@cloudflare/workers-types"],
"moduleResolution": "node",
"noEmit": true,
"skipLibCheck": true
},
"include": ["**/*.ts"],
"exclude": ["tests"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { getWorkerBResponses } from "./workerB.util";
import { getWorkerCResponses } from "./workerC.util";
import { getWorkerDResponses } from "./workerD.util";

export default {
async fetch(request, env) {
const workerBResponses = await getWorkerBResponses(request, env);
const workerCResponses = await getWorkerCResponses(request, env);
const workerDResponses = await getWorkerDResponses(request, env);

// let's return everything for now to make testing easier
return new Response(
`"worker-b" Responses\n` +
`env.DEFAULT_EXPORT.fetch() response: ${workerBResponses.fetchResponse}\n` +
`env.DEFAULT_EXPORT.bee() response: ${workerBResponses.beeResult}\n` +
`env.DEFAULT_EXPORT.busyBee("🐝") response: ${workerBResponses.busyBeeResult}\n` +
`env.DEFAULT_EXPORT.scheduled() response: ${workerBResponses.scheduledResponse}\n\n` +
`"worker-c" Responses\n` +
`env.DEFAULT_ENTRYPOINT.fetch() response: ${workerCResponses.fetchResponse}\n` +
`env.DEFAULT_ENTRYPOINT.bee() response: ${workerCResponses.beeResult}\n` +
`env.DEFAULT_ENTRYPOINT.busyBee("🐝") response: ${workerCResponses.busyBeeResult}\n` +
`env.DEFAULT_ENTRYPOINT.scheduled() response: ${workerCResponses.scheduledResponse}\n\n` +
`"worker-d" Responses\n` +
`env.NAMED_ENTRYPOINT.fetch() response: ${workerDResponses.fetchResponse}\n` +
`env.NAMED_ENTRYPOINT.bee() response: ${workerDResponses.beeResult}\n` +
`env.NAMED_ENTRYPOINT.busyBee("🐝") response: ${workerDResponses.busyBeeResult}\n` +
`env.NAMED_ENTRYPOINT.scheduled() response: ${workerDResponses.scheduledResponse}\n\n`
);
},
};
Loading