Skip to content

Commit 0e1e007

Browse files
Add support for loading local vars from .env files to the vite-plugin
1 parent db5caa9 commit 0e1e007

File tree

25 files changed

+341
-85
lines changed

25 files changed

+341
-85
lines changed
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1-
import { test } from "vitest";
1+
import fs from "node:fs";
2+
import { onTestFinished, test } from "vitest";
23

34
export * from "../vitest-setup";
45
export * from "./responses";
56

67
export function failsIf(condition: boolean) {
78
return condition ? test.fails : test;
89
}
10+
11+
export function mockFileChange(
12+
filePath: string,
13+
mutateFn: (originalContent: string) => string
14+
) {
15+
const originalContent = fs.readFileSync(filePath, "utf-8");
16+
onTestFinished(() => {
17+
fs.writeFileSync(filePath, originalContent);
18+
});
19+
fs.writeFileSync(filePath, mutateFn(originalContent));
20+
}

packages/vite-plugin-cloudflare/playground/dev-vars/__tests__/vars-changes.spec.ts

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,10 @@
1-
import * as fs from "node:fs";
21
import * as path from "node:path";
32
import { expect, test, vi } from "vitest";
4-
import { getJsonResponse, isBuild } from "../../__test-utils__";
3+
import { getJsonResponse, isBuild, mockFileChange } from "../../__test-utils__";
54

