wrangler 2.0.22 → 2.0.25

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 (75) hide show
  1. package/README.md +20 -2
  2. package/bin/wrangler.js +1 -1
  3. package/miniflare-dist/index.mjs +643 -7
  4. package/package.json +17 -5
  5. package/src/__tests__/configuration.test.ts +89 -17
  6. package/src/__tests__/dev.test.tsx +121 -8
  7. package/src/__tests__/generate.test.ts +93 -0
  8. package/src/__tests__/helpers/mock-cfetch.ts +54 -2
  9. package/src/__tests__/index.test.ts +10 -27
  10. package/src/__tests__/jest.setup.ts +31 -1
  11. package/src/__tests__/kv.test.ts +82 -61
  12. package/src/__tests__/metrics.test.ts +5 -0
  13. package/src/__tests__/publish.test.ts +573 -254
  14. package/src/__tests__/r2.test.ts +173 -71
  15. package/src/__tests__/tail.test.ts +93 -39
  16. package/src/__tests__/user.test.ts +1 -0
  17. package/src/__tests__/validate-dev-props.test.ts +56 -0
  18. package/src/__tests__/version.test.ts +35 -0
  19. package/src/__tests__/whoami.test.tsx +60 -1
  20. package/src/api/dev.ts +49 -9
  21. package/src/bundle.ts +298 -37
  22. package/src/cfetch/internal.ts +34 -2
  23. package/src/config/config.ts +15 -3
  24. package/src/config/environment.ts +40 -8
  25. package/src/config/index.ts +13 -0
  26. package/src/config/validation.ts +111 -9
  27. package/src/create-worker-preview.ts +3 -1
  28. package/src/create-worker-upload-form.ts +25 -0
  29. package/src/dev/dev.tsx +145 -31
  30. package/src/dev/local.tsx +116 -24
  31. package/src/dev/remote.tsx +39 -12
  32. package/src/dev/use-esbuild.ts +28 -0
  33. package/src/dev/validate-dev-props.ts +31 -0
  34. package/src/dev-registry.tsx +160 -0
  35. package/src/dev.tsx +148 -67
  36. package/src/generate.ts +112 -14
  37. package/src/index.tsx +252 -7
  38. package/src/inspect.ts +90 -5
  39. package/src/metrics/index.ts +1 -0
  40. package/src/metrics/metrics-dispatcher.ts +1 -0
  41. package/src/metrics/metrics-usage-headers.ts +24 -0
  42. package/src/metrics/send-event.ts +2 -2
  43. package/src/miniflare-cli/assets.ts +546 -0
  44. package/src/miniflare-cli/index.ts +157 -6
  45. package/src/module-collection.ts +3 -3
  46. package/src/pages/build.tsx +36 -28
  47. package/src/pages/constants.ts +4 -0
  48. package/src/pages/deployments.tsx +10 -10
  49. package/src/pages/dev.tsx +155 -651
  50. package/src/pages/functions/buildPlugin.ts +4 -0
  51. package/src/pages/functions/buildWorker.ts +4 -0
  52. package/src/pages/functions/routes-consolidation.test.ts +66 -0
  53. package/src/pages/functions/routes-consolidation.ts +29 -0
  54. package/src/pages/functions/routes-transformation.test.ts +271 -0
  55. package/src/pages/functions/routes-transformation.ts +125 -0
  56. package/src/pages/projects.tsx +9 -3
  57. package/src/pages/publish.tsx +57 -15
  58. package/src/pages/types.ts +9 -0
  59. package/src/pages/upload.tsx +38 -21
  60. package/src/publish.ts +139 -112
  61. package/src/r2.ts +81 -0
  62. package/src/tail/index.ts +15 -2
  63. package/src/tail/printing.ts +41 -3
  64. package/src/user/choose-account.tsx +20 -11
  65. package/src/user/user.tsx +20 -2
  66. package/src/whoami.tsx +79 -1
  67. package/src/worker.ts +12 -0
  68. package/templates/first-party-worker-module-facade.ts +18 -0
  69. package/templates/format-dev-errors.ts +32 -0
  70. package/templates/pages-shim.ts +9 -0
  71. package/templates/{static-asset-facade.js → serve-static-assets.ts} +21 -7
  72. package/templates/service-bindings-module-facade.js +51 -0
  73. package/templates/service-bindings-sw-facade.js +39 -0
  74. package/wrangler-dist/cli.d.ts +38 -3
  75. package/wrangler-dist/cli.js +45244 -25199
