Skip to content

Commit 936187d

Browse files
Ensure the nodejs_compat flag is always applied in autoconfig (#12572)
Co-authored-by: emily-shen <69125074+emily-shen@users.noreply.github.com>
1 parent 5eb79cf commit 936187d

File tree

10 files changed

+217
-35
lines changed

10 files changed

+217
-35
lines changed

.changeset/fruity-views-flow.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
Ensure the `nodejs_compat` flag is always applied in autoconfig
6+
7+
Previously, the autoconfig feature relied on individual framework configurations to specify Node.js compatibility flags, some could set `nodejs_compat` while others `nodejs_als`.
8+
9+
Now instead `nodejs_compat` is always included as a compatibility flag, this is generally beneficial and the user can always remove the flag afterwards if they want to.

packages/wrangler/src/__tests__/autoconfig/run.test.ts

Lines changed: 162 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,10 @@ describe("autoconfig (deploy)", () => {
270270
},
271271
"assets": {
272272
"directory": "dist"
273-
}
273+
},
274+
"compatibility_flags": [
275+
"nodejs_compat"
276+
]
274277
}
275278
276279
🛠️ Configuring project for Fake
@@ -288,7 +291,10 @@ describe("autoconfig (deploy)", () => {
288291
},
289292
"assets": {
290293
"directory": "dist"
291-
}
294+
},
295+
"compatibility_flags": [
296+
"nodejs_compat"
297+
]
292298
}
293299
"
294300
`);
@@ -440,7 +446,10 @@ describe("autoconfig (deploy)", () => {
440446
},
441447
"assets": {
442448
"directory": "dist"
443-
}
449+
},
450+
"compatibility_flags": [
451+
"nodejs_compat"
452+
]
444453
}
445454
"
446455
`);
@@ -455,7 +464,10 @@ describe("autoconfig (deploy)", () => {
455464
},
456465
"assets": {
457466
"directory": "dist"
458-
}
467+
},
468+
"compatibility_flags": [
469+
"nodejs_compat"
470+
]
459471
}
460472
"
461473
`);
@@ -595,5 +607,151 @@ describe("autoconfig (deploy)", () => {
595607
`[Error: The detected framework ("Some Unsupported Framework") cannot be automatically configured.]`
596608
);
597609
});
610+
611+
describe("nodejs_compat compatibility flag", () => {
612+
it("should add nodejs_compat when framework specifies no compatibility flags", async () => {
613+
mockConfirm({
614+
text: "Do you want to modify these settings?",
615+
result: false,
616+
});
617+
mockConfirm({
618+
text: "Proceed with setup?",
619+
result: true,
620+
});
621+
622+
await run.runAutoConfig({
623+
projectPath: process.cwd(),
624+
workerName: "my-worker",
625+
configured: false,
626+
outputDir: "dist",
627+
framework: {
628+
id: "no-flags-framework",
629+
name: "No Flags Framework",
630+
autoConfigSupported: true,
631+
configure: async () => ({
632+
wranglerConfig: {
633+
// No compatibility_flags specified
634+
assets: { directory: "dist" },
635+
},
636+
}),
637+
isConfigured: () => false,
638+
},
639+
packageManager: NpmPackageManager,
640+
});
641+
642+
const wranglerConfig = JSON.parse(readFileSync("wrangler.jsonc"));
643+
expect(wranglerConfig.compatibility_flags).toEqual(["nodejs_compat"]);
644+
});
645+
646+
it("should preserve other compatibility flags while adding nodejs_compat", async () => {
647+
mockConfirm({
648+
text: "Do you want to modify these settings?",
649+
result: false,
650+
});
651+
mockConfirm({
652+
text: "Proceed with setup?",
653+
result: true,
654+
});
655+
656+
await run.runAutoConfig({
657+
projectPath: process.cwd(),
658+
workerName: "my-worker",
659+
configured: false,
660+
outputDir: "dist",
661+
framework: {
662+
id: "other-flags-framework",
663+
name: "Other Flags Framework",
664+
autoConfigSupported: true,
665+
configure: async () => ({
666+
wranglerConfig: {
667+
compatibility_flags: ["global_fetch_strictly_public"],
668+
assets: { directory: "dist" },
669+
},
670+
}),
671+
isConfigured: () => false,
672+
},
673+
packageManager: NpmPackageManager,
674+
});
675+
676+
const wranglerConfig = JSON.parse(readFileSync("wrangler.jsonc"));
677+
expect(wranglerConfig.compatibility_flags).toEqual([
678+
"global_fetch_strictly_public",
679+
"nodejs_compat",
680+
]);
681+
});
682+
683+
it("should not duplicate nodejs_compat if already present", async () => {
684+
mockConfirm({
685+
text: "Do you want to modify these settings?",
686+
result: false,
687+
});
688+
mockConfirm({
689+
text: "Proceed with setup?",
690+
result: true,
691+
});
692+
693+
await run.runAutoConfig({
694+
projectPath: process.cwd(),
695+
workerName: "my-worker",
696+
configured: false,
697+
outputDir: "dist",
698+
framework: {
699+
id: "nodejs-compat-framework",
700+
name: "Nodejs Compat Framework",
701+
autoConfigSupported: true,
702+
configure: async () => ({
703+
wranglerConfig: {
704+
compatibility_flags: ["nodejs_compat"],
705+
assets: { directory: "dist" },
706+
},
707+
}),
708+
isConfigured: () => false,
709+
},
710+
packageManager: NpmPackageManager,
711+
});
712+
713+
const wranglerConfig = JSON.parse(readFileSync("wrangler.jsonc"));
714+
expect(wranglerConfig.compatibility_flags).toEqual(["nodejs_compat"]);
715+
});
716+
717+
it("should replace nodejs_als with nodejs_compat", async () => {
718+
mockConfirm({
719+
text: "Do you want to modify these settings?",
720+
result: false,
721+
});
722+
mockConfirm({
723+
text: "Proceed with setup?",
724+
result: true,
725+
});
726+
727+
await run.runAutoConfig({
728+
projectPath: process.cwd(),
729+
workerName: "my-worker",
730+
configured: false,
731+
outputDir: "dist",
732+
framework: {
733+
id: "nodejs-als-framework",
734+
name: "Nodejs Als Framework",
735+
autoConfigSupported: true,
736+
configure: async () => ({
737+
wranglerConfig: {
738+
compatibility_flags: ["nodejs_als", "some_other_flag"],
739+
assets: { directory: "dist" },
740+
},
741+
}),
742+
isConfigured: () => false,
743+
},
744+
packageManager: NpmPackageManager,
745+
});
746+
747+
const wranglerConfig = JSON.parse(readFileSync("wrangler.jsonc"));
748+
// nodejs_als should be removed, nodejs_compat should be added, some_other_flag preserved
749+
expect(wranglerConfig.compatibility_flags).toEqual([
750+
"some_other_flag",
751+
"nodejs_compat",
752+
]);
753+
expect(wranglerConfig.compatibility_flags).not.toContain("nodejs_als");
754+
});
755+
});
598756
});
599757
});

packages/wrangler/src/__tests__/setup.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ describe("wrangler setup", () => {
188188
"directory": "public",
189189
},
190190
"compatibility_date": "YYYY-MM-DD",
191+
"compatibility_flags": [
192+
"nodejs_compat",
193+
],
191194
"name": "test-name",
192195
"observability": {
193196
"enabled": true,
@@ -257,7 +260,10 @@ describe("wrangler setup", () => {
257260
},
258261
"assets": {
259262
"directory": "<DIR>"
260-
}
263+
},
264+
"compatibility_flags": [
265+
"nodejs_compat"
266+
]
261267
}
262268
263269
✋ Autoconfig process run in dry-run mode, existing now.

packages/wrangler/src/autoconfig/frameworks/astro.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class Astro extends Framework {
2424
return {
2525
wranglerConfig: {
2626
main: `${outputDir}/_worker.js/index.js`,
27-
compatibility_flags: ["nodejs_compat", "global_fetch_strictly_public"],
27+
compatibility_flags: ["global_fetch_strictly_public"],
2828
assets: {
2929
binding: "ASSETS",
3030
directory: outputDir,

packages/wrangler/src/autoconfig/frameworks/qwik.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class Qwik extends Framework {
3838
return {
3939
wranglerConfig: {
4040
main: "./dist/_worker.js",
41-
compatibility_flags: ["nodejs_compat", "global_fetch_strictly_public"],
41+
compatibility_flags: ["global_fetch_strictly_public"],
4242
assets: {
4343
binding: "ASSET",
4444
directory: "./dist",

packages/wrangler/src/autoconfig/frameworks/solid-start.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ export class SolidStart extends Framework {
5757
return {
5858
wranglerConfig: {
5959
main: "./.output/server/index.mjs",
60-
compatibility_flags: ["nodejs_compat"],
6160
assets: {
6261
binding: "ASSETS",
6362
directory: "./.output/public",

packages/wrangler/src/autoconfig/frameworks/sveltekit.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export class SvelteKit extends Framework {
3939
return {
4040
wranglerConfig: {
4141
main: ".svelte-kit/cloudflare/_worker.js",
42-
compatibility_flags: ["nodejs_als"],
4342
assets: {
4443
binding: "ASSETS",
4544
directory: ".svelte-kit/cloudflare",

packages/wrangler/src/autoconfig/frameworks/tanstack.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export class TanstackStart extends Framework {
2222

2323
return {
2424
wranglerConfig: {
25-
compatibility_flags: ["nodejs_compat"],
2625
main: "@tanstack/react-start/server-entry",
2726
},
2827
};

packages/wrangler/src/autoconfig/frameworks/waku.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export class Waku extends Framework {
4040
return {
4141
wranglerConfig: {
4242
main: "./dist/server/serve-cloudflare.js",
43-
compatibility_flags: ["nodejs_compat"],
4443
assets: {
4544
binding: "ASSETS",
4645
directory: "./dist/public",

packages/wrangler/src/autoconfig/run.ts

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ import {
2323
import { Static } from "./frameworks/static";
2424
import { getAutoConfigId } from "./telemetry-utils";
2525
import { usesTypescript } from "./uses-typescript";
26-
import type {
27-
ConfigurationResults,
28-
PackageJsonScriptsOverrides,
29-
} from "./frameworks";
26+
import type { PackageJsonScriptsOverrides } from "./frameworks";
3027
import type {
3128
AutoConfigDetails,
3229
AutoConfigDetailsForNonConfiguredProject,
@@ -119,10 +116,10 @@ export async function runAutoConfig(
119116

120117
autoConfigSummary = await buildOperationsSummary(
121118
{ ...autoConfigDetails, outputDir: autoConfigDetails.outputDir },
122-
{
119+
ensureNodejsCompatIsInConfig({
123120
...wranglerConfig,
124121
...dryRunConfigurationResults.wranglerConfig,
125-
},
122+
}),
126123
{
127124
build:
128125
dryRunConfigurationResults.buildCommandOverride ??
@@ -204,8 +201,10 @@ export async function runAutoConfig(
204201

205202
await saveWranglerJsonc(
206203
autoConfigDetails.projectPath,
207-
wranglerConfig,
208-
configurationResults.wranglerConfig
204+
ensureNodejsCompatIsInConfig({
205+
...wranglerConfig,
206+
...configurationResults.wranglerConfig,
207+
})
209208
);
210209

211210
addWranglerToGitIgnore(autoConfigDetails.projectPath);
@@ -254,27 +253,41 @@ export async function runAutoConfig(
254253
}
255254

256255
/**
257-
* Saves the a wrangler.jsonc file for the current project by combining:
258-
* - the autoconfig base values for wrangler config
259-
* - the framework's `configure()` wrangler config values
260-
* - the potential pre-existing wrangler config file generated by the framework's CLI
256+
* Given a wrangler config object this function makes sure that the `nodejs_compat` flag is present
257+
* in its `compatibility_flags` setting.
258+
*
259+
* Just to be sure the function also filters out any compatibility flag already present starting with `nodejs_` (e.g. `nodejs_als`)
260+
*
261+
* @param wranglerConfig The target wrangler config object
262+
* @returns A copy of the config object where the `compatibility_flags` settings is assured to contain `nodejs_compat`
263+
*/
264+
function ensureNodejsCompatIsInConfig(wranglerConfig: RawConfig): RawConfig {
265+
if (wranglerConfig.compatibility_flags?.includes("nodejs_compat")) {
266+
return wranglerConfig;
267+
}
268+
269+
return {
270+
...wranglerConfig,
271+
compatibility_flags: [
272+
...(wranglerConfig.compatibility_flags?.filter(
273+
(flag) => !flag.startsWith("nodejs_")
274+
) ?? []),
275+
"nodejs_compat",
276+
],
277+
};
278+
}
279+
280+
/**
281+
* Saves the a wrangler.jsonc file for the current project potentially combining new values to the potential
282+
* pre-existing wrangler config file generated by the framework's CLI
261283
*
262284
* @param projectPath The project's path
263-
* @param baseWranglerConfig The base autoconfig values for the wrangler config
264-
* @param configurationWranglerConfig The wrangler values from the framework's `configure()`
285+
* @param baseWranglerConfig The wrangler config to use
265286
*/
266287
async function saveWranglerJsonc(
267288
projectPath: string,
268-
baseWranglerConfig: RawConfig,
269-
configurationWranglerConfig:
270-
| ConfigurationResults["wranglerConfig"]
271-
| undefined
289+
wranglerConfig: RawConfig
272290
): Promise<void> {
273-
const autoconfigWranglerConfigValues = {
274-
...baseWranglerConfig,
275-
...configurationWranglerConfig,
276-
};
277-
278291
let existingWranglerConfig: RawConfig = {};
279292

280293
const wranglerConfigPath = getDirWranglerJsonConfigPath(projectPath);
@@ -291,7 +304,7 @@ async function saveWranglerJsonc(
291304
JSON.stringify(
292305
{
293306
...existingWranglerConfig,
294-
...autoconfigWranglerConfigValues,
307+
...wranglerConfig,
295308
},
296309
null,
297310
2

0 commit comments

Comments
 (0)