65
test.runIf(!isBuild)(
76
"successfully updates when a var is updated in a .dev.vars file",
8-
async ({ onTestFinished }) => {
9-
const dotDevDotVarsFilePath = path.join(__dirname, "../.dev.vars");
10-
const originalDotDevDotVars = fs.readFileSync(
11-
dotDevDotVarsFilePath,
12-
"utf-8"
13-
);
14-
15-
onTestFinished(async () => {
16-
fs.writeFileSync(dotDevDotVarsFilePath, originalDotDevDotVars);
17-
// We need to ensure that the original config is restored before the next test runs
18-
await vi.waitFor(
19-
async () => {
20-
expect(await getJsonResponse()).toEqual({
21-
"variables present in .dev.vars": {
22-
MY_DEV_VAR_A: "my .dev.vars variable A",
23-
MY_DEV_VAR_B: "my .dev.vars variable B",
24-
MY_DEV_VAR_C: "my .dev.vars variable C",
25-
},
26-
});
27-
},
28-
{ timeout: 5000 }
29-
);
30-
});
31-
7+
async () => {
328
const originalResponse = await getJsonResponse();
339
expect(originalResponse).toEqual({
3410
"variables present in .dev.vars": {
@@ -38,12 +14,13 @@ test.runIf(!isBuild)(
3814
},
3915
});
4016

41-
const updatedDotDevDotVars = originalDotDevDotVars.replace(
42-
/my \.dev\.vars variable/g,
43-
"my .dev.vars UPDATED variable"
17+
mockFileChange(path.join(__dirname, "../.dev.vars"), (content) =>
18+
content.replace(
19+
/my \.dev\.vars variable/g,
20+
"my .dev.vars UPDATED variable"
21+
)
4422
);
4523

46-
fs.writeFileSync(dotDevDotVarsFilePath, updatedDotDevDotVars);
4724
await vi.waitFor(
4825
async () => {
4926
const updatedResponse = await getJsonResponse();
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ENV_NAME = ""
2+
MY_DEV_VAR_A = "my .env variable A"
3+
MY_DEV_VAR_B = "my .env variable B"
4+
MY_DEV_VAR_C = "my .env variable C"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ENV_NAME = "staging"
2+
MY_DEV_VAR_A = "my .env staging variable A"
3+
MY_DEV_VAR_B = "my .env staging variable B"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLOUDFLARE_ENV=staging
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!.env*
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import fs from "node:fs";
2+
import { describe, expect, test } from "vitest";
3+
import { getJsonResponse, isBuild, testDir } from "../../__test-utils__";
4+
5+
const expectedVars = {
6+
MY_DEV_VAR_A: "my .env variable A",
7+
MY_DEV_VAR_B: "my .env variable B",
8+
MY_DEV_VAR_C: "my .env variable C",
9+
};
10+
11+
test("reading variables from a standard .env file", async () => {
12+
expect(await getJsonResponse()).toEqual({
13+
"variables loaded from .env": expectedVars,
14+
});
15+
});
16+
17+
describe.runIf(isBuild)("build output files", () => {
18+
test("the .dev.vars file has been created in the build directory", async () => {
19+
const distDevVarsPath = `${testDir}/dist/worker/.dev.vars`;
20+
const distDevVarsExists = fs.existsSync(distDevVarsPath);
21+
expect(distDevVarsExists).toBe(true);
22+
23+
const distDevVarsContent = fs.readFileSync(distDevVarsPath, "utf-8");
24+
expect(distDevVarsContent).toMatchInlineSnapshot(`
25+
"ENV_NAME = ""
26+
MY_DEV_VAR_A = "my .env variable A"
27+
MY_DEV_VAR_B = "my .env variable B"
28+
MY_DEV_VAR_C = "my .env variable C"
29+
"
30+
`);
31+
});
32+
33+
test("secrets from .env haven't been inlined in the js output file", async () => {
34+
const distIndexPath = `${testDir}/dist/worker/index.js`;
35+
36+
const distIndexContent = fs.readFileSync(distIndexPath, "utf-8");
37+
expect(distIndexContent).not.toContain("my .env variable");
38+
});
39+
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as path from "node:path";
2+
import { expect, test, vi } from "vitest";
3+
import { getJsonResponse, isBuild, mockFileChange } from "../../__test-utils__";
4+
5+
test.runIf(!isBuild)(
6+
"successfully updates when a var is updated in a .env file",
7+
async () => {
8+
const originalResponseContent = {
9+
"variables loaded from .env": {
10+
MY_DEV_VAR_A: "my .env variable A",
11+
MY_DEV_VAR_B: "my .env variable B",
12+
MY_DEV_VAR_C: "my .env variable C", // Note that unlike .dev.vars, we merge .env files
13+
},
14+
};
15+
const originalResponse = await getJsonResponse();
16+
expect(originalResponse).toEqual(
17+
expect.objectContaining(originalResponseContent)
18+
);
19+
20+
mockFileChange(path.join(__dirname, "../.env"), (content) =>
21+
content.replace(/my \.env/g, "my .env UPDATED")
22+
);
23+
24+
await vi.waitFor(
25+
async () => {
26+
const updatedResponse = await getJsonResponse();
27+
expect(updatedResponse).toEqual({
28+
"variables loaded from .env": {
29+
MY_DEV_VAR_A: "my .env UPDATED variable A",
30+
MY_DEV_VAR_B: "my .env UPDATED variable B",
31+
MY_DEV_VAR_C: "my .env UPDATED variable C", // Note that unlike .dev.vars, we merge .env files
32+
},
33+
});
34+
},
35+
{ timeout: 5000 }
36+
);
37+
}
38+
);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import fs from "node:fs";
2+
import { describe, expect, test } from "vitest";
3+
import { getJsonResponse, isBuild, testDir } from "../../../__test-utils__";
4+
5+
test("reading variables from a staging .env file", async () => {
6+
expect(await getJsonResponse()).toEqual({
7+
"variables loaded from .env and .env.staging": {
8+
MY_DEV_VAR_A: "my .env staging variable A",
9+
MY_DEV_VAR_B: "my .env staging variable B",
10+
MY_DEV_VAR_C: "my .env variable C", // Note that unlike .dev.vars, we merge .env files
11+
},
12+
});
13+
});
14+
describe.runIf(isBuild)("build output files", () => {
15+
test("the .dev.vars file has been created in the build directory", async () => {
16+
const distDevVarsPath = `${testDir}/dist/worker/.dev.vars`;
17+
const distDevVarsExists = fs.existsSync(distDevVarsPath);
18+
expect(distDevVarsExists).toBe(true);
19+
20+
const distDevVarsContent = fs.readFileSync(distDevVarsPath, "utf-8");
21+
expect(distDevVarsContent).toMatchInlineSnapshot(`
22+
"ENV_NAME = "staging"
23+
MY_DEV_VAR_A = "my .env staging variable A"
24+
MY_DEV_VAR_B = "my .env staging variable B"
25+
MY_DEV_VAR_C = "my .env variable C"
26+
"
27+
`);
28+
});
29+
30+
test("secrets from .env haven't been inlined in the js output file", async () => {
31+
const distIndexPath = `${testDir}/dist/worker/index.js`;
32+
33+
const distIndexContent = fs.readFileSync(distIndexPath, "utf-8");
34+
expect(distIndexContent).not.toContain("my .env");
35+
});
36+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as path from "node:path";
2+
import { expect, test, vi } from "vitest";
3+
import {
4+
getJsonResponse,
5+
isBuild,
6+
mockFileChange,
7+
} from "../../../__test-utils__";
8+
9+
test.runIf(!isBuild)(
10+
"successfully updates when a var is updated in a .env.staging file",
11+
async () => {
12+
const originalResponseContent = {
13+
"variables loaded from .env and .env.staging": {
14+
MY_DEV_VAR_A: "my .env staging variable A",
15+
MY_DEV_VAR_B: "my .env staging variable B",
16+
MY_DEV_VAR_C: "my .env variable C", // Note that unlike .dev.vars, we merge .env files
17+
},
18+
};
19+
const originalResponse = await getJsonResponse();
20+
expect(originalResponse).toEqual(originalResponseContent);
21+
22+
mockFileChange(path.join(__dirname, "../../.env"), (content) =>
23+
content.replace(/my \.env/g, "my .env UPDATED")
24+
);
25+
mockFileChange(path.join(__dirname, "../../.env.staging"), (content) =>
26+
content.replace(/my \.env staging/g, "my .env UPDATED staging")
27+
);
28+
29+
await vi.waitFor(
30+
async () => {
31+
const updatedResponse = await getJsonResponse();
32+
expect(updatedResponse).toEqual({
33+
"variables loaded from .env and .env.staging": {
34+
MY_DEV_VAR_A: "my .env UPDATED staging variable A",
35+
MY_DEV_VAR_B: "my .env UPDATED staging variable B",
36+
MY_DEV_VAR_C: "my .env UPDATED variable C", // Note that unlike .dev.vars, we merge .env files
37+
},
38+
});
39+
},
40+
{ timeout: 5000 }
41+
);
42+
}
43+
);

0 commit comments

Comments
 (0)