wrangler 2.1.4 → 2.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/miniflare-dist/index.mjs +4 -1
  2. package/package.json +1 -1
  3. package/src/__tests__/api-dev.test.ts +3 -3
  4. package/src/__tests__/api-devregistry.test.js +56 -0
  5. package/src/__tests__/configuration.test.ts +3 -0
  6. package/src/__tests__/dev.test.tsx +39 -1
  7. package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
  8. package/src/__tests__/helpers/{hello-world-worker.js → worker-scripts/hello-world-worker.js} +0 -0
  9. package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
  10. package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
  11. package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
  12. package/src/__tests__/init.test.ts +72 -0
  13. package/src/__tests__/middleware.scheduled.test.ts +135 -0
  14. package/src/__tests__/middleware.test.ts +703 -745
  15. package/src/__tests__/pages.test.ts +35 -40
  16. package/src/__tests__/publish.test.ts +57 -1
  17. package/src/api/dev.ts +2 -0
  18. package/src/bundle.ts +14 -16
  19. package/src/config/config.ts +12 -0
  20. package/src/config/validation.ts +9 -0
  21. package/src/create-worker-upload-form.ts +3 -2
  22. package/src/dev/dev.tsx +12 -21
  23. package/src/dev/local.tsx +1 -0
  24. package/src/dev/remote.tsx +38 -50
  25. package/src/dev/start-server.ts +43 -8
  26. package/src/dev/use-esbuild.ts +4 -0
  27. package/src/dev-registry.tsx +30 -0
  28. package/src/dev.tsx +21 -3
  29. package/src/index.tsx +8 -1
  30. package/src/init.ts +3 -1
  31. package/src/inspect.ts +26 -26
  32. package/src/miniflare-cli/assets.ts +8 -1
  33. package/src/pages/constants.ts +2 -1
  34. package/src/pages/dev.tsx +133 -10
  35. package/src/pages/errors.ts +48 -4
  36. package/src/pages/functions/routes-transformation.ts +1 -14
  37. package/src/pages/functions/routes-validation.test.ts +403 -0
  38. package/src/pages/functions/routes-validation.ts +202 -0
  39. package/src/pages/functions.tsx +4 -18
  40. package/src/pages/publish.tsx +6 -22
  41. package/src/publish.ts +3 -1
  42. package/src/worker.ts +1 -1
  43. package/templates/middleware/middleware-scheduled.ts +2 -1
  44. package/templates/pages-dev-pipeline.ts +35 -0
  45. package/wrangler-dist/cli.d.ts +2 -0
  46. package/wrangler-dist/cli.js +611 -353
@@ -6099,7 +6099,10 @@ async function generateAssetsFetch(directory, log) {
6099
6099
  );
6100
6100
  }
6101
6101
  const body = readFileSync5(filepath);
6102
- const contentType = (0, import_mime.getType)(filepath) || "application/octet-stream";
6102
+ let contentType = (0, import_mime.getType)(filepath) || "application/octet-stream";
6103
+ if (contentType.startsWith("text/") && !contentType.includes("charset")) {
6104
+ contentType = `${contentType}; charset=utf-8`;
6105
+ }
6103
6106
  return { body, contentType };
6104
6107
  }
