wrangler 2.0.8 → 2.0.12

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 (67) hide show
  1. package/kv-asset-handler.js +1 -0
  2. package/package.json +3 -1
  3. package/src/__tests__/configuration.test.ts +255 -142
  4. package/src/__tests__/dev.test.tsx +88 -58
  5. package/src/__tests__/index.test.ts +2 -1
  6. package/src/__tests__/init.test.ts +3 -0
  7. package/src/__tests__/kv.test.ts +23 -2
  8. package/src/__tests__/pages.test.ts +98 -1
  9. package/src/__tests__/publish.test.ts +514 -162
  10. package/src/__tests__/whoami.test.tsx +34 -0
  11. package/src/bundle.ts +9 -5
  12. package/src/cfetch/internal.ts +6 -9
  13. package/src/config/config.ts +1 -1
  14. package/src/config/environment.ts +1 -1
  15. package/src/config/validation-helpers.ts +10 -1
  16. package/src/config/validation.ts +22 -13
  17. package/src/create-worker-preview.ts +15 -15
  18. package/src/dev/dev.tsx +32 -56
  19. package/src/dev/local.tsx +10 -7
  20. package/src/dev/remote.tsx +30 -17
  21. package/src/dev/use-esbuild.ts +1 -4
  22. package/src/index.tsx +239 -244
  23. package/src/kv.ts +1 -1
  24. package/src/pages.tsx +295 -229
  25. package/src/parse.ts +21 -1
  26. package/src/proxy.ts +19 -6
  27. package/src/publish.ts +154 -16
  28. package/src/sites.tsx +49 -18
  29. package/src/user.tsx +12 -1
  30. package/src/whoami.tsx +3 -2
  31. package/src/worker.ts +2 -1
  32. package/src/zones.ts +73 -0
  33. package/templates/static-asset-facade.js +1 -5
  34. package/wrangler-dist/cli.js +73693 -73458
  35. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  36. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  37. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  38. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  39. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  40. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  41. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  42. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  43. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  44. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  45. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  46. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  47. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  48. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  49. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  50. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  51. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  52. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  53. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  54. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  55. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  56. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  57. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  58. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  59. package/vendor/wrangler-mime/LICENSE +0 -21
  60. package/vendor/wrangler-mime/Mime.js +0 -97
  61. package/vendor/wrangler-mime/README.md +0 -187
  62. package/vendor/wrangler-mime/cli.js +0 -46
  63. package/vendor/wrangler-mime/index.js +0 -4
  64. package/vendor/wrangler-mime/lite.js +0 -4
  65. package/vendor/wrangler-mime/package.json +0 -52
  66. package/vendor/wrangler-mime/types/other.js +0 -1
  67. package/vendor/wrangler-mime/types/standard.js +0 -1
@@ -3,7 +3,6 @@ import getPort from "get-port";
3
3
  import patchConsole from "patch-console";
4
4
  import dedent from "ts-dedent";
5
5
  import Dev from "../dev/dev";
6
- import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
7
6
  import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
8
7
  import { mockConsoleMethods } from "./helpers/mock-console";
9
8
  import { runInTempDir } from "./helpers/run-in-tmp";
@@ -11,8 +10,6 @@ import { runWrangler } from "./helpers/run-wrangler";
11
10
  import writeWranglerToml from "./helpers/write-wrangler-toml";
12
11
 