@@ -203,36 +203,19 @@ describe("wrangler", () => {
203
203
  await runWrangler("r2");
204
204
  await endEventLoop();
205
205
  expect(std.out).toMatchInlineSnapshot(`
206
- "wrangler r2
206
+ "wrangler r2
207
207
 
208
- 📦 Interact with an R2 store
208
+ 📦 Interact with an R2 store
209
209
 
210
- Commands:
211
- wrangler r2 bucket Manage R2 buckets
212
-
213
- Flags:
214
- -c, --config Path to .toml configuration file [string]
215
- -h, --help Show help [boolean]
216
- -v, --version Show version number [boolean]"
217
- `);
218
- });
219
- });
210
+ Commands:
211
+ wrangler r2 object Manage R2 objects
212
+ wrangler r2 bucket Manage R2 buckets
220
213
 
221
- describe("Deprecated commands", () => {
222
- it("should print a deprecation message for 'generate'", async () => {
223
- await runWrangler("generate").catch((err) => {
224
- expect(err.message).toMatchInlineSnapshot(`
225
- "Deprecation:
226
- \`wrangler generate\` has been deprecated.
227
- Try running \`wrangler init\` to generate a basic Worker, or cloning the template repository instead:
228
-
229
- \`\`\`
230
- git clone https://github.com/cloudflare/worker-template
231
- \`\`\`
232
-
233
- Please refer to https://developers.cloudflare.com/workers/wrangler/deprecations/#generate for more information."
234
- `);
235
- });
214
+ Flags:
215
+ -c, --config Path to .toml configuration file [string]
216
+ -h, --help Show help [boolean]
217
+ -v, --version Show version number [boolean]"
218
+ `);
236
219
  });
237
220
  });
238
221
 
@@ -2,10 +2,15 @@ import fetchMock from "jest-fetch-mock";
2
2
  import {
3
3
  fetchInternal,
4
4
  fetchKVGetValue,
5
+ fetchR2Objects,
5
6
  getCloudflareAPIBaseURL,
6
7
  } from "../cfetch/internal";
7
8
  import { confirm, prompt } from "../dialogs";
8
- import { mockFetchInternal, mockFetchKVGetValue } from "./helpers/mock-cfetch";
9
+ import {
10
+ mockFetchInternal,
11
+ mockFetchKVGetValue,
12
+ mockFetchR2Objects,
13
+ } from "./helpers/mock-cfetch";
9
14
  import { MockWebSocket } from "./helpers/mock-web-socket";
10
15
 
11
16
  // Mock out getPort since we don't actually care about what ports are open in unit tests.
@@ -43,6 +48,7 @@ jest.mock("../cfetch/internal");
43
48
  (getCloudflareAPIBaseURL as jest.Mock).mockReturnValue(
44
49
  "https://api.cloudflare.com/client/v4"
45
50
  );
51
+ (fetchR2Objects as jest.Mock).mockImplementation(mockFetchR2Objects);
46
52
 
47
53
  jest.mock("../dialogs");
48
54
 
@@ -118,3 +124,27 @@ jest.mock("xdg-app-paths", () => {
118
124
  }),
119
125
  };
120
126
  });
127
+
128
+ jest.mock("create-cloudflare");
129
+
130
+ jest.mock("../metrics/metrics-config", () => {
131
+ const realModule = jest.requireActual("../metrics/metrics-config");
132
+ const fakeModule = {
133
+ ...realModule,
134
+ // Although we mock out the getMetricsConfig() function in most tests,
135
+ // we need a way to reinstate it for the metrics specific tests.
136
+ // This is what `useOriginal` is for.
137
+ useOriginal: false,
138
+ getMetricsConfig: (...args: unknown[]) =>
139
+ fakeModule.useOriginal
140
+ ? realModule.getMetricsConfig(...args)
141
+ : async () => {
142
+ return {
143
+ enabled: false,
144
+ deviceId: "mock-device",
145
+ userId: undefined,
146
+ };
147
+ },
148
+ };
149
+ return fakeModule;
150
+ });
@@ -4,8 +4,10 @@ import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
4
4
  import {
5
5
  setMockResponse,
6
6
  unsetAllMocks,
7
- unsetMockFetchKVGetValues,
7
+ unsetSpecialMockFns,
8
8
  setMockFetchKVGetValue,
9
+ setMockRawResponse,
10
+ createFetchResult,
9
11
  } from "./helpers/mock-cfetch";
10
12
  import { mockConsoleMethods } from "./helpers/mock-console";
11
13
  import { clearConfirmMocks, mockConfirm } from "./helpers/mock-dialogs";
@@ -280,9 +282,9 @@ describe("wrangler", () => {
280
282
  writeWranglerConfig();
281
283
  await expect(runWrangler("kv:namespace delete --binding otherBinding"))
282
284
  .rejects.toThrowErrorMatchingInlineSnapshot(`
283
- "Not able to delete namespace.
284
- A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."
285
- `);
285
+ "Not able to delete namespace.
286
+ A namespace with binding name \\"otherBinding\\" was not found in the configured \\"kv_namespaces\\"."
287
+ `);
286
288
  expect(std.err).toMatchInlineSnapshot(`
287
289
  "X [ERROR] Not able to delete namespace.
288
290
 
@@ -299,7 +301,10 @@ describe("wrangler", () => {
299
301
  "kv:namespace delete --binding someBinding --env some-environment --preview false"
300
302
  );
301
303
 
302
- expect(std.out).toMatchInlineSnapshot(`""`);
304
+ expect(std.out).toMatchInlineSnapshot(`
305
+ "Deleting KV namespace env-bound-id.
306
+ Deleted KV namespace env-bound-id."
307
+ `);
303
308
  expect(std.err).toMatchInlineSnapshot(`""`);
304
309
  expect(requests.count).toEqual(1);
305
310
  });
@@ -919,7 +924,7 @@ describe("wrangler", () => {
919
924
 
920
925
  describe("get", () => {
921
926
  afterEach(() => {
922
- unsetMockFetchKVGetValues();
927
+ unsetSpecialMockFns();
923
928
  });
924
929
 
925
930
  it("should get a key in a given namespace specified by namespace-id", async () => {
@@ -1181,12 +1186,12 @@ describe("wrangler", () => {
1181
1186
  setIsTTY({ stdin: false, stdout: true });
1182
1187
  await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1183
1188
  .rejects.toThrowErrorMatchingInlineSnapshot(`
1184
- "More than one account available but unable to select one in non-interactive mode.
1185
- Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1186
- Available accounts are (\\"<name>\\" - \\"<id>\\"):
1187
- \\"one\\" - \\"1\\")
1188
- \\"two\\" - \\"2\\")"
1189
- `);
1189
+ "More than one account available but unable to select one in non-interactive mode.
1190
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1191
+ Available accounts are (\\"<name>\\" - \\"<id>\\"):
1192
+ \\"one\\" - \\"1\\")
1193
+ \\"two\\" - \\"2\\")"
1194
+ `);
1190
1195
  });
