wrangler 0.0.0-e2b7352 → 0.0.0-e2f9bb2

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 (86) hide show
  1. package/README.md +24 -13
  2. package/bin/wrangler.js +3 -0
  3. package/miniflare-dist/index.mjs +4828 -21
  4. package/package.json +29 -22
  5. package/pages/functions/buildPlugin.ts +92 -0
  6. package/pages/functions/buildWorker.ts +80 -4
  7. package/pages/functions/filepath-routing.test.ts +11 -0
  8. package/pages/functions/filepath-routing.ts +8 -0
  9. package/pages/functions/routes.ts +6 -1
  10. package/pages/functions/template-plugin.ts +146 -0
  11. package/pages/functions/template-worker.ts +21 -8
  12. package/src/__tests__/config-cache.test.ts +36 -0
  13. package/src/__tests__/configuration.test.ts +386 -81
  14. package/src/__tests__/dev.test.tsx +242 -21
  15. package/src/__tests__/guess-worker-format.test.ts +18 -1
  16. package/src/__tests__/helpers/mock-cfetch.ts +5 -1
  17. package/src/__tests__/helpers/mock-console.ts +20 -3
  18. package/src/__tests__/helpers/mock-dialogs.ts +24 -0
  19. package/src/__tests__/helpers/mock-http-server.ts +46 -0
  20. package/src/__tests__/helpers/mock-istty.ts +27 -0
  21. package/src/__tests__/helpers/mock-oauth-flow.ts +255 -0
  22. package/src/__tests__/helpers/run-in-tmp.ts +7 -0
  23. package/src/__tests__/helpers/write-worker-source.ts +31 -0
  24. package/src/__tests__/https-options.test.ts +5 -2
  25. package/src/__tests__/index.test.ts +25 -759
  26. package/src/__tests__/init.test.ts +1042 -0
  27. package/src/__tests__/jest.setup.ts +4 -4
  28. package/src/__tests__/kv.test.ts +130 -56
  29. package/src/__tests__/logger.test.ts +115 -0
  30. package/src/__tests__/pages.test.ts +290 -43
  31. package/src/__tests__/publish.test.ts +1699 -333
  32. package/src/__tests__/r2.test.ts +24 -8
  33. package/src/__tests__/route.test.ts +4 -4
  34. package/src/__tests__/secret.test.ts +55 -34
  35. package/src/__tests__/tail.test.ts +97 -45
  36. package/src/__tests__/user.test.ts +131 -0
  37. package/src/__tests__/whoami.test.tsx +14 -9
  38. package/src/bundle.ts +15 -1
  39. package/src/cfetch/internal.ts +0 -2
  40. package/src/cli.ts +5 -11
  41. package/src/config/README.md +1 -1
  42. package/src/config/config.ts +20 -4
  43. package/src/config/environment.ts +26 -3
  44. package/src/config/index.ts +2 -1
  45. package/src/config/validation-helpers.ts +26 -5
  46. package/src/config/validation.ts +233 -41
  47. package/src/config-cache.ts +45 -0
  48. package/src/create-worker-preview.ts +22 -13
  49. package/src/create-worker-upload-form.ts +32 -9
  50. package/src/dev/dev-vars.ts +36 -0
  51. package/src/dev/dev.tsx +60 -34
  52. package/src/dev/local.tsx +101 -21
  53. package/src/dev/remote.tsx +23 -13
  54. package/src/dev/use-esbuild.ts +19 -5
  55. package/src/dialogs.tsx +16 -6
  56. package/src/entry.ts +38 -11
  57. package/src/environment-variables.ts +3 -1
  58. package/src/errors.ts +11 -0
  59. package/src/https-options.ts +3 -2
  60. package/src/index.tsx +529 -303
  61. package/src/inspect.ts +17 -11
  62. package/src/logger.ts +66 -0
  63. package/src/miniflare-cli/index.ts +4 -0
  64. package/src/miniflare-cli/request-context.ts +40 -0
  65. package/src/module-collection.ts +7 -7
  66. package/src/open-in-browser.ts +5 -4
  67. package/src/package-manager.ts +9 -8
  68. package/src/pages.tsx +860 -55
  69. package/src/parse.ts +1 -1
  70. package/src/proxy.ts +25 -11
  71. package/src/publish.ts +260 -141
  72. package/src/sites.tsx +27 -14
  73. package/src/tail/index.ts +1 -1
  74. package/src/tail/printing.ts +13 -8
  75. package/src/update-check.ts +19 -0
  76. package/src/user.tsx +104 -38
  77. package/src/whoami.tsx +2 -1
  78. package/src/worker.ts +15 -6
  79. package/templates/gitignore +171 -0
  80. package/templates/static-asset-facade.js +1 -1
  81. package/wrangler-dist/cli.js +20948 -50169
  82. package/miniflare-dist/index.mjs.map +0 -7
  83. package/src/__tests__/logout.test.ts +0 -52
  84. package/src/__tests__/sentry.test.ts +0 -146
  85. package/src/reporting.ts +0 -131
  86. package/wrangler-dist/cli.js.map +0 -7
