wrangler 0.0.0-e2a26a0 → 0.0.0-e3a458e

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 (84) hide show
  1. package/package.json +24 -11
  2. package/pages/functions/filepath-routing.test.ts +212 -36
  3. package/pages/functions/filepath-routing.ts +69 -119
  4. package/pages/functions/routes.ts +8 -17
  5. package/pages/functions/template-worker.ts +3 -9
  6. package/src/__tests__/configuration.test.ts +2598 -0
  7. package/src/__tests__/dev.test.tsx +437 -63
  8. package/src/__tests__/dev2.test.tsx +154 -0
  9. package/src/__tests__/guess-worker-format.test.ts +58 -0
  10. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  11. package/src/__tests__/helpers/mock-account-id.ts +26 -8
  12. package/src/__tests__/helpers/mock-bin.ts +4 -1
  13. package/src/__tests__/helpers/mock-cfetch.ts +5 -5
  14. package/src/__tests__/helpers/mock-console.ts +21 -7
  15. package/src/__tests__/helpers/mock-kv.ts +9 -16
  16. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  17. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  18. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  19. package/src/__tests__/helpers/run-wrangler.ts +5 -3
  20. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  21. package/src/__tests__/https-options.test.ts +127 -0
  22. package/src/__tests__/index.test.ts +468 -20
  23. package/src/__tests__/jest.setup.ts +37 -5
  24. package/src/__tests__/kv.test.ts +426 -183
  25. package/src/__tests__/logout.test.ts +15 -13
  26. package/src/__tests__/package-manager.test.ts +2 -2
  27. package/src/__tests__/pages.test.ts +44 -0
  28. package/src/__tests__/parse.test.ts +322 -0
  29. package/src/__tests__/publish.test.ts +1733 -344
  30. package/src/__tests__/r2.test.ts +198 -0
  31. package/src/__tests__/route.test.ts +45 -0
  32. package/src/__tests__/secret.test.ts +301 -86
  33. package/src/__tests__/sentry.test.ts +146 -0
  34. package/src/__tests__/tail.test.ts +564 -0
  35. package/src/__tests__/whoami.test.tsx +21 -7
  36. package/src/bundle.ts +142 -0
  37. package/src/cfetch/index.ts +8 -6
  38. package/src/cfetch/internal.ts +60 -22
  39. package/src/cli.ts +10 -0
  40. package/src/config/README.md +107 -0
  41. package/src/config/config.ts +279 -0
  42. package/src/config/diagnostics.ts +80 -0
  43. package/src/config/environment.ts +305 -0
  44. package/src/config/index.ts +52 -0
  45. package/src/config/validation-helpers.ts +468 -0
  46. package/src/config/validation.ts +1057 -0
  47. package/src/{api/preview.ts → create-worker-preview.ts} +59 -21
  48. package/src/create-worker-upload-form.ts +217 -0
  49. package/src/dev/dev.tsx +362 -0
  50. package/src/dev/local.tsx +247 -0
  51. package/src/dev/remote.tsx +203 -0
  52. package/src/dev/use-esbuild.ts +100 -0
  53. package/src/entry.ts +159 -0
  54. package/src/environment-variables.ts +33 -0
  55. package/src/https-options.ts +122 -0
  56. package/src/index.tsx +1030 -766
  57. package/src/inspect.ts +25 -4
  58. package/src/{kv.tsx → kv.ts} +110 -55
  59. package/src/module-collection.ts +212 -22
  60. package/src/open-in-browser.ts +25 -0
  61. package/src/package-manager.ts +21 -15
  62. package/src/pages.tsx +10 -11
  63. package/src/parse.ts +183 -0
  64. package/src/proxy.ts +115 -45
  65. package/src/publish.ts +273 -329
  66. package/src/r2.ts +50 -0
  67. package/src/reporting.ts +131 -0
  68. package/src/selfsigned.d.ts +29 -0
  69. package/src/sites.tsx +66 -33
  70. package/src/tail/filters.ts +279 -0
  71. package/src/tail/index.ts +299 -0
  72. package/src/tail/printing.ts +62 -0
  73. package/src/user.tsx +223 -124
  74. package/src/{api/worker.ts → worker.ts} +44 -36
  75. package/templates/new-worker.js +1 -1
  76. package/templates/new-worker.ts +1 -1
  77. package/templates/tsconfig.json +105 -0
  78. package/wrangler-dist/cli.js +129900 -113128
  79. package/wrangler-dist/cli.js.map +3 -3
  80. package/src/__tests__/helpers/mock-user.ts +0 -27
  81. package/src/api/form_data.ts +0 -134
  82. package/src/config.ts +0 -641
  83. package/src/dev.tsx +0 -834
  84. package/src/tail.tsx +0 -73
@@ -2,17 +2,30 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import * as TOML from "@iarna/toml";
4
4
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
5
- import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
5
+ import {
6
+ createFetchResult,
7
+ setMockFetchKVGetValue,
8
+ setMockRawResponse,
9
+ setMockResponse,
10
+ unsetAllMocks,
11
+ unsetMockFetchKVGetValues,
12
+ } from "./helpers/mock-cfetch";
6
13
  import { mockConsoleMethods } from "./helpers/mock-console";
7
14
  import { mockKeyListRequest } from "./helpers/mock-kv";
8
15
  import { runInTempDir } from "./helpers/run-in-tmp";
9
16
  import { runWrangler } from "./helpers/run-wrangler";
10
- import type { WorkerMetadata } from "../api/form_data";
11
- import type { Config } from "../config";
17
+ import writeWranglerToml from "./helpers/write-wrangler-toml";
18
+ import type { WorkerMetadata } from "../create-worker-upload-form";
12
19
  import type { KVNamespaceInfo } from "../kv";
13
20
  import type { FormData, File } from "undici";
14
21
 