13
12
  describe("wrangler dev", () => {
14
- mockAccountId();
15
- mockApiToken();
16
13
  runInTempDir();
17
14
  const std = mockConsoleMethods();
18
15
  afterEach(() => {
@@ -152,10 +149,12 @@ describe("wrangler dev", () => {
152
149
  fs.writeFileSync("index.js", `export default {};`);
153
150
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
154
151
  await runWrangler("dev --host some-host.com");
155
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
156
- host: "some-host.com",
157
- id: "some-zone-id",
158
- });
152
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
153
+ expect.objectContaining({
154
+ host: "some-host.com",
155
+ zone: "some-zone-id",
156
+ })
157
+ );
159
158
  });
160
159
 
161
160
  it("should read wrangler.toml's dev.host", async () => {
@@ -168,9 +167,7 @@ describe("wrangler dev", () => {
168
167
  fs.writeFileSync("index.js", `export default {};`);
169
168
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
170
169
  await runWrangler("dev");
171
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
172
- "some-host.com"
173
- );
170
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
174
171
  });
175
172
 
176
173
  it("should read --route", async () => {
@@ -180,9 +177,7 @@ describe("wrangler dev", () => {
180
177
  fs.writeFileSync("index.js", `export default {};`);
181
178
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
182
179
  await runWrangler("dev --route http://some-host.com/some/path/*");
183
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
184
- "some-host.com"
185
- );
180
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
186
181
  });
187
182
 
188
183
  it("should read wrangler.toml's routes", async () => {
@@ -196,9 +191,7 @@ describe("wrangler dev", () => {
196
191
  fs.writeFileSync("index.js", `export default {};`);
197
192
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
198
193
  await runWrangler("dev");
199
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
200
- "some-host.com"
201
- );
194
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
202
195
  });
203
196
 
204
197
  it("should read wrangler.toml's environment specific routes", async () => {
@@ -220,9 +213,7 @@ describe("wrangler dev", () => {
220
213
  fs.writeFileSync("index.js", `export default {};`);
221
214
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
222
215
  await runWrangler("dev --env staging");
223
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
224
- "some-host.com"
225
- );
216
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
226
217
  });
227
218
 
228
219
  it("should strip leading `*` from given host when deducing a zone id", async () => {
@@ -233,9 +224,7 @@ describe("wrangler dev", () => {
233
224
  fs.writeFileSync("index.js", `export default {};`);
234
225
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
235
226
  await runWrangler("dev");
236
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
237
- "some-host.com"
238
- );
227
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
239
228
  });
240
229
 
241
230
  it("should strip leading `*.` from given host when deducing a zone id", async () => {
@@ -246,9 +235,7 @@ describe("wrangler dev", () => {
246
235
  fs.writeFileSync("index.js", `export default {};`);
247
236
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
248
237
  await runWrangler("dev");
249
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
250
- "some-host.com"
251
- );
238
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
252
239
  });
253
240
 
254
241
  it("should, when provided, use a configured zone_id", async () => {
@@ -260,10 +247,12 @@ describe("wrangler dev", () => {
260
247
  });
261
248
  fs.writeFileSync("index.js", `export default {};`);
262
249
  await runWrangler("dev");
263
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
264
- host: "some-domain.com",
265
- id: "some-zone-id",
266
- });
250
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
251
+ expect.objectContaining({
252
+ host: "some-domain.com",
253
+ zone: "some-zone-id",
254
+ })
255
+ );
267
256
  });
268
257
 
269
258
  it("should, when provided, use a zone_name to get a zone_id", async () => {
@@ -276,11 +265,13 @@ describe("wrangler dev", () => {
276
265
  fs.writeFileSync("index.js", `export default {};`);
277
266
  mockGetZones("some-zone.com", [{ id: "a-zone-id" }]);
278
267
  await runWrangler("dev");
279
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
280
- // note that it uses the provided zone_name as a host too
281
- host: "some-zone.com",
282
- id: "a-zone-id",
283
- });
268
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
269
+ expect.objectContaining({
270
+ // note that it uses the provided zone_name as a host too
271
+ host: "some-zone.com",
272
+ zone: "a-zone-id",
273
+ })
274
+ );
284
275
  });
285
276
 
286
277
  it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
@@ -292,10 +283,12 @@ describe("wrangler dev", () => {
292
283
  mockGetZones("222.333.some-host.com", []);
293
284
  mockGetZones("333.some-host.com", [{ id: "some-zone-id" }]);
294
285
  await runWrangler("dev --host 111.222.333.some-host.com");
295
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
296
- host: "111.222.333.some-host.com",
297
- id: "some-zone-id",
298
- });
286
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
287
+ expect.objectContaining({
288
+ host: "111.222.333.some-host.com",
289
+ zone: "some-zone-id",
290
+ })
291
+ );
299
292
  });
300
293
 
301
294
  it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
@@ -310,10 +303,12 @@ describe("wrangler dev", () => {
310
303
  routes: ["http://5.some-host.com/some/path/*"],
311
304
  });
312
305
  await runWrangler("dev");
313
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
314
- host: "5.some-host.com",
315
- id: "some-zone-id-5",
316
- });
306
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
307
+ expect.objectContaining({
308
+ host: "5.some-host.com",
309
+ zone: "some-zone-id-5",
310
+ })
311
+ );
317
312
  (Dev as jest.Mock).mockClear();
318
313
 
319
314
  // config.route
@@ -323,10 +318,12 @@ describe("wrangler dev", () => {
323
318
  route: "https://4.some-host.com/some/path/*",
324
319
  });
325
320
  await runWrangler("dev");
326
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
327
- host: "4.some-host.com",
328
- id: "some-zone-id-4",
329
- });
321
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
322
+ expect.objectContaining({
323
+ host: "4.some-host.com",
324
+ zone: "some-zone-id-4",
325
+ })
326
+ );
330
327
  (Dev as jest.Mock).mockClear();
331
328
 
332
329
  // --routes
@@ -336,10 +333,12 @@ describe("wrangler dev", () => {
336
333
  route: "https://4.some-host.com/some/path/*",
337
334
  });