1191
1196
 
1192
1197
  it("should error if there are multiple accounts available but not interactive on stdout", async () => {
@@ -1197,12 +1202,28 @@ describe("wrangler", () => {
1197
1202
  setIsTTY({ stdin: true, stdout: false });
1198
1203
  await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1199
1204
  .rejects.toThrowErrorMatchingInlineSnapshot(`
1200
- "More than one account available but unable to select one in non-interactive mode.
1201
- Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1202
- Available accounts are (\\"<name>\\" - \\"<id>\\"):
1203
- \\"one\\" - \\"1\\")
1204
- \\"two\\" - \\"2\\")"
1205
- `);
1205
+ "More than one account available but unable to select one in non-interactive mode.
1206
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1207
+ Available accounts are (\\"<name>\\" - \\"<id>\\"):
1208
+ \\"one\\" - \\"1\\")
1209
+ \\"two\\" - \\"2\\")"
1210
+ `);
1211
+ });
1212
+
1213
+ it("should recommend using a configuration if unable to fetch memberships", async () => {
1214
+ setMockRawResponse("/memberships", () => {
1215
+ return createFetchResult(undefined, false, [
1216
+ {
1217
+ code: 9109,
1218
+ message: "Uauthorized to access requested resource",
1219
+ },
1220
+ ]);
1221
+ });
1222
+ await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1223
+ .rejects.toThrowErrorMatchingInlineSnapshot(`
1224
+ "Failed to automatically retrieve account IDs for the logged in user.
1225
+ You may have incorrect permissions on your API token. You can skip this account check by adding an \`account_id\` in your \`wrangler.toml\`, or by setting the value of CLOUDFLARE_ACCOUNT_ID\\""
1226
+ `);
1206
1227
  });
