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
5 changes: 5 additions & 0 deletions .changeset/modern-dots-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/vite-plugin": patch
---

Provide proxy shared secret to Miniflare so that the Worker receives the original Host header
24 changes: 24 additions & 0 deletions .changeset/tender-views-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
"@cloudflare/vite-plugin": minor
---

Infer `upload_source_maps` setting in the output Worker config from the `build.sourcemap` setting in the Vite config.

If [build.sourcemap](https://vite.dev/config/build-options#build-sourcemap) is enabled for a Worker environment, as in the following example, `"upload_source_maps": true` will now automatically be added to the output `wrangler.json` file.
This removes the need to additionally specify the `upload_source_maps` property in the input Worker config.

```ts
export default defineConfig({
environments: {
my_worker: {
build: {
sourcemap: true,
},
},
},
plugins: [cloudflare()],
});
```

Note that if `upload_source_maps` is set in the input Worker config, this value will take precedence.
This makes it possible to generate source maps without uploading them.
30 changes: 21 additions & 9 deletions packages/vite-plugin-cloudflare/e2e/basic.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { rm, writeFile } from "node:fs/promises";
import { describe, expect, onTestFinished, test, vi } from "vitest";
import { describe, onTestFinished, test, vi } from "vitest";
import {
fetchJson,
isBuildAndPreviewOnWindows,
Expand All @@ -18,7 +18,7 @@ describe("basic e2e tests", () => {
describe.each(commands)('with "%s" command', (command) => {
test.skipIf(isBuildAndPreviewOnWindows(command))(
"can serve a Worker that uses a Node.js API (crypto)",
async () => {
async ({ expect }) => {
const proc = await runLongLived(pm, command, projectPath);
const url = await waitForReady(proc);
expect(await fetchJson(url + "/api/")).toEqual({
Expand All @@ -31,7 +31,7 @@ describe("basic e2e tests", () => {
// See https://github.com/cloudflare/workerd/pull/5062
test.skipIf(process.platform === "win32")(
"can listen to abort signals on the request",
async () => {
async ({ expect }) => {
const proc = await runLongLived(pm, command, projectPath);
const url = await waitForReady(proc);

Expand Down Expand Up @@ -59,7 +59,9 @@ describe("basic e2e tests", () => {
describe.skipIf(isBuildAndPreviewOnWindows(command))(
"environment variables",
() => {
test("can read vars from wrangler configuration and .env", async () => {
test("can read vars from wrangler configuration and .env", async ({
expect,
}) => {
await writeFile(
projectPath + "/.env",
"SECRET_A=dev-1\nSECRET_B=dev-2"
Expand All @@ -76,7 +78,9 @@ describe("basic e2e tests", () => {
});
});

test("will not load local dev vars from .env if there is a .dev.vars file", async () => {
test("will not load local dev vars from .env if there is a .dev.vars file", async ({
expect,
}) => {
await writeFile(
projectPath + "/.env",
"SECRET_A=dot-env-1\nSECRET_B=dot-env-2"
Expand All @@ -97,7 +101,9 @@ describe("basic e2e tests", () => {
});
});

test("will not load local dev vars from .env if CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV is set to false", async () => {
test("will not load local dev vars from .env if CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV is set to false", async ({
expect,
}) => {
await writeFile(
projectPath + "/.env",
"SECRET_A=dot-env-1\nSECRET_B=dot-env-2"
Expand All @@ -114,7 +120,9 @@ describe("basic e2e tests", () => {
});
});

test("can merge vars from wrangler configuration, .env, and .env.local", async () => {
test("can merge vars from wrangler configuration, .env, and .env.local", async ({
expect,
}) => {
await writeFile(
projectPath + "/.env",
"SECRET_A=dev-1\nSECRET_B=dev-2"
Expand All @@ -136,7 +144,9 @@ describe("basic e2e tests", () => {
});
});

test("can merge vars from wrangler configuration, .env, and .env.local, and environment specific files", async () => {
test("can merge vars from wrangler configuration, .env, and .env.local, and environment specific files", async ({
expect,
}) => {
await writeFile(
projectPath + "/.env",
"SECRET_A=dev-1\nSECRET_B=dev-2"
Expand Down Expand Up @@ -171,7 +181,9 @@ describe("basic e2e tests", () => {
});
});

test("can read vars from process.env if CLOUDFLARE_INCLUDE_PROCESS_ENV is set", async () => {
test("can read vars from process.env if CLOUDFLARE_INCLUDE_PROCESS_ENV is set", async ({
expect,
}) => {
const proc = await runLongLived(pm, command, projectPath, {
CLOUDFLARE_INCLUDE_PROCESS_ENV: "true",
});
Expand Down
6 changes: 4 additions & 2 deletions packages/vite-plugin-cloudflare/e2e/dynamic.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, test } from "vitest";
import { describe, test } from "vitest";
import { fetchJson, runLongLived, seed, waitForReady } from "./helpers.js";

const packageManagers = ["pnpm", "npm", "yarn"] as const;
Expand All @@ -7,7 +7,9 @@ describe("prebundling Node.js compatibility", () => {
describe.each(packageManagers)('with "%s" package manager', (pm) => {
const projectPath = seed("dynamic", { pm });

test("will not cause a reload on a dynamic import of a Node.js module", async () => {
test("will not cause a reload on a dynamic import of a Node.js module", async ({
expect,
}) => {
const proc = await runLongLived(pm, "dev", projectPath);
const url = await waitForReady(proc);
expect(await fetchJson(url)).toEqual("OK!");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, test } from "vitest";
import { describe, test } from "vitest";
import { runLongLived, seed } from "./helpers";

// The test here just makes sure that the validation takes place.
Expand All @@ -8,7 +8,9 @@ describe("validate Worker environment options", () => {
pm: "pnpm",
});

test("throws an error for invalid environment options", async () => {
test("throws an error for invalid environment options", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
expect(await proc.exitCode).not.toBe(0);
expect(proc.stderr).toContain(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, test } from "vitest";
import { describe, test } from "vitest";
import { runLongLived, seed } from "./helpers.js";

describe("invalid Wrangler version e2e tests", () => {
Expand All @@ -10,7 +10,9 @@ describe("invalid Wrangler version e2e tests", () => {
useStrictPeerDeps: false,
});

test("`vite dev` will error when peer installed wrangler version overrides the expected internal dependency", async () => {
test("`vite dev` will error when peer installed wrangler version overrides the expected internal dependency", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
expect(await proc.exitCode).not.toBe(0);
expect(proc.stderr).toMatch(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { describe, expect, test } from "vitest";
import { describe, test } from "vitest";
import { runLongLived, seed } from "./helpers";

describe("nodejs_compat warnings - Node.js built-ins imported directly", () => {
const projectPath = seed("nodejs-compat-warnings/direct-import", {
pm: "pnpm",
});

test("displays warnings if Node.js built-ins are imported and the `nodejs_compat` flag is not enabled", async () => {
test("displays warnings if Node.js built-ins are imported and the `nodejs_compat` flag is not enabled", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
expect(await proc.exitCode).not.toBe(0);
const errorLogs = proc.stderr.replaceAll("\\", "/");
Expand All @@ -23,7 +25,9 @@ describe("nodejs_compat warnings - Node.js built-ins imported via dependency", (
pm: "pnpm",
});

test("displays warnings if Node.js built-ins are imported and the `nodejs_compat` flag is not enabled", async () => {
test("displays warnings if Node.js built-ins are imported and the `nodejs_compat` flag is not enabled", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
expect(await proc.exitCode).not.toBe(0);
const errorLogs = proc.stderr.replaceAll("\\", "/");
Expand Down
81 changes: 40 additions & 41 deletions packages/vite-plugin-cloudflare/e2e/remote-bindings.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import assert from "node:assert";
import { readFile, writeFile } from "node:fs/promises";
import { setTimeout } from "node:timers/promises";
import { beforeAll, describe, expect, test, vi } from "vitest";
import { beforeAll, describe, test, vi } from "vitest";
import {
fetchJson,
isBuildAndPreviewOnWindows,
Expand All @@ -12,8 +12,17 @@ import {
} from "./helpers.js";

const commands = ["dev", "buildAndPreview"] as const;

if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) {
const isWindows = process.platform === "win32";

// Remote bindings tests are skipped on Windows due to slow/unreliable remote proxy
// session initialization times in CI, which causes intermittent timeout failures.
// See: https://jira.cfdata.org/browse/DEVX-2030
if (isWindows) {
describe.skip("Skipping remote bindings tests on Windows.");
} else if (
!process.env.CLOUDFLARE_ACCOUNT_ID ||
!process.env.CLOUDFLARE_API_TOKEN
) {
describe.skip("Skipping remote bindings tests without account credentials.");
} else {
describe
Expand Down Expand Up @@ -55,7 +64,7 @@ if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) {
describe.each(commands)('with "%s" command', (command) => {
test.skipIf(isBuildAndPreviewOnWindows(command))(
"can fetch from both local (/auxiliary) and remote workers",
async () => {
async ({ expect }) => {
const proc = await runLongLived("pnpm", command, projectPath);
const url = await waitForReady(proc);
expect(await fetchJson(url)).toEqual({
Expand All @@ -70,7 +79,7 @@ if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) {
// This test checks that wrapped bindings (e.g. AI) which rely on additional workers with an authed connection to the CF API work
test.skipIf(isBuildAndPreviewOnWindows(command))(
"Wrapped bindings (e.g. Workers AI) can serve a request",
async () => {
async ({ expect }) => {
const proc = await runLongLived("pnpm", command, projectPath);
const url = await waitForReady(proc);

Expand All @@ -81,7 +90,7 @@ if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) {
);
});

test("reflects changes applied during dev", async () => {
test("reflects changes applied during dev", async ({ expect }) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
const url = await waitForReady(proc);
expect(await fetchJson(url)).toEqual({
Expand Down Expand Up @@ -143,7 +152,9 @@ if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) {
pm: "pnpm",
});

test("for connection to remote bindings during dev the account_id present in the wrangler config file is used", async () => {
test("for connection to remote bindings during dev the account_id present in the wrangler config file is used", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
await vi.waitFor(
async () => {
Expand All @@ -160,55 +171,43 @@ if (!process.env.CLOUDFLARE_ACCOUNT_ID || !process.env.CLOUDFLARE_API_TOKEN) {
});
});

describe("failure to connect to remote bindings", () => {
describe.skipIf(isWindows)("failure to connect to remote bindings", () => {
const projectPath = seed("remote-bindings-incorrect-r2-config", {
pm: "pnpm",
});

describe.each(commands)('with "%s" command', (command) => {
// On Windows the path for the miniflare dependency gets pretty long and this fails in node < 22.7
// (see: https://github.com/shellscape/jsx-email/issues/225#issuecomment-2420567832), so
// we need to skip this on windows since in CI we're using node 20
// we should look into re-enable this once we can move to a node a newer version of node
test.skipIf(process.platform === "win32")(
"exit with a non zero error code and log an error",
async () => {
const proc = await runLongLived("pnpm", command, projectPath);
test("exit with a non zero error code and log an error", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", command, projectPath);

expect(await proc.exitCode).not.toBe(0);
expect(proc.stderr).toContain(
"R2 bucket 'non-existent-r2-bucket' not found. Please use a different name and try again. [code: 10085]"
);
expect(proc.stderr).toContain(
"Error: Failed to start the remote proxy session. There is likely additional logging output above."
);
}
);
expect(await proc.exitCode).not.toBe(0);
expect(proc.stderr).toContain(
"R2 bucket 'non-existent-r2-bucket' not found. Please use a different name and try again. [code: 10085]"
);
expect(proc.stderr).toContain(
"Error: Failed to start the remote proxy session. There is likely additional logging output above."
);
});
});
});
}

describe("remote bindings disabled", () => {
describe.skipIf(isWindows)("remote bindings disabled", () => {
const projectPath = seed("remote-bindings-disabled", { pm: "pnpm" });

describe.each(commands)('with "%s" command', (command) => {
// On Windows the path for the miniflare dependency gets pretty long and this fails in node < 22.7
// (see: https://github.com/shellscape/jsx-email/issues/225#issuecomment-2420567832), so
// we need to skip this on windows since in CI we're using node 20
// we should look into re-enable this once we can move to a node a newer version of node
test.skipIf(process.platform === "win32")(
"cannot connect to remote bindings",
async () => {
const proc = await runLongLived("pnpm", command, projectPath);
const url = await waitForReady(proc);
test("cannot connect to remote bindings", async ({ expect }) => {
const proc = await runLongLived("pnpm", command, projectPath);
const url = await waitForReady(proc);

const response = await fetch(url);
const response = await fetch(url);

const responseText = await response.text();
const responseText = await response.text();

expect(responseText).toContain("Error");
expect(responseText).toContain("Binding AI needs to be run remotely");
}
);
expect(responseText).toContain("Error");
expect(responseText).toContain("Binding AI needs to be run remotely");
});
});
});
6 changes: 4 additions & 2 deletions packages/vite-plugin-cloudflare/e2e/unresolved-main.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { describe, expect, test } from "vitest";
import { describe, test } from "vitest";
import { runLongLived, seed } from "./helpers";

describe("unresolved main entry file", () => {
const projectPath = seed("unresolved-main", { pm: "pnpm" });

test("throws an error when the main entry file cannot be resolved", async () => {
test("throws an error when the main entry file cannot be resolved", async ({
expect,
}) => {
const proc = await runLongLived("pnpm", "dev", projectPath);
expect(await proc.exitCode).not.toBe(0);
expect(proc.stderr).toContain(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, test } from "vitest";
import { describe, test } from "vitest";
import { runLongLived, seed } from "./helpers";

// Note: the tests here just make sure that the validation does take place, for more fine grained
Expand All @@ -9,7 +9,7 @@ describe("during development wrangler config files are validated", () => {
"no-wrangler-config-for-auxiliary-worker",
{ pm: "pnpm" }
);
test("for auxiliary workers", async () => {
test("for auxiliary workers", async ({ expect }) => {
const proc = await runLongLived(
"pnpm",
"dev",
Expand Down
Loading
Loading