338
335
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
339
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
340
- host: "3.some-host.com",
341
- id: "some-zone-id-3",
342
- });
336
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
337
+ expect.objectContaining({
338
+ host: "3.some-host.com",
339
+ zone: "some-zone-id-3",
340
+ })
341
+ );
343
342
  (Dev as jest.Mock).mockClear();
344
343
 
345
344
  // config.dev.host
@@ -352,10 +351,12 @@ describe("wrangler dev", () => {
352
351
  route: "4.some-host.com/some/path/*",
353
352
  });
354
353
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
355
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
356
- host: "2.some-host.com",
357
- id: "some-zone-id-2",
358
- });
354
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
355
+ expect.objectContaining({
356
+ host: "2.some-host.com",
357
+ zone: "some-zone-id-2",
358
+ })
359
+ );
359
360
  (Dev as jest.Mock).mockClear();
360
361
 
361
362
  // --host
@@ -370,10 +371,12 @@ describe("wrangler dev", () => {
370
371
  await runWrangler(
371
372
  "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
372
373
  );
373
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
374
- host: "1.some-host.com",
375
- id: "some-zone-id-1",
376
- });
374
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
375
+ expect.objectContaining({
376
+ host: "1.some-host.com",
377
+ zone: "some-zone-id-1",
378
+ })
379
+ );
377
380
  (Dev as jest.Mock).mockClear();
378
381
  });
379
382
 
@@ -853,6 +856,33 @@ describe("wrangler dev", () => {
853
856
  }
854
857
  `);
855
858
  });
859
+
860
+ it("should error if --experimental-public and --site are used together", async () => {
861
+ writeWranglerToml({
862
+ main: "./index.js",
863
+ });
864
+ fs.writeFileSync("index.js", `export default {};`);
865
+ await expect(
866
+ runWrangler("dev --experimental-public abc --site xyz")
867
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
868
+ `"Cannot use --experimental-public and a Site configuration together."`
869
+ );
870
+ });
871
+
872
+ it("should error if --experimental-public and config.site are used together", async () => {
873
+ writeWranglerToml({
874
+ main: "./index.js",
875
+ site: {
876
+ bucket: "xyz",
877
+ },
878
+ });
879
+ fs.writeFileSync("index.js", `export default {};`);
880
+ await expect(
881
+ runWrangler("dev --experimental-public abc")
882
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
883
+ `"Cannot use --experimental-public and a Site configuration together."`
884
+ );
885
+ });
856
886
  });
857
887
 
858
888
  describe("--inspect", () => {
@@ -242,7 +242,8 @@ describe("wrangler", () => {
242
242
  expect(std.out).toMatchInlineSnapshot(`
243
243
  "▲ [WARNING] Deprecation: \`wrangler build\` has been deprecated.
244
244
 
245
- Please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for more information.
245
+ Please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build
246
+ for more information.
246
247
  Attempting to run \`wrangler publish --dry-run --outdir=dist\` for you instead:
247
248
 
248
249
 
@@ -435,6 +435,9 @@ describe("init", () => {
435
435
  `);
436
436
  expect(fs.lstatSync(".git").isDirectory()).toBe(true);
437
437
  expect(fs.lstatSync(".gitignore").isFile()).toBe(true);
438
+ expect((await execa("git", ["branch", "--show-current"])).stdout).toEqual(
439
+ "main"
440
+ );
438
441
  });
439
442
 