1207
1228
 
1208
1229
  it("should error if there are multiple accounts available but not interactive at all", async () => {
@@ -1213,12 +1234,12 @@ describe("wrangler", () => {
1213
1234
  setIsTTY(false);
1214
1235
  await expect(runWrangler("kv:key get key --namespace-id=xxxx"))
1215
1236
  .rejects.toThrowErrorMatchingInlineSnapshot(`
1216
- "More than one account available but unable to select one in non-interactive mode.
1217
- Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1218
- Available accounts are (\\"<name>\\" - \\"<id>\\"):
1219
- \\"one\\" - \\"1\\")
1220
- \\"two\\" - \\"2\\")"
1221
- `);
1237
+ "More than one account available but unable to select one in non-interactive mode.
1238
+ Please set the appropriate \`account_id\` in your \`wrangler.toml\` file.
1239
+ Available accounts are (\\"<name>\\" - \\"<id>\\"):
1240
+ \\"one\\" - \\"1\\")
1241
+ \\"two\\" - \\"2\\")"
1242
+ `);
1222
1243
  });
1223
1244
  });
1224
1245
  });
@@ -1390,9 +1411,9 @@ describe("wrangler", () => {
1390
1411
  await expect(
1391
1412
  runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1392
1413
  ).rejects.toThrowErrorMatchingInlineSnapshot(`
1393
- "Unexpected JSON input from \\"keys.json\\".
1394
- Expected an array of key-value objects but got type \\"object\\"."
1395
- `);
1414
+ "Unexpected JSON input from \\"keys.json\\".
1415
+ Expected an array of key-value objects but got type \\"object\\"."
1416
+ `);
1396
1417
  expect(std.out).toMatchInlineSnapshot(`
1397
1418
  "
1398
1419
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
@@ -1430,30 +1451,30 @@ describe("wrangler", () => {
1430
1451
  await expect(
1431
1452
  runWrangler(`kv:bulk put --namespace-id some-namespace-id keys.json`)
1432
1453
  ).rejects.toThrowErrorMatchingInlineSnapshot(`
1433
- "Unexpected JSON input from \\"keys.json\\".
1434
- Each item in the array should be an object that matches:
1435
-
1436
- interface KeyValue {
1437
- key: string;
1438
- value: string;
1439
- expiration?: number;
1440
- expiration_ttl?: number;
1441
- metadata?: object;
1442
- base64?: boolean;
1443
- }
1444
-
1445
- The item at index 0 is 123
1446
- The item at index 1 is \\"a string\\"
1447
- The item at index 2 is {\\"key\\":\\"someKey\\"}
1448
- The item at index 3 is {\\"value\\":\\"someValue\\"}
1449
- The item at index 6 is {\\"key\\":123,\\"value\\":\\"somevalue\\"}
1450
- The item at index 7 is {\\"key\\":\\"somekey\\",\\"value\\":123}
1451
- The item at index 8 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration\\":\\"string\\"}
1452
- The item at index 9 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration_ttl\\":\\"string\\"}
1453
- The item at index 10 is {\\"key\\":123,\\"value\\":{\\"a\\":{\\"nested\\":\\"object\\"}}}
1454
- The item at index 11 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"metadata\\":123}
1455
- The item at index 12 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"base64\\":\\"string\\"}"
1456
- `);
1454
+ "Unexpected JSON input from \\"keys.json\\".
1455
+ Each item in the array should be an object that matches:
1456
+
1457
+ interface KeyValue {
1458
+ key: string;
1459
+ value: string;
1460
+ expiration?: number;
1461
+ expiration_ttl?: number;
1462
+ metadata?: object;
1463
+ base64?: boolean;
1464
+ }
1465
+
1466
+ The item at index 0 is 123
1467
+ The item at index 1 is \\"a string\\"
1468
+ The item at index 2 is {\\"key\\":\\"someKey\\"}
1469
+ The item at index 3 is {\\"value\\":\\"someValue\\"}
1470
+ The item at index 6 is {\\"key\\":123,\\"value\\":\\"somevalue\\"}
1471
+ The item at index 7 is {\\"key\\":\\"somekey\\",\\"value\\":123}
1472
+ The item at index 8 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration\\":\\"string\\"}
1473
+ The item at index 9 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"expiration_ttl\\":\\"string\\"}
1474
+ The item at index 10 is {\\"key\\":123,\\"value\\":{\\"a\\":{\\"nested\\":\\"object\\"}}}
1475
+ The item at index 11 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"metadata\\":123}
1476
+ The item at index 12 is {\\"key\\":\\"someKey1\\",\\"value\\":\\"someValue1\\",\\"base64\\":\\"string\\"}"
1477
+ `);
1457
1478
 
1458
1479
  expect(std.out).toMatchInlineSnapshot(`
1459
1480
  "
@@ -1592,10 +1613,10 @@ describe("wrangler", () => {
1592
1613
  `kv:bulk delete --namespace-id some-namespace-id keys.json`
1593
1614
  )
1594
1615
  ).rejects.toThrowErrorMatchingInlineSnapshot(`
1595
- "Unexpected JSON input from \\"keys.json\\".
1596
- Expected an array of strings but got:
1597
- 12354"
1598
- `);
1616
+ "Unexpected JSON input from \\"keys.json\\".
1617
+ Expected an array of strings but got:
1618
+ 12354"
1619
+ `);
1599
1620
  expect(std.out).toMatchInlineSnapshot(`
1600
1621
  "
1601
1622
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
@@ -1615,12 +1636,12 @@ describe("wrangler", () => {
1615
1636
  `kv:bulk delete --namespace-id some-namespace-id keys.json`
1616
1637
  )
1617
1638
  ).rejects.toThrowErrorMatchingInlineSnapshot(`
1618
- "Unexpected JSON input from \\"keys.json\\".
1619
- Expected an array of strings.
1620
- The item at index 1 is type: \\"number\\" - 12354
1621
- The item at index 2 is type: \\"object\\" - {\\"key\\":\\"someKey\\"}
1622
- The item at index 3 is type: \\"object\\" - null"
1623
- `);
1639
+ "Unexpected JSON input from \\"keys.json\\".
1640
+ Expected an array of strings.
1641
+ The item at index 1 is type: \\"number\\" - 12354
1642
+ The item at index 2 is type: \\"object\\" - {\\"key\\":\\"someKey\\"}
1643
+ The item at index 3 is type: \\"object\\" - null"
1644
+ `);
1624
1645
  expect(std.out).toMatchInlineSnapshot(`
1625
1646
  "
1626
1647
  If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
@@ -26,6 +26,9 @@ describe("metrics", () => {
26
26
  runInTempDir();
27
27
 
28
28
  beforeEach(() => {
29
+ // Tell jest to use the original version of the `getMetricsConfig()` function in these tests.
30
+ const mockMetricsConfig = jest.requireMock("../metrics/metrics-config");
31
+ mockMetricsConfig.useOriginal = true;
29
32
  global.SPARROW_SOURCE_KEY = "MOCK_KEY";
30
33
  logger.loggerLevel = "debug";
31
34
  // Create a node_modules directory to store config-cache files
@@ -65,6 +68,7 @@ describe("metrics", () => {
65
68
  properties: {
66
69
  category: "Workers",
67
70
  wranglerVersion,
71
+ os: process.platform + ":" + process.arch,
68
72
  a: 1,
69
73
  b: 2,
70
74
  },
@@ -139,6 +143,7 @@ describe("metrics", () => {
139
143
  properties: {
140
144
  category: "Workers",
141
145
  wranglerVersion,
146
+ os: process.platform + ":" + process.arch,
142
147
  a: 1,
143
148
  b: 2,
144
149
  },