wrangler 0.0.0-e043479 → 0.0.0-e0b9366

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 (51) hide show
  1. package/package.json +10 -4
  2. package/pages/functions/filepath-routing.test.ts +125 -25
  3. package/pages/functions/filepath-routing.ts +6 -3
  4. package/src/__tests__/configuration.test.ts +479 -114
  5. package/src/__tests__/dev.test.tsx +162 -8
  6. package/src/__tests__/dev2.test.tsx +152 -0
  7. package/src/__tests__/guess-worker-format.test.ts +9 -17
  8. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  9. package/src/__tests__/helpers/mock-cfetch.ts +3 -3
  10. package/src/__tests__/helpers/mock-kv.ts +9 -16
  11. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  12. package/src/__tests__/https-options.test.ts +127 -0
  13. package/src/__tests__/index.test.ts +125 -0
  14. package/src/__tests__/jest.setup.ts +1 -1
  15. package/src/__tests__/kv.test.ts +27 -53
  16. package/src/__tests__/logout.test.ts +15 -13
  17. package/src/__tests__/pages.test.ts +44 -0
  18. package/src/__tests__/publish.test.ts +504 -32
  19. package/src/__tests__/route.test.ts +45 -0
  20. package/src/__tests__/whoami.test.tsx +21 -7
  21. package/src/bundle.ts +20 -11
  22. package/src/cfetch/internal.ts +11 -5
  23. package/src/config/config.ts +53 -44
  24. package/src/config/validation-helpers.ts +110 -12
  25. package/src/config/validation.ts +59 -41
  26. package/src/{api/preview.ts → create-worker-preview.ts} +23 -4
  27. package/src/{api/form_data.ts → create-worker-upload-form.ts} +1 -1
  28. package/src/dev/dev.tsx +357 -0
  29. package/src/dev/local.tsx +241 -0
  30. package/src/dev/remote.tsx +201 -0
  31. package/src/dev/use-esbuild.ts +100 -0
  32. package/src/entry.ts +111 -9
  33. package/src/https-options.ts +122 -0
  34. package/src/index.tsx +171 -109
  35. package/src/inspect.ts +9 -1
  36. package/src/{kv.tsx → kv.ts} +0 -0
  37. package/src/module-collection.ts +85 -2
  38. package/src/open-in-browser.ts +14 -2
  39. package/src/pages.tsx +1 -1
  40. package/src/proxy.ts +102 -40
  41. package/src/publish.ts +41 -50
  42. package/src/reporting.ts +25 -9
  43. package/src/selfsigned.d.ts +29 -0
  44. package/src/sites.tsx +51 -16
  45. package/src/user.tsx +132 -77
  46. package/src/{api/worker.ts → worker.ts} +0 -23
  47. package/wrangler-dist/cli.js +5012 -3107
  48. package/wrangler-dist/cli.js.map +3 -3
  49. package/src/__tests__/helpers/mock-user.ts +0 -27
  50. package/src/dev.tsx +0 -960
  51. package/src/guess-worker-format.ts +0 -68
@@ -2,14 +2,20 @@ import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
3
  import * as TOML from "@iarna/toml";
4
4
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
5
- import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
5
+ import {
6
+ createFetchResult,
7
+ setMockFetchKVGetValue,
8
+ setMockRawResponse,
9
+ setMockResponse,
10
+ unsetAllMocks,
11
+ unsetMockFetchKVGetValues,
12
+ } from "./helpers/mock-cfetch";
6
13
  import { mockConsoleMethods } from "./helpers/mock-console";
7
14
  import { mockKeyListRequest } from "./helpers/mock-kv";
8
15
  import { runInTempDir } from "./helpers/run-in-tmp";
9
16
  import { runWrangler } from "./helpers/run-wrangler";
10
17
  import writeWranglerToml from "./helpers/write-wrangler-toml";
11
- import type { WorkerMetadata } from "../api/form_data";
12
- import type { Config } from "../config";
18
+ import type { WorkerMetadata } from "../create-worker-upload-form";
13
19
  import type { KVNamespaceInfo } from "../kv";
14
20
  import type { FormData, File } from "undici";
15
21
 
