wrangler 0.0.0-e61fba8 → 0.0.0-e62b097bb

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 (155) hide show
  1. package/README.md +42 -36
  2. package/bin/wrangler.js +86 -67
  3. package/config-schema.json +3370 -0
  4. package/package.json +132 -103
  5. package/templates/__tests__/pages-dev-util.test.ts +128 -0
  6. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  7. package/templates/__tests__/tsconfig.json +8 -0
  8. package/templates/checked-fetch.js +30 -0
  9. package/templates/facade.d.ts +19 -0
  10. package/templates/gitignore +2 -3
  11. package/templates/init-tests/test-jest-new-worker.js +23 -0
  12. package/templates/init-tests/test-vitest-new-worker.js +24 -0
  13. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  14. package/templates/middleware/common.ts +67 -0
  15. package/templates/middleware/loader-modules.ts +134 -0
  16. package/templates/middleware/loader-sw.ts +229 -0
  17. package/templates/middleware/middleware-ensure-req-body-drained.ts +18 -0
  18. package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
  19. package/templates/middleware/middleware-mock-analytics-engine.d.ts +3 -0
  20. package/templates/middleware/middleware-mock-analytics-engine.ts +30 -0
  21. package/templates/middleware/middleware-patch-console-prefix.d.ts +3 -0
  22. package/templates/middleware/middleware-patch-console-prefix.ts +21 -0
  23. package/templates/middleware/middleware-pretty-error.ts +40 -0
  24. package/templates/middleware/middleware-scheduled.ts +29 -0
  25. package/templates/middleware/middleware-serve-static-assets.d.ts +6 -0
  26. package/templates/middleware/middleware-serve-static-assets.ts +56 -0
  27. package/templates/modules-watch-stub.js +4 -0
  28. package/templates/new-worker-scheduled.js +3 -3
  29. package/templates/new-worker-scheduled.ts +16 -16
  30. package/templates/new-worker.js +3 -3
  31. package/templates/new-worker.ts +19 -16
  32. package/templates/no-op-worker.js +10 -0
  33. package/templates/pages-dev-pipeline.ts +32 -0
  34. package/templates/pages-dev-util.ts +55 -0
  35. package/templates/pages-shim.ts +9 -0
  36. package/templates/pages-template-plugin.ts +190 -0
  37. package/templates/pages-template-worker.ts +198 -0
  38. package/templates/startDevWorker/InspectorProxyWorker.ts +664 -0
  39. package/templates/startDevWorker/ProxyWorker.ts +336 -0
  40. package/templates/tsconfig-sanity.ts +11 -0
  41. package/templates/tsconfig.init.json +22 -0
  42. package/templates/tsconfig.json +6 -103
  43. package/wrangler-dist/InspectorProxyWorker.js +464 -0
  44. package/wrangler-dist/InspectorProxyWorker.js.map +6 -0
  45. package/wrangler-dist/ProxyWorker.js +241 -0
  46. package/wrangler-dist/ProxyWorker.js.map +6 -0
  47. package/wrangler-dist/cli.d.ts +26730 -0
  48. package/wrangler-dist/cli.js +165991 -119517
  49. package/Cloudflare_CA.pem +0 -18
  50. package/import_meta_url.js +0 -3
  51. package/miniflare-config-stubs/.env.empty +0 -0
  52. package/miniflare-config-stubs/package.empty.json +0 -1
  53. package/miniflare-config-stubs/wrangler.empty.toml +0 -0
  54. package/miniflare-dist/index.mjs +0 -4886
  55. package/pages/functions/buildPlugin.ts +0 -105
  56. package/pages/functions/buildWorker.ts +0 -151
  57. package/pages/functions/filepath-routing.test.ts +0 -234
  58. package/pages/functions/filepath-routing.ts +0 -189
  59. package/pages/functions/identifiers.ts +0 -78
  60. package/pages/functions/routes.ts +0 -156
  61. package/pages/functions/template-plugin.ts +0 -147
  62. package/pages/functions/template-worker.ts +0 -143
  63. package/src/__tests__/config-cache.test.ts +0 -36
  64. package/src/__tests__/configuration.test.ts +0 -3487
  65. package/src/__tests__/dev.test.tsx +0 -1010
  66. package/src/__tests__/guess-worker-format.test.ts +0 -85
  67. package/src/__tests__/helpers/clipboardy-mock.js +0 -4
  68. package/src/__tests__/helpers/cmd-shim.d.ts +0 -11
  69. package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
  70. package/src/__tests__/helpers/mock-account-id.ts +0 -48
  71. package/src/__tests__/helpers/mock-bin.ts +0 -36
  72. package/src/__tests__/helpers/mock-cfetch.ts +0 -211
  73. package/src/__tests__/helpers/mock-console.ts +0 -87
  74. package/src/__tests__/helpers/mock-dialogs.ts +0 -130
  75. package/src/__tests__/helpers/mock-http-server.ts +0 -46
  76. package/src/__tests__/helpers/mock-istty.ts +0 -27
  77. package/src/__tests__/helpers/mock-kv.ts +0 -33
  78. package/src/__tests__/helpers/mock-oauth-flow.ts +0 -255
  79. package/src/__tests__/helpers/mock-stdin.ts +0 -103
  80. package/src/__tests__/helpers/mock-web-socket.ts +0 -29
  81. package/src/__tests__/helpers/run-in-tmp.ts +0 -39
  82. package/src/__tests__/helpers/run-wrangler.ts +0 -16
  83. package/src/__tests__/helpers/write-worker-source.ts +0 -31
  84. package/src/__tests__/helpers/write-wrangler-toml.ts +0 -17
  85. package/src/__tests__/https-options.test.ts +0 -130
  86. package/src/__tests__/index.test.ts +0 -257
  87. package/src/__tests__/init.test.ts +0 -1637
  88. package/src/__tests__/jest.setup.ts +0 -77
  89. package/src/__tests__/kv.test.ts +0 -1502
  90. package/src/__tests__/logger.test.ts +0 -115
  91. package/src/__tests__/package-manager.test.ts +0 -353
  92. package/src/__tests__/pages.test.ts +0 -754
  93. package/src/__tests__/parse.test.ts +0 -330
  94. package/src/__tests__/publish.test.ts +0 -5820
  95. package/src/__tests__/r2.test.ts +0 -233
  96. package/src/__tests__/route.test.ts +0 -45
  97. package/src/__tests__/secret.test.ts +0 -481
  98. package/src/__tests__/tail.test.ts +0 -690
  99. package/src/__tests__/user.test.ts +0 -131
  100. package/src/__tests__/whoami.test.tsx +0 -139
  101. package/src/abort.d.ts +0 -3
  102. package/src/bundle.ts +0 -204
  103. package/src/cfetch/index.ts +0 -121
  104. package/src/cfetch/internal.ts +0 -142
  105. package/src/cli.ts +0 -13
  106. package/src/config/README.md +0 -107
  107. package/src/config/config.ts +0 -234
  108. package/src/config/diagnostics.ts +0 -80
  109. package/src/config/environment.ts +0 -420
  110. package/src/config/index.ts +0 -225
  111. package/src/config/validation-helpers.ts +0 -584
  112. package/src/config/validation.ts +0 -1548
  113. package/src/config-cache.ts +0 -45
  114. package/src/create-worker-preview.ts +0 -185
  115. package/src/create-worker-upload-form.ts +0 -254
  116. package/src/dev/dev-vars.ts +0 -36
  117. package/src/dev/dev.tsx +0 -395
  118. package/src/dev/local.tsx +0 -321
  119. package/src/dev/remote.tsx +0 -240
  120. package/src/dev/use-esbuild.ts +0 -115
  121. package/src/dialogs.tsx +0 -135
  122. package/src/durable.ts +0 -102
  123. package/src/entry.ts +0 -322
  124. package/src/environment-variables.ts +0 -35
  125. package/src/errors.ts +0 -11
  126. package/src/https-options.ts +0 -123
  127. package/src/index.tsx +0 -2859
  128. package/src/inspect.ts +0 -662
  129. package/src/intl-polyfill.d.ts +0 -139
  130. package/src/kv.ts +0 -408
  131. package/src/logger.ts +0 -66
  132. package/src/miniflare-cli/README.md +0 -30
  133. package/src/miniflare-cli/enum-keys.ts +0 -17
  134. package/src/miniflare-cli/index.ts +0 -41
  135. package/src/miniflare-cli/request-context.ts +0 -40
  136. package/src/module-collection.ts +0 -258
  137. package/src/open-in-browser.ts +0 -19
  138. package/src/package-manager.ts +0 -174
  139. package/src/pages.tsx +0 -2093
  140. package/src/parse.ts +0 -222
  141. package/src/paths.ts +0 -26
  142. package/src/proxy.ts +0 -478
  143. package/src/publish.ts +0 -721
  144. package/src/r2.ts +0 -50
  145. package/src/selfsigned.d.ts +0 -29
  146. package/src/sites.tsx +0 -326
  147. package/src/tail/filters.ts +0 -279
  148. package/src/tail/index.ts +0 -299
  149. package/src/tail/printing.ts +0 -67
  150. package/src/update-check.ts +0 -19
  151. package/src/user.tsx +0 -1214
  152. package/src/whoami.tsx +0 -71
  153. package/src/worker.ts +0 -181
  154. package/src/zones.ts +0 -73
  155. package/templates/static-asset-facade.js +0 -43
