wrangler 2.0.22 → 2.0.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.0.22",
3
+ "version": "2.0.23",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -53,7 +53,7 @@
53
53
  "bundle": "node -r esbuild-register scripts/bundle.ts",
54
54
  "check:type": "tsc",
55
55
  "clean": "rm -rf wrangler-dist miniflare-dist emitted-types",
56
- "dev": "npm run clean && concurrently -c black,blue 'npm run bundle -- --watch' 'npm run check:type -- --watch --preserveWatchOutput'",
56
+ "dev": "npm run clean && concurrently -c black,blue --kill-others-on-fail false 'npm run bundle -- --watch' 'npm run check:type -- --watch --preserveWatchOutput'",
57
57
  "emit-types": "tsc -p tsconfig.emit.json && node -r esbuild-register scripts/emit-types.ts",
58
58
  "prepublishOnly": "SOURCEMAPS=false npm run build",
59
59
  "start": "npm run bundle && NODE_OPTIONS=--enable-source-maps ./bin/wrangler.js",
@@ -61,6 +61,13 @@
61
61
  "test-watch": "npm run test -- --runInBand --testTimeout=50000 --watch"
62
62
  },
63
63
  "jest": {
64
+ "collectCoverage": true,
65
+ "coverageReporters": [
66
+ "json",
67
+ "html",
68
+ "text",
69
+ "cobertura"
70
+ ],
64
71
  "moduleNameMapper": {
65
72
  "clipboardy": "<rootDir>/src/__tests__/helpers/clipboardy-mock.js",
66
73
  "miniflare/cli": "<rootDir>/../../node_modules/miniflare/dist/src/cli.js"
@@ -88,6 +95,7 @@
88
95
  "@esbuild-plugins/node-globals-polyfill": "^0.1.1",
89
96
  "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
90
97
  "blake3-wasm": "^2.1.5",
98
+ "chokidar": "^3.5.3",
91
99
  "esbuild": "0.14.47",
92
100
  "miniflare": "^2.6.0",
93
101
  "nanoid": "^3.3.3",
@@ -109,7 +117,6 @@
109
117
  "@types/ws": "^8.5.3",
110
118
  "@types/yargs": "^17.0.10",
111
119
  "@webcontainer/env": "^1.0.1",
112
- "chokidar": "^3.5.3",
113
120
  "clipboardy": "^3.0.0",
114
121
  "cmd-shim": "^4.1.0",
115
122
  "command-exists": "^1.2.9",
@@ -525,9 +525,9 @@ describe("wrangler dev", () => {
525
525
 
526
526
  await expect(runWrangler("dev")).rejects
527
527
  .toThrowErrorMatchingInlineSnapshot(`
528
- "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
529
- The \`main\` property in wrangler.toml should point to the file generated by the custom build."
530
- `);
528
+ "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
529
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build."
530
+ `);
531
531
  expect(std.out).toMatchInlineSnapshot(`
532
532
  "Running custom build: node -e \\"console.log('custom build');\\"
533
533
 
@@ -673,6 +673,78 @@ describe("wrangler dev", () => {
673
673
  });
674
674
  });
675
675
 
676
+ describe("inspector port", () => {
677
+ it("should use 9229 as the default port", async () => {
678
+ writeWranglerToml({
679
+ main: "index.js",
680
+ });
681
+ fs.writeFileSync("index.js", `export default {};`);
682
+ await runWrangler("dev");
683
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9229);
684
+ expect(std).toMatchInlineSnapshot(`
685
+ Object {
686
+ "debug": "",
687
+ "err": "",
688
+ "out": "",
689
+ "warn": "",
690
+ }
691
+ `);
692
+ });
693
+
694
+ it("should read --inspector-port", async () => {
695
+ writeWranglerToml({
696
+ main: "index.js",
697
+ });
698
+ fs.writeFileSync("index.js", `export default {};`);
699
+ await runWrangler("dev --inspector-port=9999");
700
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9999);
701
+ expect(std).toMatchInlineSnapshot(`
702
+ Object {
703
+ "debug": "",
704
+ "err": "",
705
+ "out": "",
706
+ "warn": "",
707
+ }
708
+ `);
709
+ });
710
+
711
+ it("should read dev.inspector_port from wrangler.toml", async () => {
712
+ writeWranglerToml({
713
+ main: "index.js",
714
+ dev: {
715
+ inspector_port: 9999,
716
+ },
717
+ });
718
+ fs.writeFileSync("index.js", `export default {};`);
719
+ await runWrangler("dev");
720
+ expect((Dev as jest.Mock).mock.calls[0][0].inspectorPort).toEqual(9999);
721
+ expect(std).toMatchInlineSnapshot(`
722
+ Object {
723
+ "debug": "",
724
+ "err": "",
725
+ "out": "",
726
+ "warn": "",
727
+ }
728
+ `);
729
+ });
730
+
731
+ it("should error if a bad dev.inspector_port config is provided", async () => {
732
+ writeWranglerToml({
733
+ main: "index.js",
734
+ dev: {
735
+ // @ts-expect-error intentionally bad port
736
+ inspector_port: "some string",
737
+ },
738
+ });
739
+ fs.writeFileSync("index.js", `export default {};`);
740
+ await expect(runWrangler("dev")).rejects
741
+ .toThrowErrorMatchingInlineSnapshot(`
742
+ "Processing wrangler.toml configuration:
743
+ - Expected \\"dev.inspector_port\\" to be of type number but got \\"some string\\"."
744
+ `);
745
+ });
746
+ });
747
+
676
748
  describe("port", () => {
677
749
  it("should default port to 8787 if it is not in use", async () => {
678
750
  writeWranglerToml({
@@ -686,7 +758,7 @@ describe("wrangler dev", () => {
686
758
  expect(std.err).toMatchInlineSnapshot(`""`);
687
759
  });
688
760
 
689
- it("should use to `port` from `wrangler.toml`, if available", async () => {
761
+ it("should use `port` from `wrangler.toml`, if available", async () => {
690
762
  writeWranglerToml({
691
763
  main: "index.js",
692
764
  dev: {
@@ -704,6 +776,22 @@ describe("wrangler dev", () => {
704
776
  expect(std.err).toMatchInlineSnapshot(`""`);
705
777
  });
706
778
 
779
+ it("should error if a bad dev.port config is provided", async () => {
780
+ writeWranglerToml({
781
+ main: "index.js",
782
+ dev: {
783
+ // @ts-expect-error intentionally bad port
784
+ port: "some string",
785
+ },
786
+ });
787
+ fs.writeFileSync("index.js", `export default {};`);
788
+ await expect(runWrangler("dev")).rejects
789
+ .toThrowErrorMatchingInlineSnapshot(`
790
+ "Processing wrangler.toml configuration:
791
+ - Expected \\"dev.port\\" to be of type number but got \\"some string\\"."
792
+ `);
793
+ });
794
+
707
795
  it("should use --port command line arg, if provided", async () => {
708
796
  writeWranglerToml({
709
797
  main: "index.js",
@@ -6,6 +6,8 @@ import {
6
6
  unsetAllMocks,
7
7
  unsetMockFetchKVGetValues,
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
  });
@@ -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"
@@ -6108,6 +6108,82 @@ addEventListener('fetch', event => {});`
6108
6108
  expect(fs.readFileSync("dist/index.js", "utf-8")).toMatch(scriptContent);
6109
6109
  });
6110
6110
  });
6111
+
6112
+ describe("--no-bundle --minify", () => {
6113
+ it("should warn that no-bundle and minify can't be used together", async () => {
6114
+ writeWranglerToml();
6115
+ const scriptContent = `
6116
+ const xyz = 123; // a statement that would otherwise be compiled out
6117
+ `;
6118
+ fs.writeFileSync("index.js", scriptContent);
6119
+ await runWrangler(
6120
+ "publish index.js --no-bundle --minify --dry-run --outdir dist"
6121
+ );
6122
+ expect(std.warn).toMatchInlineSnapshot(`
6123
+ "▲ [WARNING] \`--minify\` and \`--no-bundle\` can't be used together. If you want to minify your Worker and disable Wrangler's bundling, please minify as part of your own bundling process.
6124
+
6125
+ "
6126
+ `);
6127
+ });
6128
+
6129
+ it("should warn that no-bundle and minify can't be used together", async () => {
6130
+ writeWranglerToml({
6131
+ no_bundle: true,
6132
+ minify: true,
6133
+ });
6134
+ const scriptContent = `
6135
+ const xyz = 123; // a statement that would otherwise be compiled out
6136
+ `;
6137
+ fs.writeFileSync("index.js", scriptContent);
6138
+ await runWrangler("publish index.js --dry-run --outdir dist");
6139
+ expect(std.warn).toMatchInlineSnapshot(`
6140
+ "▲ [WARNING] \`--minify\` and \`--no-bundle\` can't be used together. If you want to minify your Worker and disable Wrangler's bundling, please minify as part of your own bundling process.
6141
+
6142
+ "
6143
+ `);
6144
+ });
6145
+ });
6146
+
6147
+ describe("--no-bundle --node-compat", () => {
6148
+ it("should warn that no-bundle and node-compat can't be used together", async () => {
6149
+ writeWranglerToml();
6150
+ const scriptContent = `
6151
+ const xyz = 123; // a statement that would otherwise be compiled out
6152
+ `;
6153
+ fs.writeFileSync("index.js", scriptContent);
6154
+ await runWrangler(
6155
+ "publish index.js --no-bundle --node-compat --dry-run --outdir dist"
6156
+ );
6157
+ expect(std.warn).toMatchInlineSnapshot(`
6158
+ "▲ [WARNING] Enabling node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.
6159
+
6160
+
6161
+ ▲ [WARNING] \`--node-compat\` and \`--no-bundle\` can't be used together. If you want to polyfill Node.js built-ins and disable Wrangler's bundling, please polyfill as part of your own bundling process.
6162
+
6163
+ "
6164
+ `);
6165
+ });
6166
+
6167
+ it("should warn that no-bundle and node-compat can't be used together", async () => {
6168
+ writeWranglerToml({
6169
+ no_bundle: true,
6170
+ node_compat: true,
6171
+ });
6172
+ const scriptContent = `
6173
+ const xyz = 123; // a statement that would otherwise be compiled out
6174
+ `;
6175
+ fs.writeFileSync("index.js", scriptContent);
6176
+ await runWrangler("publish index.js --dry-run --outdir dist");
6177
+ expect(std.warn).toMatchInlineSnapshot(`
6178
+ "▲ [WARNING] Enabling node.js compatibility mode for built-ins and globals. This is experimental and has serious tradeoffs. Please see https://github.com/ionic-team/rollup-plugin-node-polyfills/ for more details.
6179
+
6180
+
6181
+ ▲ [WARNING] \`--node-compat\` and \`--no-bundle\` can't be used together. If you want to polyfill Node.js built-ins and disable Wrangler's bundling, please polyfill as part of your own bundling process.
6182
+
6183
+ "
6184
+ `);
6185
+ });
6186
+ });
6111
6187
  });
6112
6188
 
6113
6189
  /** Write mock assets to the file system so they can be uploaded. */
@@ -0,0 +1,35 @@
1
+ import { version } from "./../../package.json";
2
+ import { mockConsoleMethods } from "./helpers/mock-console";
3
+ import { useMockIsTTY } from "./helpers/mock-istty";
4
+ import { runWrangler } from "./helpers/run-wrangler";
5
+
6
+ describe("version", () => {
7
+ const std = mockConsoleMethods();
8
+ const { setIsTTY } = useMockIsTTY();
9
+
10
+ // We cannot test output of version banner,
11
+ // as it is disabled in jest environments
12
+
13
+ // it("should output version banner", async () => {
14
+ // await runWrangler("-v");
15
+ // expect(std.out).toMatchInlineSnapshot(`
16
+ // " ⛅️ wrangler 2.0.22
17
+ // --------------------"
18
+ // `);
19
+ // });
20
+
21
+ it("should output current version if !isTTY calling -v", async () => {
22
+ setIsTTY(false);
23
+
24
+ await runWrangler("-v");
25
+ expect(std.out).toMatch(version);
26
+ });
27
+
28
+ // This run separately as command handling is different
29
+ it("should output current version if !isTTY calling --version", async () => {
30
+ setIsTTY(false);
31
+
32
+ await runWrangler("--version");
33
+ expect(std.out).toMatch(version);
34
+ });
35
+ });
package/src/api/dev.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { startDev } from "../dev";
2
2
  import { logger } from "../logger";
3
3
 
4
+ import type { EnablePagesAssetsServiceBindingOptions } from "../miniflare-cli";
4
5
  import type { RequestInit, Response } from "undici";
5
6
 
6
7
  interface DevOptions {
@@ -13,39 +14,72 @@ interface DevOptions {
13
14
  siteInclude?: string[];
14
15
  siteExclude?: string[];
15
16
  nodeCompat?: boolean;
17
+ compatibilityDate?: string;
16
18
  experimentalEnableLocalPersistence?: boolean;
17
- _: (string | number)[]; //yargs wants this
18
- $0: string; //yargs wants this
19
+ liveReload?: boolean;
20
+ watch?: boolean;
21
+ vars: {
22
+ [key: string]: unknown;
23
+ };
24
+ kv?: {
25
+ binding: string;
26
+ id: string;
27
+ preview_id?: string;
28
+ }[];
29
+ durableObjects?: {
30
+ name: string;
31
+ class_name: string;
32
+ script_name?: string | undefined;
33
+ environment?: string | undefined;
34
+ }[];
35
+ showInteractiveDevSession?: boolean;
36
+ logLevel?: "none" | "error" | "log" | "warn" | "debug";
37
+ logPrefix?: string;
38
+ inspect?: boolean;
39
+ forceLocal?: boolean;
40
+ enablePagesAssetsServiceBinding?: EnablePagesAssetsServiceBindingOptions;
41
+ _?: (string | number)[]; //yargs wants this
42
+ $0?: string; //yargs wants this
19
43
  }
20
44
  /**
21
45
  * unstable_dev starts a wrangler dev server, and returns a promise that resolves with utility functions to interact with it.
22
46
  * @param {string} script
23
47
  * @param {DevOptions} options
24
48
  */
25
- export async function unstable_dev(script: string, options: DevOptions) {
26
- logger.warn(
27
- `unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases`
28
- );
49
+ export async function unstable_dev(
50
+ script: string,
51
+ options: DevOptions,
52
+ disableExperimentalWarning?: boolean
53
+ ) {
54
+ if (!disableExperimentalWarning) {
55
+ logger.warn(
56
+ `unstable_dev() is experimental\nunstable_dev()'s behaviour will likely change in future releases`
57
+ );
58
+ }
29
59
 
30
60
  return new Promise<{
31
61
  stop: () => void;
32
62
  fetch: (init?: RequestInit) => Promise<Response | undefined>;
63
+ waitUntilExit: () => Promise<void>;
33
64
  }>((resolve) => {
34
65
  //lmao
35
66
  return new Promise<Awaited<ReturnType<typeof startDev>>>((ready) => {
36
67
  const devServer = startDev({
37
68
  script: script,
38
- ...options,
39
- local: true,
40
- onReady: () => ready(devServer),
41
69
  inspect: false,
42
70
  logLevel: "none",
43
71
  showInteractiveDevSession: false,
72
+ _: [],
73
+ $0: "",
74
+ ...options,
75
+ local: true,
76
+ onReady: () => ready(devServer),
44
77
  });
45
78
  }).then((devServer) => {
46
79
  resolve({
47
80
  stop: devServer.stop,
48
81
  fetch: devServer.fetch,
82
+ waitUntilExit: devServer.devReactElement.waitUntilExit,
49
83
  });
50
84
  });
51
85
  });
package/src/bundle.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import assert from "node:assert";
2
2
  import * as fs from "node:fs";
3
3
  import { builtinModules } from "node:module";
4
+ import * as os from "node:os";
4
5
  import * as path from "node:path";
5
6
  import NodeGlobalsPolyfills from "@esbuild-plugins/node-globals-polyfill";
6
7
  import NodeModulesPolyfills from "@esbuild-plugins/node-modules-polyfill";
@@ -92,14 +93,37 @@ export async function bundleWorker(
92
93
  rules,
93
94
  });
94
95
 
96
+ // In dev, we want to patch `fetch()` with a special version that looks
97
+ // for bad usages and can warn the user about them; so we inject
98
+ // `checked-fetch.js` to do so. However, with yarn 3 style pnp,
99
+ // we need to extract that file to an accessible place before injecting
100
+ // it in, hence this code here.
101
+ const osTempDir = os.tmpdir();
102
+ const checkedFetchFileToInject = path.join(
103
+ osTempDir,
104
+ "--temp-wrangler-files--",
105
+ "checked-fetch.js"
106
+ );
107
+
108
+ if (checkFetch && !fs.existsSync(checkedFetchFileToInject)) {
109
+ fs.mkdirSync(path.join(osTempDir, "--temp-wrangler-files--"), {
110
+ recursive: true,
111
+ });
112
+ fs.writeFileSync(
113
+ checkedFetchFileToInject,
114
+ fs.readFileSync(path.resolve(__dirname, "../templates/checked-fetch.js"))
115
+ );
116
+ }
117
+ // TODO: we need to have similar logic like above for other files
118
+ // like the static asset facade, and other middleware that we
119
+ // plan on injecting/referencing.
120
+
95
121
  const result = await esbuild.build({
96
122
  ...getEntryPoint(entry.file, serveAssetsFromWorker),
97
123
  bundle: true,
98
124
  absWorkingDir: entry.directory,
99
125
  outdir: destination,
100
- inject: checkFetch
101
- ? [path.resolve(__dirname, "../templates/checked-fetch.js")]
102
- : [],
126
+ inject: checkFetch ? [checkedFetchFileToInject] : [],
103
127
  external: ["__STATIC_CONTENT_MANIFEST"],
104
128
  format: entry.format === "modules" ? "esm" : "iife",
105
129
  target: "es2020",
@@ -109,7 +133,9 @@ export async function bundleWorker(
109
133
  conditions: ["worker", "browser"],
110
134
  ...(process.env.NODE_ENV && {
111
135
  define: {
112
- "process.env.NODE_ENV": `"${process.env.NODE_ENV}"`,
136
+ // use process.env["NODE_ENV" + ""] so that esbuild doesn't replace it
137
+ // when we do a build of wrangler. (re: https://github.com/cloudflare/wrangler2/issues/1477)
138
+ "process.env.NODE_ENV": `"${process.env["NODE_ENV" + ""]}"`,
113
139
  ...(nodeCompat ? { global: "globalThis" } : {}),
114
140
  ...(checkFetch ? { fetch: "checkedFetch" } : {}),
115
141
  ...options.define,
@@ -180,6 +180,13 @@ export interface DevConfig {
180
180
  */
181
181
  port: number | undefined;
182
182
 
183
+ /**
184
+ * Port for the local dev server's inspector to listen on
185
+ *
186
+ * @default `9229`
187
+ */
188
+ inspector_port: number | undefined;
189
+
183
190
  /**
184
191
  * Protocol that local wrangler dev server listens to requests on.
185
192
  *