wrangler 0.0.0-e95e5a0 → 0.0.0-e978986
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.
- package/Cloudflare_CA.pem +18 -0
- package/README.md +3 -1
- package/bin/wrangler.js +36 -4
- package/package.json +11 -7
- package/pages/functions/buildPlugin.ts +13 -0
- package/pages/functions/buildWorker.ts +14 -1
- package/pages/functions/template-plugin.ts +3 -2
- package/src/__tests__/configuration.test.ts +336 -87
- package/src/__tests__/dev.test.tsx +243 -25
- package/src/__tests__/helpers/mock-dialogs.ts +41 -1
- package/src/__tests__/index.test.ts +79 -72
- package/src/__tests__/init.test.ts +182 -131
- package/src/__tests__/jest.setup.ts +8 -0
- package/src/__tests__/kv.test.ts +173 -146
- package/src/__tests__/package-manager.test.ts +154 -7
- package/src/__tests__/pages.test.ts +381 -53
- package/src/__tests__/parse.test.ts +8 -0
- package/src/__tests__/publish.test.ts +682 -89
- package/src/__tests__/r2.test.ts +55 -36
- package/src/__tests__/secret.test.ts +39 -4
- package/src/abort.d.ts +3 -0
- package/src/bundle.ts +33 -2
- package/src/cfetch/index.ts +21 -4
- package/src/cfetch/internal.ts +17 -9
- package/src/config/config.ts +1 -1
- package/src/config/environment.ts +40 -14
- package/src/config/index.ts +162 -0
- package/src/config/validation.ts +180 -65
- package/src/create-worker-preview.ts +17 -7
- package/src/create-worker-upload-form.ts +22 -8
- package/src/dev/dev.tsx +7 -6
- package/src/dev/local.tsx +6 -0
- package/src/dev/remote.tsx +15 -1
- package/src/dialogs.tsx +48 -0
- package/src/durable.ts +102 -0
- package/src/entry.ts +64 -9
- package/src/index.tsx +357 -177
- package/src/inspect.ts +39 -0
- package/src/kv.ts +114 -25
- package/src/open-in-browser.ts +5 -12
- package/src/package-manager.ts +50 -3
- package/src/pages.tsx +271 -110
- package/src/parse.ts +23 -4
- package/src/proxy.ts +38 -22
- package/src/publish.ts +227 -113
- package/src/sites.tsx +19 -17
- package/src/user.tsx +11 -1
- package/src/worker.ts +8 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.ts +16 -1
- package/wrangler-dist/cli.js +36017 -22687
|
@@ -1,11 +1,35 @@
|
|
|
1
|
-
import { writeFileSync } from "node:fs";
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createFetchResult,
|
|
5
|
+
setMockRawResponse,
|
|
6
|
+
setMockResponse,
|
|
7
|
+
unsetAllMocks,
|
|
8
|
+
} from "./helpers/mock-cfetch";
|
|
4
9
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
5
10
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
6
11
|
import { runWrangler } from "./helpers/run-wrangler";
|
|
7
|
-
import type { Project,
|
|
8
|
-
import type {
|
|
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
|
+
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
|
+
}
|
|
9
33
|
|
|
10
34
|
describe("pages", () => {
|
|
11
35
|
runInTempDir();
|
|
@@ -13,6 +37,12 @@ describe("pages", () => {
|
|
|
13
37
|
function endEventLoop() {
|
|
14
38
|
return new Promise((resolve) => setImmediate(resolve));
|
|
15
39
|
}
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
outOfBandTests.length = 0;
|
|
42
|
+
});
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
outOfBandTests.forEach((fn) => fn());
|
|
45
|
+
});
|
|
16
46
|
|
|
17
47
|
it("should should display a list of available subcommands, for pages with no subcommand", async () => {
|
|
18
48
|
await runWrangler("pages");
|
|
@@ -24,16 +54,15 @@ describe("pages", () => {
|
|
|
24
54
|
⚡️ Configure Cloudflare Pages
|
|
25
55
|
|
|
26
56
|
Commands:
|
|
27
|
-
wrangler pages dev [directory] [-- command] 🧑💻 Develop your full-stack Pages application locally
|
|
28
|
-
wrangler pages project
|
|
29
|
-
wrangler pages deployment
|
|
30
|
-
wrangler pages publish [directory]
|
|
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
|
|
31
61
|
|
|
32
62
|
Flags:
|
|
33
|
-
-c, --config
|
|
34
|
-
-h, --help
|
|
35
|
-
-v, --version
|
|
36
|
-
--legacy-env Use legacy environments [boolean]
|
|
63
|
+
-c, --config Path to .toml configuration file [string]
|
|
64
|
+
-h, --help Show help [boolean]
|
|
65
|
+
-v, --version Show version number [boolean]
|
|
37
66
|
|
|
38
67
|
🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose"
|
|
39
68
|
`);
|
|
@@ -50,7 +79,7 @@ describe("pages", () => {
|
|
|
50
79
|
expect(std.out).toMatchInlineSnapshot(`
|
|
51
80
|
"🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
|
|
52
81
|
|
|
53
|
-
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
82
|
+
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose[0m"
|
|
54
83
|
`);
|
|
55
84
|
});
|
|
56
85
|
|
|
@@ -60,7 +89,7 @@ describe("pages", () => {
|
|
|
60
89
|
expect(std.out).toMatchInlineSnapshot(`
|
|
61
90
|
"🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
|
|
62
91
|
|
|
63
|
-
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new
|
|
92
|
+
[32mIf you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose[0m"
|
|
64
93
|
`);
|
|
65
94
|
});
|
|
66
95
|
});
|
|
@@ -79,12 +108,16 @@ describe("pages", () => {
|
|
|
79
108
|
"/accounts/:accountId/pages/projects",
|
|
80
109
|
([_url, accountId], init, query) => {
|
|
81
110
|
requests.count++;
|
|
82
|
-
expect(accountId).toEqual("some-account-id");
|
|
83
|
-
expect(query.get("per_page")).toEqual("10");
|
|
84
|
-
expect(query.get("page")).toEqual(`${requests.count}`);
|
|
85
|
-
expect(init).toEqual({});
|
|
86
111
|
const pageSize = Number(query.get("per_page"));
|
|
87
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
|
+
});
|
|
88
121
|
return projects.slice((page - 1) * pageSize, page * pageSize);
|
|
89
122
|
}
|
|
90
123
|
);
|
|
@@ -159,12 +192,14 @@ describe("pages", () => {
|
|
|
159
192
|
setMockResponse(
|
|
160
193
|
"/accounts/:accountId/pages/projects",
|
|
161
194
|
([_url, accountId], init) => {
|
|
162
|
-
expect(accountId).toEqual("some-account-id");
|
|
163
|
-
expect(init.method).toEqual("POST");
|
|
164
195
|
const body = JSON.parse(init.body as string);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
+
});
|
|
168
203
|
});
|
|
169
204
|
return {
|
|
170
205
|
name: "a-new-project",
|
|
@@ -196,8 +231,10 @@ describe("pages", () => {
|
|
|
196
231
|
"/accounts/:accountId/pages/projects/:project/deployments",
|
|
197
232
|
([_url, accountId, project]) => {
|
|
198
233
|
requests.count++;
|
|
199
|
-
|
|
200
|
-
|
|
234
|
+
assertLater(() => {
|
|
235
|
+
expect(project).toEqual("images");
|
|
236
|
+
expect(accountId).toEqual("some-account-id");
|
|
237
|
+
});
|
|
201
238
|
return deployments;
|
|
202
239
|
}
|
|
203
240
|
);
|
|
@@ -258,20 +295,19 @@ describe("pages", () => {
|
|
|
258
295
|
🆙 Publish a directory of static assets as a Pages deployment
|
|
259
296
|
|
|
260
297
|
Positionals:
|
|
261
|
-
directory The directory of
|
|
298
|
+
directory The directory of static files to upload [string]
|
|
262
299
|
|
|
263
300
|
Flags:
|
|
264
|
-
-c, --config
|
|
265
|
-
-h, --help
|
|
266
|
-
-v, --version
|
|
267
|
-
--legacy-env Use legacy environments [boolean]
|
|
301
|
+
-c, --config Path to .toml configuration file [string]
|
|
302
|
+
-h, --help Show help [boolean]
|
|
303
|
+
-v, --version Show version number [boolean]
|
|
268
304
|
|
|
269
305
|
Options:
|
|
270
|
-
--project-name The name of the project you want to
|
|
271
|
-
--branch The
|
|
272
|
-
--commit-hash The
|
|
273
|
-
--commit-message The
|
|
274
|
-
--commit-dirty
|
|
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]
|
|
275
311
|
|
|
276
312
|
🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose"
|
|
277
313
|
`);
|
|
@@ -281,33 +317,68 @@ describe("pages", () => {
|
|
|
281
317
|
writeFileSync("logo.png", "foobar");
|
|
282
318
|
|
|
283
319
|
setMockResponse(
|
|
284
|
-
"/accounts/:accountId/pages/projects/foo/
|
|
285
|
-
async ([_url, accountId]
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const logoPNGFile = body.get("file") as File;
|
|
290
|
-
expect(await logoPNGFile.text()).toEqual("foobar");
|
|
291
|
-
expect(logoPNGFile.name).toEqual("logo.png");
|
|
320
|
+
"/accounts/:accountId/pages/projects/foo/upload-token",
|
|
321
|
+
async ([_url, accountId]) => {
|
|
322
|
+
assertLater(() => {
|
|
323
|
+
expect(accountId).toEqual("some-account-id");
|
|
324
|
+
});
|
|
292
325
|
|
|
293
326
|
return {
|
|
294
|
-
|
|
327
|
+
jwt: "<<funfetti-auth-jwt>>",
|
|
295
328
|
};
|
|
296
329
|
}
|
|
297
330
|
);
|
|
298
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
|
+
|
|
299
368
|
setMockResponse(
|
|
300
369
|
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
301
370
|
async ([_url, accountId], init) => {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
+
});
|
|
311
382
|
|
|
312
383
|
return {
|
|
313
384
|
url: "https://abcxyz.foo.pages.dev/",
|
|
@@ -325,5 +396,262 @@ describe("pages", () => {
|
|
|
325
396
|
// ✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
|
|
326
397
|
// `);
|
|
327
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 try to use multiple buckets (up to the max concurrency)", async () => {
|
|
492
|
+
writeFileSync("logo.txt", "foobar");
|
|
493
|
+
writeFileSync("logo.png", "foobar");
|
|
494
|
+
writeFileSync("logo.html", "foobar");
|
|
495
|
+
writeFileSync("logo.js", "foobar");
|
|
496
|
+
|
|
497
|
+
mockGetToken("<<funfetti-auth-jwt>>");
|
|
498
|
+
|
|
499
|
+
setMockResponse(
|
|
500
|
+
"/pages/assets/check-missing",
|
|
501
|
+
"POST",
|
|
502
|
+
async (_, init) => {
|
|
503
|
+
const body = JSON.parse(init.body as string) as { hashes: string[] };
|
|
504
|
+
assertLater(() => {
|
|
505
|
+
expect(init.headers).toMatchObject({
|
|
506
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
507
|
+
});
|
|
508
|
+
expect(body).toMatchObject({
|
|
509
|
+
hashes: expect.arrayContaining([
|
|
510
|
+
"d96fef225537c9f5e44a3cb27fd0b492",
|
|
511
|
+
"2082190357cfd3617ccfe04f340c6247",
|
|
512
|
+
"6be321bef99e758250dac034474ddbb8",
|
|
513
|
+
"1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
514
|
+
]),
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
return body.hashes;
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
// Accumulate multiple requests then assert afterwards
|
|
522
|
+
const requests: RequestInit[] = [];
|
|
523
|
+
setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
|
|
524
|
+
requests.push(init);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
setMockResponse(
|
|
528
|
+
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
529
|
+
async ([_url, accountId], init) => {
|
|
530
|
+
assertLater(() => {
|
|
531
|
+
expect(accountId).toEqual("some-account-id");
|
|
532
|
+
expect(init.method).toEqual("POST");
|
|
533
|
+
const body = init.body as FormData;
|
|
534
|
+
const manifest = JSON.parse(body.get("manifest") as string);
|
|
535
|
+
expect(manifest).toMatchInlineSnapshot(`
|
|
536
|
+
Object {
|
|
537
|
+
"/logo.html": "d96fef225537c9f5e44a3cb27fd0b492",
|
|
538
|
+
"/logo.js": "6be321bef99e758250dac034474ddbb8",
|
|
539
|
+
"/logo.png": "2082190357cfd3617ccfe04f340c6247",
|
|
540
|
+
"/logo.txt": "1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
541
|
+
}
|
|
542
|
+
`);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
return {
|
|
546
|
+
url: "https://abcxyz.foo.pages.dev/",
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
await runWrangler("pages publish . --project-name=foo");
|
|
552
|
+
|
|
553
|
+
// We have 3 buckets, so expect 3 uploads
|
|
554
|
+
expect(requests.length).toBe(3);
|
|
555
|
+
const bodies: UploadPayloadFile[][] = [];
|
|
556
|
+
for (const init of requests) {
|
|
557
|
+
expect(init.headers).toMatchObject({
|
|
558
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
559
|
+
});
|
|
560
|
+
bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
|
|
561
|
+
}
|
|
562
|
+
// First bucket should end up with 2 files
|
|
563
|
+
expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
|
|
564
|
+
// But we don't know the order, so flatten and test without ordering
|
|
565
|
+
expect(bodies.flatMap((b) => b)).toEqual(
|
|
566
|
+
expect.arrayContaining([
|
|
567
|
+
{
|
|
568
|
+
base64: true,
|
|
569
|
+
key: "d96fef225537c9f5e44a3cb27fd0b492",
|
|
570
|
+
metadata: { contentType: "text/html" },
|
|
571
|
+
value: "Zm9vYmFy",
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
base64: true,
|
|
575
|
+
key: "1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
576
|
+
metadata: { contentType: "text/plain" },
|
|
577
|
+
value: "Zm9vYmFy",
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
base64: true,
|
|
581
|
+
key: "6be321bef99e758250dac034474ddbb8",
|
|
582
|
+
metadata: { contentType: "application/javascript" },
|
|
583
|
+
value: "Zm9vYmFy",
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
base64: true,
|
|
587
|
+
key: "2082190357cfd3617ccfe04f340c6247",
|
|
588
|
+
metadata: { contentType: "image/png" },
|
|
589
|
+
value: "Zm9vYmFy",
|
|
590
|
+
},
|
|
591
|
+
])
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
595
|
+
"✨ Success! Uploaded 4 files (TIMINGS)
|
|
596
|
+
|
|
597
|
+
✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
|
|
598
|
+
`);
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it("should not error when directory names contain periods and houses a extensionless file", async () => {
|
|
602
|
+
mkdirSync(".well-known");
|
|
603
|
+
// Note: same content as previous test, but since it's a different extension,
|
|
604
|
+
// it hashes to a different value
|
|
605
|
+
writeFileSync(".well-known/foobar", "foobar");
|
|
606
|
+
|
|
607
|
+
mockGetToken("<<funfetti-auth-jwt>>");
|
|
608
|
+
|
|
609
|
+
setMockResponse(
|
|
610
|
+
"/pages/assets/check-missing",
|
|
611
|
+
"POST",
|
|
612
|
+
async (_, init) => {
|
|
613
|
+
const body = JSON.parse(init.body as string) as { hashes: string[] };
|
|
614
|
+
assertLater(() => {
|
|
615
|
+
expect(init.headers).toMatchObject({
|
|
616
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
617
|
+
});
|
|
618
|
+
expect(body).toMatchObject({
|
|
619
|
+
hashes: ["7b764dacfd211bebd8077828a7ddefd7"],
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
return body.hashes;
|
|
623
|
+
}
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
|
|
627
|
+
assertLater(() => {
|
|
628
|
+
expect(init.headers).toMatchObject({
|
|
629
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
630
|
+
});
|
|
631
|
+
const body = JSON.parse(init.body as string) as UploadPayloadFile[];
|
|
632
|
+
expect(body).toMatchObject([
|
|
633
|
+
{
|
|
634
|
+
key: "7b764dacfd211bebd8077828a7ddefd7",
|
|
635
|
+
value: Buffer.from("foobar").toString("base64"),
|
|
636
|
+
metadata: {
|
|
637
|
+
contentType: "application/octet-stream",
|
|
638
|
+
},
|
|
639
|
+
base64: true,
|
|
640
|
+
},
|
|
641
|
+
]);
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
setMockResponse(
|
|
646
|
+
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
647
|
+
async () => ({
|
|
648
|
+
url: "https://abcxyz.foo.pages.dev/",
|
|
649
|
+
})
|
|
650
|
+
);
|
|
651
|
+
|
|
652
|
+
await runWrangler("pages publish . --project-name=foo");
|
|
653
|
+
|
|
654
|
+
expect(std.err).toMatchInlineSnapshot(`""`);
|
|
655
|
+
});
|
|
328
656
|
});
|
|
329
657
|
});
|
|
@@ -165,6 +165,14 @@ describe("parseTOML", () => {
|
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
});
|
|
168
|
+
|
|
169
|
+
it("should cope with Windows line-endings", () => {
|
|
170
|
+
expect(
|
|
171
|
+
parseTOML(
|
|
172
|
+
"# A comment with a Windows line-ending\r\n# Another comment with a Windows line-ending\r\n"
|
|
173
|
+
)
|
|
174
|
+
).toEqual({});
|
|
175
|
+
});
|
|
168
176
|
});
|
|
169
177
|
|
|
170
178
|
describe("parseJSON", () => {
|