@@ -27,6 +33,7 @@ describe("publish", () => {
27
33
 
28
34
  afterEach(() => {
29
35
  unsetAllMocks();
36
+ unsetMockFetchKVGetValues();
30
37
  });
31
38
 
32
39
  describe("environments", () => {
@@ -143,6 +150,7 @@ describe("publish", () => {
143
150
  type: "json",
144
151
  },
145
152
  ],
153
+ expectedCompatibilityDate: "2022-01-12",
146
154
  });
147
155
  mockSubDomainRequest();
148
156
  await runWrangler("publish ./some-path/worker/index.js");
@@ -460,9 +468,8 @@ export default{
460
468
 
461
469
  it('should error if a site definition doesn\'t have a "bucket" field', async () => {
462
470
  writeWranglerToml({
463
- site: {
464
- "entry-point": "./index.js",
465
- } as Config["site"],
471
+ // @ts-expect-error we're intentionally setting an invalid config
472
+ site: {},
466
473
  });
467
474
  writeWorkerSource();
468
475
  mockUploadWorkerRequest();
@@ -471,20 +478,20 @@ export default{
471
478
  await expect(runWrangler("publish ./index.js")).rejects
472
479
  .toThrowErrorMatchingInlineSnapshot(`
473
480
  "Processing wrangler.toml configuration:
474
- - ERROR: \\"site.bucket\\" is a required field."
481
+ - \\"site.bucket\\" is a required field."
475
482
  `);
476
483
 
477
484
  expect(std.out).toMatchInlineSnapshot(`""`);
478
485
  expect(std.err).toMatchInlineSnapshot(`
479
486
  "Processing wrangler.toml configuration:
480
- - ERROR: \\"site.bucket\\" is a required field.
487
+ - \\"site.bucket\\" is a required field.
481
488
 
482
489
  %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
483
490
  `);
484
491
  expect(std.warn).toMatchInlineSnapshot(`""`);
485
492
  });
486
493
 
487
- it("should warn if there is a `site.entry-point` configuration", async () => {
494
+ it("should error if there is a `site.entry-point` configuration", async () => {
488
495
  const assets = [
489
496
  { filePath: "assets/file-1.txt", content: "Content of file-1" },
490
497
  { filePath: "assets/file-2.txt", content: "Content of file-2" },
@@ -508,22 +515,26 @@ export default{
508
515
  mockKeyListRequest(kvNamespace.id, []);
509
516
  mockUploadAssetsToKVRequest(kvNamespace.id, assets);
510
517
 
511
- await runWrangler("publish ./index.js");
518
+ await expect(runWrangler("publish ./index.js")).rejects
519
+ .toThrowErrorMatchingInlineSnapshot(`
520
+ "Processing wrangler.toml configuration:
521
+ - DEPRECATION: \\"site.entry-point\\":
522
+ The \`site.entry-point\` config field is no longer used.
523
+ The entry-point should be specified via the command line or the \`main\` config field."
524
+ `);
512
525
 
513
- expect(std.out).toMatchInlineSnapshot(`
514
- "reading assets/file-1.txt...
515
- uploading as assets/file-1.2ca234f380.txt...
516
- reading assets/file-2.txt...
517
- uploading as assets/file-2.5938485188.txt...
518
- Uploaded test-name (TIMINGS)
519
- Published test-name (TIMINGS)
520
- test-name.test-sub-domain.workers.dev"
526
+ expect(std.out).toMatchInlineSnapshot(`""`);
527
+ expect(std.err).toMatchInlineSnapshot(`
528
+ "Processing wrangler.toml configuration:
529
+ - DEPRECATION: \\"site.entry-point\\":
530
+ The \`site.entry-point\` config field is no longer used.
531
+ The entry-point should be specified via the command line or the \`main\` config field.
532
+
533
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
521
534
  `);
522
- expect(std.err).toMatchInlineSnapshot(`""`);
523
535
  expect(std.warn).toMatchInlineSnapshot(`
524
- "Deprecation notice: The \`site.entry-point\` config field is no longer used.
525
- The entry-point should be specified via the command line (e.g. \`wrangler publish path/to/script\`) or the \`main\` config field.
526
- Please remove the \`site.entry-point\` field from the \`wrangler.toml\` file."
536
+ "Processing wrangler.toml configuration:
537
+ - Unexpected fields found in site field: \\"entry-point\\""
527
538
  `);
528
539
  });
529
540
 
@@ -802,7 +813,9 @@ export default{
802
813
  mockSubDomainRequest();
803
814
  mockListKVNamespacesRequest(kvNamespace);
804
815
  // Put file-1 in the KV namespace
805
- mockKeyListRequest(kvNamespace.id, ["assets/file-1.2ca234f380.txt"]);
816
+ mockKeyListRequest(kvNamespace.id, [
817
+ { name: "assets/file-1.2ca234f380.txt" },
818
+ ]);
806
819
  // Check we do not upload file-1
807
820
  mockUploadAssetsToKVRequest(
808
821
  kvNamespace.id,
@@ -1224,6 +1237,152 @@ export default{
1224
1237
  %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1225
1238
  `);
1226
1239
  });
1240
+
1241
+ describe("expire unused assets", () => {
1242
+ it("should expire uploaded assets that aren't included anymore", async () => {
1243
+ const assets = [
1244
+ { filePath: "assets/file-1.txt", content: "Content of file-1" },
1245
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1246
+ ];
1247
+ const kvNamespace = {
1248
+ title: "__test-name-workers_sites_assets",
1249
+ id: "__test-name-workers_sites_assets-id",
1250
+ };
1251
+ writeWranglerToml({
1252
+ main: "./index.js",
1253
+ site: {
1254
+ bucket: "assets",
1255
+ },
1256
+ });
1257
+ writeWorkerSource();
1258
+ writeAssets(assets);
1259
+ mockUploadWorkerRequest();
1260
+ mockSubDomainRequest();
1261
+ mockListKVNamespacesRequest(kvNamespace);
1262
+ mockKeyListRequest(kvNamespace.id, [
1263
+ // Put file-1 in the KV namespace
1264
+ { name: "assets/file-1.2ca234f380.txt" },
1265
+ // As well as a couple from a previous upload
1266
+ { name: "assets/file-3.somehash.txt" },
1267
+ { name: "assets/file-4.anotherhash.txt" },
1268
+ ]);
1269
+
1270
+ // Check that we pull down the values of file-3.txt and file-4.txt
1271
+ setMockFetchKVGetValue(
1272
+ "some-account-id",
1273
+ "__test-name-workers_sites_assets-id",
1274
+ "assets/file-3.somehash.txt",
1275
+ Buffer.from("Content of file-3", "utf8").toString("base64")
1276
+ );
1277
+ setMockFetchKVGetValue(
1278
+ "some-account-id",
1279
+ "__test-name-workers_sites_assets-id",
1280
+ "assets/file-4.anotherhash.txt",
1281
+ Buffer.from("Content of file-4", "utf8").toString("base64")
1282
+ );
1283
+
1284
+ // and send them back up
1285
+ mockUploadAssetsToKVRequest(kvNamespace.id, [
1286
+ ...assets.filter((a) => a.filePath !== "assets/file-1.txt"),
1287
+ {
1288
+ filePath: "assets/file-3.txt",
1289
+ content: "Content of file-3",
1290
+ // expect to expire this asset 300 seconds from now
1291
+ expiration_ttl: 300,
1292
+ },
1293
+ {
1294
+ filePath: "assets/file-4.txt",
1295
+ content: "Content of file-4",
1296
+ // expect to expire this asset 300 seconds from now
1297
+ expiration_ttl: 300,
1298
+ },
1299
+ ]);
1300
+
1301
+ await runWrangler("publish");
1302
+
1303
+ expect(std.out).toMatchInlineSnapshot(`
1304
+ "reading assets/file-1.txt...
1305
+ skipping - already uploaded
1306
+ reading assets/file-2.txt...
1307
+ uploading as assets/file-2.5938485188.txt...
1308
+ expiring unused assets/file-3.somehash.txt...
1309
+ expiring unused assets/file-4.anotherhash.txt...
1310
+ Uploaded test-name (TIMINGS)
1311
+ Published test-name (TIMINGS)
1312
+ test-name.test-sub-domain.workers.dev"
1313
+ `);
1314
+ expect(std.err).toMatchInlineSnapshot(`""`);
1315
+ });
1316
+
1317
+ it("should not try to expire uploaded assets that are already set to expire", async () => {
1318
+ const assets = [
1319
+ {
1320
+ filePath: "assets/file-1.txt",
1321
+ content: "Content of file-1",
1322
+ },
1323
+ { filePath: "assets/file-2.txt", content: "Content of file-2" },
1324
+ ];
1325
+ const kvNamespace = {
1326
+ title: "__test-name-workers_sites_assets",
1327
+ id: "__test-name-workers_sites_assets-id",
1328
+ };
1329
+ writeWranglerToml({
1330
+ main: "./index.js",
1331
+ site: {
1332
+ bucket: "assets",
1333
+ },
1334
+ });
1335
+ writeWorkerSource();
1336
+ writeAssets(assets);
1337
+ mockUploadWorkerRequest();
1338
+ mockSubDomainRequest();
1339
+ mockListKVNamespacesRequest(kvNamespace);
1340
+ // These return with an expiration added on each of them
1341
+ mockKeyListRequest(kvNamespace.id, [
1342
+ // Put file-1 in the KV namespace, with an expiration
1343
+ { name: "assets/file-1.2ca234f380.txt", expiration: 10000 },
1344
+ // As well as a couple from a previous upload
1345
+ // This one's set to expire so it won't be uploaded back
1346
+ { name: "assets/file-3.somehash.txt", expiration: 10000 },
1347
+ // This one will be sent back with an expiration value
1348
+ { name: "assets/file-4.anotherhash.txt" },
1349
+ ]);
1350
+
1351
+ setMockFetchKVGetValue(
1352
+ "some-account-id",
1353
+ "__test-name-workers_sites_assets-id",
1354
+ "assets/file-4.anotherhash.txt",
1355
+ Buffer.from("Content of file-4", "utf8").toString("base64")
1356
+ );
1357
+
1358
+ mockUploadAssetsToKVRequest(kvNamespace.id, [
1359
+ // so it'll re-upload file-1 because it's set to expire
1360
+ // and file-2 because it hasn't been uploaded yet
1361
+ ...assets,
1362
+ // and it'll expire file-4 since it's just not included anymore
1363
+ {
1364
+ filePath: "assets/file-4.txt",
1365
+ content: "Content of file-4",
1366
+ // expect to expire this asset 300 seconds from now
1367
+ expiration_ttl: 300,
1368
+ },
1369
+ ]);
1370
+
1371
+ await runWrangler("publish");
1372
+
1373
+ expect(std.out).toMatchInlineSnapshot(`
1374
+ "reading assets/file-1.txt...
1375
+ uploading as assets/file-1.2ca234f380.txt...
1376
+ reading assets/file-2.txt...
1377
+ uploading as assets/file-2.5938485188.txt...
1378
+ expiring unused assets/file-4.anotherhash.txt...
1379
+ Uploaded test-name (TIMINGS)
1380
+ Published test-name (TIMINGS)
1381
+ test-name.test-sub-domain.workers.dev"
1382
+ `);
1383
+ expect(std.err).toMatchInlineSnapshot(`""`);
1384
+ });
1385
+ });
1227
1386
  });
1228
1387
 
1229
1388
  describe("workers_dev setting", () => {
@@ -1267,7 +1426,6 @@ export default{
1267
1426
  });
1268
1427
  writeWorkerSource();
1269
1428
  mockUploadWorkerRequest();
1270
- mockSubDomainRequest();
1271
1429
  mockUpdateWorkerRequest({ enabled: false });
1272
1430
 
1273
1431
  await runWrangler("publish ./index");
@@ -1279,6 +1437,193 @@ export default{
1279
1437
  expect(std.err).toMatchInlineSnapshot(`""`);
1280
1438
  });
1281
1439
 
1440
+ it("should disable the workers.dev domain if workers_dev is undefined but overwritten to `false` in environment", async () => {
1441
+ writeWranglerToml({
1442
+ env: {
1443
+ dev: {
1444
+ workers_dev: false,
1445
+ },
1446
+ },
1447
+ });
1448
+ writeWorkerSource();
1449
+ mockUploadWorkerRequest({
1450
+ env: "dev",
1451
+ });
1452
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
1453
+
1454
+ await runWrangler("publish ./index --env dev --legacy-env false");
1455
+
1456
+ expect(std.out).toMatchInlineSnapshot(`
1457
+ "Uploaded test-name (dev) (TIMINGS)
1458
+ No publish targets for test-name (dev) (TIMINGS)"
1459
+ `);
1460
+ expect(std.err).toMatchInlineSnapshot(`""`);
1461
+ });
1462
+
1463
+ it("should disable the workers.dev domain if workers_dev is `true` but overwritten to `false` in environment", async () => {
1464
+ writeWranglerToml({
1465
+ workers_dev: true,
1466
+ env: {
1467
+ dev: {
1468
+ workers_dev: false,
1469
+ },
1470
+ },
1471
+ });
1472
+ writeWorkerSource();
1473
+ mockUploadWorkerRequest({
1474
+ env: "dev",
1475
+ });
1476
+ mockUpdateWorkerRequest({ enabled: false, env: "dev" });
1477
+
1478
+ await runWrangler("publish ./index --env dev --legacy-env false");
1479
+
1480
+ expect(std.out).toMatchInlineSnapshot(`
1481
+ "Uploaded test-name (dev) (TIMINGS)
1482
+ No publish targets for test-name (dev) (TIMINGS)"
1483
+ `);
1484
+ expect(std.err).toMatchInlineSnapshot(`""`);
1485
+ });
1486
+
1487
+ it("should publish to a workers.dev domain if workers_dev is undefined but overwritten to `true` in environment", async () => {
1488
+ writeWranglerToml({
1489
+ env: {
1490
+ dev: {
1491
+ workers_dev: true,
1492
+ },
1493
+ },
1494
+ });
1495
+ writeWorkerSource();
1496
+ mockUploadWorkerRequest({
1497
+ env: "dev",
1498
+ });
1499
+ mockSubDomainRequest();
1500
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1501
+
1502
+ await runWrangler("publish ./index --env dev --legacy-env false");
1503
+
1504
+ expect(std.out).toMatchInlineSnapshot(`
1505
+ "Uploaded test-name (dev) (TIMINGS)
1506
+ Published test-name (dev) (TIMINGS)
1507
+ dev.test-name.test-sub-domain.workers.dev"
1508
+ `);
1509
+ expect(std.err).toMatchInlineSnapshot(`""`);
1510
+ });
1511
+
1512
+ it("should publish to a workers.dev domain if workers_dev is `false` but overwritten to `true` in environment", async () => {
1513
+ writeWranglerToml({
1514
+ workers_dev: false,
1515
+ env: {
1516
+ dev: {
1517
+ workers_dev: true,
1518
+ },
1519
+ },
1520
+ });
1521
+ writeWorkerSource();
1522
+ mockUploadWorkerRequest({
1523
+ env: "dev",
1524
+ });
1525
+ mockSubDomainRequest();
1526
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1527
+
1528
+ await runWrangler("publish ./index --env dev --legacy-env false");
1529
+
1530
+ expect(std.out).toMatchInlineSnapshot(`
1531
+ "Uploaded test-name (dev) (TIMINGS)
1532
+ Published test-name (dev) (TIMINGS)
1533
+ dev.test-name.test-sub-domain.workers.dev"
1534
+ `);
1535
+ expect(std.err).toMatchInlineSnapshot(`""`);
1536
+ });
1537
+
1538
+ it("should use the global compatibility_date and compatibility_flags if they are not overwritten by the environment", async () => {
1539
+ writeWranglerToml({
1540
+ compatibility_date: "2022-01-12",
1541
+ compatibility_flags: ["no_global_navigator"],
1542
+ env: {
1543
+ dev: {},
1544
+ },
1545
+ });
1546
+ writeWorkerSource();
1547
+ mockUploadWorkerRequest({
1548
+ env: "dev",
1549
+ expectedCompatibilityDate: "2022-01-12",
1550
+ expectedCompatibilityFlags: ["no_global_navigator"],
1551
+ });
1552
+ mockSubDomainRequest();
1553
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1554
+
1555
+ await runWrangler("publish ./index --env dev --legacy-env false");
1556
+
1557
+ expect(std.out).toMatchInlineSnapshot(`
1558
+ "Uploaded test-name (dev) (TIMINGS)
1559
+ Published test-name (dev) (TIMINGS)
1560
+ dev.test-name.test-sub-domain.workers.dev"
1561
+ `);
1562
+ expect(std.err).toMatchInlineSnapshot(`""`);
1563
+ });
1564
+
1565
+ it("should use the environment specific compatibility_date and compatibility_flags", async () => {
1566
+ writeWranglerToml({
1567
+ compatibility_date: "2022-01-12",
1568
+ compatibility_flags: ["no_global_navigator"],
1569
+ env: {
1570
+ dev: {
1571
+ compatibility_date: "2022-01-13",
1572
+ compatibility_flags: ["global_navigator"],
1573
+ },
1574
+ },
1575
+ });
1576
+ writeWorkerSource();
1577
+ mockUploadWorkerRequest({
1578
+ env: "dev",
1579
+ expectedCompatibilityDate: "2022-01-13",
1580
+ expectedCompatibilityFlags: ["global_navigator"],
1581
+ });
1582
+ mockSubDomainRequest();
1583
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1584
+
1585
+ await runWrangler("publish ./index --env dev --legacy-env false");
1586
+
1587
+ expect(std.out).toMatchInlineSnapshot(`
1588
+ "Uploaded test-name (dev) (TIMINGS)
1589
+ Published test-name (dev) (TIMINGS)
1590
+ dev.test-name.test-sub-domain.workers.dev"
1591
+ `);
1592
+ expect(std.err).toMatchInlineSnapshot(`""`);
1593
+ });
1594
+
1595
+ it("should use the command line --compatibility-date and --compatibility-flags if they are specified", async () => {
1596
+ writeWranglerToml({
1597
+ compatibility_date: "2022-01-12",
1598
+ compatibility_flags: ["no_global_navigator"],
1599
+ env: {
1600
+ dev: {
1601
+ compatibility_date: "2022-01-13",
1602
+ compatibility_flags: ["global_navigator"],
1603
+ },
1604
+ },
1605
+ });
1606
+ writeWorkerSource();
1607
+ mockUploadWorkerRequest({
1608
+ env: "dev",
1609
+ expectedCompatibilityDate: "2022-01-14",
1610
+ expectedCompatibilityFlags: ["url_standard"],
1611
+ });
1612
+ mockSubDomainRequest();
1613
+ mockUpdateWorkerRequest({ enabled: true, env: "dev" });
1614
+
1615
+ await runWrangler(
1616
+ "publish ./index --env dev --legacy-env false --compatibility-date 2022-01-14 --compatibility-flags url_standard"
1617
+ );
1618
+
1619
+ expect(std.out).toMatchInlineSnapshot(`
1620
+ "Uploaded test-name (dev) (TIMINGS)
1621
+ Published test-name (dev) (TIMINGS)
1622
+ dev.test-name.test-sub-domain.workers.dev"
1623
+ `);
1624
+ expect(std.err).toMatchInlineSnapshot(`""`);
1625
+ });
1626
+
1282
1627
  it("should enable the workers.dev domain if workers_dev is undefined and subdomain is not already available", async () => {
1283
1628
  writeWranglerToml();
1284
1629
  writeWorkerSource();
@@ -1312,6 +1657,22 @@ export default{
1312
1657
  `);
1313
1658
  expect(std.err).toMatchInlineSnapshot(`""`);
1314
1659
  });
1660
+
1661
+ it("should error politely when publishing to workers_dev when there is no workers.dev subdomain", async () => {
1662
+ writeWranglerToml({
1663
+ workers_dev: true,
1664
+ });
1665
+ writeWorkerSource();
1666
+ mockUploadWorkerRequest();
1667
+ mockSubDomainRequest("does-not-exist", false);
1668
+
1669
+ await expect(runWrangler("publish ./index")).rejects
1670
+ .toThrowErrorMatchingInlineSnapshot(`
1671
+ "Error: You need to register a workers.dev subdomain before publishing to workers.dev
1672
+ You can either publish your worker to one or more routes by specifying them in wrangler.toml, or register a workers.dev subdomain here:
1673
+ https://dash.cloudflare.com/some-account-id/workers/onboarding"
1674
+ `);
1675
+ });
1315
1676
  });
1316
1677
 
1317
1678
  describe("custom builds", () => {
@@ -1367,6 +1728,30 @@ export default{
1367
1728
  expect(std.warn).toMatchInlineSnapshot(`""`);
1368
1729
  });
1369
1730
  }
1731
+
1732
+ it("should throw an error if the entry doesn't exist after the build finishes", async () => {
1733
+ writeWranglerToml({
1734
+ main: "index.js",
1735
+ build: {
1736
+ command: `node -e "console.log('custom build');"`,
1737
+ },
1738
+ });
1739
+
1740
+ await expect(
1741
+ runWrangler("publish index.js")
1742
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
1743
+ `"Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\""`
1744
+ );
1745
+ expect(std.out).toMatchInlineSnapshot(
1746
+ `"running: node -e \\"console.log('custom build');\\""`
1747
+ );
1748
+ expect(std.err).toMatchInlineSnapshot(`
1749
+ "Could not resolve \\"index.js\\" after running custom build: node -e \\"console.log('custom build');\\"
1750
+
1751
+ %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
1752
+ `);
1753
+ expect(std.warn).toMatchInlineSnapshot(`""`);
1754
+ });
1370
1755
  });
1371
1756
 
1372
1757
  describe("[wasm_modules]", () => {
@@ -1447,6 +1832,7 @@ export default{
1447
1832
  expectedBindings: [
1448
1833
  { name: "TESTWASMNAME", part: "TESTWASMNAME", type: "wasm_module" },
1449
1834
  ],
1835
+ expectedCompatibilityDate: "2022-01-12",
1450
1836
  });
1451
1837
  mockSubDomainRequest();
1452
1838
  await runWrangler("publish index.js --config ./path/to/wrangler.toml");
@@ -1575,6 +1961,7 @@ export default{
1575
1961
  type: "text_blob",
1576
1962
  },
1577
1963
  ],
1964
+ expectedCompatibilityDate: "2022-01-12",
1578
1965
  });
1579
1966
  mockSubDomainRequest();
1580
1967
  await runWrangler("publish index.js --config ./path/to/wrangler.toml");
@@ -1919,6 +2306,62 @@ export default{
1919
2306
  `);
1920
2307
  });
1921
2308
  });
2309
+
2310
+ describe("legacy module specifiers", () => {
2311
+ it("should work with legacy module specifiers, with a deprecation warning (1)", async () => {
2312
+ writeWranglerToml({
2313
+ rules: [{ type: "Text", globs: ["**/*.file"], fallthrough: false }],
2314
+ });
2315
+ fs.writeFileSync(
2316
+ "./index.js",
2317
+ `import TEXT from 'text.file'; export default {};`
2318
+ );
2319
+ fs.writeFileSync("./text.file", "SOME TEXT CONTENT");
2320
+ mockSubDomainRequest();
2321
+ mockUploadWorkerRequest({
2322
+ expectedModules: {
2323
+ "./2d91d1c4dd6e57d4f5432187ab7c25f45a8973f0-text.file":
2324
+ "SOME TEXT CONTENT",
2325
+ },
2326
+ });
2327
+ await runWrangler("publish index.js");
2328
+ expect(std.out).toMatchInlineSnapshot(`
2329
+ "Uploaded test-name (TIMINGS)
2330
+ Published test-name (TIMINGS)
2331
+ test-name.test-sub-domain.workers.dev"
2332
+ `);
2333
+ expect(std.err).toMatchInlineSnapshot(`""`);
2334
+ expect(std.warn).toMatchInlineSnapshot(
2335
+ `"Deprecation warning: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"text.file\\" with \\"./text.file\\";"`
2336
+ );
2337
+ });
2338
+ });
2339
+
2340
+ it("should work with legacy module specifiers, with a deprecation warning (2)", async () => {
2341
+ writeWranglerToml();
2342
+ fs.writeFileSync(
2343
+ "./index.js",
2344
+ `import WASM from 'index.wasm'; export default {};`
2345
+ );
2346
+ fs.writeFileSync("./index.wasm", "SOME WASM CONTENT");
2347
+ mockSubDomainRequest();
2348
+ mockUploadWorkerRequest({
2349
+ expectedModules: {
2350
+ "./94b240d0d692281e6467aa42043986e5c7eea034-index.wasm":
2351
+ "SOME WASM CONTENT",
2352
+ },
2353
+ });
2354
+ await runWrangler("publish index.js");
2355
+ expect(std.out).toMatchInlineSnapshot(`
2356
+ "Uploaded test-name (TIMINGS)
2357
+ Published test-name (TIMINGS)
2358
+ test-name.test-sub-domain.workers.dev"
2359
+ `);
2360
+ expect(std.err).toMatchInlineSnapshot(`""`);
2361
+ expect(std.warn).toMatchInlineSnapshot(
2362
+ `"Deprecation warning: detected a legacy module import in \\"./index.js\\". This will stop working in the future. Replace references to \\"index.wasm\\" with \\"./index.wasm\\";"`
2363
+ );
2364
+ });
1922
2365
  });
1923
2366
 
1924
2367
  /** Write a mock Worker script to disk. */
@@ -1966,6 +2409,8 @@ function mockUploadWorkerRequest({
1966
2409
  expectedType = "esm",
1967
2410
  expectedBindings,
1968
2411
  expectedModules = {},
2412
+ expectedCompatibilityDate,
2413
+ expectedCompatibilityFlags,
1969
2414
  env = undefined,
1970
2415
  legacyEnv = false,
1971
2416
  }: {
@@ -1974,8 +2419,10 @@ function mockUploadWorkerRequest({
1974
2419
  expectedType?: "esm" | "sw";
1975
2420
  expectedBindings?: unknown;
1976
2421
  expectedModules?: Record<string, string>;
1977
- env?: string | undefined;
1978
- legacyEnv?: boolean | undefined;
2422
+ expectedCompatibilityDate?: string;
2423
+ expectedCompatibilityFlags?: string[];
2424
+ env?: string;
2425
+ legacyEnv?: boolean;
1979
2426
  } = {}) {
1980
2427
  setMockResponse(
1981
2428
  env && !legacyEnv
@@ -1997,7 +2444,6 @@ function mockUploadWorkerRequest({
1997
2444
  expectedEntry
1998
2445
  );
1999
2446
  }
2000
-
2001
2447
  const metadata = JSON.parse(
2002
2448
  formBody.get("metadata") as string
2003
2449
  ) as WorkerMetadata;
@@ -2009,6 +2455,14 @@ function mockUploadWorkerRequest({
2009
2455
  if (expectedBindings !== undefined) {
2010
2456
  expect(metadata.bindings).toEqual(expectedBindings);
2011
2457
  }
2458
+ if (expectedCompatibilityDate !== undefined) {
2459
+ expect(metadata.compatibility_date).toEqual(expectedCompatibilityDate);
2460
+ }
2461
+ if (expectedCompatibilityFlags !== undefined) {
2462
+ expect(metadata.compatibility_flags).toEqual(
2463
+ expectedCompatibilityFlags
2464
+ );
2465
+ }
2012
2466
  for (const [name, content] of Object.entries(expectedModules)) {
2013
2467
  expect(await (formBody.get(name) as File).text()).toEqual(content);
2014
2468
  }
@@ -2019,10 +2473,21 @@ function mockUploadWorkerRequest({
2019
2473
  }
2020
2474
 
2021
2475
  /** Create a mock handler for the request to get the account's subdomain. */
2022
- function mockSubDomainRequest(subdomain = "test-sub-domain") {
2023
- setMockResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2024
- return { subdomain };
2025
- });
2476
+ function mockSubDomainRequest(
2477
+ subdomain = "test-sub-domain",
2478
+ registeredWorkersDev = true
2479
+ ) {
2480
+ if (registeredWorkersDev) {
2481
+ setMockResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2482
+ return { subdomain };
2483
+ });
2484
+ } else {
2485
+ setMockRawResponse("/accounts/:accountId/workers/subdomain", "GET", () => {
2486
+ return createFetchResult(null, false, [
2487
+ { code: 10007, message: "haven't registered workers.dev" },
2488
+ ]);
2489
+ });
2490
+ }
2026
2491
  }
2027
2492
 
2028
2493
  /** Create a mock handler to toggle a <script>.<user>.workers.dev subdomain */
@@ -2103,7 +2568,12 @@ function mockListKVNamespacesRequest(...namespaces: KVNamespaceInfo[]) {
2103
2568
  /** Create a mock handler for the request that tries to do a bulk upload of assets to a KV namespace. */
2104
2569
  function mockUploadAssetsToKVRequest(
2105
2570
  expectedNamespaceId: string,
2106
- assets: { filePath: string; content: string }[]
2571
+ assets: {
2572
+ filePath: string;
2573
+ content: string;
2574
+ expiration?: number;
2575
+ expiration_ttl?: number;
2576
+ }[]
2107
2577
  ) {
2108
2578
  setMockResponse(
2109
2579
  "/accounts/:accountId/storage/kv/namespaces/:namespaceId/bulk",
@@ -2132,6 +2602,8 @@ function mockUploadAssetsToKVRequest(
2132
2602
  expect(Buffer.from(upload.value, "base64").toString()).toEqual(
2133
2603
  asset.content
2134
2604
  );
2605
+ expect(upload.expiration).toEqual(asset.expiration);
2606
+ expect(upload.expiration_ttl).toEqual(asset.expiration_ttl);
2135
2607
  }
2136
2608
  return null;
2137
2609
  }