@@ -1,6 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import * as TOML from "@iarna/toml";
4
+ import { writeAuthConfigFile } from "../user";
4
5
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
5
6
  import {
6
7
  createFetchResult,
@@ -9,32 +10,264 @@ import {
9
10
  unsetAllMocks,
10
11
  unsetMockFetchKVGetValues,
11
12
  } from "./helpers/mock-cfetch";
12
- import { mockConsoleMethods } from "./helpers/mock-console";
13
+ import { mockConsoleMethods, normalizeSlashes } from "./helpers/mock-console";
14
+ import { useMockIsTTY } from "./helpers/mock-istty";
13
15
  import { mockKeyListRequest } from "./helpers/mock-kv";
16
+ import { mockOAuthFlow } from "./helpers/mock-oauth-flow";
14
17
  import { runInTempDir } from "./helpers/run-in-tmp";
15
18
  import { runWrangler } from "./helpers/run-wrangler";
19
+ import { writeWorkerSource } from "./helpers/write-worker-source";
16
20
  import writeWranglerToml from "./helpers/write-wrangler-toml";
21
+ import type { Config } from "../config";
17
22
  import type { WorkerMetadata } from "../create-worker-upload-form";
18
23
  import type { KVNamespaceInfo } from "../kv";
24
+ import type { CfWorkerInit } from "../worker";
19
25
  import type { FormData, File } from "undici";
20
26
 
21
27
  describe("publish", () => {
28
+ mockAccountId();
29
+ mockApiToken();
30
+ runInTempDir({ homedir: "./home" });
31
+ const { setIsTTY } = useMockIsTTY();
32
+ const std = mockConsoleMethods();
33
+ const {
34
+ mockOAuthServerCallback,
35
+ mockGrantAccessToken,
36
+ mockGrantAuthorization,
37
+ mockGetMemberships,
38
+ } = mockOAuthFlow();
39
+
22
40
  beforeEach(() => {
23
41
  // @ts-expect-error we're using a very simple setTimeout mock here
24
42
  jest.spyOn(global, "setTimeout").mockImplementation((fn, _period) => {
25
- fn();
43
+ setImmediate(fn);
26
44
  });
45
+ setIsTTY(true);
27
46
  });
28
- mockAccountId();
29
- mockApiToken();
30
- runInTempDir();
31
- const std = mockConsoleMethods();
32
47
 
33
48
  afterEach(() => {
34
49
  unsetAllMocks();
35
50
  unsetMockFetchKVGetValues();
36
51
  });
37
52
 
53
+ describe("authentication", () => {
54
+ mockApiToken({ apiToken: null });
55
+ beforeEach(() => {
56
+ // @ts-expect-error disable the mock we'd setup earlier
57
+ // or else our server won't bother listening for oauth requests
58
+ // and will timeout and fail
59
+ global.setTimeout.mockRestore();
60
+ });
61
+
62
+ it("drops a user into the login flow if they're unauthenticated", async () => {
63
+ writeWranglerToml();
64
+ writeWorkerSource();
65
+ mockSubDomainRequest();
66
+ mockUploadWorkerRequest();
67
+
68
+ mockOAuthServerCallback();
69
+ const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
70
+ mockGrantAuthorization({ respondWith: "success" });
71
+
72
+ await expect(runWrangler("publish index.js")).resolves.toBeUndefined();
73
+
74
+ expect(accessTokenRequest.actual.url).toEqual(
75
+ accessTokenRequest.expected.url
76
+ );
77
+
78
+ expect(std.out).toMatchInlineSnapshot(`
79
+ "Attempting to login via OAuth...
80
+ Successfully logged in.
81
+ Uploaded test-name (TIMINGS)
82
+ Published test-name (TIMINGS)
83
+ test-name.test-sub-domain.workers.dev"
84
+ `);
85
+ expect(std.warn).toMatchInlineSnapshot(`""`);
86
+ expect(std.err).toMatchInlineSnapshot(`""`);
87
+ });
88
+
89
+ it("warns a user when they're authenticated with an API token in wrangler config file", async () => {
90
+ writeWranglerToml();
91
+ writeWorkerSource();
92
+ mockSubDomainRequest();
93
+ mockUploadWorkerRequest();
94
+ writeAuthConfigFile({
95
+ api_token: "some-api-token",
96
+ });
97
+
98
+ const accessTokenRequest = mockGrantAccessToken({ respondWith: "ok" });
99
+ mockGrantAuthorization({ respondWith: "success" });
100
+
101
+ await expect(runWrangler("publish index.js")).resolves.toBeUndefined();
102
+
103
+ expect(accessTokenRequest.actual.url).toEqual(
104
+ accessTokenRequest.expected.url
105
+ );
106
+
107
+ expect(std.out).toMatchInlineSnapshot(`
108
+ "Attempting to login via OAuth...
109
+ Successfully logged in.
110
+ Uploaded test-name (TIMINGS)
111
+ Published test-name (TIMINGS)
112
+ test-name.test-sub-domain.workers.dev"
113
+ `);
114
+ expect(std.warn).toMatchInlineSnapshot(`
115
+ "▲ [WARNING] It looks like you have used Wrangler 1's \`config\` command to login with an API token.
116
+
117
+ This is no longer supported in the current version of Wrangler.
118
+ If you wish to authenticate via an API token then please set the \`CLOUDFLARE_API_TOKEN\`
119
+ environment variable.
120
+
121
+ "
122
+ `);
123
+ expect(std.err).toMatchInlineSnapshot(`""`);
124
+ });
125
+
126
+ describe("non-TTY", () => {
127
+ const ENV_COPY = process.env;
128
+
129
+ afterEach(() => {
130
+ process.env = ENV_COPY;
131
+ });
132
+
133
+ it("should not throw an error in non-TTY if 'CLOUDFLARE_API_TOKEN' & 'account_id' are in scope", async () => {
134
+ process.env = {
135
+ CLOUDFLARE_API_TOKEN: "123456789",
136
+ };
137
+ setIsTTY(false);
138
+ writeWranglerToml({
139
+ account_id: "some-account-id",
140
+ });
141
+ writeWorkerSource();
142
+ mockSubDomainRequest();
143
+ mockUploadWorkerRequest();
144
+ mockOAuthServerCallback();
145
+
146
+ await runWrangler("publish index.js");
147
+
148
+ expect(std.out).toMatchInlineSnapshot(`
149
+ "Uploaded test-name (TIMINGS)
150
+ Published test-name (TIMINGS)
151
+ test-name.test-sub-domain.workers.dev"
152
+ `);
153
+ expect(std.err).toMatchInlineSnapshot(`""`);
154
+ });
155
+
156
+ it("should not throw an error if 'CLOUDFLARE_ACCOUNT_ID' & 'CLOUDFLARE_API_TOKEN' are in scope", async () => {
157
+ process.env = {
158
+ CLOUDFLARE_API_TOKEN: "hunter2",
159
+ CLOUDFLARE_ACCOUNT_ID: "some-account-id",
160
+ };
161
+ setIsTTY(false);
162
+ writeWranglerToml();
163
+ writeWorkerSource();
164
+ mockSubDomainRequest();
165
+ mockUploadWorkerRequest();
166
+ mockOAuthServerCallback();
167
+ mockGetMemberships({
168
+ success: true,
169
+ result: [],
170
+ });
171
+
172
+ await runWrangler("publish index.js");
173
+
174
+ expect(std.out).toMatchInlineSnapshot(`
175
+ "Uploaded test-name (TIMINGS)
176
+ Published test-name (TIMINGS)
177
+ test-name.test-sub-domain.workers.dev"
178
+ `);
179
+ expect(std.err).toMatchInlineSnapshot(`""`);
180
+ });
181
+
182
+ it("should throw an error in non-TTY & there is more than one account associated with API token", async () => {
183
+ setIsTTY(false);
184
+ process.env = {
185
+ CLOUDFLARE_API_TOKEN: "hunter2",
186
+ CLOUDFLARE_ACCOUNT_ID: undefined,
187
+ };
188
+ writeWranglerToml({
189
+ account_id: undefined,
190
+ });
191
+ writeWorkerSource();
192
+ mockSubDomainRequest();
193
+ mockUploadWorkerRequest();
194
+ mockOAuthServerCallback();
195
+ mockGetMemberships({
196
+ success: true,
197
+ result: [
198
+ { id: "IG-88", account: { id: "1701", name: "enterprise" } },
199
+ { id: "R2-D2", account: { id: "nx01", name: "enterprise-nx" } },
200
+ ],
201
+ });
202
+
203
+ await expect(runWrangler("publish index.js")).rejects
204
+ .toMatchInlineSnapshot(`
205
+ [Error: More than one account available but unable to select one in non-interactive mode.
206
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
207
+ Available accounts are ("<name>" - "<id>"):
208
+ "enterprise" - "1701")
209
+ "enterprise-nx" - "nx01")]
210
+ `);
211
+ });
212
+
213
+ it("should throw error in non-TTY if 'CLOUDFLARE_API_TOKEN' is missing", async () => {
214
+ setIsTTY(false);
215
+ writeWranglerToml({
216
+ account_id: undefined,
217
+ });
218
+ process.env = {
219
+ CLOUDFLARE_API_TOKEN: undefined,
220
+ CLOUDFLARE_ACCOUNT_ID: "badwolf",
221
+ };
222
+ writeWorkerSource();
223
+ mockSubDomainRequest();
224
+ mockUploadWorkerRequest();
225
+ mockOAuthServerCallback();
226
+ mockGetMemberships({
227
+ success: true,
228
+ result: [
229
+ { id: "IG-88", account: { id: "1701", name: "enterprise" } },
230
+ { id: "R2-D2", account: { id: "nx01", name: "enterprise-nx" } },
231
+ ],
232
+ });
233
+
234
+ await expect(runWrangler("publish index.js")).rejects.toThrowError();
235
+
236
+ expect(std.err).toMatchInlineSnapshot(`
237
+ "X [ERROR] In a non-interactive environment, it's necessary to set a CLOUDFLARE_API_TOKEN environment variable for wrangler to work. Please go to https://developers.cloudflare.com/api/tokens/create/ for instructions on how to create an api token, and assign its value to CLOUDFLARE_API_TOKEN.
238
+
239
+ "
240
+ `);
241
+ });
242
+ it("should throw error with no account ID provided and no members retrieved", async () => {
243
+ setIsTTY(false);
244
+ writeWranglerToml({
245
+ account_id: undefined,
246
+ });
247
+ process.env = {
248
+ CLOUDFLARE_API_TOKEN: "picard",
249
+ CLOUDFLARE_ACCOUNT_ID: undefined,
250
+ };
251
+ writeWorkerSource();
252
+ mockSubDomainRequest();
253
+ mockUploadWorkerRequest();
254
+ mockOAuthServerCallback();
255
+ mockGetMemberships({
256
+ success: false,
257
+ result: [],
258
+ });
259
+
260
+ await expect(runWrangler("publish index.js")).rejects.toThrowError();
261
+
262
+ expect(std.err).toMatchInlineSnapshot(`
263
+ "X [ERROR] Failed to automatically retrieve account IDs for the logged in user. In a non-interactive environment, it is mandatory to specify an account ID, either by assigning its value to CLOUDFLARE_ACCOUNT_ID, or as \`account_id\` in your \`wrangler.toml\` file.
264
+
265
+ "
266
+ `);
267
+ });
268
+ });
269
+ });
270
+
38
271
  describe("environments", () => {
39
272
  it("should use legacy environments by default", async () => {
40
273
  writeWranglerToml({ env: { "some-env": {} } });
@@ -106,14 +339,18 @@ describe("publish", () => {
106
339
  `);
107
340
  expect(std.err).toMatchInlineSnapshot(`""`);
108
341
  expect(std.warn).toMatchInlineSnapshot(`
109
- "Processing wrangler.toml configuration:
110
- - No environment found in configuration with name \\"some-env\\".
111
- Before using \`--env=some-env\` there should be an equivalent environment section in the configuration.
342
+ "▲ [WARNING] Processing wrangler.toml configuration:
343
+
344
+ - No environment found in configuration with name \\"some-env\\".
345
+ Before using \`--env=some-env\` there should be an equivalent environment section in the
346
+ configuration.
347
+
348
+ Consider adding an environment configuration section to the wrangler.toml file:
349
+ \`\`\`
350
+ [env.some-env]
351
+ \`\`\`
352
+
112
353
 
113
- Consider adding an environment configuration section to the wrangler.toml file:
114
- \`\`\`
115
- [env.some-env]
116
- \`\`\`
117
354
  "
118
355
  `);
119
356
  });
@@ -163,14 +400,21 @@ describe("publish", () => {
163
400
  mockUploadWorkerRequest({
164
401
  legacyEnv: false,
165
402
  });
166
- await runWrangler("publish index.js");
403
+ await runWrangler("publish index.js --legacy-env false");
167
404
  expect(std.out).toMatchInlineSnapshot(`
168
405
  "Uploaded test-name (TIMINGS)
169
406
  Published test-name (TIMINGS)
170
407
  test-name.test-sub-domain.workers.dev"
171
408
  `);
172
409
  expect(std.err).toMatchInlineSnapshot(`""`);
173
- expect(std.warn).toMatchInlineSnapshot(`""`);
410
+ expect(std.warn).toMatchInlineSnapshot(`
411
+ "▲ [WARNING] Processing wrangler.toml configuration:
412
+
413
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
414
+ the future. DO NOT USE IN PRODUCTION.
415
+
416
+ "
417
+ `);
174
418
  });
175
419
 
176
420
  it("publishes as an environment when provided", async () => {
@@ -188,7 +432,14 @@ describe("publish", () => {
188
432
  some-env.test-name.test-sub-domain.workers.dev"
189
433
  `);
190
434
  expect(std.err).toMatchInlineSnapshot(`""`);
191
- expect(std.warn).toMatchInlineSnapshot(`""`);
435
+ expect(std.warn).toMatchInlineSnapshot(`
436
+ "▲ [WARNING] Processing wrangler.toml configuration:
437
+
438
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
439
+ the future. DO NOT USE IN PRODUCTION.
440
+
441
+ "
442
+ `);
192
443
  });
193
444
  });
194
445
  });
@@ -237,6 +488,116 @@ describe("publish", () => {
237
488
  await runWrangler("publish ./index");
238
489
  });
239
490
 
491
+ it("should publish to a route with a pattern/{zone_id|zone_name} combo", async () => {
492
+ writeWranglerToml({
493
+ routes: [
494
+ "some-example.com/some-route/*",
495
+ { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" },
496
+ {
497
+ pattern: "*another-boring-website.com",
498
+ zone_name: "some-zone.com",
499
+ },
500
+ { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" },
501
+ "more-examples.com/*",
502
+ ],
503
+ });
504
+ writeWorkerSource();
505
+ mockUpdateWorkerRequest({ enabled: false });
506
+ mockUploadWorkerRequest({ expectedType: "esm" });
507
+ mockPublishRoutesRequest({
508
+ routes: [
509
+ "some-example.com/some-route/*",
510
+ { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" },
511
+ {
512
+ pattern: "*another-boring-website.com",
513
+ zone_name: "some-zone.com",
514
+ },
515
+ { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" },
516
+ "more-examples.com/*",
517
+ ],
518
+ });
519
+ await runWrangler("publish ./index");
520
+ expect(std).toMatchInlineSnapshot(`
521
+ Object {
522
+ "debug": "",
523
+ "err": "",
524
+ "out": "Uploaded test-name (TIMINGS)
525
+ Published test-name (TIMINGS)
526
+ some-example.com/some-route/*
527
+ *a-boring-website.com (zone id: 54sdf7fsda)
528
+ *another-boring-website.com (zone name: some-zone.com)
529
+ example.com/some-route/* (zone id: JGHFHG654gjcj)
530
+ more-examples.com/*",
531
+ "warn": "",
532
+ }
533
+ `);
534
+ });
535
+
536
+ it("should publish to a route with a pattern/{zone_id|zone_name} combo (service environments)", async () => {
537
+ writeWranglerToml({
538
+ env: {
539
+ staging: {
540
+ routes: [
541
+ "some-example.com/some-route/*",
542
+ { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" },
543
+ {
544
+ pattern: "*another-boring-website.com",
545
+ zone_name: "some-zone.com",
546
+ },
547
+ { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" },
548
+ "more-examples.com/*",
549
+ ],
550
+ },
551
+ },
552
+ });
553
+ mockSubDomainRequest();
554
+ writeWorkerSource();
555
+ mockUpdateWorkerRequest({
556
+ enabled: false,
557
+ env: "staging",
558
+ legacyEnv: false,
559
+ });
560
+ mockUploadWorkerRequest({
561
+ expectedType: "esm",
562
+ env: "staging",
563
+ legacyEnv: false,
564
+ });
565
+ mockPublishRoutesRequest({
566
+ routes: [
567
+ "some-example.com/some-route/*",
568
+ { pattern: "*a-boring-website.com", zone_id: "54sdf7fsda" },
569
+ {
570
+ pattern: "*another-boring-website.com",
571
+ zone_name: "some-zone.com",
572
+ },
573
+ { pattern: "example.com/some-route/*", zone_id: "JGHFHG654gjcj" },
574
+ "more-examples.com/*",
575
+ ],
576
+ env: "staging",
577
+ legacyEnv: false,
578
+ });
579
+ await runWrangler("publish ./index --legacy-env false --env staging");
580
+ expect(std).toMatchInlineSnapshot(`
581
+ Object {
582
+ "debug": "",
583
+ "err": "",
584
+ "out": "Uploaded test-name (staging) (TIMINGS)
585
+ Published test-name (staging) (TIMINGS)
586
+ some-example.com/some-route/*
587
+ *a-boring-website.com (zone id: 54sdf7fsda)
588
+ *another-boring-website.com (zone name: some-zone.com)
589
+ example.com/some-route/* (zone id: JGHFHG654gjcj)
590
+ more-examples.com/*",
591
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
592
+
593
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
594
+ the future. DO NOT USE IN PRODUCTION.
595
+
596
+ ",
597
+ }
598
+ `);
599
+ });
600
+
240
601
  it("should publish to legacy environment specific routes", async () => {
241
602
  writeWranglerToml({
242
603
  routes: ["example.com/some-route/*"],
@@ -368,13 +729,16 @@ describe("publish", () => {
368
729
  `);
369
730
  expect(std.err).toMatchInlineSnapshot(`""`);
370
731
  expect(std.warn).toMatchInlineSnapshot(`
371
- "Processing wrangler.toml configuration:
372
- - DEPRECATION: \\"build.upload.main\\":
373
- Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
374
- Then add the top level \`main\` field to your configuration file:
375
- \`\`\`
376
- main = \\"dist/index.js\\"
377
- \`\`\`"
732
+ "▲ [WARNING] Processing wrangler.toml configuration:
733
+
734
+ - Deprecation: \\"build.upload.main\\":
735
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
736
+ Then add the top level \`main\` field to your configuration file:
737
+ \`\`\`
738
+ main = \\"dist/index.js\\"
739
+ \`\`\`
740
+
741
+ "
378
742
  `);
379
743
  });
380
744
 
@@ -400,15 +764,19 @@ describe("publish", () => {
400
764
  `);
401
765
  expect(std.err).toMatchInlineSnapshot(`""`);
402
766
  expect(std.warn).toMatchInlineSnapshot(`
403
- "Processing ../wrangler.toml configuration:
404
- - DEPRECATION: \\"build.upload.main\\":
405
- Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
406
- Then add the top level \`main\` field to your configuration file:
407
- \`\`\`
408
- main = \\"foo/index.js\\"
409
- \`\`\`
410
- - DEPRECATION: \\"build.upload.dir\\":
411
- Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the Worker."
767
+ "▲ [WARNING] Processing ../wrangler.toml configuration:
768
+
769
+ - Deprecation: \\"build.upload.main\\":
770
+ Delete the \`build.upload.main\` and \`build.upload.dir\` fields.
771
+ Then add the top level \`main\` field to your configuration file:
772
+ \`\`\`
773
+ main = \\"foo/index.js\\"
774
+ \`\`\`
775
+ - Deprecation: \\"build.upload.dir\\":
776
+ Use the top level \\"main\\" field or a command-line argument to specify the entry-point for the
777
+ Worker.
778
+
779
+ "
412
780
  `);
413
781
  });
414
782
 
@@ -544,17 +912,32 @@ export default{
544
912
  - \\"site.bucket\\" is a required field."
545
913
  `);
546
914
 
547
- expect(std.out).toMatchInlineSnapshot(`""`);
915
+ expect(std.out).toMatchInlineSnapshot(`
916
+ "
917
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
918
+ `);
548
919
  expect(std.err).toMatchInlineSnapshot(`
549
- "Processing wrangler.toml configuration:
550
- - \\"site.bucket\\" is a required field.
920
+ "X [ERROR] Processing wrangler.toml configuration:
551
921
 
552
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
922
+ - \\"site.bucket\\" is a required field.
923
+
924
+ "
925
+ `);
926
+ expect(normalizeSlashes(std.warn)).toMatchInlineSnapshot(`
927
+ "▲ [WARNING] Processing wrangler.toml configuration:
928
+
929
+ - Because you've defined a [site] configuration, we're defaulting to \\"workers-site\\" for the
930
+ deprecated \`site.entry-point\`field.
931
+ Add the top level \`main\` field to your configuration file:
932
+ \`\`\`
933
+ main = \\"workers-site/index.js\\"
934
+ \`\`\`
935
+
936
+ "
553
937
  `);
554
- expect(std.warn).toMatchInlineSnapshot(`""`);
555
938
  });
556
939
 
557
- it("should error if there is a `site.entry-point` configuration", async () => {
940
+ it("should warn if there is a `site.entry-point` configuration", async () => {
558
941
  const assets = [
559
942
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
560
943
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -577,52 +960,35 @@ export default{
577
960
  mockListKVNamespacesRequest(kvNamespace);
578
961
  mockKeyListRequest(kvNamespace.id, []);
579
962
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
963
+ await runWrangler("publish ./index.js");
964
+
965
+ expect(std).toMatchInlineSnapshot(`
966
+ Object {
967
+ "debug": "",
968
+ "err": "",
969
+ "out": "Reading assets/file-1.txt...
970
+ Uploading as assets/file-1.2ca234f380.txt...
971
+ Reading assets/file-2.txt...
972
+ Uploading as assets/file-2.5938485188.txt...
973
+ ↗️ Done syncing assets
974
+ Uploaded test-name (TIMINGS)
975
+ Published test-name (TIMINGS)
976
+ test-name.test-sub-domain.workers.dev",
977
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
580
978
 
581
- await expect(runWrangler("publish ./index.js")).rejects
582
- .toThrowErrorMatchingInlineSnapshot(`
583
- "Processing wrangler.toml configuration:
584
- - DEPRECATION: \\"site.entry-point\\":
585
- The \`site.entry-point\` config field is no longer used.
586
- The entry-point should be specified via the command line or the \`main\` config field."
587
- `);
588
-
589
- expect(std.out).toMatchInlineSnapshot(`""`);
590
- expect(std.err).toMatchInlineSnapshot(`
591
- "Processing wrangler.toml configuration:
592
- - DEPRECATION: \\"site.entry-point\\":
593
- The \`site.entry-point\` config field is no longer used.
594
- The entry-point should be specified via the command line or the \`main\` config field.
595
-
596
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
597
- `);
598
- expect(std.warn).toMatchInlineSnapshot(`
599
- "Processing wrangler.toml configuration:
600
- - Unexpected fields found in site field: \\"entry-point\\""
601
- `);
602
- });
603
-
604
- it("should error if there is no entry-point specified", async () => {
605
- writeWranglerToml();
606
- writeWorkerSource();
607
- mockUploadWorkerRequest();
608
- mockSubDomainRequest();
609
- await expect(
610
- runWrangler("publish")
611
- ).rejects.toThrowErrorMatchingInlineSnapshot(
612
- `"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."`
613
- );
614
-
615
- expect(std.out).toMatchInlineSnapshot(`""`);
616
- expect(std.err).toMatchInlineSnapshot(`
617
- "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.
979
+ - Deprecation: \\"site.entry-point\\":
980
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration
981
+ file:
982
+ \`\`\`
983
+ main = \\"index.js\\"
984
+ \`\`\`
618
985
 
619
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
986
+ ",
987
+ }
620
988
  `);
621
989
  });
622
- });
623
990
 
624
- describe("asset upload", () => {
625
- it("should upload all the files in the directory specified by `config.site.bucket`", async () => {
991
+ it("should resolve site.entry-point relative to wrangler.toml", async () => {
626
992
  const assets = [
627
993
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
628
994
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -631,47 +997,142 @@ export default{
631
997
  title: "__test-name-workers_sites_assets",
632
998
  id: "__test-name-workers_sites_assets-id",
633
999
  };
1000
+ fs.mkdirSync("my-site");
1001
+ process.chdir("my-site");
634
1002
  writeWranglerToml({
635
- main: "./index.js",
636
1003
  site: {
637
1004
  bucket: "assets",
1005
+ "entry-point": "my-entry",
638
1006
  },
639
1007
  });
640
- writeWorkerSource();
1008
+ fs.mkdirSync("my-entry");
1009
+ fs.writeFileSync("my-entry/index.js", "export default {}");
641
1010
  writeAssets(assets);
1011
+ process.chdir("..");
642
1012
  mockUploadWorkerRequest();
643
1013
  mockSubDomainRequest();
644
1014
  mockListKVNamespacesRequest(kvNamespace);
645
1015
  mockKeyListRequest(kvNamespace.id, []);
646
1016
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
647
- await runWrangler("publish");
1017
+ await runWrangler("publish --config ./my-site/wrangler.toml");
648
1018
 
649
1019
  expect(std.out).toMatchInlineSnapshot(`
650
- "reading assets/file-1.txt...
651
- uploading as assets/file-1.2ca234f380.txt...
652
- reading assets/file-2.txt...
653
- uploading as assets/file-2.5938485188.txt...
1020
+ "Reading assets/file-1.txt...
1021
+ Uploading as assets/file-1.2ca234f380.txt...
1022
+ Reading assets/file-2.txt...
1023
+ Uploading as assets/file-2.5938485188.txt...
654
1024
  ↗️ Done syncing assets
655
1025
  Uploaded test-name (TIMINGS)
656
1026
  Published test-name (TIMINGS)
657
1027
  test-name.test-sub-domain.workers.dev"
658
1028
  `);
659
1029
  expect(std.err).toMatchInlineSnapshot(`""`);
1030
+ expect(normalizeSlashes(std.warn)).toMatchInlineSnapshot(`
1031
+ "▲ [WARNING] Processing my-site/wrangler.toml configuration:
1032
+
1033
+ - Deprecation: \\"site.entry-point\\":
1034
+ Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration
1035
+ file:
1036
+ \`\`\`
1037
+ main = \\"my-entry/index.js\\"
1038
+ \`\`\`
1039
+
1040
+ "
1041
+ `);
660
1042
  });
661
1043
 
662
- it("when using a service worker type, it should add an asset manifest as a text_blob, and bind to a namespace", async () => {
663
- const assets = [
664
- { filePath: "assets/file-1.txt", content: "Content of file-1" },
665
- { filePath: "assets/file-2.txt", content: "Content of file-2" },
666
- ];
667
- const kvNamespace = {
668
- title: "__test-name-workers_sites_assets",
669
- id: "__test-name-workers_sites_assets-id",
670
- };
1044
+ it("should error if both main and site.entry-point are specified", async () => {
671
1045
  writeWranglerToml({
672
- main: "./index.js",
1046
+ main: "some-entry",
673
1047
  site: {
674
- bucket: "assets",
1048
+ bucket: "some-bucket",
1049
+ "entry-point": "./index.js",
1050
+ },
1051
+ });
1052
+
1053
+ await expect(runWrangler("publish")).rejects
1054
+ .toThrowErrorMatchingInlineSnapshot(`
1055
+ "Processing wrangler.toml configuration:
1056
+ - Don't define both the \`main\` and \`site.entry-point\` fields in your configuration.
1057
+ They serve the same purpose: to point to the entry-point of your worker.
1058
+ Delete the deprecated \`site.entry-point\` field from your config."
1059
+ `);
1060
+ });
1061
+
1062
+ it("should error if there is no entry-point specified", async () => {
1063
+ writeWranglerToml();
1064
+ writeWorkerSource();
1065
+ mockUploadWorkerRequest();
1066
+ mockSubDomainRequest();
1067
+ await expect(
1068
+ runWrangler("publish")
1069
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1070
+ `"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."`
1071
+ );
1072
+
1073
+ expect(std.out).toMatchInlineSnapshot(`
1074
+ "
1075
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1076
+ `);
1077
+ expect(std.err).toMatchInlineSnapshot(`
1078
+ "X [ERROR] 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.
1079
+
1080
+ "
1081
+ `);
1082
+ });
1083
+ });
1084
+
1085
+ describe("asset upload", () => {
1086
+ it("should upload all the files in the directory specified by `config.site.bucket`", async () => {
1087
+ const assets = [
1088
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
1089
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1090
+ ];
1091
+ const kvNamespace = {
1092
+ title: "__test-name-workers_sites_assets",
1093
+ id: "__test-name-workers_sites_assets-id",
1094
+ };
1095
+ writeWranglerToml({
1096
+ main: "./index.js",
1097
+ site: {
1098
+ bucket: "assets",
1099
+ },
1100
+ });
1101
+ writeWorkerSource();
1102
+ writeAssets(assets);
1103
+ mockUploadWorkerRequest();
1104
+ mockSubDomainRequest();
1105
+ mockListKVNamespacesRequest(kvNamespace);
1106
+ mockKeyListRequest(kvNamespace.id, []);
1107
+ mockUploadAssetsToKVRequest(kvNamespace.id, assets);
1108
+ await runWrangler("publish");
1109
+
1110
+ expect(std.out).toMatchInlineSnapshot(`
1111
+ "Reading assets/file-1.txt...
1112
+ Uploading as assets/file-1.2ca234f380.txt...
1113
+ Reading assets/file-2.txt...
1114
+ Uploading as assets/file-2.5938485188.txt...
1115
+ ↗️ Done syncing assets
1116
+ Uploaded test-name (TIMINGS)
1117
+ Published test-name (TIMINGS)
1118
+ test-name.test-sub-domain.workers.dev"
1119
+ `);
1120
+ expect(std.err).toMatchInlineSnapshot(`""`);
1121
+ });
1122
+
1123
+ it("when using a service-worker type, it should add an asset manifest as a text_blob, and bind to a namespace", async () => {
1124
+ const assets = [
1125
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
1126
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1127
+ ];
1128
+ const kvNamespace = {
1129
+ title: "__test-name-workers_sites_assets",
1130
+ id: "__test-name-workers_sites_assets-id",
1131
+ };
1132
+ writeWranglerToml({
1133
+ main: "./index.js",
1134
+ site: {
1135
+ bucket: "assets",
675
1136
  },
676
1137
  });
677
1138
  writeWorkerSource({ type: "sw" });
@@ -703,10 +1164,10 @@ export default{
703
1164
  await runWrangler("publish");
704
1165
 
705
1166
  expect(std.out).toMatchInlineSnapshot(`
706
- "reading assets/file-1.txt...
707
- uploading as assets/file-1.2ca234f380.txt...
708
- reading assets/file-2.txt...
709
- uploading as assets/file-2.5938485188.txt...
1167
+ "Reading assets/file-1.txt...
1168
+ Uploading as assets/file-1.2ca234f380.txt...
1169
+ Reading assets/file-2.txt...
1170
+ Uploading as assets/file-2.5938485188.txt...
710
1171
  ↗️ Done syncing assets
711
1172
  Uploaded test-name (TIMINGS)
712
1173
  Published test-name (TIMINGS)
@@ -753,10 +1214,10 @@ export default{
753
1214
  await runWrangler("publish");
754
1215
 
755
1216
  expect(std.out).toMatchInlineSnapshot(`
756
- "reading assets/file-1.txt...
757
- uploading as assets/file-1.2ca234f380.txt...
758
- reading assets/file-2.txt...
759
- uploading as assets/file-2.5938485188.txt...
1217
+ "Reading assets/file-1.txt...
1218
+ Uploading as assets/file-1.2ca234f380.txt...
1219
+ Reading assets/file-2.txt...
1220
+ Uploading as assets/file-2.5938485188.txt...
760
1221
  ↗️ Done syncing assets
761
1222
  Uploaded test-name (TIMINGS)
762
1223
  Published test-name (TIMINGS)
@@ -801,10 +1262,10 @@ export default{
801
1262
  await runWrangler("publish --env some-env --legacy-env false");
802
1263
 
803
1264
  expect(std.out).toMatchInlineSnapshot(`
804
- "reading assets/file-1.txt...
805
- uploading as assets/file-1.2ca234f380.txt...
806
- reading assets/file-2.txt...
807
- uploading as assets/file-2.5938485188.txt...
1265
+ "Reading assets/file-1.txt...
1266
+ Uploading as assets/file-1.2ca234f380.txt...
1267
+ Reading assets/file-2.txt...
1268
+ Uploading as assets/file-2.5938485188.txt...
808
1269
  ↗️ Done syncing assets
809
1270
  Uploaded test-name (some-env) (TIMINGS)
810
1271
  Published test-name (some-env) (TIMINGS)
@@ -850,10 +1311,10 @@ export default{
850
1311
  await runWrangler("publish --env some-env --legacy-env true");
851
1312
 
852
1313
  expect(std.out).toMatchInlineSnapshot(`
853
- "reading assets/file-1.txt...
854
- uploading as assets/file-1.2ca234f380.txt...
855
- reading assets/file-2.txt...
856
- uploading as assets/file-2.5938485188.txt...
1314
+ "Reading assets/file-1.txt...
1315
+ Uploading as assets/file-1.2ca234f380.txt...
1316
+ Reading assets/file-2.txt...
1317
+ Uploading as assets/file-2.5938485188.txt...
857
1318
  ↗️ Done syncing assets
858
1319
  Uploaded test-name-some-env (TIMINGS)
859
1320
  Published test-name-some-env (TIMINGS)
@@ -894,10 +1355,10 @@ export default{
894
1355
  await runWrangler("publish");
895
1356
 
896
1357
  expect(std.out).toMatchInlineSnapshot(`
897
- "reading assets/file-1.txt...
898
- skipping - already uploaded
899
- reading assets/file-2.txt...
900
- uploading as assets/file-2.5938485188.txt...
1358
+ "Reading assets/file-1.txt...
1359
+ Skipping - already uploaded.
1360
+ Reading assets/file-2.txt...
1361
+ Uploading as assets/file-2.5938485188.txt...
901
1362
  ↗️ Done syncing assets
902
1363
  Uploaded test-name (TIMINGS)
903
1364
  Published test-name (TIMINGS)
@@ -935,8 +1396,8 @@ export default{
935
1396
  await runWrangler("publish --site-include file-1.txt");
936
1397
 
937
1398
  expect(std.out).toMatchInlineSnapshot(`
938
- "reading assets/file-1.txt...
939
- uploading as assets/file-1.2ca234f380.txt...
1399
+ "Reading assets/file-1.txt...
1400
+ Uploading as assets/file-1.2ca234f380.txt...
940
1401
  ↗️ Done syncing assets
941
1402
  Uploaded test-name (TIMINGS)
942
1403
  Published test-name (TIMINGS)
@@ -974,8 +1435,8 @@ export default{
974
1435
  await runWrangler("publish --site-exclude file-2.txt");
975
1436
 
976
1437
  expect(std.out).toMatchInlineSnapshot(`
977
- "reading assets/file-1.txt...
978
- uploading as assets/file-1.2ca234f380.txt...
1438
+ "Reading assets/file-1.txt...
1439
+ Uploading as assets/file-1.2ca234f380.txt...
979
1440
  ↗️ Done syncing assets
980
1441
  Uploaded test-name (TIMINGS)
981
1442
  Published test-name (TIMINGS)
@@ -1014,8 +1475,8 @@ export default{
1014
1475
  await runWrangler("publish");
1015
1476
 
1016
1477
  expect(std.out).toMatchInlineSnapshot(`
1017
- "reading assets/file-1.txt...
1018
- uploading as assets/file-1.2ca234f380.txt...
1478
+ "Reading assets/file-1.txt...
1479
+ Uploading as assets/file-1.2ca234f380.txt...
1019
1480
  ↗️ Done syncing assets
1020
1481
  Uploaded test-name (TIMINGS)
1021
1482
  Published test-name (TIMINGS)
@@ -1054,8 +1515,8 @@ export default{
1054
1515
  await runWrangler("publish");
1055
1516
 
1056
1517
  expect(std.out).toMatchInlineSnapshot(`
1057
- "reading assets/file-1.txt...
1058
- uploading as assets/file-1.2ca234f380.txt...
1518
+ "Reading assets/file-1.txt...
1519
+ Uploading as assets/file-1.2ca234f380.txt...
1059
1520
  ↗️ Done syncing assets
1060
1521
  Uploaded test-name (TIMINGS)
1061
1522
  Published test-name (TIMINGS)
@@ -1094,8 +1555,8 @@ export default{
1094
1555
  await runWrangler("publish --site-include file-1.txt");
1095
1556
 
1096
1557
  expect(std.out).toMatchInlineSnapshot(`
1097
- "reading assets/file-1.txt...
1098
- uploading as assets/file-1.2ca234f380.txt...
1558
+ "Reading assets/file-1.txt...
1559
+ Uploading as assets/file-1.2ca234f380.txt...
1099
1560
  ↗️ Done syncing assets
1100
1561
  Uploaded test-name (TIMINGS)
1101
1562
  Published test-name (TIMINGS)
@@ -1134,8 +1595,8 @@ export default{
1134
1595
  await runWrangler("publish --site-exclude file-2.txt");
1135
1596
 
1136
1597
  expect(std.out).toMatchInlineSnapshot(`
1137
- "reading assets/file-1.txt...
1138
- uploading as assets/file-1.2ca234f380.txt...
1598
+ "Reading assets/file-1.txt...
1599
+ Uploading as assets/file-1.2ca234f380.txt...
1139
1600
  ↗️ Done syncing assets
1140
1601
  Uploaded test-name (TIMINGS)
1141
1602
  Published test-name (TIMINGS)
@@ -1176,8 +1637,8 @@ export default{
1176
1637
  await runWrangler("publish");
1177
1638
 
1178
1639
  expect(std.out).toMatchInlineSnapshot(`
1179
- "reading assets/directory-1/file-1.txt...
1180
- uploading as assets/directory-1/file-1.2ca234f380.txt...
1640
+ "Reading assets/directory-1/file-1.txt...
1641
+ Uploading as assets/directory-1/file-1.2ca234f380.txt...
1181
1642
  ↗️ Done syncing assets
1182
1643
  Uploaded test-name (TIMINGS)
1183
1644
  Published test-name (TIMINGS)
@@ -1222,8 +1683,8 @@ export default{
1222
1683
  await runWrangler("publish");
1223
1684
 
1224
1685
  expect(std.out).toMatchInlineSnapshot(`
1225
- "reading assets/.well-known/file-2.txt...
1226
- uploading as assets/.well-known/file-2.5938485188.txt...
1686
+ "Reading assets/.well-known/file-2.txt...
1687
+ Uploading as assets/.well-known/file-2.5938485188.txt...
1227
1688
  ↗️ Done syncing assets
1228
1689
  Uploaded test-name (TIMINGS)
1229
1690
  Published test-name (TIMINGS)
@@ -1269,13 +1730,15 @@ export default{
1269
1730
  );
1270
1731
 
1271
1732
  expect(std.out).toMatchInlineSnapshot(`
1272
- "reading assets/large-file.txt...
1273
- uploading as assets/large-file.0ea0637a45.txt..."
1733
+ "Reading assets/large-file.txt...
1734
+ Uploading as assets/large-file.0ea0637a45.txt...
1735
+
1736
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1274
1737
  `);
1275
1738
  expect(std.err).toMatchInlineSnapshot(`
1276
- "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
1739
+ "X [ERROR] 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
1277
1740
 
1278
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1741
+ "
1279
1742
  `);
1280
1743
  });
1281
1744
 
@@ -1307,13 +1770,15 @@ export default{
1307
1770
  `"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\\","`
1308
1771
  );
1309
1772
 
1310
- expect(std.out).toMatchInlineSnapshot(
1311
- `"reading 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.txt..."`
1312
- );
1773
+ expect(std.out).toMatchInlineSnapshot(`
1774
+ "Reading 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.txt...
1775
+
1776
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1777
+ `);
1313
1778
  expect(std.err).toMatchInlineSnapshot(`
1314
- "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\\",
1779
+ "X [ERROR] 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\\",
1315
1780
 
1316
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1781
+ "
1317
1782
  `);
1318
1783
  });
1319
1784
 
@@ -1359,12 +1824,12 @@ export default{
1359
1824
  await runWrangler("publish");
1360
1825
 
1361
1826
  expect(std.out).toMatchInlineSnapshot(`
1362
- "reading assets/file-1.txt...
1363
- skipping - already uploaded
1364
- reading assets/file-2.txt...
1365
- uploading as assets/file-2.5938485188.txt...
1366
- deleting assets/file-3.somehash.txt from the asset store...
1367
- deleting assets/file-4.anotherhash.txt from the asset store...
1827
+ "Reading assets/file-1.txt...
1828
+ Skipping - already uploaded.
1829
+ Reading assets/file-2.txt...
1830
+ Uploading as assets/file-2.5938485188.txt...
1831
+ Deleting assets/file-3.somehash.txt from the asset store...
1832
+ Deleting assets/file-4.anotherhash.txt from the asset store...
1368
1833
  ↗️ Done syncing assets
1369
1834
  Uploaded test-name (TIMINGS)
1370
1835
  Published test-name (TIMINGS)
@@ -1396,7 +1861,26 @@ export default{
1396
1861
  workers_dev: true,
1397
1862
  });
1398
1863
  writeWorkerSource();
1399
- mockUploadWorkerRequest();
1864
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1865
+ mockSubDomainRequest();
1866
+ mockUpdateWorkerRequest({ enabled: true });
1867
+
1868
+ await runWrangler("publish ./index");
1869
+
1870
+ expect(std.out).toMatchInlineSnapshot(`
1871
+ "Uploaded test-name (TIMINGS)
1872
+ Published test-name (TIMINGS)
1873
+ test-name.test-sub-domain.workers.dev"
1874
+ `);
1875
+ expect(std.err).toMatchInlineSnapshot(`""`);
1876
+ });
1877
+
1878
+ it("should not try to enable the workers.dev domain if it has been enabled before", async () => {
1879
+ writeWranglerToml({
1880
+ workers_dev: true,
1881
+ });
1882
+ writeWorkerSource();
1883
+ mockUploadWorkerRequest({ available_on_subdomain: true });
1400
1884
  mockSubDomainRequest();
1401
1885
 
1402
1886
  await runWrangler("publish ./index");
@@ -1426,6 +1910,25 @@ export default{
1426
1910
  expect(std.err).toMatchInlineSnapshot(`""`);
1427
1911
  });
1428
1912
 
1913
+ it("should not try to disable the workers.dev domain if it is not already available", async () => {
1914
+ writeWranglerToml({
1915
+ workers_dev: false,
1916
+ });
1917
+ writeWorkerSource();
1918
+ mockSubDomainRequest("test-sub-domain", false);
1919
+ mockUploadWorkerRequest({ available_on_subdomain: false });
1920
+
1921
+ // note the lack of a mock for the subdomain disable request
1922
+
1923
+ await runWrangler("publish ./index");
1924
+
1925
+ expect(std.out).toMatchInlineSnapshot(`
1926
+ "Uploaded test-name (TIMINGS)
1927
+ No publish targets for test-name (TIMINGS)"
1928
+ `);
1929
+ expect(std.err).toMatchInlineSnapshot(`""`);
1930
+ });
1931
+
1429
1932
  it("should disable the workers.dev domain if workers_dev is undefined but overwritten to `false` in environment", async () => {
1430
1933
  writeWranglerToml({
1431
1934
  env: {
@@ -1931,7 +2434,7 @@ export default{
1931
2434
 
1932
2435
  await runWrangler("publish index.js");
1933
2436
  expect(std.out).toMatchInlineSnapshot(`
1934
- "running: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\"
2437
+ "Running custom build: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\"
1935
2438
  Uploaded test-name (TIMINGS)
1936
2439
  Published test-name (TIMINGS)
1937
2440
  test-name.test-sub-domain.workers.dev"
@@ -1955,7 +2458,7 @@ export default{
1955
2458
 
1956
2459
  await runWrangler("publish index.js");
1957
2460
  expect(std.out).toMatchInlineSnapshot(`
1958
- "running: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js
2461
+ "Running custom build: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js
1959
2462
  Uploaded test-name (TIMINGS)
1960
2463
  Published test-name (TIMINGS)
1961
2464
  test-name.test-sub-domain.workers.dev"
@@ -1978,21 +2481,499 @@ export default{
1978
2481
  ).rejects.toThrowErrorMatchingInlineSnapshot(
1979
2482
  `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
1980
2483
  );
1981
- expect(std.out).toMatchInlineSnapshot(
1982
- `"running: node -e \\"console.log('custom build');\\""`
1983
- );
2484
+ expect(std.out).toMatchInlineSnapshot(`
2485
+ "Running custom build: node -e \\"console.log('custom build');\\"
2486
+
2487
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2488
+ `);
1984
2489
  expect(std.err).toMatchInlineSnapshot(`
1985
- "Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
2490
+ "X [ERROR] Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
2491
+
2492
+ "
2493
+ `);
2494
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2495
+ });
2496
+
2497
+ it("should minify the script when `--minify` is true (sw)", async () => {
2498
+ writeWranglerToml({
2499
+ main: "./index.js",
2500
+ });
2501
+ fs.writeFileSync(
2502
+ "./index.js",
2503
+ `export
2504
+ default {
2505
+ fetch() {
2506
+ return new Response( "hello Cpt Picard" )
2507
+ }
2508
+ }
2509
+ `
2510
+ );
2511
+
2512
+ mockUploadWorkerRequest({
2513
+ expectedEntry: 'fetch(){return new Response("hello Cpt Picard")',
2514
+ });
2515
+
2516
+ mockSubDomainRequest();
2517
+ await runWrangler("publish index.js --minify");
2518
+ expect(std.out).toMatchInlineSnapshot(`
2519
+ "Uploaded test-name (TIMINGS)
2520
+ Published test-name (TIMINGS)
2521
+ test-name.test-sub-domain.workers.dev"
2522
+ `);
2523
+ expect(std.err).toMatchInlineSnapshot(`""`);
2524
+ });
2525
+
2526
+ it("should minify the script when `minify` in config is true (esm)", async () => {
2527
+ writeWranglerToml({
2528
+ main: "./index.js",
2529
+ legacy_env: false,
2530
+ env: {
2531
+ testEnv: {
2532
+ minify: true,
2533
+ },
2534
+ },
2535
+ });
2536
+ fs.writeFileSync(
2537
+ "./index.js",
2538
+ `export
2539
+ default {
2540
+ fetch() {
2541
+ return new Response( "hello Cpt Picard" )
2542
+ }
2543
+ }
2544
+ `
2545
+ );
2546
+
2547
+ mockUploadWorkerRequest({
2548
+ env: "testEnv",
2549
+ expectedType: "esm",
2550
+ legacyEnv: false,
2551
+ expectedEntry: `fetch(){return new Response("hello Cpt Picard")`,
2552
+ });
2553
+
2554
+ mockSubDomainRequest();
2555
+ await runWrangler("publish -e testEnv index.js");
2556
+ expect(std.out).toMatchInlineSnapshot(`
2557
+ "Uploaded test-name (testEnv) (TIMINGS)
2558
+ Published test-name (testEnv) (TIMINGS)
2559
+ testEnv.test-name.test-sub-domain.workers.dev"
2560
+ `);
2561
+ expect(std.err).toMatchInlineSnapshot(`""`);
2562
+ });
2563
+ });
2564
+
2565
+ describe("durable object migrations", () => {
2566
+ it("should warn when you try to publish durable objects without migrations", async () => {
2567
+ writeWranglerToml({
2568
+ durable_objects: {
2569
+ bindings: [{ name: "SOMENAME", class_name: "SomeClass" }],
2570
+ },
2571
+ });
2572
+ fs.writeFileSync(
2573
+ "index.js",
2574
+ `export class SomeClass{}; export default {};`
2575
+ );
2576
+ mockSubDomainRequest();
2577
+ mockUploadWorkerRequest();
2578
+ await runWrangler("publish index.js");
2579
+ expect(std.out).toMatchInlineSnapshot(`
2580
+ "Uploaded test-name (TIMINGS)
2581
+ Published test-name (TIMINGS)
2582
+ test-name.test-sub-domain.workers.dev"
2583
+ `);
2584
+ expect(std.err).toMatchInlineSnapshot(`""`);
2585
+ expect(std.warn).toMatchInlineSnapshot(`
2586
+ "▲ [WARNING] In wrangler.toml, you have configured [durable_objects] exported by this Worker (SomeClass), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details.
2587
+
2588
+ "
2589
+ `);
2590
+ });
2591
+
2592
+ it("does not warn if all the durable object bindings are to external classes", async () => {
2593
+ writeWranglerToml({
2594
+ durable_objects: {
2595
+ bindings: [
2596
+ {
2597
+ name: "SOMENAME",
2598
+ class_name: "SomeClass",
2599
+ script_name: "some-script",
2600
+ },
2601
+ ],
2602
+ },
2603
+ });
2604
+ fs.writeFileSync(
2605
+ "index.js",
2606
+ `export class SomeClass{}; export default {};`
2607
+ );
2608
+ mockSubDomainRequest();
2609
+ mockUploadWorkerRequest();
2610
+ await runWrangler("publish index.js");
2611
+ expect(std.out).toMatchInlineSnapshot(`
2612
+ "Uploaded test-name (TIMINGS)
2613
+ Published test-name (TIMINGS)
2614
+ test-name.test-sub-domain.workers.dev"
2615
+ `);
2616
+ expect(std.err).toMatchInlineSnapshot(`""`);
2617
+ expect(std.warn).toMatchInlineSnapshot(`""`);
2618
+ });
2619
+
2620
+ it("should publish all migrations on first publish", async () => {
2621
+ writeWranglerToml({
2622
+ durable_objects: {
2623
+ bindings: [
2624
+ { name: "SOMENAME", class_name: "SomeClass" },
2625
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2626
+ ],
2627
+ },
2628
+ migrations: [
2629
+ { tag: "v1", new_classes: ["SomeClass"] },
2630
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2631
+ ],
2632
+ });
2633
+ fs.writeFileSync(
2634
+ "index.js",
2635
+ `export class SomeClass{}; export class SomeOtherClass{}; export default {};`
2636
+ );
2637
+ mockSubDomainRequest();
2638
+ mockLegacyScriptData({ scripts: [] }); // no previously uploaded scripts at all
2639
+ mockUploadWorkerRequest({
2640
+ expectedMigrations: {
2641
+ new_tag: "v2",
2642
+ steps: [
2643
+ { new_classes: ["SomeClass"] },
2644
+ { new_classes: ["SomeOtherClass"] },
2645
+ ],
2646
+ },
2647
+ });
1986
2648
 
1987
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2649
+ await runWrangler("publish index.js");
2650
+ expect(std.out).toMatchInlineSnapshot(`
2651
+ "Uploaded test-name (TIMINGS)
2652
+ Published test-name (TIMINGS)
2653
+ test-name.test-sub-domain.workers.dev"
1988
2654
  `);
2655
+ expect(std.err).toMatchInlineSnapshot(`""`);
1989
2656
  expect(std.warn).toMatchInlineSnapshot(`""`);
1990
2657
  });
2658
+
2659
+ it("should upload migrations past a previously uploaded tag", async () => {
2660
+ writeWranglerToml({
2661
+ durable_objects: {
2662
+ bindings: [
2663
+ { name: "SOMENAME", class_name: "SomeClass" },
2664
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2665
+ ],
2666
+ },
2667
+ migrations: [
2668
+ { tag: "v1", new_classes: ["SomeClass"] },
2669
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2670
+ ],
2671
+ });
2672
+ fs.writeFileSync(
2673
+ "index.js",
2674
+ `export class SomeClass{}; export class SomeOtherClass{}; export default {};`
2675
+ );
2676
+ mockSubDomainRequest();
2677
+ mockLegacyScriptData({
2678
+ scripts: [{ id: "test-name", migration_tag: "v1" }],
2679
+ });
2680
+ mockUploadWorkerRequest({
2681
+ expectedMigrations: {
2682
+ old_tag: "v1",
2683
+ new_tag: "v2",
2684
+ steps: [
2685
+ {
2686
+ new_classes: ["SomeOtherClass"],
2687
+ },
2688
+ ],
2689
+ },
2690
+ });
2691
+
2692
+ await runWrangler("publish index.js");
2693
+ expect(std).toMatchInlineSnapshot(`
2694
+ Object {
2695
+ "debug": "",
2696
+ "err": "",
2697
+ "out": "Uploaded test-name (TIMINGS)
2698
+ Published test-name (TIMINGS)
2699
+ test-name.test-sub-domain.workers.dev",
2700
+ "warn": "",
2701
+ }
2702
+ `);
2703
+ });
2704
+
2705
+ it("should not send migrations if they've all already been sent", async () => {
2706
+ writeWranglerToml({
2707
+ durable_objects: {
2708
+ bindings: [
2709
+ { name: "SOMENAME", class_name: "SomeClass" },
2710
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2711
+ ],
2712
+ },
2713
+ migrations: [
2714
+ { tag: "v1", new_classes: ["SomeClass"] },
2715
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2716
+ { tag: "v3", new_classes: ["YetAnotherClass"] },
2717
+ ],
2718
+ });
2719
+ fs.writeFileSync(
2720
+ "index.js",
2721
+ `export class SomeClass{}; export class SomeOtherClass{}; export class YetAnotherClass{}; export default {};`
2722
+ );
2723
+ mockSubDomainRequest();
2724
+ mockLegacyScriptData({
2725
+ scripts: [{ id: "test-name", migration_tag: "v3" }],
2726
+ });
2727
+ mockUploadWorkerRequest({
2728
+ expectedMigrations: undefined,
2729
+ });
2730
+
2731
+ await runWrangler("publish index.js");
2732
+ expect(std).toMatchInlineSnapshot(`
2733
+ Object {
2734
+ "debug": "",
2735
+ "err": "",
2736
+ "out": "Uploaded test-name (TIMINGS)
2737
+ Published test-name (TIMINGS)
2738
+ test-name.test-sub-domain.workers.dev",
2739
+ "warn": "",
2740
+ }
2741
+ `);
2742
+ });
2743
+
2744
+ describe("service environments", () => {
2745
+ it("should publish all migrations on first publish", async () => {
2746
+ writeWranglerToml({
2747
+ durable_objects: {
2748
+ bindings: [
2749
+ { name: "SOMENAME", class_name: "SomeClass" },
2750
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2751
+ ],
2752
+ },
2753
+ migrations: [
2754
+ { tag: "v1", new_classes: ["SomeClass"] },
2755
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2756
+ ],
2757
+ });
2758
+ fs.writeFileSync(
2759
+ "index.js",
2760
+ `export class SomeClass{}; export class SomeOtherClass{}; export default {};`
2761
+ );
2762
+ mockSubDomainRequest();
2763
+ mockServiceScriptData({}); // no scripts at all
2764
+ mockUploadWorkerRequest({
2765
+ legacyEnv: false,
2766
+ expectedMigrations: {
2767
+ new_tag: "v2",
2768
+ steps: [
2769
+ { new_classes: ["SomeClass"] },
2770
+ { new_classes: ["SomeOtherClass"] },
2771
+ ],
2772
+ },
2773
+ });
2774
+
2775
+ await runWrangler("publish index.js --legacy-env false");
2776
+ expect(std.out).toMatchInlineSnapshot(`
2777
+ "Uploaded test-name (TIMINGS)
2778
+ Published test-name (TIMINGS)
2779
+ test-name.test-sub-domain.workers.dev"
2780
+ `);
2781
+ expect(std.err).toMatchInlineSnapshot(`""`);
2782
+ expect(std.warn).toMatchInlineSnapshot(`
2783
+ "▲ [WARNING] Processing wrangler.toml configuration:
2784
+
2785
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
2786
+ the future. DO NOT USE IN PRODUCTION.
2787
+
2788
+ "
2789
+ `);
2790
+ });
2791
+
2792
+ it("should publish all migrations on first publish (--env)", async () => {
2793
+ writeWranglerToml({
2794
+ durable_objects: {
2795
+ bindings: [
2796
+ { name: "SOMENAME", class_name: "SomeClass" },
2797
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2798
+ ],
2799
+ },
2800
+ env: {
2801
+ xyz: {
2802
+ durable_objects: {
2803
+ bindings: [
2804
+ { name: "SOMENAME", class_name: "SomeClass" },
2805
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2806
+ ],
2807
+ },
2808
+ },
2809
+ },
2810
+ migrations: [
2811
+ { tag: "v1", new_classes: ["SomeClass"] },
2812
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2813
+ ],
2814
+ });
2815
+ fs.writeFileSync(
2816
+ "index.js",
2817
+ `export class SomeClass{}; export class SomeOtherClass{}; export default {};`
2818
+ );
2819
+ mockSubDomainRequest();
2820
+ mockServiceScriptData({ env: "xyz" }); // no scripts at all
2821
+ mockUploadWorkerRequest({
2822
+ legacyEnv: false,
2823
+ env: "xyz",
2824
+ expectedMigrations: {
2825
+ new_tag: "v2",
2826
+ steps: [
2827
+ { new_classes: ["SomeClass"] },
2828
+ { new_classes: ["SomeOtherClass"] },
2829
+ ],
2830
+ },
2831
+ });
2832
+
2833
+ await runWrangler("publish index.js --legacy-env false --env xyz");
2834
+ expect(std.out).toMatchInlineSnapshot(`
2835
+ "Uploaded test-name (xyz) (TIMINGS)
2836
+ Published test-name (xyz) (TIMINGS)
2837
+ xyz.test-name.test-sub-domain.workers.dev"
2838
+ `);
2839
+ expect(std.err).toMatchInlineSnapshot(`""`);
2840
+ expect(std.warn).toMatchInlineSnapshot(`
2841
+ "▲ [WARNING] Processing wrangler.toml configuration:
2842
+
2843
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
2844
+ the future. DO NOT USE IN PRODUCTION.
2845
+
2846
+ "
2847
+ `);
2848
+ });
2849
+
2850
+ it("should use a script's current migration tag when publishing migrations", async () => {
2851
+ writeWranglerToml({
2852
+ durable_objects: {
2853
+ bindings: [
2854
+ { name: "SOMENAME", class_name: "SomeClass" },
2855
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2856
+ ],
2857
+ },
2858
+ migrations: [
2859
+ { tag: "v1", new_classes: ["SomeClass"] },
2860
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2861
+ ],
2862
+ });
2863
+ fs.writeFileSync(
2864
+ "index.js",
2865
+ `export class SomeClass{}; export class SomeOtherClass{}; export default {};`
2866
+ );
2867
+ mockSubDomainRequest();
2868
+ mockServiceScriptData({
2869
+ script: { id: "test-name", migration_tag: "v1" },
2870
+ });
2871
+ mockUploadWorkerRequest({
2872
+ legacyEnv: false,
2873
+ expectedMigrations: {
2874
+ old_tag: "v1",
2875
+ new_tag: "v2",
2876
+ steps: [
2877
+ {
2878
+ new_classes: ["SomeOtherClass"],
2879
+ },
2880
+ ],
2881
+ },
2882
+ });
2883
+
2884
+ await runWrangler("publish index.js --legacy-env false");
2885
+ expect(std).toMatchInlineSnapshot(`
2886
+ Object {
2887
+ "debug": "",
2888
+ "err": "",
2889
+ "out": "Uploaded test-name (TIMINGS)
2890
+ Published test-name (TIMINGS)
2891
+ test-name.test-sub-domain.workers.dev",
2892
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
2893
+
2894
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
2895
+ the future. DO NOT USE IN PRODUCTION.
2896
+
2897
+ ",
2898
+ }
2899
+ `);
2900
+ });
2901
+
2902
+ it("should use an environment's current migration tag when publishing migrations", async () => {
2903
+ writeWranglerToml({
2904
+ durable_objects: {
2905
+ bindings: [
2906
+ { name: "SOMENAME", class_name: "SomeClass" },
2907
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2908
+ ],
2909
+ },
2910
+ env: {
2911
+ xyz: {
2912
+ durable_objects: {
2913
+ bindings: [
2914
+ { name: "SOMENAME", class_name: "SomeClass" },
2915
+ { name: "SOMEOTHERNAME", class_name: "SomeOtherClass" },
2916
+ ],
2917
+ },
2918
+ },
2919
+ },
2920
+ migrations: [
2921
+ { tag: "v1", new_classes: ["SomeClass"] },
2922
+ { tag: "v2", new_classes: ["SomeOtherClass"] },
2923
+ ],
2924
+ });
2925
+ fs.writeFileSync(
2926
+ "index.js",
2927
+ `export class SomeClass{}; export class SomeOtherClass{}; export default {};`
2928
+ );
2929
+ mockSubDomainRequest();
2930
+ mockServiceScriptData({
2931
+ script: { id: "test-name", migration_tag: "v1" },
2932
+ env: "xyz",
2933
+ });
2934
+ mockUploadWorkerRequest({
2935
+ legacyEnv: false,
2936
+ env: "xyz",
2937
+ expectedMigrations: {
2938
+ old_tag: "v1",
2939
+ new_tag: "v2",
2940
+ steps: [
2941
+ {
2942
+ new_classes: ["SomeOtherClass"],
2943
+ },
2944
+ ],
2945
+ },
2946
+ });
2947
+
2948
+ await runWrangler("publish index.js --legacy-env false --env xyz");
2949
+ expect(std).toMatchInlineSnapshot(`
2950
+ Object {
2951
+ "debug": "",
2952
+ "err": "",
2953
+ "out": "Uploaded test-name (xyz) (TIMINGS)
2954
+ Published test-name (xyz) (TIMINGS)
2955
+ xyz.test-name.test-sub-domain.workers.dev",
2956
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
2957
+
2958
+ - Experimental: Service environments are in beta, and their behaviour is guaranteed to change in
2959
+ the future. DO NOT USE IN PRODUCTION.
2960
+
2961
+ ",
2962
+ }
2963
+ `);
2964
+ });
2965
+ });
1991
2966
  });
1992
2967
 
1993
2968
  describe("bindings", () => {
1994
2969
  it("should allow bindings with different names", async () => {
1995
2970
  writeWranglerToml({
2971
+ migrations: [
2972
+ {
2973
+ tag: "v1",
2974
+ new_classes: ["SomeDurableObject", "AnotherDurableObject"],
2975
+ },
2976
+ ],
1996
2977
  durable_objects: {
1997
2978
  bindings: [
1998
2979
  {
@@ -2041,6 +3022,10 @@ export default{
2041
3022
  WASM_MODULE_ONE: "./some_wasm.wasm",
2042
3023
  WASM_MODULE_TWO: "./more_wasm.wasm",
2043
3024
  },
3025
+ data_blobs: {
3026
+ DATA_BLOB_ONE: "./some-data-blob.bin",
3027
+ DATA_BLOB_TWO: "./more-data-blob.bin",
3028
+ },
2044
3029
  });
2045
3030
 
2046
3031
  writeWorkerSource({ type: "sw" });
@@ -2052,6 +3037,9 @@ export default{
2052
3037
  fs.writeFileSync("./some_wasm.wasm", "some wasm");
2053
3038
  fs.writeFileSync("./more_wasm.wasm", "more wasm");
2054
3039
 
3040
+ fs.writeFileSync("./some-data-blob.bin", "some data");
3041
+ fs.writeFileSync("./more-data-blob.bin", "more data");
3042
+
2055
3043
  mockUploadWorkerRequest({
2056
3044
  expectedType: "sw",
2057
3045
  expectedBindings: [
@@ -2105,6 +3093,8 @@ export default{
2105
3093
  },
2106
3094
  { name: "TEXT_BLOB_ONE", part: "TEXT_BLOB_ONE", type: "text_blob" },
2107
3095
  { name: "TEXT_BLOB_TWO", part: "TEXT_BLOB_TWO", type: "text_blob" },
3096
+ { name: "DATA_BLOB_ONE", part: "DATA_BLOB_ONE", type: "data_blob" },
3097
+ { name: "DATA_BLOB_TWO", part: "DATA_BLOB_TWO", type: "data_blob" },
2108
3098
  {
2109
3099
  data: { some: { unsafe: "thing" } },
2110
3100
  name: "UNSAFE_BINDING_ONE",
@@ -2118,6 +3108,7 @@ export default{
2118
3108
  ],
2119
3109
  });
2120
3110
  mockSubDomainRequest();
3111
+ mockLegacyScriptData({ scripts: [] });
2121
3112
 
2122
3113
  await expect(runWrangler("publish index.js")).resolves.toBeUndefined();
2123
3114
  expect(std.out).toMatchInlineSnapshot(`
@@ -2127,8 +3118,11 @@ export default{
2127
3118
  `);
2128
3119
  expect(std.err).toMatchInlineSnapshot(`""`);
2129
3120
  expect(std.warn).toMatchInlineSnapshot(`
2130
- "Processing wrangler.toml configuration:
2131
- - \\"unsafe\\" fields are experimental and may change or break at any time."
3121
+ "▲ [WARNING] Processing wrangler.toml configuration:
3122
+
3123
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
3124
+
3125
+ "
2132
3126
  `);
2133
3127
  });
2134
3128
 
@@ -2188,6 +3182,10 @@ export default{
2188
3182
  WASM_MODULE_ONE: "./some_wasm.wasm",
2189
3183
  CONFLICTING_NAME_THREE: "./more_wasm.wasm",
2190
3184
  },
3185
+ data_blobs: {
3186
+ DATA_BLOB_ONE: "./some_data.bin",
3187
+ CONFLICTING_NAME_THREE: "./more_data.bin",
3188
+ },
2191
3189
  });
2192
3190
 
2193
3191
  writeWorkerSource({ type: "sw" });
@@ -2204,26 +3202,34 @@ export default{
2204
3202
  [Error: Processing wrangler.toml configuration:
2205
3203
  - CONFLICTING_NAME_ONE assigned to Durable Object, KV Namespace, and R2 Bucket bindings.
2206
3204
  - CONFLICTING_NAME_TWO assigned to Durable Object and KV Namespace bindings.
2207
- - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, and WASM Module bindings.
3205
+ - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, WASM Module, and Data Blob bindings.
2208
3206
  - CONFLICTING_NAME_FOUR assigned to Text Blob and Unsafe bindings.
2209
3207
  - Bindings must have unique names, so that they can all be referenced in the worker.
2210
3208
  Please change your bindings to have unique names.]
2211
3209
  `);
2212
- expect(std.out).toMatchInlineSnapshot(`""`);
3210
+ expect(std.out).toMatchInlineSnapshot(`
3211
+ "
3212
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3213
+ `);
2213
3214
  expect(std.err).toMatchInlineSnapshot(`
2214
- "Processing wrangler.toml configuration:
2215
- - CONFLICTING_NAME_ONE assigned to Durable Object, KV Namespace, and R2 Bucket bindings.
2216
- - CONFLICTING_NAME_TWO assigned to Durable Object and KV Namespace bindings.
2217
- - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, and WASM Module bindings.
2218
- - CONFLICTING_NAME_FOUR assigned to Text Blob and Unsafe bindings.
2219
- - Bindings must have unique names, so that they can all be referenced in the worker.
2220
- Please change your bindings to have unique names.
3215
+ "X [ERROR] Processing wrangler.toml configuration:
3216
+
3217
+ - CONFLICTING_NAME_ONE assigned to Durable Object, KV Namespace, and R2 Bucket bindings.
3218
+ - CONFLICTING_NAME_TWO assigned to Durable Object and KV Namespace bindings.
3219
+ - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, WASM
3220
+ Module, and Data Blob bindings.
3221
+ - CONFLICTING_NAME_FOUR assigned to Text Blob and Unsafe bindings.
3222
+ - Bindings must have unique names, so that they can all be referenced in the worker.
3223
+ Please change your bindings to have unique names.
2221
3224
 
2222
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3225
+ "
2223
3226
  `);
2224
3227
  expect(std.warn).toMatchInlineSnapshot(`
2225
- "Processing wrangler.toml configuration:
2226
- - \\"unsafe\\" fields are experimental and may change or break at any time."
3228
+ "▲ [WARNING] Processing wrangler.toml configuration:
3229
+
3230
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
3231
+
3232
+ "
2227
3233
  `);
2228
3234
  });
2229
3235
 
@@ -2271,7 +3277,7 @@ export default{
2271
3277
  },
2272
3278
  ],
2273
3279
  },
2274
- // text_blobs, vars, and wasm_modules are fine because they're object literals,
3280
+ // text_blobs, vars, wasm_modules and data_blobs are fine because they're object literals,
2275
3281
  // and by definition cannot have two keys of the same name
2276
3282
  //
2277
3283
  // text_blobs: {
@@ -2300,21 +3306,28 @@ export default{
2300
3306
  - Bindings must have unique names, so that they can all be referenced in the worker.
2301
3307
  Please change your bindings to have unique names.]
2302
3308
  `);
2303
- expect(std.out).toMatchInlineSnapshot(`""`);
3309
+ expect(std.out).toMatchInlineSnapshot(`
3310
+ "
3311
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3312
+ `);
2304
3313
  expect(std.err).toMatchInlineSnapshot(`
2305
- "Processing wrangler.toml configuration:
2306
- - CONFLICTING_DURABLE_OBJECT_NAME assigned to multiple Durable Object bindings.
2307
- - CONFLICTING_KV_NAMESPACE_NAME assigned to multiple KV Namespace bindings.
2308
- - CONFLICTING_R2_BUCKET_NAME assigned to multiple R2 Bucket bindings.
2309
- - CONFLICTING_UNSAFE_NAME assigned to multiple Unsafe bindings.
2310
- - Bindings must have unique names, so that they can all be referenced in the worker.
2311
- Please change your bindings to have unique names.
3314
+ "X [ERROR] Processing wrangler.toml configuration:
3315
+
3316
+ - CONFLICTING_DURABLE_OBJECT_NAME assigned to multiple Durable Object bindings.
3317
+ - CONFLICTING_KV_NAMESPACE_NAME assigned to multiple KV Namespace bindings.
3318
+ - CONFLICTING_R2_BUCKET_NAME assigned to multiple R2 Bucket bindings.
3319
+ - CONFLICTING_UNSAFE_NAME assigned to multiple Unsafe bindings.
3320
+ - Bindings must have unique names, so that they can all be referenced in the worker.
3321
+ Please change your bindings to have unique names.
2312
3322
 
2313
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3323
+ "
2314
3324
  `);
2315
3325
  expect(std.warn).toMatchInlineSnapshot(`
2316
- "Processing wrangler.toml configuration:
2317
- - \\"unsafe\\" fields are experimental and may change or break at any time."
3326
+ "▲ [WARNING] Processing wrangler.toml configuration:
3327
+
3328
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
3329
+
3330
+ "
2318
3331
  `);
2319
3332
  });
2320
3333
 
@@ -2400,6 +3413,10 @@ export default{
2400
3413
  WASM_MODULE_ONE: "./some_wasm.wasm",
2401
3414
  CONFLICTING_NAME_THREE: "./more_wasm.wasm",
2402
3415
  },
3416
+ data_blobs: {
3417
+ DATA_BLOB_ONE: "./some_data.bin",
3418
+ CONFLICTING_NAME_THREE: "./more_data.bin",
3419
+ },
2403
3420
  });
2404
3421
 
2405
3422
  writeWorkerSource({ type: "sw" });
@@ -2417,29 +3434,37 @@ export default{
2417
3434
  - CONFLICTING_DURABLE_OBJECT_NAME assigned to multiple Durable Object bindings.
2418
3435
  - CONFLICTING_KV_NAMESPACE_NAME assigned to multiple KV Namespace bindings.
2419
3436
  - CONFLICTING_R2_BUCKET_NAME assigned to multiple R2 Bucket bindings.
2420
- - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, and WASM Module bindings.
3437
+ - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, WASM Module, and Data Blob bindings.
2421
3438
  - CONFLICTING_NAME_FOUR assigned to R2 Bucket, Text Blob, and Unsafe bindings.
2422
3439
  - CONFLICTING_UNSAFE_NAME assigned to multiple Unsafe bindings.
2423
3440
  - Bindings must have unique names, so that they can all be referenced in the worker.
2424
3441
  Please change your bindings to have unique names.]
2425
3442
  `);
2426
- expect(std.out).toMatchInlineSnapshot(`""`);
3443
+ expect(std.out).toMatchInlineSnapshot(`
3444
+ "
3445
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3446
+ `);
2427
3447
  expect(std.err).toMatchInlineSnapshot(`
2428
- "Processing wrangler.toml configuration:
2429
- - CONFLICTING_DURABLE_OBJECT_NAME assigned to multiple Durable Object bindings.
2430
- - CONFLICTING_KV_NAMESPACE_NAME assigned to multiple KV Namespace bindings.
2431
- - CONFLICTING_R2_BUCKET_NAME assigned to multiple R2 Bucket bindings.
2432
- - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, and WASM Module bindings.
2433
- - CONFLICTING_NAME_FOUR assigned to R2 Bucket, Text Blob, and Unsafe bindings.
2434
- - CONFLICTING_UNSAFE_NAME assigned to multiple Unsafe bindings.
2435
- - Bindings must have unique names, so that they can all be referenced in the worker.
2436
- Please change your bindings to have unique names.
2437
-
2438
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3448
+ "X [ERROR] Processing wrangler.toml configuration:
3449
+
3450
+ - CONFLICTING_DURABLE_OBJECT_NAME assigned to multiple Durable Object bindings.
3451
+ - CONFLICTING_KV_NAMESPACE_NAME assigned to multiple KV Namespace bindings.
3452
+ - CONFLICTING_R2_BUCKET_NAME assigned to multiple R2 Bucket bindings.
3453
+ - CONFLICTING_NAME_THREE assigned to R2 Bucket, Text Blob, Unsafe, Environment Variable, WASM
3454
+ Module, and Data Blob bindings.
3455
+ - CONFLICTING_NAME_FOUR assigned to R2 Bucket, Text Blob, and Unsafe bindings.
3456
+ - CONFLICTING_UNSAFE_NAME assigned to multiple Unsafe bindings.
3457
+ - Bindings must have unique names, so that they can all be referenced in the worker.
3458
+ Please change your bindings to have unique names.
3459
+
3460
+ "
2439
3461
  `);
2440
3462
  expect(std.warn).toMatchInlineSnapshot(`
2441
- "Processing wrangler.toml configuration:
2442
- - \\"unsafe\\" fields are experimental and may change or break at any time."
3463
+ "▲ [WARNING] Processing wrangler.toml configuration:
3464
+
3465
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
3466
+
3467
+ "
2443
3468
  `);
2444
3469
  });
2445
3470
 
@@ -2486,12 +3511,15 @@ export default{
2486
3511
  ).rejects.toThrowErrorMatchingInlineSnapshot(
2487
3512
  `"You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code"`
2488
3513
  );
2489
- expect(std.out).toMatchInlineSnapshot(`""`);
3514
+ expect(std.out).toMatchInlineSnapshot(`
3515
+ "
3516
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3517
+ `);
2490
3518
  expect(std.err).toMatchInlineSnapshot(`
2491
- "You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code
3519
+ "X [ERROR] You cannot configure [wasm_modules] with an ES module worker. Instead, import the .wasm module directly in your code
2492
3520
 
2493
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2494
- `);
3521
+ "
3522
+ `);
2495
3523
  expect(std.warn).toMatchInlineSnapshot(`""`);
2496
3524
  });
2497
3525
 
@@ -2612,14 +3640,17 @@ export default{
2612
3640
  await expect(
2613
3641
  runWrangler("publish index.js")
2614
3642
  ).rejects.toThrowErrorMatchingInlineSnapshot(
2615
- `"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"`
3643
+ `"You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your wrangler.toml"`
2616
3644
  );
2617
- expect(std.out).toMatchInlineSnapshot(`""`);
3645
+ expect(std.out).toMatchInlineSnapshot(`
3646
+ "
3647
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3648
+ `);
2618
3649
  expect(std.err).toMatchInlineSnapshot(`
2619
- "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
3650
+ "X [ERROR] You cannot configure [text_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your wrangler.toml
2620
3651
 
2621
- %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2622
- `);
3652
+ "
3653
+ `);
2623
3654
  expect(std.warn).toMatchInlineSnapshot(`""`);
2624
3655
  });
2625
3656
 
@@ -2667,6 +3698,109 @@ export default{
2667
3698
  });
2668
3699
  });
2669
3700
 
3701
+ describe("[data_blobs]", () => {
3702
+ it("should be able to define data blobs for service-worker format workers", async () => {
3703
+ writeWranglerToml({
3704
+ data_blobs: {
3705
+ TESTDATABLOBNAME: "./path/to/data.bin",
3706
+ },
3707
+ });
3708
+ writeWorkerSource({ type: "sw" });
3709
+ fs.mkdirSync("./path/to", { recursive: true });
3710
+ fs.writeFileSync("./path/to/data.bin", "SOME DATA CONTENT");
3711
+ mockUploadWorkerRequest({
3712
+ expectedType: "sw",
3713
+ expectedModules: { TESTDATABLOBNAME: "SOME DATA CONTENT" },
3714
+ expectedBindings: [
3715
+ {
3716
+ name: "TESTDATABLOBNAME",
3717
+ part: "TESTDATABLOBNAME",
3718
+ type: "data_blob",
3719
+ },
3720
+ ],
3721
+ });
3722
+ mockSubDomainRequest();
3723
+ await runWrangler("publish index.js");
3724
+ expect(std.out).toMatchInlineSnapshot(`
3725
+ "Uploaded test-name (TIMINGS)
3726
+ Published test-name (TIMINGS)
3727
+ test-name.test-sub-domain.workers.dev"
3728
+ `);
3729
+ expect(std.err).toMatchInlineSnapshot(`""`);
3730
+ expect(std.warn).toMatchInlineSnapshot(`""`);
3731
+ });
3732
+
3733
+ it("should error when defining data blobs for modules format workers", async () => {
3734
+ writeWranglerToml({
3735
+ data_blobs: {
3736
+ TESTDATABLOBNAME: "./path/to/data.bin",
3737
+ },
3738
+ });
3739
+ writeWorkerSource({ type: "esm" });
3740
+ fs.mkdirSync("./path/to", { recursive: true });
3741
+ fs.writeFileSync("./path/to/data.bin", "SOME DATA CONTENT");
3742
+
3743
+ await expect(
3744
+ runWrangler("publish index.js")
3745
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
3746
+ `"You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your wrangler.toml"`
3747
+ );
3748
+ expect(std.out).toMatchInlineSnapshot(`
3749
+ "
3750
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
3751
+ `);
3752
+ expect(std.err).toMatchInlineSnapshot(`
3753
+ "X [ERROR] You cannot configure [data_blobs] with an ES module worker. Instead, import the file directly in your code, and optionally configure \`[rules]\` in your wrangler.toml
3754
+
3755
+ "
3756
+ `);
3757
+ expect(std.warn).toMatchInlineSnapshot(`""`);
3758
+ });
3759
+
3760
+ it("should resolve data blobs relative to the wrangler.toml file", async () => {
3761
+ fs.mkdirSync("./path/to/and/the/path/to/", { recursive: true });
3762
+ fs.writeFileSync(
3763
+ "./path/to/wrangler.toml",
3764
+ TOML.stringify({
3765
+ compatibility_date: "2022-01-12",
3766
+ name: "test-name",
3767
+ data_blobs: {
3768
+ TESTDATABLOBNAME: "./and/the/path/to/data.bin",
3769
+ },
3770
+ }),
3771
+
3772
+ "utf-8"
3773
+ );
3774
+
3775
+ writeWorkerSource({ type: "sw" });
3776
+ fs.writeFileSync(
3777
+ "./path/to/and/the/path/to/data.bin",
3778
+ "SOME DATA CONTENT"
3779
+ );
3780
+ mockUploadWorkerRequest({
3781
+ expectedType: "sw",
3782
+ expectedModules: { TESTDATABLOBNAME: "SOME DATA CONTENT" },
3783
+ expectedBindings: [
3784
+ {
3785
+ name: "TESTDATABLOBNAME",
3786
+ part: "TESTDATABLOBNAME",
3787
+ type: "data_blob",
3788
+ },
3789
+ ],
3790
+ expectedCompatibilityDate: "2022-01-12",
3791
+ });
3792
+ mockSubDomainRequest();
3793
+ await runWrangler("publish index.js --config ./path/to/wrangler.toml");
3794
+ expect(std.out).toMatchInlineSnapshot(`
3795
+ "Uploaded test-name (TIMINGS)
3796
+ Published test-name (TIMINGS)
3797
+ test-name.test-sub-domain.workers.dev"
3798
+ `);
3799
+ expect(std.err).toMatchInlineSnapshot(`""`);
3800
+ expect(std.warn).toMatchInlineSnapshot(`""`);
3801
+ });
3802
+ });
3803
+
2670
3804
  describe("[vars]", () => {
2671
3805
  it("should support json bindings", async () => {
2672
3806
  writeWranglerToml({
@@ -2736,9 +3870,16 @@ export default{
2736
3870
  },
2737
3871
  ],
2738
3872
  },
3873
+ migrations: [{ tag: "v1", new_classes: ["ExampleDurableObject"] }],
2739
3874
  });
2740
- writeWorkerSource({ type: "esm" });
3875
+ fs.writeFileSync(
3876
+ "index.js",
3877
+ `export class ExampleDurableObject {}; export default{};`
3878
+ );
2741
3879
  mockSubDomainRequest();
3880
+ mockLegacyScriptData({
3881
+ scripts: [{ id: "test-name", migration_tag: "v1" }],
3882
+ });
2742
3883
  mockUploadWorkerRequest({
2743
3884
  expectedBindings: [
2744
3885
  {
@@ -2805,9 +3946,16 @@ export default{
2805
3946
  },
2806
3947
  ],
2807
3948
  },
3949
+ migrations: [{ tag: "v1", new_classes: ["ExampleDurableObject"] }],
2808
3950
  });
2809
- writeWorkerSource({ type: "esm" });
3951
+ fs.writeFileSync(
3952
+ "index.js",
3953
+ `export class ExampleDurableObject {}; export default{};`
3954
+ );
2810
3955
  mockSubDomainRequest();
3956
+ mockLegacyScriptData({
3957
+ scripts: [{ id: "test-name", migration_tag: "v1" }],
3958
+ });
2811
3959
  mockUploadWorkerRequest({
2812
3960
  expectedType: "esm",
2813
3961
  expectedBindings: [
@@ -2829,7 +3977,7 @@ export default{
2829
3977
  expect(std.warn).toMatchInlineSnapshot(`""`);
2830
3978
  });
2831
3979
 
2832
- it("should error when detecting service workers implementing durable objects", async () => {
3980
+ it("should error when detecting a service-worker worker implementing durable objects", async () => {
2833
3981
  writeWranglerToml({
2834
3982
  durable_objects: {
2835
3983
  bindings: [
@@ -2845,7 +3993,7 @@ export default{
2845
3993
 
2846
3994
  await expect(runWrangler("publish index.js")).rejects
2847
3995
  .toThrowErrorMatchingInlineSnapshot(`
2848
- "You seem to be trying to use Durable Objects in a Worker written with Service Worker syntax.
3996
+ "You seem to be trying to use Durable Objects in a Worker written as a service-worker.
2849
3997
  You can use Durable Objects defined in other Workers by specifying a \`script_name\` in your wrangler.toml, where \`script_name\` is the name of the Worker that implements that Durable Object. For example:
2850
3998
  { name = EXAMPLE_DO_BINDING, class_name = ExampleDurableObject } ==> { name = EXAMPLE_DO_BINDING, class_name = ExampleDurableObject, script_name = example-do-binding-worker }
2851
3999
  Alternatively, migrate your worker to ES Module syntax to implement a Durable Object in this Worker:
@@ -2887,9 +4035,12 @@ export default{
2887
4035
  `);
2888
4036
  expect(std.err).toMatchInlineSnapshot(`""`);
2889
4037
  expect(std.warn).toMatchInlineSnapshot(`
2890
- "Processing wrangler.toml configuration:
2891
- - \\"unsafe\\" fields are experimental and may change or break at any time."
2892
- `);
4038
+ "▲ [WARNING] Processing wrangler.toml configuration:
4039
+
4040
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
4041
+
4042
+ "
4043
+ `);
2893
4044
  });
2894
4045
  it("should warn if using unsafe bindings already handled by wrangler", async () => {
2895
4046
  writeWranglerToml({
@@ -2923,13 +4074,17 @@ export default{
2923
4074
  `);
2924
4075
  expect(std.err).toMatchInlineSnapshot(`""`);
2925
4076
  expect(std.warn).toMatchInlineSnapshot(`
2926
- "Processing wrangler.toml configuration:
2927
- - \\"unsafe\\" fields are experimental and may change or break at any time.
2928
- - \\"unsafe.bindings[0]\\": {\\"name\\":\\"my-binding\\",\\"type\\":\\"plain_text\\",\\"text\\":\\"text\\"}
2929
- - The binding type \\"plain_text\\" is directly supported by wrangler.
2930
- Consider migrating this unsafe binding to a format for 'plain_text' bindings that is supported by wrangler for optimal support.
2931
- For more details, see https://developers.cloudflare.com/workers/cli-wrangler/configuration"
2932
- `);
4077
+ "▲ [WARNING] Processing wrangler.toml configuration:
4078
+
4079
+ - \\"unsafe\\" fields are experimental and may change or break at any time.
4080
+ - \\"unsafe.bindings[0]\\": {\\"name\\":\\"my-binding\\",\\"type\\":\\"plain_text\\",\\"text\\":\\"text\\"}
4081
+ - The binding type \\"plain_text\\" is directly supported by wrangler.
4082
+ Consider migrating this unsafe binding to a format for 'plain_text' bindings that is
4083
+ supported by wrangler for optimal support.
4084
+ For more details, see https://developers.cloudflare.com/workers/cli-wrangler/configuration
4085
+
4086
+ "
4087
+ `);
2933
4088
  });
2934
4089
  });
2935
4090
  });
@@ -3024,14 +4179,19 @@ export default{
3024
4179
  `);
3025
4180
  expect(std.err).toMatchInlineSnapshot(`""`);
3026
4181
  expect(std.warn).toMatchInlineSnapshot(`
3027
- "Processing wrangler.toml configuration:
3028
- - 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:
3029
- \`\`\`
3030
- [[rules]]
3031
- type = \\"Text\\"
3032
- globs = [ \\"**/*.file\\" ]
3033
- fallthrough = true
3034
- \`\`\`"
4182
+ "▲ [WARNING] Processing wrangler.toml configuration:
4183
+
4184
+ - Deprecation: The \`build.upload.rules\` config field is no longer used, the rules should be
4185
+ specified via the \`rules\` config field. Delete the \`build.upload\` field from the configuration
4186
+ file, and add this:
4187
+ \`\`\`
4188
+ [[rules]]
4189
+ type = \\"Text\\"
4190
+ globs = [ \\"**/*.file\\" ]
4191
+ fallthrough = true
4192
+ \`\`\`
4193
+
4194
+ "
3035
4195
  `);
3036
4196
  });
3037
4197
 
@@ -3123,8 +4283,12 @@ export default{
3123
4283
  );
3124
4284
  // and the warnings because fallthrough was not explicitly set
3125
4285
  expect(std.warn).toMatchInlineSnapshot(`
3126
- "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.
3127
- 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."
4286
+ "▲ [WARNING] 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.
4287
+
4288
+
4289
+ ▲ [WARNING] 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.
4290
+
4291
+ "
3128
4292
  `);
3129
4293
  });
3130
4294
 
@@ -3187,93 +4351,215 @@ export default{
3187
4351
  test-name.test-sub-domain.workers.dev"
3188
4352
  `);
3189
4353
  expect(std.err).toMatchInlineSnapshot(`""`);
3190
- expect(std.warn).toMatchInlineSnapshot(
3191
- `"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\\";"`
4354
+ expect(std.warn).toMatchInlineSnapshot(`
4355
+ "▲ [WARNING] Deprecation: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"text.file\\" with \\"./text.file\\";
4356
+
4357
+ "
4358
+ `);
4359
+ });
4360
+
4361
+ it("should work with legacy module specifiers, with a deprecation warning (2)", async () => {
4362
+ writeWranglerToml();
4363
+ fs.writeFileSync(
4364
+ "./index.js",
4365
+ `import WASM from 'index.wasm'; export default {};`
4366
+ );
4367
+ fs.writeFileSync("./index.wasm", "SOME WASM CONTENT");
4368
+ mockSubDomainRequest();
4369
+ mockUploadWorkerRequest({
4370
+ expectedModules: {
4371
+ "./94b240d0d692281e6467aa42043986e5c7eea034-index.wasm":
4372
+ "SOME WASM CONTENT",
4373
+ },
4374
+ });
4375
+ await runWrangler("publish index.js");
4376
+ expect(std.out).toMatchInlineSnapshot(`
4377
+ "Uploaded test-name (TIMINGS)
4378
+ Published test-name (TIMINGS)
4379
+ test-name.test-sub-domain.workers.dev"
4380
+ `);
4381
+ expect(std.err).toMatchInlineSnapshot(`""`);
4382
+ expect(std.warn).toMatchInlineSnapshot(`
4383
+ "▲ [WARNING] Deprecation: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"index.wasm\\" with \\"./index.wasm\\";
4384
+
4385
+ "
4386
+ `);
4387
+ });
4388
+
4389
+ it("should not match regular module specifiers when there aren't any possible legacy module matches", async () => {
4390
+ // see https://github.com/cloudflare/wrangler2/issues/655 for bug details
4391
+
4392
+ fs.writeFileSync(
4393
+ "./index.js",
4394
+ `import inner from './inner/index.js'; export default {};`
4395
+ );
4396
+ fs.mkdirSync("./inner", { recursive: true });
4397
+ fs.writeFileSync("./inner/index.js", `export default 123`);
4398
+ mockSubDomainRequest();
4399
+ mockUploadWorkerRequest();
4400
+
4401
+ await runWrangler(
4402
+ "publish index.js --compatibility-date 2022-03-17 --name test-name"
3192
4403
  );
4404
+ expect(std.out).toMatchInlineSnapshot(`
4405
+ "Uploaded test-name (TIMINGS)
4406
+ Published test-name (TIMINGS)
4407
+ test-name.test-sub-domain.workers.dev"
4408
+ `);
4409
+ expect(std.err).toMatchInlineSnapshot(`""`);
4410
+ expect(std.warn).toMatchInlineSnapshot(`""`);
3193
4411
  });
3194
4412
  });
3195
4413
 
3196
- it("should work with legacy module specifiers, with a deprecation warning (2)", async () => {
3197
- writeWranglerToml();
3198
- fs.writeFileSync(
3199
- "./index.js",
3200
- `import WASM from 'index.wasm'; export default {};`
3201
- );
3202
- fs.writeFileSync("./index.wasm", "SOME WASM CONTENT");
3203
- mockSubDomainRequest();
3204
- mockUploadWorkerRequest({
3205
- expectedModules: {
3206
- "./94b240d0d692281e6467aa42043986e5c7eea034-index.wasm":
3207
- "SOME WASM CONTENT",
3208
- },
4414
+ describe("tsconfig", () => {
4415
+ it("should use compilerOptions.paths to resolve modules", async () => {
4416
+ writeWranglerToml({
4417
+ main: "index.ts",
4418
+ });
4419
+ fs.writeFileSync(
4420
+ "index.ts",
4421
+ `import { foo } from '~lib/foo'; export default { fetch() { return new Response(foo)} }`
4422
+ );
4423
+ fs.mkdirSync("lib", { recursive: true });
4424
+ fs.writeFileSync("lib/foo.ts", `export const foo = 123;`);
4425
+ fs.writeFileSync(
4426
+ "tsconfig.json",
4427
+ JSON.stringify({
4428
+ compilerOptions: {
4429
+ baseUrl: ".",
4430
+ paths: {
4431
+ "~lib/*": ["lib/*"],
4432
+ },
4433
+ },
4434
+ })
4435
+ );
4436
+ mockSubDomainRequest();
4437
+ mockUploadWorkerRequest({
4438
+ expectedEntry: "var foo = 123;", // make sure it imported the module correctly
4439
+ });
4440
+ await runWrangler("publish index.ts");
4441
+ expect(std).toMatchInlineSnapshot(`
4442
+ Object {
4443
+ "debug": "",
4444
+ "err": "",
4445
+ "out": "Uploaded test-name (TIMINGS)
4446
+ Published test-name (TIMINGS)
4447
+ test-name.test-sub-domain.workers.dev",
4448
+ "warn": "",
4449
+ }
4450
+ `);
4451
+ });
4452
+
4453
+ it("should output to target es2020 even if tsconfig says otherwise", async () => {
4454
+ writeWranglerToml();
4455
+ writeWorkerSource();
4456
+ fs.writeFileSync(
4457
+ "tsconfig.json",
4458
+ JSON.stringify({
4459
+ compilerOptions: {
4460
+ target: "es5",
4461
+ module: "commonjs",
4462
+ },
4463
+ })
4464
+ );
4465
+ mockSubDomainRequest();
4466
+ mockUploadWorkerRequest({
4467
+ expectedEntry: "export {", // just check that the export is preserved
4468
+ });
4469
+ await runWrangler("publish index.js"); // this would throw if we tried to compile with es5
4470
+ expect(std).toMatchInlineSnapshot(`
4471
+ Object {
4472
+ "debug": "",
4473
+ "err": "",
4474
+ "out": "Uploaded test-name (TIMINGS)
4475
+ Published test-name (TIMINGS)
4476
+ test-name.test-sub-domain.workers.dev",
4477
+ "warn": "",
4478
+ }
4479
+ `);
4480
+ });
4481
+ });
4482
+
4483
+ describe("--outdir", () => {
4484
+ it("should generate built assets at --outdir if specified", async () => {
4485
+ writeWranglerToml();
4486
+ writeWorkerSource();
4487
+ mockSubDomainRequest();
4488
+ mockUploadWorkerRequest();
4489
+ await runWrangler("publish index.js --outdir some-dir");
4490
+ expect(fs.existsSync("some-dir/index.js")).toBe(true);
4491
+ expect(fs.existsSync("some-dir/index.js.map")).toBe(true);
4492
+ expect(std).toMatchInlineSnapshot(`
4493
+ Object {
4494
+ "debug": "",
4495
+ "err": "",
4496
+ "out": "Uploaded test-name (TIMINGS)
4497
+ Published test-name (TIMINGS)
4498
+ test-name.test-sub-domain.workers.dev",
4499
+ "warn": "",
4500
+ }
4501
+ `);
3209
4502
  });
3210
- await runWrangler("publish index.js");
3211
- expect(std.out).toMatchInlineSnapshot(`
3212
- "Uploaded test-name (TIMINGS)
3213
- Published test-name (TIMINGS)
3214
- test-name.test-sub-domain.workers.dev"
3215
- `);
3216
- expect(std.err).toMatchInlineSnapshot(`""`);
3217
- expect(std.warn).toMatchInlineSnapshot(
3218
- `"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\\";"`
3219
- );
3220
4503
  });
3221
4504
 
3222
- it("should not match regular module specifiers when there aren't any possible legacy module matches", async () => {
3223
- // see https://github.com/cloudflare/wrangler2/issues/655 for bug details
4505
+ describe("--dry-run", () => {
4506
+ it("should not publish the worker if --dry-run is specified", async () => {
4507
+ writeWranglerToml();
4508
+ writeWorkerSource();
4509
+ await runWrangler("publish index.js --dry-run");
4510
+ expect(std).toMatchInlineSnapshot(`
4511
+ Object {
4512
+ "debug": "",
4513
+ "err": "",
4514
+ "out": "--dry-run: exiting now.",
4515
+ "warn": "",
4516
+ }
4517
+ `);
4518
+ });
4519
+ });
3224
4520
 
3225
- fs.writeFileSync(
3226
- "./index.js",
3227
- `import inner from './inner/index.js'; export default {};`
3228
- );
3229
- fs.mkdirSync("./inner", { recursive: true });
3230
- fs.writeFileSync("./inner/index.js", `export default 123`);
3231
- mockSubDomainRequest();
3232
- mockUploadWorkerRequest();
4521
+ describe("--node-compat", () => {
4522
+ it("should warn when using node compatibility mode", async () => {
4523
+ writeWranglerToml();
4524
+ writeWorkerSource();
4525
+ await runWrangler("publish index.js --node-compat --dry-run");
4526
+ expect(std).toMatchInlineSnapshot(`
4527
+ Object {
4528
+ "debug": "",
4529
+ "err": "",
4530
+ "out": "--dry-run: exiting now.",
4531
+ "warn": "▲ [WARNING] Enabling node.js compatibility mode for builtins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.
4532
+
4533
+ ",
4534
+ }
4535
+ `);
4536
+ });
3233
4537
 
3234
- await runWrangler(
3235
- "publish index.js --compatibility-date 2022-03-17 --name test-name"
3236
- );
3237
- expect(std.out).toMatchInlineSnapshot(`
3238
- "Uploaded test-name (TIMINGS)
3239
- Published test-name (TIMINGS)
3240
- test-name.test-sub-domain.workers.dev"
3241
- `);
3242
- expect(std.err).toMatchInlineSnapshot(`""`);
3243
- expect(std.warn).toMatchInlineSnapshot(`""`);
4538
+ it("should polyfill node builtins when enabled", async () => {
4539
+ writeWranglerToml();
4540
+ fs.writeFileSync(
4541
+ "index.js",
4542
+ `
4543
+ import path from 'path';
4544
+ console.log(path.join("some/path/to", "a/file.txt"));
4545
+ export default {}
4546
+ `
4547
+ );
4548
+ await runWrangler("publish index.js --node-compat --dry-run"); // this would throw if node compatibility didn't exist
4549
+ expect(std).toMatchInlineSnapshot(`
4550
+ Object {
4551
+ "debug": "",
4552
+ "err": "",
4553
+ "out": "--dry-run: exiting now.",
4554
+ "warn": "▲ [WARNING] Enabling node.js compatibility mode for builtins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.
4555
+
4556
+ ",
4557
+ }
4558
+ `);
4559
+ });
3244
4560
  });
3245
4561
  });
3246
4562
 
3247
- /** Write a mock Worker script to disk. */
3248
- function writeWorkerSource({
3249
- basePath = ".",
3250
- format = "js",
3251
- type = "esm",
3252
- }: {
3253
- basePath?: string;
3254
- format?: "js" | "ts" | "jsx" | "tsx" | "mjs";
3255
- type?: "esm" | "sw";
3256
- } = {}) {
3257
- if (basePath !== ".") {
3258
- fs.mkdirSync(basePath, { recursive: true });
3259
- }
3260
- fs.writeFileSync(
3261
- `${basePath}/index.${format}`,
3262
- type === "esm"
3263
- ? `import { foo } from "./another";
3264
- export default {
3265
- async fetch(request) {
3266
- return new Response('Hello' + foo);
3267
- },
3268
- };`
3269
- : `import { foo } from "./another";
3270
- addEventListener('fetch', event => {
3271
- event.respondWith(new Response('Hello' + foo));
3272
- })`
3273
- );
3274
- fs.writeFileSync(`${basePath}/another.${format}`, `export const foo = 100;`);
3275
- }
3276
-
3277
4563
  /** Write mock assets to the file system so they can be uploaded. */
3278
4564
  function writeAssets(assets: { filePath: string; content: string }[]) {
3279
4565
  for (const asset of assets) {
@@ -3283,27 +4569,32 @@ function writeAssets(assets: { filePath: string; content: string }[]) {
3283
4569
  }
3284
4570
 
3285
4571
  /** Create a mock handler for the request to upload a worker script. */
3286
- function mockUploadWorkerRequest({
3287
- available_on_subdomain = true,
3288
- expectedEntry,
3289
- expectedType = "esm",
3290
- expectedBindings,
3291
- expectedModules = {},
3292
- expectedCompatibilityDate,
3293
- expectedCompatibilityFlags,
3294
- env = undefined,
3295
- legacyEnv = false,
3296
- }: {
3297
- available_on_subdomain?: boolean;
3298
- expectedEntry?: string;
3299
- expectedType?: "esm" | "sw";
3300
- expectedBindings?: unknown;
3301
- expectedModules?: Record<string, string>;
3302
- expectedCompatibilityDate?: string;
3303
- expectedCompatibilityFlags?: string[];
3304
- env?: string;
3305
- legacyEnv?: boolean;
3306
- } = {}) {
4572
+ function mockUploadWorkerRequest(
4573
+ options: {
4574
+ available_on_subdomain?: boolean;
4575
+ expectedEntry?: string;
4576
+ expectedType?: "esm" | "sw";
4577
+ expectedBindings?: unknown;
4578
+ expectedModules?: Record<string, string>;
4579
+ expectedCompatibilityDate?: string;
4580
+ expectedCompatibilityFlags?: string[];
4581
+ expectedMigrations?: CfWorkerInit["migrations"];
4582
+ env?: string;
4583
+ legacyEnv?: boolean;
4584
+ } = {}
4585
+ ) {
4586
+ const {
4587
+ available_on_subdomain = true,
4588
+ expectedEntry,
4589
+ expectedType = "esm",
4590
+ expectedBindings,
4591
+ expectedModules = {},
4592
+ expectedCompatibilityDate,
4593
+ expectedCompatibilityFlags,
4594
+ env = undefined,
4595
+ legacyEnv = false,
4596
+ expectedMigrations,
4597
+ } = options;
3307
4598
  setMockResponse(
3308
4599
  env && !legacyEnv
3309
4600
  ? "/accounts/:accountId/workers/services/:scriptName/environments/:envName"
@@ -3317,7 +4608,7 @@ function mockUploadWorkerRequest({
3317
4608
  if (!legacyEnv) {
3318
4609
  expect(envName).toEqual(env);
3319
4610
  }
3320
- expect(queryParams.get("available_on_subdomain")).toEqual("true");
4611
+ expect(queryParams.get("include_subdomain_availability")).toEqual("true");
3321
4612
  const formBody = body as FormData;
3322
4613
  if (expectedEntry !== undefined) {
3323
4614
  expect(await (formBody.get("index.js") as File).text()).toMatch(
@@ -3332,17 +4623,20 @@ function mockUploadWorkerRequest({
3332
4623
  } else {
3333
4624
  expect(metadata.body_part).toEqual("index.js");
3334
4625
  }
3335
- if (expectedBindings !== undefined) {
4626
+ if ("expectedBindings" in options) {
3336
4627
  expect(metadata.bindings).toEqual(expectedBindings);
3337
4628
  }
3338
- if (expectedCompatibilityDate !== undefined) {
4629
+ if ("expectedCompatibilityDate" in options) {
3339
4630
  expect(metadata.compatibility_date).toEqual(expectedCompatibilityDate);
3340
4631
  }
3341
- if (expectedCompatibilityFlags !== undefined) {
4632
+ if ("expectedCompatibilityFlags" in options) {
3342
4633
  expect(metadata.compatibility_flags).toEqual(
3343
4634
  expectedCompatibilityFlags
3344
4635
  );
3345
4636
  }
4637
+ if ("expectedMigrations" in options) {
4638
+ expect(metadata.migrations).toEqual(expectedMigrations);
4639
+ }
3346
4640
  for (const [name, content] of Object.entries(expectedModules)) {
3347
4641
  expect(await (formBody.get(name) as File).text()).toEqual(content);
3348
4642
  }
@@ -3402,11 +4696,11 @@ function mockUpdateWorkerRequest({
3402
4696
  }
3403
4697
 
3404
4698
  function mockPublishRoutesRequest({
3405
- routes,
4699
+ routes = [],
3406
4700
  env = undefined,
3407
4701
  legacyEnv = false,
3408
4702
  }: {
3409
- routes: string[];
4703
+ routes: Config["routes"];
3410
4704
  env?: string | undefined;
3411
4705
  legacyEnv?: boolean | undefined;
3412
4706
  }) {
@@ -3426,7 +4720,9 @@ function mockPublishRoutesRequest({
3426
4720
  }
3427
4721
 
3428
4722
  expect(JSON.parse(body as string)).toEqual(
3429
- routes.map((pattern) => ({ pattern }))
4723
+ routes.map((route) =>
4724
+ typeof route !== "object" ? { pattern: route } : route
4725
+ )
3430
4726
  );
3431
4727
  return null;
3432
4728
  }
@@ -3507,3 +4803,73 @@ function mockDeleteUnusedAssetsRequest(
3507
4803
  }
3508
4804
  );
3509
4805
  }
4806
+
4807
+ type LegacyScriptInfo = { id: string; migration_tag?: string };
4808
+
4809
+ function mockLegacyScriptData(options: { scripts: LegacyScriptInfo[] }) {
4810
+ const { scripts } = options;
4811
+ setMockResponse(
4812
+ "/accounts/:accountId/workers/scripts",
4813
+ "GET",
4814
+ ([_url, accountId]) => {
4815
+ expect(accountId).toEqual("some-account-id");
4816
+ return scripts;
4817
+ }
4818
+ );
4819
+ }
4820
+
4821
+ type DurableScriptInfo = { id: string; migration_tag?: string };
4822
+
4823
+ function mockServiceScriptData(options: {
4824
+ script?: DurableScriptInfo;
4825
+ scriptName?: string;
4826
+ env?: string;
4827
+ }) {
4828
+ const { script } = options;
4829
+ if (options.env) {
4830
+ if (!script) {
4831
+ setMockRawResponse(
4832
+ "/accounts/:accountId/workers/services/:scriptName/environments/:envName",
4833
+ "GET",
4834
+ () => {
4835
+ return createFetchResult(null, false, [
4836
+ { code: 10092, message: "workers.api.error.environment_not_found" },
4837
+ ]);
4838
+ }
4839
+ );
4840
+ return;
4841
+ }
4842
+ setMockResponse(
4843
+ "/accounts/:accountId/workers/services/:scriptName/environments/:envName",
4844
+ "GET",
4845
+ ([_url, accountId, scriptName, envName]) => {
4846
+ expect(accountId).toEqual("some-account-id");
4847
+ expect(scriptName).toEqual(options.scriptName || "test-name");
4848
+ expect(envName).toEqual(options.env);
4849
+ return { script };
4850
+ }
4851
+ );
4852
+ } else {
4853
+ if (!script) {
4854
+ setMockRawResponse(
4855
+ "/accounts/:accountId/workers/services/:scriptName",
4856
+ "GET",
4857
+ () => {
4858
+ return createFetchResult(null, false, [
4859
+ { code: 10090, message: "workers.api.error.service_not_found" },
4860
+ ]);
4861
+ }
4862
+ );
4863
+ return;
4864
+ }
4865
+ setMockResponse(
4866
+ "/accounts/:accountId/workers/services/:scriptName",
4867
+ "GET",
4868
+ ([_url, accountId, scriptName]) => {
4869
+ expect(accountId).toEqual("some-account-id");
4870
+ expect(scriptName).toEqual(options.scriptName || "test-name");
4871
+ return { default_environment: { script } };
4872
+ }
4873
+ );
4874
+ }
4875
+ }