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

Allow internal Wrangler config path overrides via env

`@cloudflare/vite-plugin` now checks `CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH` when `configPath` is not set explicitly. This lets integrators provide generated Wrangler configs outside the project root without requiring users to thread `configPath` through framework config.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { mkdir, rm, writeFile } from "node:fs/promises";
import path from "node:path";
import { describe, test } from "vitest";
import { fetchJson, runLongLived, seed, waitForReady } from "./helpers.js";

describe("generated Wrangler config path", () => {
const projectPath = seed("dynamic", { pm: "pnpm" });

test("can serve a Vite app using CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH", async ({
expect,
}) => {
await mkdir(path.join(projectPath, ".generated"), { recursive: true });
await writeFile(
path.join(projectPath, ".generated/wrangler.jsonc"),
JSON.stringify(
{
name: "cloudflare-vite-e2e-generated-config-path",
main: "../src/index.ts",
compatibility_date: "2024-12-30",
compatibility_flags: ["nodejs_compat"],
},
null,
2
)
);
await rm(path.join(projectPath, "wrangler.jsonc"));

const proc = await runLongLived("pnpm", "dev", projectPath, {
CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH: ".generated/wrangler.jsonc",
});
const url = await waitForReady(proc);

expect(await fetchJson(url)).toEqual("OK!");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { removeDirSync } from "@cloudflare/workers-utils";
import { afterEach, assert, beforeEach, describe, test } from "vitest";
import { afterEach, assert, beforeEach, describe, test, vi } from "vitest";
import { resolvePluginConfig } from "../plugin-config";
import type {
AssetsOnlyResolvedConfig,
Expand Down Expand Up @@ -588,6 +588,127 @@ describe("resolvePluginConfig - zero-config mode", () => {
});
});

describe("resolvePluginConfig - internal config path env fallback", () => {
let tempDir: string;
let originalConfigPathEnvVar: string | undefined;

beforeEach(() => {
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "vite-plugin-test-"));
originalConfigPathEnvVar = process.env.CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH;
});

afterEach(() => {
vi.unstubAllEnvs();
if (originalConfigPathEnvVar === undefined) {
delete process.env.CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH;
} else {
process.env.CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH =
originalConfigPathEnvVar;
}
removeDirSync(tempDir);
});

const viteEnv = { mode: "development", command: "serve" as const };

function createWorkerConfig(dir: string, name: string) {
const configPath = path.join(dir, "wrangler.jsonc");
fs.mkdirSync(path.join(dir, "src"), { recursive: true });
fs.writeFileSync(
configPath,
JSON.stringify({
name,
main: "./src/index.ts",
compatibility_date: "2024-01-01",
})
);
fs.writeFileSync(path.join(dir, "src/index.ts"), "export default {}");
return configPath;
}

test("should resolve entry worker config from CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH loaded from env files", ({
expect,
}) => {
const hiddenConfigPath = createWorkerConfig(
path.join(tempDir, ".sst"),
"hidden-worker"
);
fs.writeFileSync(
path.join(tempDir, ".env.development"),
"CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH=.sst/wrangler.jsonc\n"
);

const result = resolvePluginConfig(
{},
{ root: tempDir },
viteEnv
) as WorkersResolvedConfig;

expect(result.type).toBe("workers");
const entryWorker = result.environmentNameToWorkerMap.get(
result.entryWorkerEnvironmentName
);
assert(entryWorker);
expect(entryWorker.config.name).toBe("hidden-worker");
expect(entryWorker.config.main).toBe(
path.join(tempDir, ".sst", "src/index.ts")
);
expect([...result.configPaths]).toEqual([hiddenConfigPath]);
});

test("should prefer CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH over auto-discovered config", ({
expect,
}) => {
createWorkerConfig(tempDir, "root-worker");
const hiddenConfigPath = createWorkerConfig(
path.join(tempDir, ".sst"),
"hidden-worker"
);
vi.stubEnv("CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH", ".sst/wrangler.jsonc");

const result = resolvePluginConfig(
{},
{ root: tempDir },
viteEnv
) as WorkersResolvedConfig;

expect(result.type).toBe("workers");
const entryWorker = result.environmentNameToWorkerMap.get(
result.entryWorkerEnvironmentName
);
assert(entryWorker);
expect(entryWorker.config.name).toBe("hidden-worker");
expect([...result.configPaths]).toEqual([hiddenConfigPath]);
});

test("should prefer explicit configPath over CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH", ({
expect,
}) => {
createWorkerConfig(path.join(tempDir, ".sst"), "hidden-worker");
const explicitConfigPath = createWorkerConfig(
path.join(tempDir, "visible"),
"explicit-worker"
);
vi.stubEnv("CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH", ".sst/wrangler.jsonc");

const result = resolvePluginConfig(
{ configPath: explicitConfigPath },
{ root: tempDir },
viteEnv
) as WorkersResolvedConfig;

expect(result.type).toBe("workers");
const entryWorker = result.environmentNameToWorkerMap.get(
result.entryWorkerEnvironmentName
);
assert(entryWorker);
expect(entryWorker.config.name).toBe("explicit-worker");
expect(entryWorker.config.main).toBe(
path.join(tempDir, "visible", "src/index.ts")
);
expect([...result.configPaths]).toEqual([explicitConfigPath]);
});
});

describe("resolvePluginConfig - defaults fill in missing fields", () => {
let tempDir: string;

Expand Down
4 changes: 3 additions & 1 deletion packages/vite-plugin-cloudflare/src/plugin-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,11 @@ export function resolvePluginConfig(
const configPaths = new Set<string>();
const cloudflareEnv = prefixedEnv.CLOUDFLARE_ENV;
const validateAndAddEnvironmentName = createEnvironmentNameValidator();
const requestedEntryWorkerConfigPath =
pluginConfig.configPath ?? prefixedEnv.CLOUDFLARE_VITE_WRANGLER_CONFIG_PATH;
const configPath = getValidatedWranglerConfigPath(
root,
pluginConfig.configPath
requestedEntryWorkerConfigPath
);

// Build entry worker config: defaults → file config → config()
Expand Down
Loading