@@ -1,754 +0,0 @@
1
- import { mkdirSync, writeFileSync } from "node:fs";
2
- import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
3
- import {
4
- createFetchResult,
5
- setMockRawResponse,
6
- setMockResponse,
7
- unsetAllMocks,
8
- } from "./helpers/mock-cfetch";
9
- import { mockConsoleMethods } from "./helpers/mock-console";
10
- import { runInTempDir } from "./helpers/run-in-tmp";
11
- import { runWrangler } from "./helpers/run-wrangler";
12
- import type { Deployment, Project, UploadPayloadFile } from "../pages";
13
- import type { FormData, RequestInit } from "undici";
14
-
15
- // Asserting within mock responses get swallowed, so run them out-of-band
16
- const outOfBandTests: (() => void)[] = [];
17
- function assertLater(fn: () => void) {
18
- outOfBandTests.push(fn);
19
- }
20
-
21
- function mockGetToken(jwt: string) {
22
- return setMockResponse(
23
- "/accounts/:accountId/pages/projects/foo/upload-token",
24
- async ([_url, accountId]) => {
25
- assertLater(() => {
26
- expect(accountId).toEqual("some-account-id");
27
- });
28
-
29
- return { jwt };
30
- }
31
- );
32
- }
33
-
34
- describe("pages", () => {
35
- runInTempDir();
36
- const std = mockConsoleMethods();
37
- function endEventLoop() {
38
- return new Promise((resolve) => setImmediate(resolve));
39
- }
40
- beforeEach(() => {
41
- outOfBandTests.length = 0;
42
- });
43
- afterEach(() => {
44
- outOfBandTests.forEach((fn) => fn());
45
- });
46
-
47
- it("should should display a list of available subcommands, for pages with no subcommand", async () => {
48
- await runWrangler("pages");
49
- await endEventLoop();
50
-
51
- expect(std.out).toMatchInlineSnapshot(`
52
- "wrangler pages
53
-
54
- ⚡️ Configure Cloudflare Pages
55
-
56
- Commands:
57
- wrangler pages dev [directory] [-- command..] 🧑‍💻 Develop your full-stack Pages application locally
58
- wrangler pages project ⚡️ Interact with your Pages projects
59
- wrangler pages deployment 🚀 Interact with the deployments of a project
60
- wrangler pages publish [directory] 🆙 Publish a directory of static assets as a Pages deployment
61
-
62
- Flags:
63
- -c, --config Path to .toml configuration file [string]
64
- -h, --help Show help [boolean]
65
- -v, --version Show version number [boolean]
66
-
67
- 🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose"
68
- `);
69
- });
70
-
71
- describe("beta message for subcommands", () => {
72
- it("should display for pages:dev", async () => {
73
- await expect(
74
- runWrangler("pages dev")
75
- ).rejects.toThrowErrorMatchingInlineSnapshot(
76
- `"Must specify a directory of static assets to serve or a command to run."`
77
- );
78
-
79
- expect(std.out).toMatchInlineSnapshot(`
80
- "🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
81
-
82
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
83
- `);
84
- });
85
-
86
- it("should display for pages:functions:build", async () => {
87
- await expect(runWrangler("pages functions build")).rejects.toThrowError();
88
-
89
- expect(std.out).toMatchInlineSnapshot(`
90
- "🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
91
-
92
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
93
- `);
94
- });
95
- });
96
-
97
- describe("project list", () => {
98
- mockAccountId();
99
- mockApiToken();
100
-
101
- afterEach(() => {
102
- unsetAllMocks();
103
- });
104
-
105
- function mockListRequest(projects: unknown[]) {
106
- const requests = { count: 0 };
107
- setMockResponse(
108
- "/accounts/:accountId/pages/projects",
109
- ([_url, accountId], init, query) => {
110
- requests.count++;
111
- const pageSize = Number(query.get("per_page"));
112
- const page = Number(query.get("page"));
113
- const expectedPageSize = 10;
114
- const expectedPage = requests.count;
115
- assertLater(() => {
116
- expect(accountId).toEqual("some-account-id");
117
- expect(pageSize).toEqual(expectedPageSize);
118
- expect(page).toEqual(expectedPage);
119
- expect(init).toEqual({});
120
- });
121
- return projects.slice((page - 1) * pageSize, page * pageSize);
122
- }
123
- );
124
- return requests;
125
- }
126
-
127
- it("should make request to list projects", async () => {
128
- const projects: Project[] = [
129
- {
130
- name: "dogs",
131
- subdomain: "docs.pages.dev",
132
- domains: ["dogs.pages.dev"],
133
- source: {
134
- type: "github",
135
- },
136
- latest_deployment: {
137
- modified_on: "2021-11-17T14:52:26.133835Z",
138
- },
139
- created_on: "2021-11-17T14:52:26.133835Z",
140
- production_branch: "main",
141
- },
142
- {
143
- name: "cats",
144
- subdomain: "cats.pages.dev",
145
- domains: ["cats.pages.dev", "kitten.com"],
146
- latest_deployment: {
147
- modified_on: "2021-11-17T14:52:26.133835Z",
148
- },
149
- created_on: "2021-11-17T14:52:26.133835Z",
150
- production_branch: "main",
151
- },
152
- ];
153
-
154
- const requests = mockListRequest(projects);
155
- await runWrangler("pages project list");
156
-
157
- expect(requests.count).toBe(1);
158
- });
159
-
160
- it("should make multiple requests for paginated results", async () => {
161
- const projects: Project[] = [];
162
- for (let i = 0; i < 15; i++) {
163
- projects.push({
164
- name: "dogs" + i,
165
- subdomain: i + "dogs.pages.dev",
166
- domains: [i + "dogs.pages.dev"],
167
- source: {
168
- type: "github",
169
- },
170
- latest_deployment: {
171
- modified_on: "2021-11-17T14:52:26.133835Z",
172
- },
173
- created_on: "2021-11-17T14:52:26.133835Z",
174
- production_branch: "main",
175
- });
176
- }
177
- const requests = mockListRequest(projects);
178
- await runWrangler("pages project list");
179
- expect(requests.count).toEqual(2);
180
- });
181
- });
182
-
183
- describe("project create", () => {
184
- mockAccountId();
185
- mockApiToken();
186
-
187
- afterEach(() => {
188
- unsetAllMocks();
189
- });
190
-
191
- it("should create a project with a production branch", async () => {
192
- setMockResponse(
193
- "/accounts/:accountId/pages/projects",
194
- ([_url, accountId], init) => {
195
- const body = JSON.parse(init.body as string);
196
- assertLater(() => {
197
- expect(accountId).toEqual("some-account-id");
198
- expect(init.method).toEqual("POST");
199
- expect(body).toEqual({
200
- name: "a-new-project",
201
- production_branch: "main",
202
- });
203
- });
204
- return {
205
- name: "a-new-project",
206
- subdomain: "a-new-project.pages.dev",
207
- production_branch: "main",
208
- };
209
- }
210
- );
211
- await runWrangler(
212
- "pages project create a-new-project --production-branch=main"
213
- );
214
- expect(std.out).toMatchInlineSnapshot(`
215
- "✨ Successfully created the 'a-new-project' project. It will be available at https://a-new-project.pages.dev/ once you create your first deployment.
216
- To deploy a folder of assets, run 'wrangler pages publish [directory]'."
217
- `);
218
- });
219
- });
220
-
221
- describe("deployment list", () => {
222
- mockAccountId();
223
- mockApiToken();
224
-
225
- afterEach(() => {
226
- unsetAllMocks();
227
- });
228
- function mockListRequest(deployments: unknown[]) {
229
- const requests = { count: 0 };
230
- setMockResponse(
231
- "/accounts/:accountId/pages/projects/:project/deployments",
232
- ([_url, accountId, project]) => {
233
- requests.count++;
234
- assertLater(() => {
235
- expect(project).toEqual("images");
236
- expect(accountId).toEqual("some-account-id");
237
- });
238
- return deployments;
239
- }
240
- );
241
- return requests;
242
- }
243
-
244
- it("should make request to list deployments", async () => {
245
- const deployments: Deployment[] = [
246
- {
247
- id: "87bbc8fe-16be-45cd-81e0-63d722e82cdf",
248
- url: "https://87bbc8fe.images.pages.dev",
249
- environment: "preview",
250
- latest_stage: {
251
- ended_on: "2021-11-17T14:52:26.133835Z",
252
- status: "success",
253
- },
254
- deployment_trigger: {
255
- metadata: {
256
- branch: "main",
257
- commit_hash: "c7649364c4cb32ad4f65b530b9424e8be5bec9d6",
258
- },
259
- },
260
- project_name: "images",
261
- },
262
- ];
263
-
264
- const requests = mockListRequest(deployments);
265
- await runWrangler("pages deployment list --project-name=images");
266
-
267
- expect(requests.count).toBe(1);
268
- });
269
- });
270
-
271
- describe("deployment create", () => {
272
- let actualProcessEnvCI: string | undefined;
273
-
274
- mockAccountId();
275
- mockApiToken();
276
- runInTempDir();
277
-
278
- beforeEach(() => {
279
- actualProcessEnvCI = process.env.CI;
280
- process.env.CI = "true";
281
- });
282
-
283
- afterEach(() => {
284
- unsetAllMocks();
285
- process.env.CI = actualProcessEnvCI;
286
- });
287
-
288
- it("should be aliased with 'wrangler pages publish'", async () => {
289
- await runWrangler("pages publish --help");
290
- await endEventLoop();
291
-
292
- expect(std.out).toMatchInlineSnapshot(`
293
- "wrangler pages publish [directory]
294
-
295
- 🆙 Publish a directory of static assets as a Pages deployment
296
-
297
- Positionals:
298
- directory The directory of static files to upload [string]
299
-
300
- Flags:
301
- -c, --config Path to .toml configuration file [string]
302
- -h, --help Show help [boolean]
303
- -v, --version Show version number [boolean]
304
-
305
- Options:
306
- --project-name The name of the project you want to deploy to [string]
307
- --branch The name of the branch you want to deploy to [string]
308
- --commit-hash The SHA to attach to this deployment [string]
309
- --commit-message The commit message to attach to this deployment [string]
310
- --commit-dirty Whether or not the workspace should be considered dirty for this deployment [boolean]
311
-
312
- 🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose"
313
- `);
314
- });
315
-
316
- it("should upload a directory of files", async () => {
317
- writeFileSync("logo.png", "foobar");
318
-
319
- setMockResponse(
320
- "/accounts/:accountId/pages/projects/foo/upload-token",
321
- async ([_url, accountId]) => {
322
- assertLater(() => {
323
- expect(accountId).toEqual("some-account-id");
324
- });
325
-
326
- return {
327
- jwt: "<<funfetti-auth-jwt>>",
328
- };
329
- }
330
- );
331
-
332
- setMockResponse(
333
- "/pages/assets/check-missing",
334
- "POST",
335
- async (_, init) => {
336
- const body = JSON.parse(init.body as string) as { hashes: string[] };
337
- assertLater(() => {
338
- expect(init.headers).toMatchObject({
339
- Authorization: "Bearer <<funfetti-auth-jwt>>",
340
- });
341
- expect(body).toMatchObject({
342
- hashes: ["2082190357cfd3617ccfe04f340c6247"],
343
- });
344
- });
345
- return body.hashes;
346
- }
347
- );
348
-
349
- setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
350
- assertLater(() => {
351
- expect(init.headers).toMatchObject({
352
- Authorization: "Bearer <<funfetti-auth-jwt>>",
353
- });
354
- const body = JSON.parse(init.body as string) as UploadPayloadFile[];
355
- expect(body).toMatchObject([
356
- {
357
- key: "2082190357cfd3617ccfe04f340c6247",
358
- value: Buffer.from("foobar").toString("base64"),
359
- metadata: {
360
- contentType: "image/png",
361
- },
362
- base64: true,
363
- },
364
- ]);
365
- });
366
- });
367
-
368
- setMockResponse(
369
- "/accounts/:accountId/pages/projects/foo/deployments",
370
- async ([_url, accountId], init) => {
371
- assertLater(() => {
372
- expect(accountId).toEqual("some-account-id");
373
- expect(init.method).toEqual("POST");
374
- const body = init.body as FormData;
375
- const manifest = JSON.parse(body.get("manifest") as string);
376
- expect(manifest).toMatchInlineSnapshot(`
377
- Object {
378
- "/logo.png": "2082190357cfd3617ccfe04f340c6247",
379
- }
380
- `);
381
- });
382
-
383
- return {
384
- url: "https://abcxyz.foo.pages.dev/",
385
- };
386
- }
387
- );
388
-
389
- await runWrangler("pages publish . --project-name=foo");
390
-
391
- // TODO: Unmounting somehow loses this output
392
-
393
- // expect(std.out).toMatchInlineSnapshot(`
394
- // "✨ Success! Uploaded 1 files (TIMINGS)
395
-
396
- // ✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
397
- // `);
398
- });
399
-
400
- it("should retry uploads", async () => {
401
- writeFileSync("logo.txt", "foobar");
402
-
403
- mockGetToken("<<funfetti-auth-jwt>>");
404
-
405
- setMockResponse(
406
- "/pages/assets/check-missing",
407
- "POST",
408
- async (_, init) => {
409
- const body = JSON.parse(init.body as string) as { hashes: string[] };
410
- assertLater(() => {
411
- expect(init.headers).toMatchObject({
412
- Authorization: "Bearer <<funfetti-auth-jwt>>",
413
- });
414
- expect(body).toMatchObject({
415
- hashes: ["1a98fb08af91aca4a7df1764a2c4ddb0"],
416
- });
417
- });
418
- return body.hashes;
419
- }
420
- );
421
-
422
- // Accumulate multiple requests then assert afterwards
423
- const requests: RequestInit[] = [];
424
- setMockRawResponse("/pages/assets/upload", "POST", async (_, init) => {
425
- requests.push(init);
426
-
427
- if (requests.length < 2) {
428
- return createFetchResult(null, false, [
429
- {
430
- code: 800000,
431
- message: "Something exploded, please retry",
432
- },
433
- ]);
434
- } else {
435
- return createFetchResult(null, true);
436
- }
437
- });
438
-
439
- setMockResponse(
440
- "/accounts/:accountId/pages/projects/foo/deployments",
441
- async ([_url, accountId], init) => {
442
- assertLater(() => {
443
- expect(accountId).toEqual("some-account-id");
444
- expect(init.method).toEqual("POST");
445
- const body = init.body as FormData;
446
- const manifest = JSON.parse(body.get("manifest") as string);
447
- expect(manifest).toMatchInlineSnapshot(`
448
- Object {
449
- "/logo.txt": "1a98fb08af91aca4a7df1764a2c4ddb0",
450
- }
451
- `);
452
- });
453
-
454
- return {
455
- url: "https://abcxyz.foo.pages.dev/",
456
- };
457
- }
458
- );
459
-
460
- await runWrangler("pages publish . --project-name=foo");
461
-
462
- // Assert two identical requests
463
- expect(requests.length).toBe(2);
464
- for (const init of requests) {
465
- assertLater(() => {
466
- expect(init.headers).toMatchObject({
467
- Authorization: "Bearer <<funfetti-auth-jwt>>",
468
- });
469
-
470
- const body = JSON.parse(init.body as string) as UploadPayloadFile[];
471
- expect(body).toMatchObject([
472
- {
473
- key: "1a98fb08af91aca4a7df1764a2c4ddb0",
474
- value: Buffer.from("foobar").toString("base64"),
475
- metadata: {
476
- contentType: "text/plain",
477
- },
478
- base64: true,
479
- },
480
- ]);
481
- });
482
- }
483
-
484
- expect(std.out).toMatchInlineSnapshot(`
485
- "✨ Success! Uploaded 1 files (TIMINGS)
486
-
487
- ✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
488
- `);
489
- });
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
-
588
- it("should try to use multiple buckets (up to the max concurrency)", async () => {
589
- writeFileSync("logo.txt", "foobar");
590
- writeFileSync("logo.png", "foobar");
591
- writeFileSync("logo.html", "foobar");
592
- writeFileSync("logo.js", "foobar");
593
-
594
- mockGetToken("<<funfetti-auth-jwt>>");
595
-
596
- setMockResponse(
597
- "/pages/assets/check-missing",
598
- "POST",
599
- async (_, init) => {
600
- const body = JSON.parse(init.body as string) as { hashes: string[] };
601
- assertLater(() => {
602
- expect(init.headers).toMatchObject({
603
- Authorization: "Bearer <<funfetti-auth-jwt>>",
604
- });
605
- expect(body).toMatchObject({
606
- hashes: expect.arrayContaining([
607
- "d96fef225537c9f5e44a3cb27fd0b492",
608
- "2082190357cfd3617ccfe04f340c6247",
609
- "6be321bef99e758250dac034474ddbb8",
610
- "1a98fb08af91aca4a7df1764a2c4ddb0",
611
- ]),
612
- });
613
- });
614
- return body.hashes;
615
- }
616
- );
617
-
618
- // Accumulate multiple requests then assert afterwards
619
- const requests: RequestInit[] = [];
620
- setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
621
- requests.push(init);
622
- });
623
-
624
- setMockResponse(
625
- "/accounts/:accountId/pages/projects/foo/deployments",
626
- async ([_url, accountId], init) => {
627
- assertLater(() => {
628
- expect(accountId).toEqual("some-account-id");
629
- expect(init.method).toEqual("POST");
630
- const body = init.body as FormData;
631
- const manifest = JSON.parse(body.get("manifest") as string);
632
- expect(manifest).toMatchInlineSnapshot(`
633
- Object {
634
- "/logo.html": "d96fef225537c9f5e44a3cb27fd0b492",
635
- "/logo.js": "6be321bef99e758250dac034474ddbb8",
636
- "/logo.png": "2082190357cfd3617ccfe04f340c6247",
637
- "/logo.txt": "1a98fb08af91aca4a7df1764a2c4ddb0",
638
- }
639
- `);
640
- });
641
-
642
- return {
643
- url: "https://abcxyz.foo.pages.dev/",
644
- };
645
- }
646
- );
647
-
648
- await runWrangler("pages publish . --project-name=foo");
649
-
650
- // We have 3 buckets, so expect 3 uploads
651
- expect(requests.length).toBe(3);
652
- const bodies: UploadPayloadFile[][] = [];
653
- for (const init of requests) {
654
- expect(init.headers).toMatchObject({
655
- Authorization: "Bearer <<funfetti-auth-jwt>>",
656
- });
657
- bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
658
- }
659
- // First bucket should end up with 2 files
660
- expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
661
- // But we don't know the order, so flatten and test without ordering
662
- expect(bodies.flatMap((b) => b)).toEqual(
663
- expect.arrayContaining([
664
- {
665
- base64: true,
666
- key: "d96fef225537c9f5e44a3cb27fd0b492",
667
- metadata: { contentType: "text/html" },
668
- value: "Zm9vYmFy",
669
- },
670
- {
671
- base64: true,
672
- key: "1a98fb08af91aca4a7df1764a2c4ddb0",
673
- metadata: { contentType: "text/plain" },
674
- value: "Zm9vYmFy",
675
- },
676
- {
677
- base64: true,
678
- key: "6be321bef99e758250dac034474ddbb8",
679
- metadata: { contentType: "application/javascript" },
680
- value: "Zm9vYmFy",
681
- },
682
- {
683
- base64: true,
684
- key: "2082190357cfd3617ccfe04f340c6247",
685
- metadata: { contentType: "image/png" },
686
- value: "Zm9vYmFy",
687
- },
688
- ])
689
- );
690
-
691
- expect(std.out).toMatchInlineSnapshot(`
692
- "✨ Success! Uploaded 4 files (TIMINGS)
693
-
694
- ✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
695
- `);
696
- });
697
-
698
- it("should not error when directory names contain periods and houses a extensionless file", async () => {
699
- mkdirSync(".well-known");
700
- // Note: same content as previous test, but since it's a different extension,
701
- // it hashes to a different value
702
- writeFileSync(".well-known/foobar", "foobar");
703
-
704
- mockGetToken("<<funfetti-auth-jwt>>");
705
-
706
- setMockResponse(
707
- "/pages/assets/check-missing",
708
- "POST",
709
- async (_, init) => {
710
- const body = JSON.parse(init.body as string) as { hashes: string[] };
711
- assertLater(() => {
712
- expect(init.headers).toMatchObject({
713
- Authorization: "Bearer <<funfetti-auth-jwt>>",
714
- });
715
- expect(body).toMatchObject({
716
- hashes: ["7b764dacfd211bebd8077828a7ddefd7"],
717
- });
718
- });
719
- return body.hashes;
720
- }
721
- );
722
-
723
- setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
724
- assertLater(() => {
725
- expect(init.headers).toMatchObject({
726
- Authorization: "Bearer <<funfetti-auth-jwt>>",
727
- });
728
- const body = JSON.parse(init.body as string) as UploadPayloadFile[];
729
- expect(body).toMatchObject([
730
- {
731
- key: "7b764dacfd211bebd8077828a7ddefd7",
732
- value: Buffer.from("foobar").toString("base64"),
733
- metadata: {
734
- contentType: "application/octet-stream",
735
- },
736
- base64: true,
737
- },
738
- ]);
739
- });
740
- });
741
-
742
- setMockResponse(
743
- "/accounts/:accountId/pages/projects/foo/deployments",
744
- async () => ({
745
- url: "https://abcxyz.foo.pages.dev/",
746
- })
747
- );
748
-
749
- await runWrangler("pages publish . --project-name=foo");
750
-
751
- expect(std.err).toMatchInlineSnapshot(`""`);
752
- });
753
- });
754
- });