15
22
  describe("publish", () => {
23
+ beforeEach(() => {
24
+ // @ts-expect-error we're using a very simple setTimeout mock here
25
+ jest.spyOn(global, "setTimeout").mockImplementation((fn, _period) => {
26
+ fn();
27
+ });
28
+ });
16
29
  mockAccountId();
17
30
  mockApiToken();
18
31
  runInTempDir();
@@ -20,6 +33,194 @@ describe("publish", () => {
20
33
 
21
34
  afterEach(() => {
22
35
  unsetAllMocks();
36
+ unsetMockFetchKVGetValues();
37
+ });
38
+
39
+ describe("environments", () => {
40
+ it("should use legacy environments by default", async () => {
41
+ writeWranglerToml();
42
+ writeWorkerSource();
43
+ mockSubDomainRequest();
44
+ mockUploadWorkerRequest({
45
+ env: "some-env",
46
+ legacyEnv: true,
47
+ });
48
+ await runWrangler("publish index.js --env some-env");
49
+ expect(std.out).toMatchInlineSnapshot(`
50
+ "Uploaded test-name-some-env (TIMINGS)
51
+ Published test-name-some-env (TIMINGS)
52
+ test-name-some-env.test-sub-domain.workers.dev"
53
+ `);
54
+ expect(std.err).toMatchInlineSnapshot(`""`);
55
+ expect(std.warn).toMatchInlineSnapshot(`""`);
56
+ });
57
+
58
+ describe("legacy", () => {
59
+ it("uses the script name when no environment is specified", async () => {
60
+ writeWranglerToml();
61
+ writeWorkerSource();
62
+ mockSubDomainRequest();
63
+ mockUploadWorkerRequest({
64
+ legacyEnv: true,
65
+ });
66
+ await runWrangler("publish index.js --legacy-env true");
67
+ expect(std.out).toMatchInlineSnapshot(`
68
+ "Uploaded test-name (TIMINGS)
69
+ Published test-name (TIMINGS)
70
+ test-name.test-sub-domain.workers.dev"
71
+ `);
72
+ expect(std.err).toMatchInlineSnapshot(`""`);
73
+ expect(std.warn).toMatchInlineSnapshot(`""`);
74
+ });
75
+
76
+ it("appends the environment name when provided", async () => {
77
+ writeWranglerToml();
78
+ writeWorkerSource();
79
+ mockSubDomainRequest();
80
+ mockUploadWorkerRequest({
81
+ env: "some-env",
82
+ legacyEnv: true,
83
+ });
84
+ await runWrangler("publish index.js --env some-env --legacy-env true");
85
+ expect(std.out).toMatchInlineSnapshot(`
86
+ "Uploaded test-name-some-env (TIMINGS)
87
+ Published test-name-some-env (TIMINGS)
88
+ test-name-some-env.test-sub-domain.workers.dev"
89
+ `);
90
+ expect(std.err).toMatchInlineSnapshot(`""`);
91
+ expect(std.warn).toMatchInlineSnapshot(`""`);
92
+ });
93
+ });
94
+
95
+ describe("services", () => {
96
+ it("uses the script name when no environment is specified", async () => {
97
+ writeWranglerToml();
98
+ writeWorkerSource();
99
+ mockSubDomainRequest();
100
+ mockUploadWorkerRequest({
101
+ legacyEnv: false,
102
+ });
103
+ await runWrangler("publish index.js");
104
+ expect(std.out).toMatchInlineSnapshot(`
105
+ "Uploaded test-name (TIMINGS)
106
+ Published test-name (TIMINGS)
107
+ test-name.test-sub-domain.workers.dev"
108
+ `);
109
+ expect(std.err).toMatchInlineSnapshot(`""`);
110
+ expect(std.warn).toMatchInlineSnapshot(`""`);
111
+ });
112
+
113
+ it("publishes as an environment when provided", async () => {
114
+ writeWranglerToml();
115
+ writeWorkerSource();
116
+ mockSubDomainRequest();
117
+ mockUploadWorkerRequest({
118
+ env: "some-env",
119
+ legacyEnv: false,
120
+ });
121
+ await runWrangler("publish index.js --env some-env --legacy-env false");
122
+ expect(std.out).toMatchInlineSnapshot(`
123
+ "Uploaded test-name (some-env) (TIMINGS)
124
+ Published test-name (some-env) (TIMINGS)
125
+ some-env.test-name.test-sub-domain.workers.dev"
126
+ `);
127
+ expect(std.err).toMatchInlineSnapshot(`""`);
128
+ expect(std.warn).toMatchInlineSnapshot(`""`);
129
+ });
130
+ });
131
+ });
132
+
133
+ it("should resolve wrangler.toml relative to the entrypoint", async () => {
134
+ fs.mkdirSync("./some-path/worker", { recursive: true });
135
+ fs.writeFileSync(
136
+ "./some-path/wrangler.toml",
137
+ TOML.stringify({
138
+ name: "test-name",
139
+ compatibility_date: "2022-01-12",
140
+ vars: { xyz: 123 },
141
+ }),
142
+ "utf-8"
143
+ );
144
+ writeWorkerSource({ basePath: "./some-path/worker" });
145
+ mockUploadWorkerRequest({
146
+ expectedBindings: [
147
+ {
148
+ json: 123,
149
+ name: "xyz",
150
+ type: "json",
151
+ },
152
+ ],
153
+ expectedCompatibilityDate: "2022-01-12",
154
+ });
155
+ mockSubDomainRequest();
156
+ await runWrangler("publish ./some-path/worker/index.js");
157
+ expect(std.out).toMatchInlineSnapshot(`
158
+ "Uploaded test-name (TIMINGS)
159
+ Published test-name (TIMINGS)
160
+ test-name.test-sub-domain.workers.dev"
161
+ `);
162
+ expect(std.err).toMatchInlineSnapshot(`""`);
163
+ });
164
+
165
+ describe("routes", () => {
166
+ it("should publish the worker to a route", async () => {
167
+ writeWranglerToml({
168
+ routes: ["example.com/some-route/*"],
169
+ });
170
+ writeWorkerSource();
171
+ mockUpdateWorkerRequest({ enabled: false });
172
+ mockUploadWorkerRequest({ expectedType: "esm" });
173
+ mockPublishRoutesRequest({ routes: ["example.com/some-route/*"] });
174
+ await runWrangler("publish ./index");
175
+ });
176
+
177
+ it("should publish to legacy environment specific routes", async () => {
178
+ writeWranglerToml({
179
+ routes: ["example.com/some-route/*"],
180
+ env: {
181
+ dev: {
182
+ routes: ["dev-example.com/some-route/*"],
183
+ },
184
+ },
185
+ });
186
+ writeWorkerSource();
187
+ mockUpdateWorkerRequest({ enabled: false, legacyEnv: true, env: "dev" });
188
+ mockUploadWorkerRequest({
189
+ expectedType: "esm",
190
+ legacyEnv: true,
191
+ env: "dev",
192
+ });
193
+ mockPublishRoutesRequest({
194
+ routes: ["dev-example.com/some-route/*"],
195
+ legacyEnv: true,
196
+ env: "dev",
197
+ });
198
+ await runWrangler("publish ./index --env dev --legacy-env true");
199
+ });
200
+
201
+ it("services: should publish to service environment specific routes", async () => {
202
+ writeWranglerToml({
203
+ routes: ["example.com/some-route/*"],
204
+ env: {
205
+ dev: {
206
+ routes: ["dev-example.com/some-route/*"],
207
+ },
208
+ },
209
+ });
210
+ writeWorkerSource();
211
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
212
+ mockUploadWorkerRequest({
213
+ expectedType: "esm",
214
+ env: "dev",
215
+ });
216
+ mockPublishRoutesRequest({
217
+ routes: ["dev-example.com/some-route/*"],
218
+ env: "dev",
219
+ });
220
+ await runWrangler("publish ./index --env dev --legacy-env false");
221
+ });
222
+
223
+ it.todo("should error if it's a workers.dev route");
23
224
  });
24
225
 
25
226
  describe("entry-points", () => {
@@ -32,17 +233,13 @@ describe("publish", () => {
32
233
  await runWrangler("publish ./index");
33
234
 
34
235
  expect(std.out).toMatchInlineSnapshot(`
35
- "Uploaded
36
- test-name
37
- (TIMINGS)
38
- Deployed
39
- test-name
40
- (TIMINGS)
41
-
42
- test-name.test-sub-domain.workers.dev"
43
- `);
236
+ "Uploaded test-name (TIMINGS)
237
+ Published test-name (TIMINGS)
238
+ test-name.test-sub-domain.workers.dev"
239
+ `);
44
240
  expect(std.err).toMatchInlineSnapshot(`""`);
45
241
  });
242
+
46
243
  it("should be able to use `index` with no extension as the entry-point (sw)", async () => {
47
244
  writeWranglerToml();
48
245
  writeWorkerSource({ type: "sw" });
@@ -52,20 +249,15 @@ describe("publish", () => {
52
249
  await runWrangler("publish ./index");
53
250
 
54
251
  expect(std.out).toMatchInlineSnapshot(`
55
- "Uploaded
56
- test-name
57
- (TIMINGS)
58
- Deployed
59
- test-name
60
- (TIMINGS)
61
-
62
- test-name.test-sub-domain.workers.dev"
63
- `);
252
+ "Uploaded test-name (TIMINGS)
253
+ Published test-name (TIMINGS)
254
+ test-name.test-sub-domain.workers.dev"
255
+ `);
64
256
  expect(std.err).toMatchInlineSnapshot(`""`);
65
257
  });
66
258
 
67
- it("should be able to use the `build.upload.main` config as the entry-point for ESM sources", async () => {
68
- writeWranglerToml({ build: { upload: { main: "./index.js" } } });
259
+ it("should be able to use the `main` config as the entry-point for ESM sources", async () => {
260
+ writeWranglerToml({ main: "./index.js" });
69
261
  writeWorkerSource();
70
262
  mockUploadWorkerRequest();
71
263
  mockSubDomainRequest();
@@ -73,16 +265,107 @@ describe("publish", () => {
73
265
  await runWrangler("publish");
74
266
 
75
267
  expect(std.out).toMatchInlineSnapshot(`
76
- "Uploaded
77
- test-name
78
- (TIMINGS)
79
- Deployed
80
- test-name
81
- (TIMINGS)
82
-
83
- test-name.test-sub-domain.workers.dev"
84
- `);
268
+ "Uploaded test-name (TIMINGS)
269
+ Published test-name (TIMINGS)
270
+ test-name.test-sub-domain.workers.dev"
271
+ `);
272
+ expect(std.err).toMatchInlineSnapshot(`""`);
273
+ });
274
+
275
+ it("should use `main` relative to the wrangler.toml not cwd", async () => {
276
+ writeWranglerToml({
277
+ main: "./foo/index.js",
278
+ });
279
+ writeWorkerSource({ basePath: "foo" });
280
+ mockUploadWorkerRequest({ expectedEntry: "var foo = 100;" });
281
+ mockSubDomainRequest();
282
+ process.chdir("foo");
283
+ await runWrangler("publish");
284
+
285
+ expect(std.out).toMatchInlineSnapshot(`
286
+ "Uploaded test-name (TIMINGS)
287
+ Published test-name (TIMINGS)
288
+ test-name.test-sub-domain.workers.dev"
289
+ `);
290
+ expect(std.err).toMatchInlineSnapshot(`""`);
291
+ });
292
+
293
+ it('should use `build.upload.main` as an entry point, where `build.upload.dir` defaults to "./dist", and log a deprecation warning', async () => {
294
+ writeWranglerToml({ build: { upload: { main: "./index.js" } } });
295
+ writeWorkerSource({ basePath: "./dist" });
296
+ mockUploadWorkerRequest();
297
+ mockSubDomainRequest();
298
+
299
+ await runWrangler("publish");
300
+
301
+ expect(std.out).toMatchInlineSnapshot(`
302
+ "Uploaded test-name (TIMINGS)
303
+ Published test-name (TIMINGS)
304
+ test-name.test-sub-domain.workers.dev"
305
+ `);
306
+ expect(std.err).toMatchInlineSnapshot(`""`);
307
+ expect(std.warn).toMatchInlineSnapshot(`
308
+ "Processing wrangler.toml configuration:
309
+ - DEPRECATION: \\"build.upload.main\\":
310
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
311
+ Then add the top level \`main\` field to your configuration file:
312
+ \`\`\`
313
+ main = \\"dist/index.js\\"
314
+ \`\`\`"
315
+ `);
316
+ });
317
+
318
+ it("should use `build.upload.main` relative to `build.upload.dir`", async () => {
319
+ writeWranglerToml({
320
+ build: {
321
+ upload: {
322
+ main: "./index.js",
323
+ dir: "./foo",
324
+ },
325
+ },
326
+ });
327
+ writeWorkerSource({ basePath: "./foo" });
328
+ mockUploadWorkerRequest({ expectedEntry: "var foo = 100;" });
329
+ mockSubDomainRequest();
330
+ process.chdir("foo");
331
+ await runWrangler("publish");
332
+
333
+ expect(std.out).toMatchInlineSnapshot(`
334
+ "Uploaded test-name (TIMINGS)
335
+ Published test-name (TIMINGS)
336
+ test-name.test-sub-domain.workers.dev"
337
+ `);
85
338
  expect(std.err).toMatchInlineSnapshot(`""`);
339
+ expect(std.warn).toMatchInlineSnapshot(`
340
+ "Processing ../wrangler.toml configuration:
341
+ - DEPRECATION: \\"build.upload.main\\":
342
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
343
+ Then add the top level \`main\` field to your configuration file:
344
+ \`\`\`
345
+ main = \\"foo/index.js\\"
346
+ \`\`\`
347
+ - DEPRECATION: \\"build.upload.dir\\":
348
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker."
349
+ `);
350
+ });
351
+
352
+ it("should error when both `main` and `build.upload.main` are used", async () => {
353
+ writeWranglerToml({
354
+ main: "./index.js",
355
+ build: {
356
+ upload: {
357
+ main: "./index.js",
358
+ dir: "./foo",
359
+ },
360
+ },
361
+ });
362
+ await expect(runWrangler("publish")).rejects
363
+ .toThrowErrorMatchingInlineSnapshot(`
364
+ "Processing wrangler.toml configuration:
365
+ - Don't define both the \`main\` and \`build.upload.main\` fields in your configuration.
366
+ They serve the same purpose: to point to the entry-point of your worker.
367
+ Delete the \`build.upload.main\` and \`build.upload.dir\` field from your config."
368
+ `);
86
369
  });
87
370
 
88
371
  it("should be able to transpile TypeScript (esm)", async () => {
@@ -93,15 +376,10 @@ describe("publish", () => {
93
376
  await runWrangler("publish index.ts");
94
377
 
95
378
  expect(std.out).toMatchInlineSnapshot(`
96
- "Uploaded
97
- test-name
98
- (TIMINGS)
99
- Deployed
100
- test-name
101
- (TIMINGS)
102
-
103
- test-name.test-sub-domain.workers.dev"
104
- `);
379
+ "Uploaded test-name (TIMINGS)
380
+ Published test-name (TIMINGS)
381
+ test-name.test-sub-domain.workers.dev"
382
+ `);
105
383
  expect(std.err).toMatchInlineSnapshot(`""`);
106
384
  });
107
385
 
@@ -116,19 +394,14 @@ describe("publish", () => {
116
394
  await runWrangler("publish index.ts");
117
395
 
118
396
  expect(std.out).toMatchInlineSnapshot(`
119
- "Uploaded
120
- test-name
121
- (TIMINGS)
122
- Deployed
123
- test-name
124
- (TIMINGS)
125
-
126
- test-name.test-sub-domain.workers.dev"
127
- `);
397
+ "Uploaded test-name (TIMINGS)
398
+ Published test-name (TIMINGS)
399
+ test-name.test-sub-domain.workers.dev"
400
+ `);
128
401
  expect(std.err).toMatchInlineSnapshot(`""`);
129
402
  });
130
403
 
131
- it("should inline referenced text modules into the worker", async () => {
404
+ it("should add referenced text modules into the form upload", async () => {
132
405
  writeWranglerToml();
133
406
  fs.writeFileSync(
134
407
  "./index.js",
@@ -142,18 +415,18 @@ export default{
142
415
  `
143
416
  );
144
417
  fs.writeFileSync("./textfile.txt", "Hello, World!");
145
- mockUploadWorkerRequest({ expectedEntry: "Hello, World!" });
418
+ mockUploadWorkerRequest({
419
+ expectedModules: {
420
+ "./0a0a9f2a6772942557ab5355d76af442f8f65e01-textfile.txt":
421
+ "Hello, World!",
422
+ },
423
+ });
146
424
  mockSubDomainRequest();
147
425
  await runWrangler("publish index.js");
148
426
  expect(std.out).toMatchInlineSnapshot(`
149
- "Uploaded
150
- test-name
151
- (TIMINGS)
152
- Deployed
153
- test-name
154
- (TIMINGS)
155
-
156
- test-name.test-sub-domain.workers.dev"
427
+ "Uploaded test-name (TIMINGS)
428
+ Published test-name (TIMINGS)
429
+ test-name.test-sub-domain.workers.dev"
157
430
  `);
158
431
  expect(std.err).toMatchInlineSnapshot(`""`);
159
432
  });
@@ -167,15 +440,10 @@ export default{
167
440
  await runWrangler("publish ./src/index.js");
168
441
 
169
442
  expect(std.out).toMatchInlineSnapshot(`
170
- "Uploaded
171
- test-name
172
- (TIMINGS)
173
- Deployed
174
- test-name
175
- (TIMINGS)
176
-
177
- test-name.test-sub-domain.workers.dev"
178
- `);
443
+ "Uploaded test-name (TIMINGS)
444
+ Published test-name (TIMINGS)
445
+ test-name.test-sub-domain.workers.dev"
446
+ `);
179
447
  expect(std.err).toMatchInlineSnapshot(`""`);
180
448
  });
181
449
 
@@ -191,50 +459,39 @@ export default{
191
459
  await runWrangler("publish ./src/index.js");
192
460
 
193
461
  expect(std.out).toMatchInlineSnapshot(`
194
- "Uploaded
195
- test-name
196
- (TIMINGS)
197
- Deployed
198
- test-name
199
- (TIMINGS)
200
-
201
- test-name.test-sub-domain.workers.dev"
202
- `);
462
+ "Uploaded test-name (TIMINGS)
463
+ Published test-name (TIMINGS)
464
+ test-name.test-sub-domain.workers.dev"
465
+ `);
203
466
  expect(std.err).toMatchInlineSnapshot(`""`);
204
467
  });
205
468
 
206
469
  it('should error if a site definition doesn\'t have a "bucket" field', async () => {
207
470
  writeWranglerToml({
208
- // @ts-expect-error we're purposely missing the required `site.bucket` field
209
- site: {
210
- "entry-point": "./index.js",
211
- },
471
+ // @ts-expect-error we're intentionally setting an invalid config
472
+ site: {},
212
473
  });
213
474
  writeWorkerSource();
214
475
  mockUploadWorkerRequest();
215
476
  mockSubDomainRequest();
216
477
 
217
- await expect(
218
- runWrangler("publish ./index.js")
219
- ).rejects.toThrowErrorMatchingInlineSnapshot(
220
- `"A [site] definition requires a \`bucket\` field with a path to the site's public directory."`
221
- );
478
+ await expect(runWrangler("publish ./index.js")).rejects
479
+ .toThrowErrorMatchingInlineSnapshot(`
480
+ "Processing wrangler.toml configuration:
481
+ - \\"site.bucket\\" is a required field."
482
+ `);
222
483
 
223
484
  expect(std.out).toMatchInlineSnapshot(`""`);
224
485
  expect(std.err).toMatchInlineSnapshot(`
225
- "A [site] definition requires a \`bucket\` field with a path to the site's public directory.
486
+ "Processing wrangler.toml configuration:
487
+ - \\"site.bucket\\" is a required field.
226
488
 
227
- %s
228
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
229
- `);
230
- expect(std.warn).toMatchInlineSnapshot(`
231
- "Deprecation notice: The \`site.entry-point\` config field is no longer used.
232
- The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field.
233
- Please remove the \`site.entry-point\` field from the \`wrangler.toml\` file."
489
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
234
490
  `);
491
+ expect(std.warn).toMatchInlineSnapshot(`""`);
235
492
  });
236
493
 
237
- it("should warn if there is a `site.entry-point` configuration", async () => {
494
+ it("should error if there is a `site.entry-point` configuration", async () => {
238
495
  const assets = [
239
496
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
240
497
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -258,27 +515,26 @@ export default{
258
515
  mockKeyListRequest(kvNamespace.id, []);
259
516
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
260
517
 
261
- await runWrangler("publish ./index.js");
518
+ await expect(runWrangler("publish ./index.js")).rejects
519
+ .toThrowErrorMatchingInlineSnapshot(`
520
+ "Processing wrangler.toml configuration:
521
+ - DEPRECATION: \\"site.entry-point\\":
522
+ The \`site.entry-point\` config field is no longer used.
523
+ The entry-point should be specified via the command line or the \`main\` config field."
524
+ `);
262
525
 
263
- expect(std.out).toMatchInlineSnapshot(`
264
- "reading assets/file-1.txt...
265
- uploading as assets/file-1.2ca234f380.txt...
266
- reading assets/file-2.txt...
267
- uploading as assets/file-2.5938485188.txt...
268
- Uploaded
269
- test-name
270
- (TIMINGS)
271
- Deployed
272
- test-name
273
- (TIMINGS)
274
-
275
- test-name.test-sub-domain.workers.dev"
526
+ expect(std.out).toMatchInlineSnapshot(`""`);
527
+ expect(std.err).toMatchInlineSnapshot(`
528
+ "Processing wrangler.toml configuration:
529
+ - DEPRECATION: \\"site.entry-point\\":
530
+ The \`site.entry-point\` config field is no longer used.
531
+ The entry-point should be specified via the command line or the \`main\` config field.
532
+
533
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
276
534
  `);
277
- expect(std.err).toMatchInlineSnapshot(`""`);
278
535
  expect(std.warn).toMatchInlineSnapshot(`
279
- "Deprecation notice: The \`site.entry-point\` config field is no longer used.
280
- The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field.
281
- Please remove the \`site.entry-point\` field from the \`wrangler.toml\` file."
536
+ "Processing wrangler.toml configuration:
537
+ - Unexpected fields found in site field: \\"entry-point\\""
282
538
  `);
283
539
  });
284
540
 
@@ -290,15 +546,14 @@ export default{
290
546
  await expect(
291
547
  runWrangler("publish")
292
548
  ).rejects.toThrowErrorMatchingInlineSnapshot(
293
- `"Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field."`
549
+ `"Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field."`
294
550
  );
295
551
 
296
552
  expect(std.out).toMatchInlineSnapshot(`""`);
297
553
  expect(std.err).toMatchInlineSnapshot(`
298
- "Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`build.upload.main\` config field.
554
+ "Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field.
299
555
 
300
- %s
301
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
556
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
302
557
  `);
303
558
  });
304
559
  });
@@ -314,7 +569,7 @@ export default{
314
569
  id: "__test-name-workers_sites_assets-id",
315
570
  };
316
571
  writeWranglerToml({
317
- build: { upload: { main: "./index.js" } },
572
+ main: "./index.js",
318
573
  site: {
319
574
  bucket: "assets",
320
575
  },
@@ -333,19 +588,14 @@ export default{
333
588
  uploading as assets/file-1.2ca234f380.txt...
334
589
  reading assets/file-2.txt...
335
590
  uploading as assets/file-2.5938485188.txt...
336
- Uploaded
337
- test-name
338
- (TIMINGS)
339
- Deployed
340
- test-name
341
- (TIMINGS)
342
-
343
- test-name.test-sub-domain.workers.dev"
591
+ Uploaded test-name (TIMINGS)
592
+ Published test-name (TIMINGS)
593
+ test-name.test-sub-domain.workers.dev"
344
594
  `);
345
595
  expect(std.err).toMatchInlineSnapshot(`""`);
346
596
  });
347
597
 
348
- it("when using a service worker type, it should inline an asset manifest, and bind to a namespace", async () => {
598
+ it("when using a service worker type, it should add an asset manifest as a text_blob, and bind to a namespace", async () => {
349
599
  const assets = [
350
600
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
351
601
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -355,7 +605,7 @@ export default{
355
605
  id: "__test-name-workers_sites_assets-id",
356
606
  };
357
607
  writeWranglerToml({
358
- build: { upload: { main: "./index.js" } },
608
+ main: "./index.js",
359
609
  site: {
360
610
  bucket: "assets",
361
611
  },
@@ -364,13 +614,21 @@ export default{
364
614
  writeAssets(assets);
365
615
  mockUploadWorkerRequest({
366
616
  expectedType: "sw",
367
- expectedEntry: `const __STATIC_CONTENT_MANIFEST = {"file-1.txt":"assets/file-1.2ca234f380.txt","file-2.txt":"assets/file-2.5938485188.txt"};`,
617
+ expectedModules: {
618
+ __STATIC_CONTENT_MANIFEST:
619
+ '{"file-1.txt":"assets/file-1.2ca234f380.txt","file-2.txt":"assets/file-2.5938485188.txt"}',
620
+ },
368
621
  expectedBindings: [
369
622
  {
370
623
  name: "__STATIC_CONTENT",
371
624
  namespace_id: "__test-name-workers_sites_assets-id",
372
625
  type: "kv_namespace",
373
626
  },
627
+ {
628
+ name: "__STATIC_CONTENT_MANIFEST",
629
+ part: "__STATIC_CONTENT_MANIFEST",
630
+ type: "text_blob",
631
+ },
374
632
  ],
375
633
  });
376
634
  mockSubDomainRequest();
@@ -385,14 +643,9 @@ export default{
385
643
  uploading as assets/file-1.2ca234f380.txt...
386
644
  reading assets/file-2.txt...
387
645
  uploading as assets/file-2.5938485188.txt...
388
- Uploaded
389
- test-name
390
- (TIMINGS)
391
- Deployed
392
- test-name
393
- (TIMINGS)
394
-
395
- test-name.test-sub-domain.workers.dev"
646
+ Uploaded test-name (TIMINGS)
647
+ Published test-name (TIMINGS)
648
+ test-name.test-sub-domain.workers.dev"
396
649
  `);
397
650
  expect(std.err).toMatchInlineSnapshot(`""`);
398
651
  });
@@ -407,7 +660,7 @@ export default{
407
660
  id: "__test-name-workers_sites_assets-id",
408
661
  };
409
662
  writeWranglerToml({
410
- build: { upload: { main: "./index.js" } },
663
+ main: "./index.js",
411
664
  site: {
412
665
  bucket: "assets",
413
666
  },
@@ -439,19 +692,14 @@ export default{
439
692
  uploading as assets/file-1.2ca234f380.txt...
440
693
  reading assets/file-2.txt...
441
694
  uploading as assets/file-2.5938485188.txt...
442
- Uploaded
443
- test-name
444
- (TIMINGS)
445
- Deployed
446
- test-name
447
- (TIMINGS)
448
-
449
- test-name.test-sub-domain.workers.dev"
695
+ Uploaded test-name (TIMINGS)
696
+ Published test-name (TIMINGS)
697
+ test-name.test-sub-domain.workers.dev"
450
698
  `);
451
699
  expect(std.err).toMatchInlineSnapshot(`""`);
452
700
  });
453
701
 
454
- it("should make environment specific kv namespace for assets", async () => {
702
+ it("should make environment specific kv namespace for assets, even for service envs", async () => {
455
703
  // This is the same test as the one before this, but with an env arg
456
704
  const assets = [
457
705
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
@@ -462,7 +710,7 @@ export default{
462
710
  id: "__test-name-some-env-workers_sites_assets-id",
463
711
  };
464
712
  writeWranglerToml({
465
- build: { upload: { main: "./index.js" } },
713
+ main: "./index.js",
466
714
  site: {
467
715
  bucket: "assets",
468
716
  },
@@ -483,21 +731,63 @@ export default{
483
731
  mockListKVNamespacesRequest(kvNamespace);
484
732
  mockKeyListRequest(kvNamespace.id, []);
485
733
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
486
- await runWrangler("publish --env some-env");
734
+ await runWrangler("publish --env some-env --legacy-env false");
487
735
 
488
736
  expect(std.out).toMatchInlineSnapshot(`
489
737
  "reading assets/file-1.txt...
490
738
  uploading as assets/file-1.2ca234f380.txt...
491
739
  reading assets/file-2.txt...
492
740
  uploading as assets/file-2.5938485188.txt...
493
- Uploaded
494
- test-name (some-env)
495
- (TIMINGS)
496
- Deployed
497
- test-name (some-env)
498
- (TIMINGS)
499
-
500
- some-env.test-name.test-sub-domain.workers.dev"
741
+ Uploaded test-name (some-env) (TIMINGS)
742
+ Published test-name (some-env) (TIMINGS)
743
+ some-env.test-name.test-sub-domain.workers.dev"
744
+ `);
745
+ expect(std.err).toMatchInlineSnapshot(`""`);
746
+ });
747
+
748
+ it("should make environment specific kv namespace for assets, even for legacy envs", async () => {
749
+ // And this is the same test as the one before this, but with legacyEnv:true
750
+ const assets = [
751
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
752
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
753
+ ];
754
+ const kvNamespace = {
755
+ title: "__test-name-some-env-workers_sites_assets",
756
+ id: "__test-name-some-env-workers_sites_assets-id",
757
+ };
758
+ writeWranglerToml({
759
+ main: "./index.js",
760
+ site: {
761
+ bucket: "assets",
762
+ },
763
+ });
764
+ writeWorkerSource();
765
+ writeAssets(assets);
766
+ mockUploadWorkerRequest({
767
+ legacyEnv: true,
768
+ env: "some-env",
769
+ expectedBindings: [
770
+ {
771
+ name: "__STATIC_CONTENT",
772
+ namespace_id: "__test-name-some-env-workers_sites_assets-id",
773
+ type: "kv_namespace",
774
+ },
775
+ ],
776
+ });
777
+ mockSubDomainRequest();
778
+ mockListKVNamespacesRequest(kvNamespace);
779
+ mockKeyListRequest(kvNamespace.id, []);
780
+ mockUploadAssetsToKVRequest(kvNamespace.id, assets);
781
+ await runWrangler("publish --env some-env --legacy-env true");
782
+
783
+ expect(std.out).toMatchInlineSnapshot(`
784
+ "reading assets/file-1.txt...
785
+ uploading as assets/file-1.2ca234f380.txt...
786
+ reading assets/file-2.txt...
787
+ uploading as assets/file-2.5938485188.txt...
788
+ Uploaded test-name-some-env (TIMINGS)
789
+ Published test-name-some-env (TIMINGS)
790
+ test-name-some-env.test-sub-domain.workers.dev"
501
791
  `);
502
792
  expect(std.err).toMatchInlineSnapshot(`""`);
503
793
  });
@@ -512,7 +802,7 @@ export default{
512
802
  id: "__test-name-workers_sites_assets-id",
513
803
  };
514
804
  writeWranglerToml({
515
- build: { upload: { main: "./index.js" } },
805
+ main: "./index.js",
516
806
  site: {
517
807
  bucket: "assets",
518
808
  },
@@ -523,7 +813,9 @@ export default{
523
813
  mockSubDomainRequest();
524
814
  mockListKVNamespacesRequest(kvNamespace);
525
815
  // Put file-1 in the KV namespace
526
- mockKeyListRequest(kvNamespace.id, ["assets/file-1.2ca234f380.txt"]);
816
+ mockKeyListRequest(kvNamespace.id, [
817
+ { name: "assets/file-1.2ca234f380.txt" },
818
+ ]);
527
819
  // Check we do not upload file-1
528
820
  mockUploadAssetsToKVRequest(
529
821
  kvNamespace.id,
@@ -536,14 +828,9 @@ export default{
536
828
  skipping - already uploaded
537
829
  reading assets/file-2.txt...
538
830
  uploading as assets/file-2.5938485188.txt...
539
- Uploaded
540
- test-name
541
- (TIMINGS)
542
- Deployed
543
- test-name
544
- (TIMINGS)
545
-
546
- test-name.test-sub-domain.workers.dev"
831
+ Uploaded test-name (TIMINGS)
832
+ Published test-name (TIMINGS)
833
+ test-name.test-sub-domain.workers.dev"
547
834
  `);
548
835
  expect(std.err).toMatchInlineSnapshot(`""`);
549
836
  });
@@ -558,7 +845,7 @@ export default{
558
845
  id: "__test-name-workers_sites_assets-id",
559
846
  };
560
847
  writeWranglerToml({
561
- build: { upload: { main: "./index.js" } },
848
+ main: "./index.js",
562
849
  site: {
563
850
  bucket: "assets",
564
851
  },
@@ -577,17 +864,12 @@ export default{
577
864
  await runWrangler("publish --site-include file-1.txt");
578
865
 
579
866
  expect(std.out).toMatchInlineSnapshot(`
580
- "reading assets/file-1.txt...
581
- uploading as assets/file-1.2ca234f380.txt...
582
- Uploaded
583
- test-name
584
- (TIMINGS)
585
- Deployed
586
- test-name
587
- (TIMINGS)
588
-
589
- test-name.test-sub-domain.workers.dev"
590
- `);
867
+ "reading assets/file-1.txt...
868
+ uploading as assets/file-1.2ca234f380.txt...
869
+ Uploaded test-name (TIMINGS)
870
+ Published test-name (TIMINGS)
871
+ test-name.test-sub-domain.workers.dev"
872
+ `);
591
873
  expect(std.err).toMatchInlineSnapshot(`""`);
592
874
  });
593
875
 
@@ -601,7 +883,7 @@ export default{
601
883
  id: "__test-name-workers_sites_assets-id",
602
884
  };
603
885
  writeWranglerToml({
604
- build: { upload: { main: "./index.js" } },
886
+ main: "./index.js",
605
887
  site: {
606
888
  bucket: "assets",
607
889
  },
@@ -620,17 +902,12 @@ export default{
620
902
  await runWrangler("publish --site-exclude file-2.txt");
621
903
 
622
904
  expect(std.out).toMatchInlineSnapshot(`
623
- "reading assets/file-1.txt...
624
- uploading as assets/file-1.2ca234f380.txt...
625
- Uploaded
626
- test-name
627
- (TIMINGS)
628
- Deployed
629
- test-name
630
- (TIMINGS)
631
-
632
- test-name.test-sub-domain.workers.dev"
633
- `);
905
+ "reading assets/file-1.txt...
906
+ uploading as assets/file-1.2ca234f380.txt...
907
+ Uploaded test-name (TIMINGS)
908
+ Published test-name (TIMINGS)
909
+ test-name.test-sub-domain.workers.dev"
910
+ `);
634
911
  expect(std.err).toMatchInlineSnapshot(`""`);
635
912
  });
636
913
 
@@ -644,7 +921,7 @@ export default{
644
921
  id: "__test-name-workers_sites_assets-id",
645
922
  };
646
923
  writeWranglerToml({
647
- build: { upload: { main: "./index.js" } },
924
+ main: "./index.js",
648
925
  site: {
649
926
  bucket: "assets",
650
927
  include: ["file-1.txt"],
@@ -664,17 +941,12 @@ export default{
664
941
  await runWrangler("publish");
665
942
 
666
943
  expect(std.out).toMatchInlineSnapshot(`
667
- "reading assets/file-1.txt...
668
- uploading as assets/file-1.2ca234f380.txt...
669
- Uploaded
670
- test-name
671
- (TIMINGS)
672
- Deployed
673
- test-name
674
- (TIMINGS)
675
-
676
- test-name.test-sub-domain.workers.dev"
677
- `);
944
+ "reading assets/file-1.txt...
945
+ uploading as assets/file-1.2ca234f380.txt...
946
+ Uploaded test-name (TIMINGS)
947
+ Published test-name (TIMINGS)
948
+ test-name.test-sub-domain.workers.dev"
949
+ `);
678
950
  expect(std.err).toMatchInlineSnapshot(`""`);
679
951
  });
680
952
 
@@ -688,7 +960,7 @@ export default{
688
960
  id: "__test-name-workers_sites_assets-id",
689
961
  };
690
962
  writeWranglerToml({
691
- build: { upload: { main: "./index.js" } },
963
+ main: "./index.js",
692
964
  site: {
693
965
  bucket: "assets",
694
966
  exclude: ["file-2.txt"],
@@ -708,17 +980,12 @@ export default{
708
980
  await runWrangler("publish");
709
981
 
710
982
  expect(std.out).toMatchInlineSnapshot(`
711
- "reading assets/file-1.txt...
712
- uploading as assets/file-1.2ca234f380.txt...
713
- Uploaded
714
- test-name
715
- (TIMINGS)
716
- Deployed
717
- test-name
718
- (TIMINGS)
719
-
720
- test-name.test-sub-domain.workers.dev"
721
- `);
983
+ "reading assets/file-1.txt...
984
+ uploading as assets/file-1.2ca234f380.txt...
985
+ Uploaded test-name (TIMINGS)
986
+ Published test-name (TIMINGS)
987
+ test-name.test-sub-domain.workers.dev"
988
+ `);
722
989
  expect(std.err).toMatchInlineSnapshot(`""`);
723
990
  });
724
991
 
@@ -732,7 +999,7 @@ export default{
732
999
  id: "__test-name-workers_sites_assets-id",
733
1000
  };
734
1001
  writeWranglerToml({
735
- build: { upload: { main: "./index.js" } },
1002
+ main: "./index.js",
736
1003
  site: {
737
1004
  bucket: "assets",
738
1005
  include: ["file-2.txt"],
@@ -752,17 +1019,12 @@ export default{
752
1019
  await runWrangler("publish --site-include file-1.txt");
753
1020
 
754
1021
  expect(std.out).toMatchInlineSnapshot(`
755
- "reading assets/file-1.txt...
756
- uploading as assets/file-1.2ca234f380.txt...
757
- Uploaded
758
- test-name
759
- (TIMINGS)
760
- Deployed
761
- test-name
762
- (TIMINGS)
763
-
764
- test-name.test-sub-domain.workers.dev"
765
- `);
1022
+ "reading assets/file-1.txt...
1023
+ uploading as assets/file-1.2ca234f380.txt...
1024
+ Uploaded test-name (TIMINGS)
1025
+ Published test-name (TIMINGS)
1026
+ test-name.test-sub-domain.workers.dev"
1027
+ `);
766
1028
  expect(std.err).toMatchInlineSnapshot(`""`);
767
1029
  });
768
1030
 
@@ -776,7 +1038,7 @@ export default{
776
1038
  id: "__test-name-workers_sites_assets-id",
777
1039
  };
778
1040
  writeWranglerToml({
779
- build: { upload: { main: "./index.js" } },
1041
+ main: "./index.js",
780
1042
  site: {
781
1043
  bucket: "assets",
782
1044
  exclude: ["assets/file-1.txt"],
@@ -796,20 +1058,15 @@ export default{
796
1058
  await runWrangler("publish --site-exclude file-2.txt");
797
1059
 
798
1060
  expect(std.out).toMatchInlineSnapshot(`
799
- "reading assets/file-1.txt...
800
- uploading as assets/file-1.2ca234f380.txt...
801
- Uploaded
802
- test-name
803
- (TIMINGS)
804
- Deployed
805
- test-name
806
- (TIMINGS)
807
-
808
- test-name.test-sub-domain.workers.dev"
809
- `);
810
- expect(std.err).toMatchInlineSnapshot(`""`);
811
- });
812
-
1061
+ "reading assets/file-1.txt...
1062
+ uploading as assets/file-1.2ca234f380.txt...
1063
+ Uploaded test-name (TIMINGS)
1064
+ Published test-name (TIMINGS)
1065
+ test-name.test-sub-domain.workers.dev"
1066
+ `);
1067
+ expect(std.err).toMatchInlineSnapshot(`""`);
1068
+ });
1069
+
813
1070
  it("should walk directories except node_modules", async () => {
814
1071
  const assets = [
815
1072
  {
@@ -826,7 +1083,7 @@ export default{
826
1083
  id: "__test-name-workers_sites_assets-id",
827
1084
  };
828
1085
  writeWranglerToml({
829
- build: { upload: { main: "./index.js" } },
1086
+ main: "./index.js",
830
1087
  site: {
831
1088
  bucket: "assets",
832
1089
  },
@@ -844,14 +1101,9 @@ export default{
844
1101
  expect(std.out).toMatchInlineSnapshot(`
845
1102
  "reading assets/directory-1/file-1.txt...
846
1103
  uploading as assets/directory-1/file-1.2ca234f380.txt...
847
- Uploaded
848
- test-name
849
- (TIMINGS)
850
- Deployed
851
- test-name
852
- (TIMINGS)
853
-
854
- test-name.test-sub-domain.workers.dev"
1104
+ Uploaded test-name (TIMINGS)
1105
+ Published test-name (TIMINGS)
1106
+ test-name.test-sub-domain.workers.dev"
855
1107
  `);
856
1108
  expect(std.err).toMatchInlineSnapshot(`""`);
857
1109
  });
@@ -876,7 +1128,7 @@ export default{
876
1128
  id: "__test-name-workers_sites_assets-id",
877
1129
  };
878
1130
  writeWranglerToml({
879
- build: { upload: { main: "./index.js" } },
1131
+ main: "./index.js",
880
1132
  site: {
881
1133
  bucket: "assets",
882
1134
  },
@@ -894,14 +1146,9 @@ export default{
894
1146
  expect(std.out).toMatchInlineSnapshot(`
895
1147
  "reading assets/.well-known/file-2.txt...
896
1148
  uploading as assets/.well-known/file-2.5938485188.txt...
897
- Uploaded
898
- test-name
899
- (TIMINGS)
900
- Deployed
901
- test-name
902
- (TIMINGS)
903
-
904
- test-name.test-sub-domain.workers.dev"
1149
+ Uploaded test-name (TIMINGS)
1150
+ Published test-name (TIMINGS)
1151
+ test-name.test-sub-domain.workers.dev"
905
1152
  `);
906
1153
  expect(std.err).toMatchInlineSnapshot(`""`);
907
1154
  });
@@ -923,7 +1170,7 @@ export default{
923
1170
  id: "__test-name-workers_sites_assets-id",
924
1171
  };
925
1172
  writeWranglerToml({
926
- build: { upload: { main: "./index.js" } },
1173
+ main: "./index.js",
927
1174
  site: {
928
1175
  bucket: "assets",
929
1176
  exclude: ["assets/file-1.txt"],
@@ -949,8 +1196,7 @@ export default{
949
1196
  expect(std.err).toMatchInlineSnapshot(`
950
1197
  "File assets/too-large-file.txt is too big, it should be under 25 MiB. See https://developers.cloudflare.com/workers/platform/limits#kv-limits
951
1198
 
952
- %s
953
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1199
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
954
1200
  `);
955
1201
  });
956
1202
 
@@ -964,7 +1210,7 @@ export default{
964
1210
  id: "__test-name-workers_sites_assets-id",
965
1211
  };
966
1212
  writeWranglerToml({
967
- build: { upload: { main: "./index.js" } },
1213
+ main: "./index.js",
968
1214
  site: {
969
1215
  bucket: "assets",
970
1216
  },
@@ -988,13 +1234,453 @@ export default{
988
1234
  expect(std.err).toMatchInlineSnapshot(`
989
1235
  "The asset path key \\"assets/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.3da0d0cd12.txt\\" exceeds the maximum key size limit of 512. See https://developers.cloudflare.com/workers/platform/limits#kv-limits\\",
990
1236
 
991
- %s
992
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1237
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1238
+ `);
1239
+ });
1240
+
1241
+ describe("expire unused assets", () => {
1242
+ it("should expire uploaded assets that aren't included anymore", async () => {
1243
+ const assets = [
1244
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
1245
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1246
+ ];
1247
+ const kvNamespace = {
1248
+ title: "__test-name-workers_sites_assets",
1249
+ id: "__test-name-workers_sites_assets-id",
1250
+ };
1251
+ writeWranglerToml({
1252
+ main: "./index.js",
1253
+ site: {
1254
+ bucket: "assets",
1255
+ },
1256
+ });
1257
+ writeWorkerSource();
1258
+ writeAssets(assets);
1259
+ mockUploadWorkerRequest();
1260
+ mockSubDomainRequest();
1261
+ mockListKVNamespacesRequest(kvNamespace);
1262
+ mockKeyListRequest(kvNamespace.id, [
1263
+ // Put file-1 in the KV namespace
1264
+ { name: "assets/file-1.2ca234f380.txt" },
1265
+ // As well as a couple from a previous upload
1266
+ { name: "assets/file-3.somehash.txt" },
1267
+ { name: "assets/file-4.anotherhash.txt" },
1268
+ ]);
1269
+
1270
+ // Check that we pull down the values of file-3.txt and file-4.txt
1271
+ setMockFetchKVGetValue(
1272
+ "some-account-id",
1273
+ "__test-name-workers_sites_assets-id",
1274
+ "assets/file-3.somehash.txt",
1275
+ Buffer.from("Content of file-3", "utf8").toString("base64")
1276
+ );
1277
+ setMockFetchKVGetValue(
1278
+ "some-account-id",
1279
+ "__test-name-workers_sites_assets-id",
1280
+ "assets/file-4.anotherhash.txt",
1281
+ Buffer.from("Content of file-4", "utf8").toString("base64")
1282
+ );
1283
+
1284
+ // and send them back up
1285
+ mockUploadAssetsToKVRequest(kvNamespace.id, [
1286
+ ...assets.filter((a) => a.filePath !== "assets/file-1.txt"),
1287
+ {
1288
+ filePath: "assets/file-3.txt",
1289
+ content: "Content of file-3",
1290
+ // expect to expire this asset 300 seconds from now
1291
+ expiration_ttl: 300,
1292
+ },
1293
+ {
1294
+ filePath: "assets/file-4.txt",
1295
+ content: "Content of file-4",
1296
+ // expect to expire this asset 300 seconds from now
1297
+ expiration_ttl: 300,
1298
+ },
1299
+ ]);
1300
+
1301
+ await runWrangler("publish");
1302
+
1303
+ expect(std.out).toMatchInlineSnapshot(`
1304
+ "reading assets/file-1.txt...
1305
+ skipping - already uploaded
1306
+ reading assets/file-2.txt...
1307
+ uploading as assets/file-2.5938485188.txt...
1308
+ expiring unused assets/file-3.somehash.txt...
1309
+ expiring unused assets/file-4.anotherhash.txt...
1310
+ Uploaded test-name (TIMINGS)
1311
+ Published test-name (TIMINGS)
1312
+ test-name.test-sub-domain.workers.dev"
1313
+ `);
1314
+ expect(std.err).toMatchInlineSnapshot(`""`);
1315
+ });
1316
+
1317
+ it("should not try to expire uploaded assets that are already set to expire", async () => {
1318
+ const assets = [
1319
+ {
1320
+ filePath: "assets/file-1.txt",
1321
+ content: "Content of file-1",
1322
+ },
1323
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1324
+ ];
1325
+ const kvNamespace = {
1326
+ title: "__test-name-workers_sites_assets",
1327
+ id: "__test-name-workers_sites_assets-id",
1328
+ };
1329
+ writeWranglerToml({
1330
+ main: "./index.js",
1331
+ site: {
1332
+ bucket: "assets",
1333
+ },
1334
+ });
1335
+ writeWorkerSource();
1336
+ writeAssets(assets);
1337
+ mockUploadWorkerRequest();
1338
+ mockSubDomainRequest();
1339
+ mockListKVNamespacesRequest(kvNamespace);
1340
+ // These return with an expiration added on each of them
1341
+ mockKeyListRequest(kvNamespace.id, [
1342
+ // Put file-1 in the KV namespace, with an expiration
1343
+ { name: "assets/file-1.2ca234f380.txt", expiration: 10000 },
1344
+ // As well as a couple from a previous upload
1345
+ // This one's set to expire so it won't be uploaded back
1346
+ { name: "assets/file-3.somehash.txt", expiration: 10000 },
1347
+ // This one will be sent back with an expiration value
1348
+ { name: "assets/file-4.anotherhash.txt" },
1349
+ ]);
1350
+
1351
+ setMockFetchKVGetValue(
1352
+ "some-account-id",
1353
+ "__test-name-workers_sites_assets-id",
1354
+ "assets/file-4.anotherhash.txt",
1355
+ Buffer.from("Content of file-4", "utf8").toString("base64")
1356
+ );
1357
+
1358
+ mockUploadAssetsToKVRequest(kvNamespace.id, [
1359
+ // so it'll re-upload file-1 because it's set to expire
1360
+ // and file-2 because it hasn't been uploaded yet
1361
+ ...assets,
1362
+ // and it'll expire file-4 since it's just not included anymore
1363
+ {
1364
+ filePath: "assets/file-4.txt",
1365
+ content: "Content of file-4",
1366
+ // expect to expire this asset 300 seconds from now
1367
+ expiration_ttl: 300,
1368
+ },
1369
+ ]);
1370
+
1371
+ await runWrangler("publish");
1372
+
1373
+ expect(std.out).toMatchInlineSnapshot(`
1374
+ "reading assets/file-1.txt...
1375
+ uploading as assets/file-1.2ca234f380.txt...
1376
+ reading assets/file-2.txt...
1377
+ uploading as assets/file-2.5938485188.txt...
1378
+ expiring unused assets/file-4.anotherhash.txt...
1379
+ Uploaded test-name (TIMINGS)
1380
+ Published test-name (TIMINGS)
1381
+ test-name.test-sub-domain.workers.dev"
1382
+ `);
1383
+ expect(std.err).toMatchInlineSnapshot(`""`);
1384
+ });
1385
+ });
1386
+ });
1387
+
1388
+ describe("workers_dev setting", () => {
1389
+ it("should publish to a workers.dev domain if workers_dev is undefined", async () => {
1390
+ writeWranglerToml();
1391
+ writeWorkerSource();
1392
+ mockUploadWorkerRequest();
1393
+ mockSubDomainRequest();
1394
+
1395
+ await runWrangler("publish ./index");
1396
+
1397
+ expect(std.out).toMatchInlineSnapshot(`
1398
+ "Uploaded test-name (TIMINGS)
1399
+ Published test-name (TIMINGS)
1400
+ test-name.test-sub-domain.workers.dev"
1401
+ `);
1402
+ expect(std.err).toMatchInlineSnapshot(`""`);
1403
+ });
1404
+
1405
+ it("should publish to the workers.dev domain if workers_dev is `true`", async () => {
1406
+ writeWranglerToml({
1407
+ workers_dev: true,
1408
+ });
1409
+ writeWorkerSource();
1410
+ mockUploadWorkerRequest();
1411
+ mockSubDomainRequest();
1412
+
1413
+ await runWrangler("publish ./index");
1414
+
1415
+ expect(std.out).toMatchInlineSnapshot(`
1416
+ "Uploaded test-name (TIMINGS)
1417
+ Published test-name (TIMINGS)
1418
+ test-name.test-sub-domain.workers.dev"
1419
+ `);
1420
+ expect(std.err).toMatchInlineSnapshot(`""`);
1421
+ });
1422
+
1423
+ it("should disable the workers.dev domain if workers_dev is `false`", async () => {
1424
+ writeWranglerToml({
1425
+ workers_dev: false,
1426
+ });
1427
+ writeWorkerSource();
1428
+ mockUploadWorkerRequest();
1429
+ mockUpdateWorkerRequest({ enabled: false });
1430
+
1431
+ await runWrangler("publish ./index");
1432
+
1433
+ expect(std.out).toMatchInlineSnapshot(`
1434
+ "Uploaded test-name (TIMINGS)
1435
+ No publish targets for test-name (TIMINGS)"
1436
+ `);
1437
+ expect(std.err).toMatchInlineSnapshot(`""`);
1438
+ });
1439
+
1440
+ it("should disable the workers.dev domain if workers_dev is undefined but overwritten to `false` in environment", async () => {
1441
+ writeWranglerToml({
1442
+ env: {
1443
+ dev: {
1444
+ workers_dev: false,
1445
+ },
1446
+ },
1447
+ });
1448
+ writeWorkerSource();
1449
+ mockUploadWorkerRequest({
1450
+ env: "dev",
1451
+ });
1452
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
1453
+
1454
+ await runWrangler("publish ./index --env dev --legacy-env false");
1455
+
1456
+ expect(std.out).toMatchInlineSnapshot(`
1457
+ "Uploaded test-name (dev) (TIMINGS)
1458
+ No publish targets for test-name (dev) (TIMINGS)"
1459
+ `);
1460
+ expect(std.err).toMatchInlineSnapshot(`""`);
1461
+ });
1462
+
1463
+ it("should disable the workers.dev domain if workers_dev is `true` but overwritten to `false` in environment", async () => {
1464
+ writeWranglerToml({
1465
+ workers_dev: true,
1466
+ env: {
1467
+ dev: {
1468
+ workers_dev: false,
1469
+ },
1470
+ },
1471
+ });
1472
+ writeWorkerSource();
1473
+ mockUploadWorkerRequest({
1474
+ env: "dev",
1475
+ });
1476
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
1477
+
1478
+ await runWrangler("publish ./index --env dev --legacy-env false");
1479
+
1480
+ expect(std.out).toMatchInlineSnapshot(`
1481
+ "Uploaded test-name (dev) (TIMINGS)
1482
+ No publish targets for test-name (dev) (TIMINGS)"
1483
+ `);
1484
+ expect(std.err).toMatchInlineSnapshot(`""`);
1485
+ });
1486
+
1487
+ it("should publish to a workers.dev domain if workers_dev is undefined but overwritten to `true` in environment", async () => {
1488
+ writeWranglerToml({
1489
+ env: {
1490
+ dev: {
1491
+ workers_dev: true,
1492
+ },
1493
+ },
1494
+ });
1495
+ writeWorkerSource();
1496
+ mockUploadWorkerRequest({
1497
+ env: "dev",
1498
+ });
1499
+ mockSubDomainRequest();
1500
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1501
+
1502
+ await runWrangler("publish ./index --env dev --legacy-env false");
1503
+
1504
+ expect(std.out).toMatchInlineSnapshot(`
1505
+ "Uploaded test-name (dev) (TIMINGS)
1506
+ Published test-name (dev) (TIMINGS)
1507
+ dev.test-name.test-sub-domain.workers.dev"
1508
+ `);
1509
+ expect(std.err).toMatchInlineSnapshot(`""`);
1510
+ });
1511
+
1512
+ it("should publish to a workers.dev domain if workers_dev is `false` but overwritten to `true` in environment", async () => {
1513
+ writeWranglerToml({
1514
+ workers_dev: false,
1515
+ env: {
1516
+ dev: {
1517
+ workers_dev: true,
1518
+ },
1519
+ },
1520
+ });
1521
+ writeWorkerSource();
1522
+ mockUploadWorkerRequest({
1523
+ env: "dev",
1524
+ });
1525
+ mockSubDomainRequest();
1526
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1527
+
1528
+ await runWrangler("publish ./index --env dev --legacy-env false");
1529
+
1530
+ expect(std.out).toMatchInlineSnapshot(`
1531
+ "Uploaded test-name (dev) (TIMINGS)
1532
+ Published test-name (dev) (TIMINGS)
1533
+ dev.test-name.test-sub-domain.workers.dev"
1534
+ `);
1535
+ expect(std.err).toMatchInlineSnapshot(`""`);
1536
+ });
1537
+
1538
+ it("should use the global compatibility_date and compatibility_flags if they are not overwritten by the environment", async () => {
1539
+ writeWranglerToml({
1540
+ compatibility_date: "2022-01-12",
1541
+ compatibility_flags: ["no_global_navigator"],
1542
+ env: {
1543
+ dev: {},
1544
+ },
1545
+ });
1546
+ writeWorkerSource();
1547
+ mockUploadWorkerRequest({
1548
+ env: "dev",
1549
+ expectedCompatibilityDate: "2022-01-12",
1550
+ expectedCompatibilityFlags: ["no_global_navigator"],
1551
+ });
1552
+ mockSubDomainRequest();
1553
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1554
+
1555
+ await runWrangler("publish ./index --env dev --legacy-env false");
1556
+
1557
+ expect(std.out).toMatchInlineSnapshot(`
1558
+ "Uploaded test-name (dev) (TIMINGS)
1559
+ Published test-name (dev) (TIMINGS)
1560
+ dev.test-name.test-sub-domain.workers.dev"
1561
+ `);
1562
+ expect(std.err).toMatchInlineSnapshot(`""`);
1563
+ });
1564
+
1565
+ it("should use the environment specific compatibility_date and compatibility_flags", async () => {
1566
+ writeWranglerToml({
1567
+ compatibility_date: "2022-01-12",
1568
+ compatibility_flags: ["no_global_navigator"],
1569
+ env: {
1570
+ dev: {
1571
+ compatibility_date: "2022-01-13",
1572
+ compatibility_flags: ["global_navigator"],
1573
+ },
1574
+ },
1575
+ });
1576
+ writeWorkerSource();
1577
+ mockUploadWorkerRequest({
1578
+ env: "dev",
1579
+ expectedCompatibilityDate: "2022-01-13",
1580
+ expectedCompatibilityFlags: ["global_navigator"],
1581
+ });
1582
+ mockSubDomainRequest();
1583
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1584
+
1585
+ await runWrangler("publish ./index --env dev --legacy-env false");
1586
+
1587
+ expect(std.out).toMatchInlineSnapshot(`
1588
+ "Uploaded test-name (dev) (TIMINGS)
1589
+ Published test-name (dev) (TIMINGS)
1590
+ dev.test-name.test-sub-domain.workers.dev"
1591
+ `);
1592
+ expect(std.err).toMatchInlineSnapshot(`""`);
1593
+ });
1594
+
1595
+ it("should use the command line --compatibility-date and --compatibility-flags if they are specified", async () => {
1596
+ writeWranglerToml({
1597
+ compatibility_date: "2022-01-12",
1598
+ compatibility_flags: ["no_global_navigator"],
1599
+ env: {
1600
+ dev: {
1601
+ compatibility_date: "2022-01-13",
1602
+ compatibility_flags: ["global_navigator"],
1603
+ },
1604
+ },
1605
+ });
1606
+ writeWorkerSource();
1607
+ mockUploadWorkerRequest({
1608
+ env: "dev",
1609
+ expectedCompatibilityDate: "2022-01-14",
1610
+ expectedCompatibilityFlags: ["url_standard"],
1611
+ });
1612
+ mockSubDomainRequest();
1613
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1614
+
1615
+ await runWrangler(
1616
+ "publish ./index --env dev --legacy-env false --compatibility-date 2022-01-14 --compatibility-flags url_standard"
1617
+ );
1618
+
1619
+ expect(std.out).toMatchInlineSnapshot(`
1620
+ "Uploaded test-name (dev) (TIMINGS)
1621
+ Published test-name (dev) (TIMINGS)
1622
+ dev.test-name.test-sub-domain.workers.dev"
1623
+ `);
1624
+ expect(std.err).toMatchInlineSnapshot(`""`);
1625
+ });
1626
+
1627
+ it("should enable the workers.dev domain if workers_dev is undefined and subdomain is not already available", async () => {
1628
+ writeWranglerToml();
1629
+ writeWorkerSource();
1630
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1631
+ mockSubDomainRequest();
1632
+ mockUpdateWorkerRequest({ enabled: true });
1633
+
1634
+ await runWrangler("publish ./index");
1635
+
1636
+ expect(std.out).toMatchInlineSnapshot(`
1637
+ "Uploaded test-name (TIMINGS)
1638
+ Published test-name (TIMINGS)
1639
+ test-name.test-sub-domain.workers.dev"
1640
+ `);
1641
+ expect(std.err).toMatchInlineSnapshot(`""`);
1642
+ });
1643
+
1644
+ it("should enable the workers.dev domain if workers_dev is true and subdomain is not already available", async () => {
1645
+ writeWranglerToml({ workers_dev: true });
1646
+ writeWorkerSource();
1647
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1648
+ mockSubDomainRequest();
1649
+ mockUpdateWorkerRequest({ enabled: true });
1650
+
1651
+ await runWrangler("publish ./index");
1652
+
1653
+ expect(std.out).toMatchInlineSnapshot(`
1654
+ "Uploaded test-name (TIMINGS)
1655
+ Published test-name (TIMINGS)
1656
+ test-name.test-sub-domain.workers.dev"
993
1657
  `);
1658
+ expect(std.err).toMatchInlineSnapshot(`""`);
1659
+ });
1660
+
1661
+ it("should error politely when publishing to workers_dev when there is no workers.dev subdomain", async () => {
1662
+ writeWranglerToml({
1663
+ workers_dev: true,
1664
+ });
1665
+ writeWorkerSource();
1666
+ mockUploadWorkerRequest();
1667
+ mockSubDomainRequest("does-not-exist", false);
1668
+
1669
+ await expect(runWrangler("publish ./index")).rejects
1670
+ .toThrowErrorMatchingInlineSnapshot(`
1671
+ "Error: You need to register a workers.dev subdomain before publishing to workers.dev
1672
+ You can either publish your worker to one or more routes by specifying them in wrangler.toml, or register a workers.dev subdomain here:
1673
+ https://dash.cloudflare.com/some-account-id/workers/onboarding"
1674
+ `);
994
1675
  });
995
1676
  });
996
1677
 
997
1678
  describe("custom builds", () => {
1679
+ beforeEach(() => {
1680
+ // @ts-expect-error disable the mock we'd setup earlier
1681
+ // or else custom builds will timeout immediately
1682
+ global.setTimeout.mockRestore();
1683
+ });
998
1684
  it("should run a custom build before publishing", async () => {
999
1685
  writeWranglerToml({
1000
1686
  build: {
@@ -1009,16 +1695,10 @@ export default{
1009
1695
 
1010
1696
  await runWrangler("publish index.js");
1011
1697
  expect(std.out).toMatchInlineSnapshot(`
1012
- "running:
1013
- node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\"
1014
- Uploaded
1015
- test-name
1016
- (TIMINGS)
1017
- Deployed
1018
- test-name
1019
- (TIMINGS)
1020
-
1021
- test-name.test-sub-domain.workers.dev"
1698
+ "running: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\"
1699
+ Uploaded test-name (TIMINGS)
1700
+ Published test-name (TIMINGS)
1701
+ test-name.test-sub-domain.workers.dev"
1022
1702
  `);
1023
1703
  expect(std.err).toMatchInlineSnapshot(`""`);
1024
1704
  expect(std.warn).toMatchInlineSnapshot(`""`);
@@ -1039,67 +1719,677 @@ export default{
1039
1719
 
1040
1720
  await runWrangler("publish index.js");
1041
1721
  expect(std.out).toMatchInlineSnapshot(`
1042
- "running:
1043
- echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js
1044
- Uploaded
1045
- test-name
1046
- (TIMINGS)
1047
- Deployed
1048
- test-name
1049
- (TIMINGS)
1050
-
1051
- test-name.test-sub-domain.workers.dev"
1722
+ "running: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js
1723
+ Uploaded test-name (TIMINGS)
1724
+ Published test-name (TIMINGS)
1725
+ test-name.test-sub-domain.workers.dev"
1052
1726
  `);
1053
1727
  expect(std.err).toMatchInlineSnapshot(`""`);
1054
1728
  expect(std.warn).toMatchInlineSnapshot(`""`);
1055
1729
  });
1056
1730
  }
1057
- });
1058
- });
1059
-
1060
- /** Write a mock wrangler.toml file to disk. */
1061
- function writeWranglerToml(config: Omit<Config, "env"> = {}) {
1062
- // We Omit `env` from config because TOML.stringify() appears to
1063
- // have a weird type signature that appears to fail. We'll revisit this
1064
- // when we write tests for publishing environments
1065
- fs.writeFileSync(
1066
- "./wrangler.toml",
1067
- TOML.stringify({
1068
- compatibility_date: "2022-01-12",
1069
- name: "test-name",
1070
- ...config,
1071
- }),
1072
-
1073
- "utf-8"
1074
- );
1075
- }
1076
1731
 
1077
- /** Write a mock Worker script to disk. */
1078
- function writeWorkerSource({
1079
- basePath = ".",
1080
- format = "js",
1081
- type = "esm",
1082
- }: {
1083
- basePath?: string;
1084
- format?: "js" | "ts" | "jsx" | "tsx" | "mjs";
1085
- type?: "esm" | "sw";
1086
- } = {}) {
1087
- if (basePath !== ".") {
1088
- fs.mkdirSync(basePath, { recursive: true });
1089
- }
1090
- fs.writeFileSync(
1091
- `${basePath}/index.${format}`,
1092
- type === "esm"
1093
- ? `import { foo } from "./another";
1094
- export default {
1095
- async fetch(request) {
1096
- return new Response('Hello' + foo);
1732
+ it("should throw an error if the entry doesn't exist after the build finishes", async () => {
1733
+ writeWranglerToml({
1734
+ main: "index.js",
1735
+ build: {
1736
+ command: `node -e "console.log('custom build');"`,
1097
1737
  },
1098
- };`
1099
- : `import { foo } from "./another";
1100
- addEventListener('fetch', event => {
1101
- event.respondWith(new Response('Hello' + foo));
1102
- })`
1738
+ });
1739
+
1740
+ await expect(
1741
+ runWrangler("publish index.js")
1742
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1743
+ `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
1744
+ );
1745
+ expect(std.out).toMatchInlineSnapshot(
1746
+ `"running: node -e \\"console.log('custom build');\\""`
1747
+ );
1748
+ expect(std.err).toMatchInlineSnapshot(`
1749
+ "Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
1750
+
1751
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1752
+ `);
1753
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1754
+ });
1755
+ });
1756
+
1757
+ describe("[wasm_modules]", () => {
1758
+ it("should be able to define wasm modules for service-worker format workers", async () => {
1759
+ writeWranglerToml({
1760
+ wasm_modules: {
1761
+ TESTWASMNAME: "./path/to/test.wasm",
1762
+ },
1763
+ });
1764
+ writeWorkerSource({ type: "sw" });
1765
+ fs.mkdirSync("./path/to", { recursive: true });
1766
+ fs.writeFileSync("./path/to/test.wasm", "SOME WASM CONTENT");
1767
+ mockUploadWorkerRequest({
1768
+ expectedType: "sw",
1769
+ expectedModules: { TESTWASMNAME: "SOME WASM CONTENT" },
1770
+ expectedBindings: [
1771
+ { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1772
+ ],
1773
+ });
1774
+ mockSubDomainRequest();
1775
+ await runWrangler("publish index.js");
1776
+ expect(std.out).toMatchInlineSnapshot(`
1777
+ "Uploaded test-name (TIMINGS)
1778
+ Published test-name (TIMINGS)
1779
+ test-name.test-sub-domain.workers.dev"
1780
+ `);
1781
+ expect(std.err).toMatchInlineSnapshot(`""`);
1782
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1783
+ });
1784
+
1785
+ it("should error when defining wasm modules for modules format workers", async () => {
1786
+ writeWranglerToml({
1787
+ wasm_modules: {
1788
+ TESTWASMNAME: "./path/to/test.wasm",
1789
+ },
1790
+ });
1791
+ writeWorkerSource({ type: "esm" });
1792
+ fs.mkdirSync("./path/to", { recursive: true });
1793
+ fs.writeFileSync("./path/to/test.wasm", "SOME WASM CONTENT");
1794
+
1795
+ await expect(
1796
+ runWrangler("publish index.js")
1797
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1798
+ `"You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"`
1799
+ );
1800
+ expect(std.out).toMatchInlineSnapshot(`""`);
1801
+ expect(std.err).toMatchInlineSnapshot(`
1802
+ "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code
1803
+
1804
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1805
+ `);
1806
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1807
+ });
1808
+
1809
+ it("should resolve wasm modules relative to the wrangler.toml file", async () => {
1810
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
1811
+ fs.writeFileSync(
1812
+ "./path/to/wrangler.toml",
1813
+ TOML.stringify({
1814
+ compatibility_date: "2022-01-12",
1815
+ name: "test-name",
1816
+ wasm_modules: {
1817
+ TESTWASMNAME: "./and/the/path/to/test.wasm",
1818
+ },
1819
+ }),
1820
+
1821
+ "utf-8"
1822
+ );
1823
+
1824
+ writeWorkerSource({ type: "sw" });
1825
+ fs.writeFileSync(
1826
+ "./path/to/and/the/path/to/test.wasm",
1827
+ "SOME WASM CONTENT"
1828
+ );
1829
+ mockUploadWorkerRequest({
1830
+ expectedType: "sw",
1831
+ expectedModules: { TESTWASMNAME: "SOME WASM CONTENT" },
1832
+ expectedBindings: [
1833
+ { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1834
+ ],
1835
+ expectedCompatibilityDate: "2022-01-12",
1836
+ });
1837
+ mockSubDomainRequest();
1838
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
1839
+ expect(std.out).toMatchInlineSnapshot(`
1840
+ "Uploaded test-name (TIMINGS)
1841
+ Published test-name (TIMINGS)
1842
+ test-name.test-sub-domain.workers.dev"
1843
+ `);
1844
+ expect(std.err).toMatchInlineSnapshot(`""`);
1845
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1846
+ });
1847
+
1848
+ it("should be able to import .wasm modules from service-worker format workers", async () => {
1849
+ writeWranglerToml();
1850
+ fs.writeFileSync("./index.js", "import TESTWASMNAME from './test.wasm';");
1851
+ fs.writeFileSync("./test.wasm", "SOME WASM CONTENT");
1852
+ mockUploadWorkerRequest({
1853
+ expectedType: "sw",
1854
+ expectedModules: {
1855
+ __94b240d0d692281e6467aa42043986e5c7eea034_test_wasm:
1856
+ "SOME WASM CONTENT",
1857
+ },
1858
+ expectedBindings: [
1859
+ {
1860
+ name: "__94b240d0d692281e6467aa42043986e5c7eea034_test_wasm",
1861
+ part: "__94b240d0d692281e6467aa42043986e5c7eea034_test_wasm",
1862
+ type: "wasm_module",
1863
+ },
1864
+ ],
1865
+ });
1866
+ mockSubDomainRequest();
1867
+ await runWrangler("publish index.js");
1868
+ expect(std.out).toMatchInlineSnapshot(`
1869
+ "Uploaded test-name (TIMINGS)
1870
+ Published test-name (TIMINGS)
1871
+ test-name.test-sub-domain.workers.dev"
1872
+ `);
1873
+ expect(std.err).toMatchInlineSnapshot(`""`);
1874
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1875
+ });
1876
+ });
1877
+
1878
+ describe("[text_blobs]", () => {
1879
+ it("should be able to define text blobs for service-worker format workers", async () => {
1880
+ writeWranglerToml({
1881
+ text_blobs: {
1882
+ TESTTEXTBLOBNAME: "./path/to/text.file",
1883
+ },
1884
+ });
1885
+ writeWorkerSource({ type: "sw" });
1886
+ fs.mkdirSync("./path/to", { recursive: true });
1887
+ fs.writeFileSync("./path/to/text.file", "SOME TEXT CONTENT");
1888
+ mockUploadWorkerRequest({
1889
+ expectedType: "sw",
1890
+ expectedModules: { TESTTEXTBLOBNAME: "SOME TEXT CONTENT" },
1891
+ expectedBindings: [
1892
+ {
1893
+ name: "TESTTEXTBLOBNAME",
1894
+ part: "TESTTEXTBLOBNAME",
1895
+ type: "text_blob",
1896
+ },
1897
+ ],
1898
+ });
1899
+ mockSubDomainRequest();
1900
+ await runWrangler("publish index.js");
1901
+ expect(std.out).toMatchInlineSnapshot(`
1902
+ "Uploaded test-name (TIMINGS)
1903
+ Published test-name (TIMINGS)
1904
+ test-name.test-sub-domain.workers.dev"
1905
+ `);
1906
+ expect(std.err).toMatchInlineSnapshot(`""`);
1907
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1908
+ });
1909
+
1910
+ it("should error when defining text blobs for modules format workers", async () => {
1911
+ writeWranglerToml({
1912
+ text_blobs: {
1913
+ TESTTEXTBLOBNAME: "./path/to/text.file",
1914
+ },
1915
+ });
1916
+ writeWorkerSource({ type: "esm" });
1917
+ fs.mkdirSync("./path/to", { recursive: true });
1918
+ fs.writeFileSync("./path/to/text.file", "SOME TEXT CONTENT");
1919
+
1920
+ await expect(
1921
+ runWrangler("publish index.js")
1922
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1923
+ `"You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[build.upload.rules]\` in your wrangler.toml"`
1924
+ );
1925
+ expect(std.out).toMatchInlineSnapshot(`""`);
1926
+ expect(std.err).toMatchInlineSnapshot(`
1927
+ "You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[build.upload.rules]\` in your wrangler.toml
1928
+
1929
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1930
+ `);
1931
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1932
+ });
1933
+
1934
+ it("should resolve text blobs relative to the wrangler.toml file", async () => {
1935
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
1936
+ fs.writeFileSync(
1937
+ "./path/to/wrangler.toml",
1938
+ TOML.stringify({
1939
+ compatibility_date: "2022-01-12",
1940
+ name: "test-name",
1941
+ text_blobs: {
1942
+ TESTTEXTBLOBNAME: "./and/the/path/to/text.file",
1943
+ },
1944
+ }),
1945
+
1946
+ "utf-8"
1947
+ );
1948
+
1949
+ writeWorkerSource({ type: "sw" });
1950
+ fs.writeFileSync(
1951
+ "./path/to/and/the/path/to/text.file",
1952
+ "SOME TEXT CONTENT"
1953
+ );
1954
+ mockUploadWorkerRequest({
1955
+ expectedType: "sw",
1956
+ expectedModules: { TESTTEXTBLOBNAME: "SOME TEXT CONTENT" },
1957
+ expectedBindings: [
1958
+ {
1959
+ name: "TESTTEXTBLOBNAME",
1960
+ part: "TESTTEXTBLOBNAME",
1961
+ type: "text_blob",
1962
+ },
1963
+ ],
1964
+ expectedCompatibilityDate: "2022-01-12",
1965
+ });
1966
+ mockSubDomainRequest();
1967
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
1968
+ expect(std.out).toMatchInlineSnapshot(`
1969
+ "Uploaded test-name (TIMINGS)
1970
+ Published test-name (TIMINGS)
1971
+ test-name.test-sub-domain.workers.dev"
1972
+ `);
1973
+ expect(std.err).toMatchInlineSnapshot(`""`);
1974
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1975
+ });
1976
+ });
1977
+
1978
+ describe("vars bindings", () => {
1979
+ it("should support json bindings", async () => {
1980
+ writeWranglerToml({
1981
+ vars: {
1982
+ text: "plain ol' string",
1983
+ count: 1,
1984
+ complex: { enabled: true, id: 123 },
1985
+ },
1986
+ });
1987
+ writeWorkerSource();
1988
+ mockSubDomainRequest();
1989
+ mockUploadWorkerRequest({
1990
+ expectedBindings: [
1991
+ { name: "text", type: "plain_text", text: "plain ol' string" },
1992
+ { name: "count", type: "json", json: 1 },
1993
+ {
1994
+ name: "complex",
1995
+ type: "json",
1996
+ json: { enabled: true, id: 123 },
1997
+ },
1998
+ ],
1999
+ });
2000
+
2001
+ await runWrangler("publish index.js");
2002
+ expect(std.out).toMatchInlineSnapshot(`
2003
+ "Uploaded test-name (TIMINGS)
2004
+ Published test-name (TIMINGS)
2005
+ test-name.test-sub-domain.workers.dev"
2006
+ `);
2007
+ expect(std.err).toMatchInlineSnapshot(`""`);
2008
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2009
+ });
2010
+ });
2011
+
2012
+ describe("r2 bucket bindings", () => {
2013
+ it("should support r2 bucket bindings", async () => {
2014
+ writeWranglerToml({
2015
+ r2_buckets: [{ binding: "FOO", bucket_name: "foo-bucket" }],
2016
+ });
2017
+ writeWorkerSource();
2018
+ mockSubDomainRequest();
2019
+ mockUploadWorkerRequest({
2020
+ expectedBindings: [
2021
+ { bucket_name: "foo-bucket", name: "FOO", type: "r2_bucket" },
2022
+ ],
2023
+ });
2024
+
2025
+ await runWrangler("publish index.js");
2026
+ expect(std.out).toMatchInlineSnapshot(`
2027
+ "Uploaded test-name (TIMINGS)
2028
+ Published test-name (TIMINGS)
2029
+ test-name.test-sub-domain.workers.dev"
2030
+ `);
2031
+ expect(std.err).toMatchInlineSnapshot(`""`);
2032
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2033
+ });
2034
+ });
2035
+
2036
+ describe("unsafe bindings", () => {
2037
+ it("should warn if using unsafe bindings", async () => {
2038
+ writeWranglerToml({
2039
+ unsafe: {
2040
+ bindings: [
2041
+ {
2042
+ name: "my-binding",
2043
+ type: "binding-type",
2044
+ param: "binding-param",
2045
+ },
2046
+ ],
2047
+ },
2048
+ });
2049
+ writeWorkerSource();
2050
+ mockSubDomainRequest();
2051
+ mockUploadWorkerRequest({
2052
+ expectedBindings: [
2053
+ {
2054
+ name: "my-binding",
2055
+ type: "binding-type",
2056
+ param: "binding-param",
2057
+ },
2058
+ ],
2059
+ });
2060
+
2061
+ await runWrangler("publish index.js");
2062
+ expect(std.out).toMatchInlineSnapshot(`
2063
+ "Uploaded test-name (TIMINGS)
2064
+ Published test-name (TIMINGS)
2065
+ test-name.test-sub-domain.workers.dev"
2066
+ `);
2067
+ expect(std.err).toMatchInlineSnapshot(`""`);
2068
+ expect(std.warn).toMatchInlineSnapshot(`
2069
+ "Processing wrangler.toml configuration:
2070
+ - \\"unsafe\\" fields are experimental and may change or break at any time."
2071
+ `);
2072
+ });
2073
+ it("should warn if using unsafe bindings already handled by wrangler", async () => {
2074
+ writeWranglerToml({
2075
+ unsafe: {
2076
+ bindings: [
2077
+ {
2078
+ name: "my-binding",
2079
+ type: "plain_text",
2080
+ text: "text",
2081
+ },
2082
+ ],
2083
+ },
2084
+ });
2085
+ writeWorkerSource();
2086
+ mockSubDomainRequest();
2087
+ mockUploadWorkerRequest({
2088
+ expectedBindings: [
2089
+ {
2090
+ name: "my-binding",
2091
+ type: "plain_text",
2092
+ text: "text",
2093
+ },
2094
+ ],
2095
+ });
2096
+
2097
+ await runWrangler("publish index.js");
2098
+ expect(std.out).toMatchInlineSnapshot(`
2099
+ "Uploaded test-name (TIMINGS)
2100
+ Published test-name (TIMINGS)
2101
+ test-name.test-sub-domain.workers.dev"
2102
+ `);
2103
+ expect(std.err).toMatchInlineSnapshot(`""`);
2104
+ expect(std.warn).toMatchInlineSnapshot(`
2105
+ "Processing wrangler.toml configuration:
2106
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
2107
+ - \\"unsafe.bindings[0]\\": {\\"name\\":\\"my-binding\\",\\"type\\":\\"plain_text\\",\\"text\\":\\"text\\"}
2108
+ - The binding type \\"plain_text\\" is directly supported by wrangler.
2109
+ Consider migrating this unsafe binding to a format for 'plain_text' bindings that is supported by wrangler for optimal support.
2110
+ For more details, see https://developers.cloudflare.com/workers/cli-wrangler/configuration"
2111
+ `);
2112
+ });
2113
+ });
2114
+
2115
+ describe("upload rules", () => {
2116
+ it("should be able to define rules for uploading non-js modules (sw)", async () => {
2117
+ writeWranglerToml({
2118
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2119
+ });
2120
+ fs.writeFileSync("./index.js", `import TEXT from './text.file';`);
2121
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2122
+ mockSubDomainRequest();
2123
+ mockUploadWorkerRequest({
2124
+ expectedType: "sw",
2125
+ expectedBindings: [
2126
+ {
2127
+ name: "__2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file",
2128
+ part: "__2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file",
2129
+ type: "text_blob",
2130
+ },
2131
+ ],
2132
+ expectedModules: {
2133
+ __2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0_text_file:
2134
+ "SOME TEXT CONTENT",
2135
+ },
2136
+ });
2137
+ await runWrangler("publish index.js");
2138
+ expect(std.out).toMatchInlineSnapshot(`
2139
+ "Uploaded test-name (TIMINGS)
2140
+ Published test-name (TIMINGS)
2141
+ test-name.test-sub-domain.workers.dev"
2142
+ `);
2143
+ expect(std.err).toMatchInlineSnapshot(`""`);
2144
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2145
+ });
2146
+
2147
+ it("should be able to define rules for uploading non-js modules (esm)", async () => {
2148
+ writeWranglerToml({
2149
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2150
+ });
2151
+ fs.writeFileSync(
2152
+ "./index.js",
2153
+ `import TEXT from './text.file'; export default {};`
2154
+ );
2155
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2156
+ mockSubDomainRequest();
2157
+ mockUploadWorkerRequest({
2158
+ expectedType: "esm",
2159
+ expectedBindings: [],
2160
+ expectedModules: {
2161
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2162
+ "SOME TEXT CONTENT",
2163
+ },
2164
+ });
2165
+ await runWrangler("publish index.js");
2166
+ expect(std.out).toMatchInlineSnapshot(`
2167
+ "Uploaded test-name (TIMINGS)
2168
+ Published test-name (TIMINGS)
2169
+ test-name.test-sub-domain.workers.dev"
2170
+ `);
2171
+ expect(std.err).toMatchInlineSnapshot(`""`);
2172
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2173
+ });
2174
+
2175
+ it("should log a deprecation warning when using `build.upload.rules`", async () => {
2176
+ writeWranglerToml({
2177
+ build: {
2178
+ upload: {
2179
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: true }],
2180
+ },
2181
+ },
2182
+ });
2183
+ fs.writeFileSync(
2184
+ "./index.js",
2185
+ `import TEXT from './text.file'; export default {};`
2186
+ );
2187
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2188
+ mockSubDomainRequest();
2189
+ mockUploadWorkerRequest({
2190
+ expectedType: "esm",
2191
+ expectedBindings: [],
2192
+ expectedModules: {
2193
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2194
+ "SOME TEXT CONTENT",
2195
+ },
2196
+ });
2197
+ await runWrangler("publish index.js");
2198
+ expect(std.out).toMatchInlineSnapshot(`
2199
+ "Uploaded test-name (TIMINGS)
2200
+ Published test-name (TIMINGS)
2201
+ test-name.test-sub-domain.workers.dev"
2202
+ `);
2203
+ expect(std.err).toMatchInlineSnapshot(`""`);
2204
+ expect(std.warn).toMatchInlineSnapshot(`
2205
+ "Processing wrangler.toml configuration:
2206
+ - DEPRECATION: The \`build.upload.rules\` config field is no longer used, the rules should be specified via the \`rules\` config field. Delete the \`build.upload\` field from the configuration file, and add this:
2207
+ \`\`\`
2208
+ [[rules]]
2209
+ type = \\"Text\\"
2210
+ globs = [ \\"**/*.file\\" ]
2211
+ fallthrough = true
2212
+ \`\`\`"
2213
+ `);
2214
+ });
2215
+
2216
+ it("should be able to use fallthrough:true for multiple rules", async () => {
2217
+ writeWranglerToml({
2218
+ rules: [
2219
+ { type: "Text", globs: ["**/*.file"], fallthrough: true },
2220
+ { type: "Text", globs: ["**/*.other"], fallthrough: true },
2221
+ ],
2222
+ });
2223
+ fs.writeFileSync(
2224
+ "./index.js",
2225
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2226
+ );
2227
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2228
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
2229
+ mockSubDomainRequest();
2230
+ mockUploadWorkerRequest({
2231
+ expectedType: "esm",
2232
+ expectedBindings: [],
2233
+ expectedModules: {
2234
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2235
+ "SOME TEXT CONTENT",
2236
+ "./16347a01366873ed80fe45115119de3c92ab8db0-other.other":
2237
+ "SOME OTHER TEXT CONTENT",
2238
+ },
2239
+ });
2240
+ await runWrangler("publish index.js");
2241
+ expect(std.out).toMatchInlineSnapshot(`
2242
+ "Uploaded test-name (TIMINGS)
2243
+ Published test-name (TIMINGS)
2244
+ test-name.test-sub-domain.workers.dev"
2245
+ `);
2246
+ expect(std.err).toMatchInlineSnapshot(`""`);
2247
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2248
+ });
2249
+
2250
+ it("should be able to use fallthrough:false for multiple rules", async () => {
2251
+ writeWranglerToml({
2252
+ rules: [
2253
+ { type: "Text", globs: ["**/*.file"], fallthrough: false },
2254
+ { type: "Text", globs: ["**/*.other"] },
2255
+ ],
2256
+ });
2257
+ fs.writeFileSync(
2258
+ "./index.js",
2259
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2260
+ );
2261
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2262
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
2263
+
2264
+ // We throw an error when we come across a file that matched a rule
2265
+ // but was skipped because of fallthrough = false
2266
+ let err: Error | undefined;
2267
+ try {
2268
+ await runWrangler("publish index.js");
2269
+ } catch (e) {
2270
+ err = e as Error;
2271
+ }
2272
+ expect(err?.message).toMatch(
2273
+ `The file ./other.other matched a module rule in your configuration ({"type":"Text","globs":["**/*.other"]}), but was ignored because a previous rule with the same type was not marked as \`fallthrough = true\`.`
2274
+ );
2275
+ });
2276
+
2277
+ it("should warn when multiple rules for the same type do not have fallback defined", async () => {
2278
+ writeWranglerToml({
2279
+ rules: [
2280
+ { type: "Text", globs: ["**/*.file"] },
2281
+ { type: "Text", globs: ["**/*.other"] },
2282
+ ],
2283
+ });
2284
+ fs.writeFileSync(
2285
+ "./index.js",
2286
+ `import TEXT from './text.file'; import OTHER from './other.other'; export default {};`
2287
+ );
2288
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2289
+ fs.writeFileSync("./other.other", "SOME OTHER TEXT CONTENT");
2290
+
2291
+ // We throw an error when we come across a file that matched a rule
2292
+ // but was skipped because of fallthrough = false
2293
+ let err: Error | undefined;
2294
+ try {
2295
+ await runWrangler("publish index.js");
2296
+ } catch (e) {
2297
+ err = e as Error;
2298
+ }
2299
+ expect(err?.message).toMatch(
2300
+ `The file ./other.other matched a module rule in your configuration ({"type":"Text","globs":["**/*.other"]}), but was ignored because a previous rule with the same type was not marked as \`fallthrough = true\`.`
2301
+ );
2302
+ // and the warnings because fallthrough was not explicitly set
2303
+ expect(std.warn).toMatchInlineSnapshot(`
2304
+ "The module rule at position 1 ({\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.other\\"]}) has the same type as a previous rule (at position 0, {\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.file\\"]}). This rule will be ignored. To the previous rule, add \`fallthrough = true\` to allow this one to also be used, or \`fallthrough = false\` to silence this warning.
2305
+ The default module rule {\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.txt\\",\\"**/*.html\\"]} has the same type as a previous rule (at position 0, {\\"type\\":\\"Text\\",\\"globs\\":[\\"**/*.file\\"]}). This rule will be ignored. To the previous rule, add \`fallthrough = true\` to allow the default one to also be used, or \`fallthrough = false\` to silence this warning."
2306
+ `);
2307
+ });
2308
+ });
2309
+
2310
+ describe("legacy module specifiers", () => {
2311
+ it("should work with legacy module specifiers, with a deprecation warning (1)", async () => {
2312
+ writeWranglerToml({
2313
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: false }],
2314
+ });
2315
+ fs.writeFileSync(
2316
+ "./index.js",
2317
+ `import TEXT from 'text.file'; export default {};`
2318
+ );
2319
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2320
+ mockSubDomainRequest();
2321
+ mockUploadWorkerRequest({
2322
+ expectedModules: {
2323
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2324
+ "SOME TEXT CONTENT",
2325
+ },
2326
+ });
2327
+ await runWrangler("publish index.js");
2328
+ expect(std.out).toMatchInlineSnapshot(`
2329
+ "Uploaded test-name (TIMINGS)
2330
+ Published test-name (TIMINGS)
2331
+ test-name.test-sub-domain.workers.dev"
2332
+ `);
2333
+ expect(std.err).toMatchInlineSnapshot(`""`);
2334
+ expect(std.warn).toMatchInlineSnapshot(
2335
+ `"Deprecation warning: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"text.file\\" with \\"./text.file\\";"`
2336
+ );
2337
+ });
2338
+ });
2339
+
2340
+ it("should work with legacy module specifiers, with a deprecation warning (2)", async () => {
2341
+ writeWranglerToml();
2342
+ fs.writeFileSync(
2343
+ "./index.js",
2344
+ `import WASM from 'index.wasm'; export default {};`
2345
+ );
2346
+ fs.writeFileSync("./index.wasm", "SOME WASM CONTENT");
2347
+ mockSubDomainRequest();
2348
+ mockUploadWorkerRequest({
2349
+ expectedModules: {
2350
+ "./94b240d0d692281e6467aa42043986e5c7eea034-index.wasm":
2351
+ "SOME WASM CONTENT",
2352
+ },
2353
+ });
2354
+ await runWrangler("publish index.js");
2355
+ expect(std.out).toMatchInlineSnapshot(`
2356
+ "Uploaded test-name (TIMINGS)
2357
+ Published test-name (TIMINGS)
2358
+ test-name.test-sub-domain.workers.dev"
2359
+ `);
2360
+ expect(std.err).toMatchInlineSnapshot(`""`);
2361
+ expect(std.warn).toMatchInlineSnapshot(
2362
+ `"Deprecation warning: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"index.wasm\\" with \\"./index.wasm\\";"`
2363
+ );
2364
+ });
2365
+ });
2366
+
2367
+ /** Write a mock Worker script to disk. */
2368
+ function writeWorkerSource({
2369
+ basePath = ".",
2370
+ format = "js",
2371
+ type = "esm",
2372
+ }: {
2373
+ basePath?: string;
2374
+ format?: "js" | "ts" | "jsx" | "tsx" | "mjs";
2375
+ type?: "esm" | "sw";
2376
+ } = {}) {
2377
+ if (basePath !== ".") {
2378
+ fs.mkdirSync(basePath, { recursive: true });
2379
+ }
2380
+ fs.writeFileSync(
2381
+ `${basePath}/index.${format}`,
2382
+ type === "esm"
2383
+ ? `import { foo } from "./another";
2384
+ export default {
2385
+ async fetch(request) {
2386
+ return new Response('Hello' + foo);
2387
+ },
2388
+ };`
2389
+ : `import { foo } from "./another";
2390
+ addEventListener('fetch', event => {
2391
+ event.respondWith(new Response('Hello' + foo));
2392
+ })`
1103
2393
  );
1104
2394
  fs.writeFileSync(`${basePath}/another.${format}`, `export const foo = 100;`);
1105
2395
  }
@@ -1119,31 +2409,41 @@ function mockUploadWorkerRequest({
1119
2409
  expectedType = "esm",
1120
2410
  expectedBindings,
1121
2411
  expectedModules = {},
2412
+ expectedCompatibilityDate,
2413
+ expectedCompatibilityFlags,
1122
2414
  env = undefined,
2415
+ legacyEnv = false,
1123
2416
  }: {
1124
2417
  available_on_subdomain?: boolean;
1125
2418
  expectedEntry?: string;
1126
2419
  expectedType?: "esm" | "sw";
1127
2420
  expectedBindings?: unknown;
1128
2421
  expectedModules?: Record<string, string>;
1129
- env?: string | undefined;
2422
+ expectedCompatibilityDate?: string;
2423
+ expectedCompatibilityFlags?: string[];
2424
+ env?: string;
2425
+ legacyEnv?: boolean;
1130
2426
  } = {}) {
1131
2427
  setMockResponse(
1132
- env
1133
- ? `/accounts/:accountId/workers/services/:scriptName/environments/:envName`
2428
+ env && !legacyEnv
2429
+ ? "/accounts/:accountId/workers/services/:scriptName/environments/:envName"
1134
2430
  : "/accounts/:accountId/workers/scripts/:scriptName",
1135
2431
  "PUT",
1136
- async ([_url, accountId, scriptName], { body }, queryParams) => {
2432
+ async ([_url, accountId, scriptName, envName], { body }, queryParams) => {
1137
2433
  expect(accountId).toEqual("some-account-id");
1138
- expect(scriptName).toEqual("test-name");
1139
- expect(queryParams.get("available_on_subdomains")).toEqual("true");
2434
+ expect(scriptName).toEqual(
2435
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2436
+ );
2437
+ if (!legacyEnv) {
2438
+ expect(envName).toEqual(env);
2439
+ }
2440
+ expect(queryParams.get("available_on_subdomain")).toEqual("true");
1140
2441
  const formBody = body as FormData;
1141
2442
  if (expectedEntry !== undefined) {
1142
2443
  expect(await (formBody.get("index.js") as File).text()).toMatch(
1143
2444
  expectedEntry
1144
2445
  );
1145
2446
  }
1146
-
1147
2447
  const metadata = JSON.parse(
1148
2448
  formBody.get("metadata") as string
1149
2449
  ) as WorkerMetadata;
@@ -1155,8 +2455,16 @@ function mockUploadWorkerRequest({
1155
2455
  if (expectedBindings !== undefined) {
1156
2456
  expect(metadata.bindings).toEqual(expectedBindings);
1157
2457
  }
2458
+ if (expectedCompatibilityDate !== undefined) {
2459
+ expect(metadata.compatibility_date).toEqual(expectedCompatibilityDate);
2460
+ }
2461
+ if (expectedCompatibilityFlags !== undefined) {
2462
+ expect(metadata.compatibility_flags).toEqual(
2463
+ expectedCompatibilityFlags
2464
+ );
2465
+ }
1158
2466
  for (const [name, content] of Object.entries(expectedModules)) {
1159
- expect(await (formBody.get(name) as File).text()).toMatch(content);
2467
+ expect(await (formBody.get(name) as File).text()).toEqual(content);
1160
2468
  }
1161
2469
 
1162
2470
  return { available_on_subdomain };
@@ -1165,10 +2473,84 @@ function mockUploadWorkerRequest({
1165
2473
  }
1166
2474
 
1167
2475
  /** Create a mock handler for the request to get the account's subdomain. */
1168
- function mockSubDomainRequest(subdomain = "test-sub-domain") {
1169
- setMockResponse("/accounts/:accountId/workers/subdomain", () => {
1170
- return { subdomain };
1171
- });
2476
+ function mockSubDomainRequest(
2477
+ subdomain = "test-sub-domain",
2478
+ registeredWorkersDev = true
2479
+ ) {
2480
+ if (registeredWorkersDev) {
2481
+ setMockResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2482
+ return { subdomain };
2483
+ });
2484
+ } else {
2485
+ setMockRawResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2486
+ return createFetchResult(null, false, [
2487
+ { code: 10007, message: "haven't registered workers.dev" },
2488
+ ]);
2489
+ });
2490
+ }
2491
+ }
2492
+
2493
+ /** Create a mock handler to toggle a <script>.<user>.workers.dev subdomain */
2494
+ function mockUpdateWorkerRequest({
2495
+ env,
2496
+ enabled,
2497
+ legacyEnv = false,
2498
+ }: {
2499
+ enabled: boolean;
2500
+ env?: string | undefined;
2501
+ legacyEnv?: boolean | undefined;
2502
+ }) {
2503
+ const requests = { count: 0 };
2504
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
2505
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
2506
+ setMockResponse(
2507
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/subdomain`,
2508
+ "POST",
2509
+ ([_url, accountId, scriptName, envName], { body }) => {
2510
+ expect(accountId).toEqual("some-account-id");
2511
+ expect(scriptName).toEqual(
2512
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2513
+ );
2514
+ if (!legacyEnv) {
2515
+ expect(envName).toEqual(env);
2516
+ }
2517
+ expect(JSON.parse(body as string)).toEqual({ enabled });
2518
+ return null;
2519
+ }
2520
+ );
2521
+ return requests;
2522
+ }
2523
+
2524
+ function mockPublishRoutesRequest({
2525
+ routes,
2526
+ env = undefined,
2527
+ legacyEnv = false,
2528
+ }: {
2529
+ routes: string[];
2530
+ env?: string | undefined;
2531
+ legacyEnv?: boolean | undefined;
2532
+ }) {
2533
+ const servicesOrScripts = env && !legacyEnv ? "services" : "scripts";
2534
+ const environment = env && !legacyEnv ? "/environments/:envName" : "";
2535
+
2536
+ setMockResponse(
2537
+ `/accounts/:accountId/workers/${servicesOrScripts}/:scriptName${environment}/routes`,
2538
+ "PUT",
2539
+ ([_url, accountId, scriptName, envName], { body }) => {
2540
+ expect(accountId).toEqual("some-account-id");
2541
+ expect(scriptName).toEqual(
2542
+ legacyEnv && env ? `test-name-${env}` : "test-name"
2543
+ );
2544
+ if (!legacyEnv) {
2545
+ expect(envName).toEqual(env);
2546
+ }
2547
+
2548
+ expect(JSON.parse(body as string)).toEqual(
2549
+ routes.map((pattern) => ({ pattern }))
2550
+ );
2551
+ return null;
2552
+ }
2553
+ );
1172
2554
  }
1173
2555
 
1174
2556
  /** Create a mock handler for the request to get a list of all KV namespaces. */
@@ -1186,7 +2568,12 @@ function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
1186
2568
  /** Create a mock handler for the request that tries to do a bulk upload of assets to a KV namespace. */
1187
2569
  function mockUploadAssetsToKVRequest(
1188
2570
  expectedNamespaceId: string,
1189
- assets: { filePath: string; content: string }[]
2571
+ assets: {
2572
+ filePath: string;
2573
+ content: string;
2574
+ expiration?: number;
2575
+ expiration_ttl?: number;
2576
+ }[]
1190
2577
  ) {
1191
2578
  setMockResponse(
1192
2579
  "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
@@ -1215,6 +2602,8 @@ function mockUploadAssetsToKVRequest(
1215
2602
  expect(Buffer.from(upload.value, "base64").toString()).toEqual(
1216
2603
  asset.content
1217
2604
  );
2605
+ expect(upload.expiration).toEqual(asset.expiration);
2606
+ expect(upload.expiration_ttl).toEqual(asset.expiration_ttl);
1218
2607
  }
1219
2608
  return null;
1220
2609
  }