440
443
  it("should not offer to initialize a git repo if it's already inside one", async () => {
@@ -448,10 +448,11 @@ describe("wrangler", () => {
448
448
  });
449
449
 
450
450
  it("should put a key with a value loaded from a given path", async () => {
451
- writeFileSync("foo.txt", "file-contents", "utf-8");
451
+ const buf = Buffer.from("file-contents", "utf-8");
452
+ writeFileSync("foo.txt", buf);
452
453
  const requests = mockKeyPutRequest("some-namespace-id", {
453
454
  key: "my-key",
454
- value: "file-contents",
455
+ value: buf,
455
456
  });
456
457
  await runWrangler(
457
458
  "kv:key put my-key --namespace-id some-namespace-id --path foo.txt"
@@ -463,6 +464,26 @@ describe("wrangler", () => {
463
464
  expect(requests.count).toEqual(1);
464
465
  });
465
466
 
467
+ it("should put a key with a binary value loaded from a given path", async () => {
468
+ const buf = Buffer.from(
469
+ "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAiSURBVHgB7coxEQAACMPAgH/PgAM6dGwu49fA/deIBXrgAj2cAhIFT4QxAAAAAElFTkSuQmCC",
470
+ "base64"
471
+ );
472
+ writeFileSync("test.png", buf);
473
+ const requests = mockKeyPutRequest("another-namespace-id", {
474
+ key: "my-key",
475
+ value: buf,
476
+ });
477
+ await runWrangler(
478
+ "kv:key put my-key --namespace-id another-namespace-id --path test.png"
479
+ );
480
+ expect(std.out).toMatchInlineSnapshot(
481
+ `"Writing the contents of test.png to the key \\"my-key\\" on namespace another-namespace-id."`
482
+ );
483
+ expect(std.err).toMatchInlineSnapshot(`""`);
484
+ expect(requests.count).toEqual(1);
485
+ });
486
+
466
487
  it("should error if no key is provided", async () => {
467
488
  await expect(
468
489
  runWrangler("kv:key put")
@@ -19,7 +19,7 @@ function assertLater(fn: () => void) {
19
19
  }
20
20
 
21
21
  function mockGetToken(jwt: string) {
22
- setMockResponse(
22
+ return setMockResponse(
23
23
  "/accounts/:accountId/pages/projects/foo/upload-token",
24
24
  async ([_url, accountId]) => {
25
25
  assertLater(() => {
@@ -488,6 +488,103 @@ describe("pages", () => {
488
488
  `);
489
489
  });
490
490
 
491
+ it("should refetch a JWT if it expires while uploading", async () => {
492
+ writeFileSync("logo.txt", "foobar");
493
+
494
+ const cancelMockGetToken = mockGetToken("<<funfetti-auth-jwt>>");
495
+
496
+ setMockResponse(
497
+ "/pages/assets/check-missing",
498
+ "POST",
499
+ async (_, init) => {
500
+ const body = JSON.parse(init.body as string) as { hashes: string[] };
501
+ assertLater(() => {
502
+ expect(init.headers).toMatchObject({
503
+ Authorization: "Bearer <<funfetti-auth-jwt>>",
504
+ });
505
+ expect(body).toMatchObject({
506
+ hashes: ["1a98fb08af91aca4a7df1764a2c4ddb0"],
507
+ });
508
+ });
509
+ return body.hashes;
510
+ }
511
+ );
512
+
513
+ // Accumulate multiple requests then assert afterwards
514
+ const requests: RequestInit[] = [];
515
+ setMockRawResponse("/pages/assets/upload", "POST", async (_, init) => {
516
+ requests.push(init);
517
+
518
+ // Fail just the first request
519
+ if (requests.length < 2) {
520
+ cancelMockGetToken();
521
+ mockGetToken("<<funfetti-auth-jwt2>>");
522
+ return createFetchResult(null, false, [
523
+ {
524
+ code: 8000013,
525
+ message: "Authorization failed",
526
+ },
527
+ ]);
528
+ } else {
529
+ return createFetchResult(null, true);
530
+ }
531
+ });
532
+
533
+ setMockResponse(
534
+ "/accounts/:accountId/pages/projects/foo/deployments",
535
+ async ([_url, accountId], init) => {
536
+ assertLater(() => {
537
+ expect(accountId).toEqual("some-account-id");
538
+ expect(init.method).toEqual("POST");
539
+ const body = init.body as FormData;
540
+ const manifest = JSON.parse(body.get("manifest") as string);
541
+ expect(manifest).toMatchInlineSnapshot(`
542
+ Object {
543
+ "/logo.txt": "1a98fb08af91aca4a7df1764a2c4ddb0",
544
+ }
545
+ `);
546
+ });
547
+
548
+ return {
549
+ url: "https://abcxyz.foo.pages.dev/",
550
+ };
551
+ }
552
+ );
553
+
554
+ await runWrangler("pages publish . --project-name=foo");
555
+
556
+ // Assert two requests
557
+ expect(requests.length).toBe(2);
558
+
559
+ expect(requests[0].headers).toMatchObject({
560
+ Authorization: "Bearer <<funfetti-auth-jwt>>",
561
+ });
562
+
563
+ expect(requests[1].headers).toMatchObject({
564
+ Authorization: "Bearer <<funfetti-auth-jwt2>>",
565
+ });
566
+
567
+ for (const init of requests) {
568
+ const body = JSON.parse(init.body as string) as UploadPayloadFile[];
569
+ expect(body).toMatchObject([
570
+ {
571
+ key: "1a98fb08af91aca4a7df1764a2c4ddb0",
572
+ value: Buffer.from("foobar").toString("base64"),
573
+ metadata: {
574
+ contentType: "text/plain",
575
+ },
576
+ base64: true,
577
+ },
578
+ ]);
579
+ }
580
+
581
+ expect(std.out).toMatchInlineSnapshot(`
582
+ "✨ Success! Uploaded 1 files (TIMINGS)
583
+
584
+ ✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
585
+ `);
586
+ });
587
+
491
588
  it("should try to use multiple buckets (up to the max concurrency)", async () => {
492
589
  writeFileSync("logo.txt", "foobar");
493
590
  writeFileSync("logo.png", "foobar");