6105
6108
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.1.4",
3
+ "version": "2.1.6",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -8,7 +8,7 @@ jest.unmock("undici");
8
8
  describe("unstable_dev", () => {
9
9
  it("should return Hello World", async () => {
10
10
  const worker = await unstable_dev(
11
- "src/__tests__/helpers/hello-world-worker.js",
11
+ "src/__tests__/helpers/worker-scripts/hello-world-worker.js",
12
12
  {},
13
13
  { disableExperimentalWarning: true }
14
14
  );
@@ -24,7 +24,7 @@ describe("unstable_dev", () => {
24
24
  describe("unstable dev fetch input protocol", () => {
25
25
  it("should use http localProtocol", async () => {
26
26
  const worker = await unstable_dev(
27
- "src/__tests__/helpers/hello-world-worker.js",
27
+ "src/__tests__/helpers/worker-scripts/hello-world-worker.js",
28
28
  { localProtocol: "http" },
29
29
  { disableExperimentalWarning: true }
30
30
  );
@@ -38,7 +38,7 @@ describe("unstable dev fetch input protocol", () => {
38
38
 
39
39
  it("should use undefined localProtocol", async () => {
40
40
  const worker = await unstable_dev(
41
- "src/__tests__/helpers/hello-world-worker.js",
41
+ "src/__tests__/helpers/worker-scripts/hello-world-worker.js",
42
42
  { localProtocol: undefined },
43
43
  { disableExperimentalWarning: true }
44
44
  );
@@ -0,0 +1,56 @@
1
+ import { unstable_dev } from "../api";
2
+ import { fetch } from "undici";
3
+
4
+ jest.unmock("undici");
5
+
6
+ /**
7
+ * a huge caveat to how testing multi-worker scripts works:
8
+ * you can't shutdown the first worker you spun up, or it'll kill the devRegistry
9
+ */
10
+ describe("multi-worker testing", () => {
11
+ let childWorker;
12
+ let parentWorker;
13
+
14
+ beforeAll(async () => {
15
+ childWorker = await unstable_dev(
16
+ "src/__tests__/helpers/worker-scripts/hello-world-worker.js",
17
+ { config: "src/__tests__/helpers/worker-scripts/child-wrangler.toml" },
18
+ { disableExperimentalWarning: true }
19
+ );
20
+ parentWorker = await unstable_dev(
21
+ "src/__tests__/helpers/worker-scripts/parent-worker.js",
22
+ { config: "src/__tests__/helpers/worker-scripts/parent-wrangler.toml" },
23
+ { disableExperimentalWarning: true }
24
+ );
25
+ });
26
+
27
+ afterAll(async () => {
28
+ await childWorker.stop();
29
+ await parentWorker.stop();
30
+ });
31
+
32
+ it("parentWorker and childWorker should be added devRegistry", async () => {
33
+ const resp = await fetch("http://localhost:6284/workers");
34
+ if (resp) {
35
+ const parsedResp = await resp.json();
36
+ expect(parsedResp.parent).toBeTruthy();
37
+ expect(parsedResp.child).toBeTruthy();
38
+ }
39
+ });
40
+
41
+ it("childWorker should return Hello World itself", async () => {
42
+ const resp = await childWorker.fetch();
43
+ if (resp) {
44
+ const text = await resp.text();
45
+ expect(text).toMatchInlineSnapshot(`"Hello World!"`);
46
+ }
47
+ });
48
+
49
+ it("parentWorker should return Hello World by invoking the child worker", async () => {
50
+ const resp = await parentWorker.fetch();
51
+ if (resp) {
52
+ const parsedResp = await resp.text();
53
+ expect(parsedResp).toEqual("Parent worker sees: Hello World!");
54
+ }
55
+ });
56
+ });
@@ -73,6 +73,7 @@ describe("normalizeAndValidateConfig()", () => {
73
73
  minify: undefined,
74
74
  node_compat: undefined,
75
75
  first_party_worker: undefined,
76
+ keep_vars: undefined,
76
77
  });
77
78
  expect(diagnostics.hasErrors()).toBe(false);
78
79
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -106,6 +107,7 @@ describe("normalizeAndValidateConfig()", () => {
106
107
  const expectedConfig = {
107
108
  legacy_env: "FOO",
108
109
  send_metrics: "BAD",
110
+ keep_vars: "NEVER",
109
111
  dev: {
110
112
  ip: 222,
111
113
  port: "FOO",
@@ -128,6 +130,7 @@ describe("normalizeAndValidateConfig()", () => {
128
130
  "Processing wrangler configuration:
129
131
  - Expected \\"legacy_env\\" to be of type boolean but got \\"FOO\\".
130
132
  - Expected \\"send_metrics\\" to be of type boolean but got \\"BAD\\".
133
+ - Expected \\"keep_vars\\" to be of type boolean but got \\"NEVER\\".
131
134
  - Expected \\"dev.ip\\" to be of type string but got 222.
132
135
  - Expected \\"dev.port\\" to be of type number but got \\"FOO\\".
133
136
  - Expected \\"dev.local_protocol\\" field to be one of [\\"http\\",\\"https\\"] but got \\"wss\\".
@@ -1027,7 +1027,9 @@ describe("wrangler dev", () => {
1027
1027
  --node-compat Enable node.js compatibility [boolean]
1028
1028
  --persist Enable persistence for local mode, using default path: .wrangler/state [boolean]
1029
1029
  --persist-to Specify directory to use for local persistence (implies --persist) [string]
1030
- --inspect Enable dev tools [deprecated] [boolean]",
1030
+ --inspect Enable dev tools [deprecated] [boolean]
1031
+ --test-scheduled Test scheduled events by visiting /__scheduled in browser [boolean] [default: false]
1032
+ --log-level Specify logging level [choices: \\"debug\\", \\"info\\", \\"log\\", \\"warn\\", \\"error\\", \\"none\\"] [default: \\"log\\"]",
1031
1033
  "warn": "",
1032
1034
  }
1033
1035
  `);
@@ -1211,6 +1213,42 @@ describe("wrangler dev", () => {
1211
1213
  });
1212
1214
  });
1213
1215
 
1216
+ describe("--log-level", () => {
1217
+ it("should not output warnings with log-level 'none'", async () => {
1218
+ fs.writeFileSync("index.js", `export default {};`);
1219
+ await runWrangler("dev index.js --inspect --log-level none");
1220
+ expect(std).toMatchInlineSnapshot(`
1221
+ Object {
1222
+ "debug": "",
1223
+ "err": "",
1224
+ "out": "",
1225
+ "warn": "",
1226
+ }
1227
+ `);
1228
+ });
1229
+
1230
+ it("should output warnings with log-level 'warn'", async () => {
1231
+ fs.writeFileSync("index.js", `export default {};`);
1232
+ await runWrangler("dev index.js --inspect --log-level warn");
1233
+ expect(std).toMatchInlineSnapshot(`
1234
+ Object {
1235
+ "debug": "",
1236
+ "err": "",
1237
+ "out": "",
1238
+ "warn": "▲ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.
1239
+
1240
+ ",
1241
+ }
1242
+ `);
1243
+ });
1244
+
1245
+ it("should not output Errors with log-level error", async () => {
1246
+ fs.writeFileSync("index.js", `export default {};`);
1247
+ await runWrangler("dev index.js --inspect --log-level debug");
1248
+ expect(std.debug.length > 1).toBe(true);
1249
+ });
1250
+ });
1251
+
1214
1252
  describe("service bindings", () => {
1215
1253
  it("should warn when using service bindings", async () => {
1216
1254
  writeWranglerToml({
@@ -0,0 +1 @@
1
+ name = 'child'
@@ -0,0 +1 @@
1
+ name = 'hello-world'
@@ -0,0 +1,8 @@
1
+ export default {
2
+ async fetch(req, env) {
3
+ const resp = await env.CHILD.fetch(req);
4
+ const text = await resp.text();
5
+ console.log("text: ", text);
6
+ return new Response(`Parent worker sees: ${text}`);
7
+ },
8
+ };
@@ -0,0 +1,5 @@
1
+ name = 'parent'
2
+
3
+ [[services]]
4
+ binding = "CHILD"
5
+ service = 'child'
@@ -2270,6 +2270,12 @@ describe("init", () => {
2270
2270
  expectedAccountId = "",
2271
2271
  expectedScriptName = "",
2272
2272
  expectedEnvironment = "",
2273
+ expectedCompatDate,
2274
+ }: {
2275
+ expectedAccountId: string;
2276
+ expectedScriptName: string;
2277
+ expectedEnvironment: string;
2278
+ expectedCompatDate: string | undefined;
2273
2279
  }) {
2274
2280
  setMockResponse(
2275
2281
  `/accounts/:accountId/workers/services/:scriptName`,
@@ -2278,6 +2284,9 @@ describe("init", () => {
2278
2284
  expect(accountId).toEqual(expectedAccountId);
2279
2285
  expect(scriptName).toEqual(expectedScriptName);
2280
2286
 
2287
+ if (expectedCompatDate === undefined)
2288
+ (mockServiceMetadata.default_environment.script
2289
+ .compatibility_date as unknown) = expectedCompatDate;
2281
2290
  return mockServiceMetadata;
2282
2291
  }
2283
2292
  );
@@ -2340,6 +2349,7 @@ describe("init", () => {
2340
2349
  expectedAccountId: "LCARS",
2341
2350
  expectedScriptName: "memory-crystal",
2342
2351
  expectedEnvironment: "test",
2352
+ expectedCompatDate: "1987-9-27",
2343
2353
  });
2344
2354
  setMockFetchDashScript({
2345
2355
  accountId: "LCARS",
@@ -2394,6 +2404,7 @@ describe("init", () => {
2394
2404
  expectedAccountId: "LCARS",
2395
2405
  expectedScriptName: "isolinear-optical-chip",
2396
2406
  expectedEnvironment: "test",
2407
+ expectedCompatDate: "1987-9-27",
2397
2408
  });
2398
2409
  setMockFetchDashScript({
2399
2410
  accountId: "LCARS",
@@ -2447,6 +2458,7 @@ describe("init", () => {
2447
2458
  expectedAccountId: "LCARS",
2448
2459
  expectedScriptName: "isolinear-optical-chip",
2449
2460
  expectedEnvironment: "test",
2461
+ expectedCompatDate: "1987-9-27",
2450
2462
  });
2451
2463
  setMockFetchDashScript({
2452
2464
  accountId: "LCARS",
@@ -2494,6 +2506,66 @@ describe("init", () => {
2494
2506
  },
2495
2507
  });
2496
2508
  });
2509
+
2510
+ it("should use fallback compatibility date if none is upstream", async () => {
2511
+ const mockDate = "1988-08-07";
2512
+ jest
2513
+ .spyOn(Date.prototype, "toISOString")
2514
+ .mockImplementation(() => `${mockDate}T00:00:00.000Z`);
2515
+
2516
+ mockSupportingDashRequests({
2517
+ expectedAccountId: "LCARS",
2518
+ expectedScriptName: "isolinear-optical-chip",
2519
+ expectedEnvironment: "test",
2520
+ expectedCompatDate: undefined,
2521
+ });
2522
+ setMockFetchDashScript({
2523
+ accountId: "LCARS",
2524
+ fromDashScriptName: "isolinear-optical-chip",
2525
+ environment: mockServiceMetadata.default_environment.environment,
2526
+ mockResponse: mockDashboardScript,
2527
+ });
2528
+ mockConfirm(
2529
+ {
2530
+ text: "Would you like to use git to manage this Worker?",
2531
+ result: false,
2532
+ },
2533
+ {
2534
+ text: "Would you like to use TypeScript?",
2535
+ result: true,
2536
+ },
2537
+ {
2538
+ text: "No package.json found. Would you like to create one?",
2539
+ result: true,
2540
+ },
2541
+ {
2542
+ text: "Would you like to install the type definitions for Workers into your package.json?",
2543
+ result: true,
2544
+ }
2545
+ );
2546
+
2547
+ await runWrangler("init --from-dash isolinear-optical-chip");
2548
+
2549
+ mockConfigExpected.compatibility_date = "1988-08-07";
2550
+ checkFiles({
2551
+ items: {
2552
+ "isolinear-optical-chip/src/index.ts": {
2553
+ contents: mockDashboardScript,
2554
+ },
2555
+ "isolinear-optical-chip/package.json": {
2556
+ contents: expect.objectContaining({
2557
+ name: "isolinear-optical-chip",
2558
+ }),
2559
+ },
2560
+ "isolinear-optical-chip/tsconfig.json": true,
2561
+ "isolinear-optical-chip/wrangler.toml": wranglerToml({
2562
+ ...mockConfigExpected,
2563
+ name: "isolinear-optical-chip",
2564
+ }),
2565
+ },
2566
+ });
2567
+ });
2568
+
2497
2569
  it("should throw an error to retry if a request fails", async () => {
2498
2570
  setMockResponse(
2499
2571
  `/accounts/:accountId/workers/services/:scriptName`,
@@ -0,0 +1,135 @@
1
+ import * as fs from "node:fs";
2
+ import { unstable_dev } from "../api";
3
+ import { runInTempDir } from "./helpers/run-in-tmp";
4
+
5
+ jest.unmock("undici");
6
+
7
+ describe("run scheduled events with middleware", () => {
8
+ describe("module workers", () => {
9
+ runInTempDir();
10
+
11
+ beforeEach(() => {
12
+ const scriptContent = `
13
+ export default {
14
+ fetch(request, env, ctx) {
15
+ const url = new URL(request.url);
16
+ if (url.pathname === "/__scheduled") {
17
+ return new Response("Fetch triggered at /__scheduled");
18
+ }
19
+ return new Response("Hello world!");
20
+ },
21
+ scheduled(controller, env, ctx) {
22
+ console.log("Doing something scheduled in modules...");
23
+ },
24
+ };
25
+ `;
26
+ fs.writeFileSync("index.js", scriptContent);
27
+ });
28
+
29
+ it("should not intercept when middleware is not enabled", async () => {
30
+ const worker = await unstable_dev(
31
+ "index.js",
32
+ {},
33
+ { disableExperimentalWarning: true }
34
+ );
35
+
36
+ const resp = await worker.fetch("/__scheduled");
37
+ let text;
38
+ if (resp) text = await resp.text();
39
+ expect(text).toMatchInlineSnapshot(`"Fetch triggered at /__scheduled"`);
40
+ await worker.stop();
41
+ });
42
+
43
+ it("should intercept when middleware is enabled", async () => {
44
+ const worker = await unstable_dev(
45
+ "index.js",
46
+ { testScheduled: true },
47
+ { disableExperimentalWarning: true }
48
+ );
49
+
50
+ const resp = await worker.fetch("/__scheduled");
51
+ let text;
52
+ if (resp) text = await resp.text();
53
+ expect(text).toMatchInlineSnapshot(`"Ran scheduled event"`);
54
+ await worker.stop();
55
+ });
56
+
57
+ it("should not trigger scheduled event on wrong route", async () => {
58
+ const worker = await unstable_dev(
59
+ "index.js",
60
+ { testScheduled: true },
61
+ { disableExperimentalWarning: true }
62
+ );
63
+
64
+ const resp = await worker.fetch("/test");
65
+ let text;
66
+ if (resp) text = await resp.text();
67
+ expect(text).toMatchInlineSnapshot(`"Hello world!"`);
68
+ await worker.stop();
69
+ });
70
+ });
71
+
72
+ describe("service workers", () => {
73
+ runInTempDir();
74
+
75
+ beforeEach(() => {
76
+ const scriptContent = `
77
+ addEventListener("scheduled", (event) => {
78
+ console.log("Doing something scheduled in service worker...");
79
+ });
80
+
81
+ addEventListener("fetch", (event) => {
82
+ const url = new URL(event.request.url);
83
+ if (url.pathname === "/__scheduled") {
84
+ event.respondWith(new Response("Fetch triggered at /__scheduled"));
85
+ } else {
86
+ event.respondWith(new Response("Hello world!"));
87
+ }
88
+ });
89
+ `;
90
+ fs.writeFileSync("index.js", scriptContent);
91
+ });
92
+
93
+ it("should not intercept when middleware is not enabled", async () => {
94
+ const worker = await unstable_dev(
95
+ "index.js",
96
+ {},
97
+ { disableExperimentalWarning: true }
98
+ );
99
+
100
+ const resp = await worker.fetch("/__scheduled");
101
+ let text;
102
+ if (resp) text = await resp.text();
103
+ expect(text).toMatchInlineSnapshot(`"Fetch triggered at /__scheduled"`);
104
+ await worker.stop();
105
+ });
106
+
107
+ it("should intercept when middleware is enabled", async () => {
108
+ const worker = await unstable_dev(
109
+ "index.js",
110
+ { testScheduled: true },
111
+ { disableExperimentalWarning: true }
112
+ );
113
+
114
+ const resp = await worker.fetch("/__scheduled");
115
+ let text;
116
+ if (resp) text = await resp.text();
117
+ expect(text).toMatchInlineSnapshot(`"Ran scheduled event"`);
118
+ await worker.stop();
119
+ });
120
+
121
+ it("should not trigger scheduled event on wrong route", async () => {
122
+ const worker = await unstable_dev(
123
+ "index.js",
124
+ { testScheduled: true },
125
+ { disableExperimentalWarning: true }
126
+ );
127
+
128
+ const resp = await worker.fetch("/test");
129
+ let text;
130
+ if (resp) text = await resp.text();
131
+ expect(text).toMatchInlineSnapshot(`"Hello world!"`);
132
+ await worker.stop();
133
+ });
134
+ });
135
+ });