wrangler 0.0.0-fb43821 → 0.0.0-fb53fda

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 (104) hide show
  1. package/README.md +1 -1
  2. package/bin/wrangler.js +12 -3
  3. package/miniflare-dist/index.mjs +79 -0
  4. package/miniflare-dist/index.mjs.map +7 -0
  5. package/package.json +46 -17
  6. package/pages/functions/buildWorker.ts +62 -0
  7. package/pages/functions/filepath-routing.test.ts +223 -0
  8. package/pages/functions/filepath-routing.ts +181 -0
  9. package/pages/functions/identifiers.ts +78 -0
  10. package/pages/functions/routes.ts +151 -0
  11. package/pages/functions/template-worker.ts +130 -0
  12. package/src/__tests__/configuration.test.ts +2790 -0
  13. package/src/__tests__/dev.test.tsx +532 -0
  14. package/src/__tests__/guess-worker-format.test.ts +68 -0
  15. package/src/__tests__/{clipboardy-mock.js → helpers/clipboardy-mock.js} +0 -0
  16. package/src/__tests__/helpers/cmd-shim.d.ts +11 -0
  17. package/src/__tests__/helpers/faye-websocket.d.ts +6 -0
  18. package/src/__tests__/helpers/mock-account-id.ts +48 -0
  19. package/src/__tests__/helpers/mock-bin.ts +36 -0
  20. package/src/__tests__/helpers/mock-cfetch.ts +207 -0
  21. package/src/__tests__/helpers/mock-console.ts +70 -0
  22. package/src/__tests__/helpers/mock-dialogs.ts +65 -0
  23. package/src/__tests__/helpers/mock-kv.ts +33 -0
  24. package/src/__tests__/helpers/mock-stdin.ts +103 -0
  25. package/src/__tests__/helpers/mock-web-socket.ts +29 -0
  26. package/src/__tests__/helpers/run-in-tmp.ts +32 -0
  27. package/src/__tests__/helpers/run-wrangler.ts +16 -0
  28. package/src/__tests__/helpers/write-wrangler-toml.ts +17 -0
  29. package/src/__tests__/https-options.test.ts +127 -0
  30. package/src/__tests__/index.test.ts +770 -209
  31. package/src/__tests__/jest.setup.ts +69 -0
  32. package/src/__tests__/kv.test.ts +1380 -0
  33. package/src/__tests__/logout.test.ts +52 -0
  34. package/src/__tests__/package-manager.test.ts +206 -0
  35. package/src/__tests__/pages.test.ts +82 -0
  36. package/src/__tests__/parse.test.ts +322 -0
  37. package/src/__tests__/publish.test.ts +3431 -0
  38. package/src/__tests__/r2.test.ts +198 -0
  39. package/src/__tests__/route.test.ts +45 -0
  40. package/src/__tests__/secret.test.ts +425 -0
  41. package/src/__tests__/sentry.test.ts +146 -0
  42. package/src/__tests__/tail.test.ts +562 -0
  43. package/src/__tests__/whoami.test.tsx +100 -0
  44. package/src/bundle.ts +142 -0
  45. package/src/cfetch/index.ts +104 -0
  46. package/src/cfetch/internal.ts +139 -0
  47. package/src/cli.ts +16 -7
  48. package/src/config/README.md +107 -0
  49. package/src/config/config.ts +218 -0
  50. package/src/config/diagnostics.ts +80 -0
  51. package/src/config/environment.ts +366 -0
  52. package/src/config/index.ts +62 -0
  53. package/src/config/validation-helpers.ts +554 -0
  54. package/src/config/validation.ts +1191 -0
  55. package/src/{api/preview.ts → create-worker-preview.ts} +63 -25
  56. package/src/create-worker-upload-form.ts +217 -0
  57. package/src/dev/dev.tsx +390 -0
  58. package/src/dev/local.tsx +232 -0
  59. package/src/dev/remote.tsx +203 -0
  60. package/src/dev/use-esbuild.ts +100 -0
  61. package/src/dialogs.tsx +4 -4
  62. package/src/entry.ts +237 -0
  63. package/src/environment-variables.ts +33 -0
  64. package/src/https-options.ts +122 -0
  65. package/src/index.tsx +1417 -915
  66. package/src/inspect.ts +617 -0
  67. package/src/intl-polyfill.d.ts +139 -0
  68. package/src/kv.ts +319 -0
  69. package/src/miniflare-cli/README.md +30 -0
  70. package/src/miniflare-cli/enum-keys.ts +17 -0
  71. package/src/miniflare-cli/index.ts +37 -0
  72. package/src/module-collection.ts +229 -35
  73. package/src/open-in-browser.ts +25 -0
  74. package/src/package-manager.ts +126 -0
  75. package/src/pages.tsx +470 -227
  76. package/src/parse.ts +183 -0
  77. package/src/paths.ts +26 -0
  78. package/src/proxy.ts +440 -0
  79. package/src/publish.ts +292 -290
  80. package/src/r2.ts +50 -0
  81. package/src/reporting.ts +131 -0
  82. package/src/selfsigned.d.ts +29 -0
  83. package/src/sites.tsx +224 -59
  84. package/src/tail/filters.ts +279 -0
  85. package/src/tail/index.ts +299 -0
  86. package/src/tail/printing.ts +62 -0
  87. package/src/user.tsx +301 -203
  88. package/src/whoami.tsx +69 -0
  89. package/src/worker.ts +163 -0
  90. package/templates/new-worker.js +15 -0
  91. package/templates/new-worker.ts +15 -0
  92. package/{static-asset-facade.js → templates/static-asset-facade.js} +0 -0
  93. package/templates/tsconfig.json +105 -0
  94. package/wrangler-dist/cli.js +134241 -116339
  95. package/wrangler-dist/cli.js.map +3 -3
  96. package/src/__tests__/mock-cfetch.js +0 -42
  97. package/src/api/form_data.ts +0 -141
  98. package/src/api/inspect.ts +0 -430
  99. package/src/api/worker.ts +0 -161
  100. package/src/cfetch.ts +0 -72
  101. package/src/config.ts +0 -122
  102. package/src/dev.tsx +0 -776
  103. package/src/kv.tsx +0 -211
  104. package/src/tail.tsx +0 -71
@@ -1,169 +1,181 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as fsp from "node:fs/promises";
3
- import * as os from "node:os";
4
- import * as path from "node:path";
5
3
  import * as TOML from "@iarna/toml";
6
- import { main } from "../index";
7
- import { setMock, unsetAllMocks } from "./mock-cfetch";
8
- import { confirm } from "../dialogs";
9
-
10
- jest.mock("../cfetch", () => jest.requireActual("./mock-cfetch"));
11
-
12
- jest.mock("../dialogs", () => {
13
- return {
14
- ...jest.requireActual<object>("../dialogs"),
15
- confirm: jest
16
- .fn()
17
- .mockName("confirmMock")
18
- .mockImplementation(() => {
19
- // By default (if not configured by mockConfirm()) calls to `confirm()` should throw.
20
- throw new Error("Unexpected call to `confirm()`.");
21
- }),
22
- };
23
- });
4
+ import { parseConfigFileTextToJson } from "typescript";
5
+ import { version as wranglerVersion } from "../../package.json";
6
+ import { getPackageManager } from "../package-manager";
7
+ import { mockConsoleMethods } from "./helpers/mock-console";
8
+ import { mockConfirm } from "./helpers/mock-dialogs";
9
+ import { runInTempDir } from "./helpers/run-in-tmp";
10
+ import { runWrangler } from "./helpers/run-wrangler";
11
+ import type { PackageManager } from "../package-manager";
24
12
 
25
- /**
26
- * Mock the implementation of `confirm()` that will respond with configured results
27
- * for configured confirmation text messages.
28
- *
29
- * If there is a call to `confirm()` that does not match any of the expectations
30
- * then an error is thrown.
31
- */
32
- function mockConfirm(...expectations: { text: string; result: boolean }[]) {
33
- (confirm as jest.Mock).mockImplementation((text: string) => {
34
- for (const { text: expectedText, result } of expectations) {
35
- if (text === expectedText) {
36
- return result;
37
- }
38
- }
39
- throw new Error(`Unexpected confirmation message: ${text}`);
40
- });
41
- }
42
-
43
- async function w(cmd?: string) {
44
- const logSpy = jest.spyOn(console, "log").mockImplementation();
45
- const errorSpy = jest.spyOn(console, "error").mockImplementation();
46
- const warnSpy = jest.spyOn(console, "warn").mockImplementation();
47
- try {
48
- await main(cmd?.split(" ") ?? []);
49
- return {
50
- stdout: logSpy.mock.calls.flat(2).join("\n"),
51
- stderr: errorSpy.mock.calls.flat(2).join("\n"),
52
- warnings: warnSpy.mock.calls.flat(2).join("\n"),
13
+ describe("wrangler", () => {
14
+ let mockPackageManager: PackageManager;
15
+ runInTempDir();
16
+
17
+ beforeEach(() => {
18
+ mockPackageManager = {
19
+ cwd: process.cwd(),
20
+ // @ts-expect-error we're making a fake package manager here
21
+ type: "mockpm",
22
+ addDevDeps: jest.fn(),
23
+ install: jest.fn(),
53
24
  };
54
- } finally {
55
- logSpy.mockRestore();
56
- errorSpy.mockRestore();
57
- warnSpy.mockRestore();
58
- }
59
- }
25
+ (getPackageManager as jest.Mock).mockResolvedValue(mockPackageManager);
26
+ });
27
+
28
+ const std = mockConsoleMethods();
60
29
 
61
- describe("wrangler", () => {
62
30
  describe("no command", () => {
63
31
  it("should display a list of available commands", async () => {
64
- const { stdout, stderr } = await w();
32
+ await runWrangler();
65
33
 
66
- expect(stdout).toMatchInlineSnapshot(`
34
+ expect(std.out).toMatchInlineSnapshot(`
67
35
  "wrangler
68
36
 
69
37
  Commands:
70
38
  wrangler init [name] 📥 Create a wrangler.toml configuration file
71
- wrangler dev <filename> 👂 Start a local server for developing your worker
39
+ wrangler whoami 🕵️ Retrieve your user info and test your auth config
40
+ wrangler dev [script] 👂 Start a local server for developing your worker
72
41
  wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
73
- wrangler tail [name] 🦚 Starts a log tailing session for a deployed Worker.
42
+ wrangler tail [name] 🦚 Starts a log tailing session for a published Worker.
74
43
  wrangler secret 🤫 Generate a secret that can be referenced in the worker script
75
44
  wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
76
45
  wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
77
46
  wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
78
47
  wrangler pages ⚡️ Configure Cloudflare Pages
48
+ wrangler r2 📦 Interact with an R2 store
79
49
 
80
50
  Flags:
81
- -c, --config Path to .toml configuration file [string]
82
- -h, --help Show help [boolean]
83
- -v, --version Show version number [boolean]
84
-
85
- Options:
86
- -l, --local Run on my machine [boolean] [default: false]"
51
+ -c, --config Path to .toml configuration file [string]
52
+ -h, --help Show help [boolean]
53
+ -v, --version Show version number [boolean]
54
+ --legacy-env Use legacy environments [boolean]"
87
55
  `);
88
56
 
89
- expect(stderr).toMatchInlineSnapshot(`""`);
57
+ expect(std.err).toMatchInlineSnapshot(`""`);
90
58
  });
91
59
  });
92
60
 
93
61
  describe("invalid command", () => {
94
62
  it("should display an error", async () => {
95
- const { stdout, stderr } = await w("invalid-command");
63
+ await expect(
64
+ runWrangler("invalid-command")
65
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
66
+ `"Unknown argument: invalid-command"`
67
+ );
96
68
 
97
- expect(stdout).toMatchInlineSnapshot(`
69
+ expect(std.out).toMatchInlineSnapshot(`""`);
70
+ expect(std.err).toMatchInlineSnapshot(`
98
71
  "wrangler
99
72
 
100
73
  Commands:
101
74
  wrangler init [name] 📥 Create a wrangler.toml configuration file
102
- wrangler dev <filename> 👂 Start a local server for developing your worker
75
+ wrangler whoami 🕵️ Retrieve your user info and test your auth config
76
+ wrangler dev [script] 👂 Start a local server for developing your worker
103
77
  wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
104
- wrangler tail [name] 🦚 Starts a log tailing session for a deployed Worker.
78
+ wrangler tail [name] 🦚 Starts a log tailing session for a published Worker.
105
79
  wrangler secret 🤫 Generate a secret that can be referenced in the worker script
106
80
  wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
107
81
  wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
108
82
  wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
109
83
  wrangler pages ⚡️ Configure Cloudflare Pages
84
+ wrangler r2 📦 Interact with an R2 store
110
85
 
111
86
  Flags:
112
- -c, --config Path to .toml configuration file [string]
113
- -h, --help Show help [boolean]
114
- -v, --version Show version number [boolean]
115
-
116
- Options:
117
- -l, --local Run on my machine [boolean] [default: false]"
118
- `);
87
+ -c, --config Path to .toml configuration file [string]
88
+ -h, --help Show help [boolean]
89
+ -v, --version Show version number [boolean]
90
+ --legacy-env Use legacy environments [boolean]
119
91
 
120
- expect(stderr).toMatchInlineSnapshot(`
121
- "
122
- Unknown command: invalid-command."
92
+ Unknown argument: invalid-command"
123
93
  `);
124
94
  });
125
95
  });
126
96
 
127
97
  describe("init", () => {
128
- const ogcwd = process.cwd();
129
- let tmpDir: string;
130
-
131
- beforeEach(async () => {
132
- tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "init-"));
133
- process.chdir(tmpDir);
134
- });
135
-
136
- afterEach(async () => {
137
- process.chdir(ogcwd);
138
- await fsp.rm(tmpDir, { recursive: true });
139
- });
140
-
141
98
  it("should create a wrangler.toml", async () => {
142
99
  mockConfirm({
143
100
  text: "No package.json found. Would you like to create one?",
144
101
  result: false,
145
102
  });
146
- await w("init");
103
+ await runWrangler("init");
147
104
  const parsed = TOML.parse(await fsp.readFile("./wrangler.toml", "utf-8"));
148
105
  expect(typeof parsed.compatibility_date).toBe("string");
106
+ expect(parsed.name).toContain("wrangler-tests");
149
107
  expect(fs.existsSync("./package.json")).toBe(false);
150
108
  expect(fs.existsSync("./tsconfig.json")).toBe(false);
151
109
  });
152
110
 
111
+ it("should create a wrangler.toml and a directory for a named Worker ", async () => {
112
+ mockConfirm({
113
+ text: "No package.json found. Would you like to create one?",
114
+ result: false,
115
+ });
116
+ await runWrangler("init my-worker");
117
+ const parsed = TOML.parse(
118
+ await fsp.readFile("./my-worker/wrangler.toml", "utf-8")
119
+ );
120
+ expect(typeof parsed.compatibility_date).toBe("string");
121
+ expect(parsed.name).toBe("my-worker");
122
+ expect(fs.existsSync("./my-worker/package.json")).toBe(false);
123
+ expect(fs.existsSync("./my-worker/tsconfig.json")).toBe(false);
124
+ });
125
+
153
126
  it("should display warning when wrangler.toml already exists, and exit if user does not want to carry on", async () => {
154
- fs.closeSync(fs.openSync("./wrangler.toml", "w"));
127
+ fs.writeFileSync(
128
+ "./wrangler.toml",
129
+ 'compatibility_date="something-else"', // use a fake value to make sure the file is not overwritten
130
+ "utf-8"
131
+ );
155
132
  mockConfirm({
156
133
  text: "Do you want to continue initializing this project?",
157
134
  result: false,
158
135
  });
159
- const { stderr } = await w("init");
160
- expect(stderr).toContain("wrangler.toml file already exists!");
136
+ await runWrangler("init");
137
+ expect(std.warn).toContain("wrangler.toml file already exists!");
161
138
  const parsed = TOML.parse(await fsp.readFile("./wrangler.toml", "utf-8"));
162
- expect(typeof parsed.compatibility_date).toBe("undefined");
139
+ expect(parsed.compatibility_date).toBe("something-else");
140
+ });
141
+
142
+ it("should not overwrite an existing wrangler.toml, after agreeing to other prompts", async () => {
143
+ fs.writeFileSync(
144
+ "./wrangler.toml",
145
+ 'compatibility_date="something-else"', // use a fake value to make sure the file is not overwritten
146
+ "utf-8"
147
+ );
148
+ mockConfirm(
149
+ {
150
+ text: "Do you want to continue initializing this project?",
151
+ result: true,
152
+ },
153
+ {
154
+ text: "No package.json found. Would you like to create one?",
155
+ result: true,
156
+ },
157
+ {
158
+ text: "Would you like to use TypeScript?",
159
+ result: true,
160
+ },
161
+ {
162
+ text: "Would you like to create a Worker at src/index.ts?",
163
+ result: true,
164
+ }
165
+ );
166
+
167
+ await runWrangler("init");
168
+ expect(fs.readFileSync("./wrangler.toml", "utf-8")).toMatchInlineSnapshot(
169
+ `"compatibility_date=\\"something-else\\""`
170
+ );
163
171
  });
164
172
 
165
173
  it("should display warning when wrangler.toml already exists, but continue if user does want to carry on", async () => {
166
- fs.closeSync(fs.openSync("./wrangler.toml", "w"));
174
+ fs.writeFileSync(
175
+ "./wrangler.toml",
176
+ `compatibility_date="something-else"`,
177
+ "utf-8"
178
+ );
167
179
  mockConfirm(
168
180
  {
169
181
  text: "Do you want to continue initializing this project?",
@@ -174,10 +186,10 @@ describe("wrangler", () => {
174
186
  result: false,
175
187
  }
176
188
  );
177
- const { stderr } = await w("init");
178
- expect(stderr).toContain("wrangler.toml file already exists!");
189
+ await runWrangler("init");
190
+ expect(std.warn).toContain("wrangler.toml file already exists!");
179
191
  const parsed = TOML.parse(await fsp.readFile("./wrangler.toml", "utf-8"));
180
- expect(typeof parsed.compatibility_date).toBe("string");
192
+ expect(parsed.compatibility_date).toBe("something-else");
181
193
  });
182
194
 
183
195
  it("should create a package.json if none is found and user confirms", async () => {
@@ -187,25 +199,95 @@ describe("wrangler", () => {
187
199
  result: true,
188
200
  },
189
201
  {
190
- text: "Would you like to use typescript?",
202
+ text: "Would you like to use TypeScript?",
203
+ result: false,
204
+ },
205
+ {
206
+ text: "Would you like to create a Worker at src/index.js?",
191
207
  result: false,
192
208
  }
193
209
  );
194
- await w("init");
210
+ await runWrangler("init");
195
211
  expect(fs.existsSync("./package.json")).toBe(true);
196
212
  const packageJson = JSON.parse(
197
213
  fs.readFileSync("./package.json", "utf-8")
198
214
  );
199
- expect(packageJson.name).toEqual("worker"); // TODO: should we infer the name from the directory?
200
- expect(packageJson.version).toEqual("0.0.1");
215
+ expect(packageJson.name).toContain("wrangler-tests");
216
+ expect(packageJson.version).toEqual("0.0.0");
217
+ expect(packageJson.devDependencies).toEqual({
218
+ wrangler: expect.any(String),
219
+ });
201
220
  expect(fs.existsSync("./tsconfig.json")).toBe(false);
221
+ expect(mockPackageManager.install).toHaveBeenCalled();
222
+ });
223
+
224
+ it("should create a package.json, with the specified name, if none is found and user confirms", async () => {
225
+ mockConfirm(
226
+ {
227
+ text: "No package.json found. Would you like to create one?",
228
+ result: true,
229
+ },
230
+ {
231
+ text: "Would you like to use TypeScript?",
232
+ result: false,
233
+ },
234
+ {
235
+ text: "Would you like to create a Worker at src/index.js?",
236
+ result: false,
237
+ }
238
+ );
239
+ await runWrangler("init my-worker");
240
+ const packageJson = JSON.parse(
241
+ fs.readFileSync("./my-worker/package.json", "utf-8")
242
+ );
243
+ expect(packageJson.name).toBe("my-worker");
202
244
  });
203
245
 
204
246
  it("should not touch an existing package.json in the same directory", async () => {
205
- mockConfirm({
206
- text: "Would you like to use typescript?",
207
- result: false,
208
- });
247
+ mockConfirm(
248
+ {
249
+ text: "Would you like to install wrangler into your package.json?",
250
+ result: false,
251
+ },
252
+ {
253
+ text: "Would you like to use TypeScript?",
254
+ result: false,
255
+ },
256
+ {
257
+ text: "Would you like to create a Worker at src/index.js?",
258
+ result: false,
259
+ }
260
+ );
261
+
262
+ fs.writeFileSync(
263
+ "./package.json",
264
+ JSON.stringify({ name: "test", version: "1.0.0" }),
265
+ "utf-8"
266
+ );
267
+
268
+ await runWrangler("init");
269
+ const packageJson = JSON.parse(
270
+ fs.readFileSync("./package.json", "utf-8")
271
+ );
272
+ expect(packageJson.name).toEqual("test");
273
+ expect(packageJson.version).toEqual("1.0.0");
274
+ });
275
+
276
+ it("should offer to install wrangler into an existing package.json", async () => {
277
+ mockConfirm(
278
+ {
279
+ text: "Would you like to install wrangler into your package.json?",
280
+ result: true,
281
+ },
282
+ {
283
+ text: "Would you like to use TypeScript?",
284
+ result: false,
285
+ },
286
+ {
287
+ text: "Would you like to create a Worker at src/index.js?",
288
+ result: false,
289
+ }
290
+ );
209
291
 
210
292
  fs.writeFileSync(
211
293
  "./package.json",
@@ -213,19 +295,32 @@ describe("wrangler", () => {
213
295
  "utf-8"
214
296
  );
215
297
 
216
- await w("init");
298
+ await runWrangler("init");
217
299
  const packageJson = JSON.parse(
218
300
  fs.readFileSync("./package.json", "utf-8")
219
301
  );
220
302
  expect(packageJson.name).toEqual("test");
221
303
  expect(packageJson.version).toEqual("1.0.0");
304
+ expect(mockPackageManager.addDevDeps).toHaveBeenCalledWith(
305
+ `wrangler@${wranglerVersion}`
306
+ );
222
307
  });
223
308
 
224
309
  it("should not touch an existing package.json in an ancestor directory", async () => {
225
- mockConfirm({
226
- text: "Would you like to use typescript?",
227
- result: false,
228
- });
310
+ mockConfirm(
311
+ {
312
+ text: "Would you like to install wrangler into your package.json?",
313
+ result: false,
314
+ },
315
+ {
316
+ text: "Would you like to use TypeScript?",
317
+ result: false,
318
+ },
319
+ {
320
+ text: "Would you like to create a Worker at src/index.js?",
321
+ result: false,
322
+ }
323
+ );
229
324
 
230
325
  fs.writeFileSync(
231
326
  "./package.json",
@@ -236,15 +331,299 @@ describe("wrangler", () => {
236
331
  fs.mkdirSync("./sub-1/sub-2", { recursive: true });
237
332
  process.chdir("./sub-1/sub-2");
238
333
 
239
- await w("init");
334
+ await runWrangler("init");
240
335
  expect(fs.existsSync("./package.json")).toBe(false);
241
336
  expect(fs.existsSync("../../package.json")).toBe(true);
242
337
 
243
338
  const packageJson = JSON.parse(
244
339
  fs.readFileSync("../../package.json", "utf-8")
245
340
  );
246
- expect(packageJson.name).toEqual("test");
247
- expect(packageJson.version).toEqual("1.0.0");
341
+ expect(packageJson).toMatchInlineSnapshot(`
342
+ Object {
343
+ "name": "test",
344
+ "version": "1.0.0",
345
+ }
346
+ `);
347
+ });
348
+
349
+ it("should offer to create a worker in a non-typescript project", async () => {
350
+ mockConfirm(
351
+ {
352
+ text: "Would you like to install wrangler into your package.json?",
353
+ result: false,
354
+ },
355
+ {
356
+ text: "Would you like to use TypeScript?",
357
+ result: false,
358
+ },
359
+ {
360
+ text: "Would you like to create a Worker at src/index.js?",
361
+ result: true,
362
+ }
363
+ );
364
+
365
+ fs.writeFileSync(
366
+ "./package.json",
367
+ JSON.stringify({ name: "test", version: "1.0.0" }),
368
+ "utf-8"
369
+ );
370
+
371
+ await runWrangler("init");
372
+ expect(fs.existsSync("./src/index.js")).toBe(true);
373
+ expect(fs.existsSync("./src/index.ts")).toBe(false);
374
+ });
375
+
376
+ it("should offer to create a worker in a typescript project", async () => {
377
+ mockConfirm(
378
+ {
379
+ text: "Would you like to install wrangler into your package.json?",
380
+ result: false,
381
+ },
382
+ {
383
+ text: "Would you like to use TypeScript?",
384
+ result: true,
385
+ },
386
+ {
387
+ text: "Would you like to create a Worker at src/index.ts?",
388
+ result: true,
389
+ }
390
+ );
391
+
392
+ fs.writeFileSync(
393
+ "./package.json",
394
+ JSON.stringify({ name: "test", version: "1.0.0" }),
395
+ "utf-8"
396
+ );
397
+
398
+ await runWrangler("init");
399
+ expect(fs.existsSync("./src/index.js")).toBe(false);
400
+ expect(fs.existsSync("./src/index.ts")).toBe(true);
401
+ });
402
+
403
+ it("should add scripts for a typescript project with .ts extension", async () => {
404
+ mockConfirm(
405
+ {
406
+ text: "No package.json found. Would you like to create one?",
407
+ result: true,
408
+ },
409
+ {
410
+ text: "Would you like to install wrangler into your package.json?",
411
+ result: false,
412
+ },
413
+ {
414
+ text: "Would you like to use TypeScript?",
415
+ result: true,
416
+ },
417
+ {
418
+ text: "Would you like to create a Worker at src/index.ts?",
419
+ result: true,
420
+ }
421
+ );
422
+ await runWrangler("init");
423
+
424
+ expect(fs.existsSync("./package.json")).toBe(true);
425
+ const packageJson = JSON.parse(
426
+ fs.readFileSync("./package.json", "utf-8")
427
+ );
428
+
429
+ expect(fs.existsSync("./src/index.js")).toBe(false);
430
+ expect(fs.existsSync("./src/index.ts")).toBe(true);
431
+
432
+ expect(packageJson.scripts.start).toBe("wrangler dev");
433
+ expect(packageJson.scripts.publish).toBe("wrangler publish");
434
+ expect(packageJson.name).toContain("wrangler-tests");
435
+ expect(packageJson.version).toEqual("0.0.0");
436
+ expect(std.out).toMatchInlineSnapshot(`
437
+ "✨ Successfully created wrangler.toml
438
+ ✨ Created package.json
439
+ ✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies
440
+ ✨ Created src/index.ts
441
+
442
+ To start developing your Worker, run \`npm start\`
443
+ To publish your Worker to the Internet, run \`npm run publish\`"
444
+ `);
445
+ });
446
+
447
+ it("should not overwrite package.json scripts for a typescript project", async () => {
448
+ mockConfirm(
449
+ {
450
+ text: "Would you like to install wrangler into your package.json?",
451
+ result: false,
452
+ },
453
+ {
454
+ text: "Would you like to use TypeScript?",
455
+ result: true,
456
+ },
457
+ {
458
+ text: "Would you like to create a Worker at src/index.ts?",
459
+ result: true,
460
+ }
461
+ );
462
+ await fsp.writeFile(
463
+ "./package.json",
464
+ JSON.stringify({
465
+ scripts: {
466
+ start: "test-start",
467
+ publish: "test-publish",
468
+ },
469
+ })
470
+ );
471
+ const packageJson = JSON.parse(
472
+ fs.readFileSync("./package.json", "utf-8")
473
+ );
474
+ await runWrangler("init");
475
+
476
+ expect(fs.existsSync("./src/index.js")).toBe(false);
477
+ expect(fs.existsSync("./src/index.ts")).toBe(true);
478
+
479
+ expect(packageJson.scripts.start).toBe("test-start");
480
+ expect(packageJson.scripts.publish).toBe("test-publish");
481
+ expect(std.out).toMatchInlineSnapshot(`
482
+ "✨ Successfully created wrangler.toml
483
+ ✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies
484
+ ✨ Created src/index.ts
485
+
486
+ To start developing your Worker, run \`npx wrangler dev\`
487
+ To publish your Worker to the Internet, run \`npx wrangler publish\`"
488
+ `);
489
+ });
490
+
491
+ it("should add missing scripts for a non-ts project with .js extension", async () => {
492
+ mockConfirm(
493
+ {
494
+ text: "No package.json found. Would you like to create one?",
495
+ result: true,
496
+ },
497
+ {
498
+ text: "Would you like to install wrangler into your package.json?",
499
+ result: false,
500
+ },
501
+ {
502
+ text: "Would you like to use TypeScript?",
503
+ result: false,
504
+ },
505
+ {
506
+ text: "Would you like to create a Worker at src/index.js?",
507
+ result: true,
508
+ }
509
+ );
510
+ await runWrangler("init");
511
+
512
+ expect(fs.existsSync("./package.json")).toBe(true);
513
+ const packageJson = JSON.parse(
514
+ fs.readFileSync("./package.json", "utf-8")
515
+ );
516
+
517
+ expect(fs.existsSync("./src/index.js")).toBe(true);
518
+ expect(fs.existsSync("./src/index.ts")).toBe(false);
519
+
520
+ expect(packageJson.scripts.start).toBe("wrangler dev");
521
+ expect(packageJson.scripts.publish).toBe("wrangler publish");
522
+ expect(packageJson.name).toContain("wrangler-tests");
523
+ expect(packageJson.version).toEqual("0.0.0");
524
+ expect(std.out).toMatchInlineSnapshot(`
525
+ "✨ Successfully created wrangler.toml
526
+ ✨ Created package.json
527
+ ✨ Created src/index.js
528
+
529
+ To start developing your Worker, run \`npm start\`
530
+ To publish your Worker to the Internet, run \`npm run publish\`"
531
+ `);
532
+ });
533
+
534
+ it("should not overwrite package.json scripts for a non-ts project with .js extension", async () => {
535
+ mockConfirm(
536
+ {
537
+ text: "Would you like to install wrangler into your package.json?",
538
+ result: false,
539
+ },
540
+ {
541
+ text: "Would you like to use TypeScript?",
542
+ result: false,
543
+ },
544
+ {
545
+ text: "Would you like to create a Worker at src/index.js?",
546
+ result: true,
547
+ }
548
+ );
549
+ await fsp.writeFile(
550
+ "./package.json",
551
+ JSON.stringify({
552
+ scripts: {
553
+ start: "test-start",
554
+ publish: "test-publish",
555
+ },
556
+ })
557
+ );
558
+ const packageJson = JSON.parse(
559
+ fs.readFileSync("./package.json", "utf-8")
560
+ );
561
+ await runWrangler("init");
562
+
563
+ expect(fs.existsSync("./src/index.js")).toBe(true);
564
+ expect(fs.existsSync("./src/index.ts")).toBe(false);
565
+
566
+ expect(packageJson.scripts.start).toBe("test-start");
567
+ expect(packageJson.scripts.publish).toBe("test-publish");
568
+ expect(std.out).toMatchInlineSnapshot(`
569
+ "✨ Successfully created wrangler.toml
570
+ ✨ Created src/index.js
571
+
572
+ To start developing your Worker, run \`npx wrangler dev\`
573
+ To publish your Worker to the Internet, run \`npx wrangler publish\`"
574
+ `);
575
+ });
576
+
577
+ it("should not offer to create a worker in a non-ts project if a file already exists at the location", async () => {
578
+ mockConfirm(
579
+ {
580
+ text: "Would you like to install wrangler into your package.json?",
581
+ result: false,
582
+ },
583
+ {
584
+ text: "Would you like to use TypeScript?",
585
+ result: false,
586
+ }
587
+ );
588
+
589
+ fs.writeFileSync(
590
+ "./package.json",
591
+ JSON.stringify({ name: "test", version: "1.0.0" }),
592
+ "utf-8"
593
+ );
594
+ fs.mkdirSync("./src", { recursive: true });
595
+ const PLACEHOLDER = "/* placeholder text */";
596
+ fs.writeFileSync("./src/index.js", PLACEHOLDER, "utf-8");
597
+
598
+ await runWrangler("init");
599
+ expect(fs.readFileSync("./src/index.js", "utf-8")).toBe(PLACEHOLDER);
600
+ expect(fs.existsSync("./src/index.ts")).toBe(false);
601
+ });
602
+
603
+ it("should not offer to create a worker in a ts project if a file already exists at the location", async () => {
604
+ mockConfirm(
605
+ {
606
+ text: "Would you like to install wrangler into your package.json?",
607
+ result: false,
608
+ },
609
+ {
610
+ text: "Would you like to use TypeScript?",
611
+ result: true,
612
+ }
613
+ );
614
+
615
+ fs.writeFileSync(
616
+ "./package.json",
617
+ JSON.stringify({ name: "test", version: "1.0.0" }),
618
+ "utf-8"
619
+ );
620
+ fs.mkdirSync("./src", { recursive: true });
621
+ const PLACEHOLDER = "/* placeholder text */";
622
+ fs.writeFileSync("./src/index.ts", PLACEHOLDER, "utf-8");
623
+
624
+ await runWrangler("init");
625
+ expect(fs.existsSync("./src/index.js")).toBe(false);
626
+ expect(fs.readFileSync("./src/index.ts", "utf-8")).toBe(PLACEHOLDER);
248
627
  });
249
628
 
250
629
  it("should create a tsconfig.json and install `workers-types` if none is found and user confirms", async () => {
@@ -254,30 +633,42 @@ describe("wrangler", () => {
254
633
  result: true,
255
634
  },
256
635
  {
257
- text: "Would you like to use typescript?",
636
+ text: "Would you like to use TypeScript?",
258
637
  result: true,
638
+ },
639
+ {
640
+ text: "Would you like to create a Worker at src/index.ts?",
641
+ result: false,
259
642
  }
260
643
  );
261
- await w("init");
644
+ await runWrangler("init");
262
645
  expect(fs.existsSync("./tsconfig.json")).toBe(true);
263
- const tsconfigJson = JSON.parse(
264
- fs.readFileSync("./tsconfig.json", "utf-8")
265
- );
646
+ const { config: tsconfigJson, error: tsConfigParseError } =
647
+ parseConfigFileTextToJson(
648
+ "./tsconfig.json",
649
+ fs.readFileSync("./tsconfig.json", "utf-8")
650
+ );
651
+ expect(tsConfigParseError).toBeUndefined();
266
652
  expect(tsconfigJson.compilerOptions.types).toEqual([
267
653
  "@cloudflare/workers-types",
268
654
  ]);
269
- const packageJson = JSON.parse(
270
- fs.readFileSync("./package.json", "utf-8")
655
+ expect(mockPackageManager.addDevDeps).toHaveBeenCalledWith(
656
+ "@cloudflare/workers-types",
657
+ "typescript"
271
658
  );
272
- expect(packageJson.devDependencies).toEqual({
273
- "@cloudflare/workers-types": expect.any(String),
274
- });
275
659
  });
276
660
 
277
661
  it("should not touch an existing tsconfig.json in the same directory", async () => {
278
662
  fs.writeFileSync(
279
663
  "./package.json",
280
- JSON.stringify({ name: "test", version: "1.0.0" }),
664
+ JSON.stringify({
665
+ name: "test",
666
+ version: "1.0.0",
667
+ devDependencies: {
668
+ wrangler: "0.0.0",
669
+ "@cloudflare/workers-types": "0.0.0",
670
+ },
671
+ }),
281
672
  "utf-8"
282
673
  );
283
674
  fs.writeFileSync(
@@ -286,17 +677,64 @@ describe("wrangler", () => {
286
677
  "utf-8"
287
678
  );
288
679
 
289
- await w("init");
680
+ await runWrangler("init");
290
681
  const tsconfigJson = JSON.parse(
291
682
  fs.readFileSync("./tsconfig.json", "utf-8")
292
683
  );
293
684
  expect(tsconfigJson.compilerOptions).toEqual({});
294
685
  });
295
686
 
296
- it("should not touch an existing package.json in an ancestor directory", async () => {
687
+ it("should offer to install type definitions in an existing typescript project", async () => {
688
+ mockConfirm(
689
+ {
690
+ text: "Would you like to install wrangler into your package.json?",
691
+ result: false,
692
+ },
693
+ {
694
+ text: "Would you like to install the type definitions for Workers into your package.json?",
695
+ result: true,
696
+ },
697
+ {
698
+ text: "Would you like to create a Worker at src/index.ts?",
699
+ result: false,
700
+ }
701
+ );
297
702
  fs.writeFileSync(
298
703
  "./package.json",
299
- JSON.stringify({ name: "test", version: "1.0.0" }),
704
+ JSON.stringify({
705
+ name: "test",
706
+ version: "1.0.0",
707
+ }),
708
+ "utf-8"
709
+ );
710
+ fs.writeFileSync(
711
+ "./tsconfig.json",
712
+ JSON.stringify({ compilerOptions: {} }),
713
+ "utf-8"
714
+ );
715
+
716
+ await runWrangler("init");
717
+ const tsconfigJson = JSON.parse(
718
+ fs.readFileSync("./tsconfig.json", "utf-8")
719
+ );
720
+ // unchanged tsconfig
721
+ expect(tsconfigJson.compilerOptions).toEqual({});
722
+ expect(mockPackageManager.addDevDeps).toHaveBeenCalledWith(
723
+ "@cloudflare/workers-types"
724
+ );
725
+ });
726
+
727
+ it("should not touch an existing tsconfig.json in an ancestor directory", async () => {
728
+ fs.writeFileSync(
729
+ "./package.json",
730
+ JSON.stringify({
731
+ name: "test",
732
+ version: "1.0.0",
733
+ devDependencies: {
734
+ wrangler: "0.0.0",
735
+ "@cloudflare/workers-types": "0.0.0",
736
+ },
737
+ }),
300
738
  "utf-8"
301
739
  );
302
740
  fs.writeFileSync(
@@ -308,7 +746,7 @@ describe("wrangler", () => {
308
746
  fs.mkdirSync("./sub-1/sub-2", { recursive: true });
309
747
  process.chdir("./sub-1/sub-2");
310
748
 
311
- await w("init");
749
+ await runWrangler("init");
312
750
  expect(fs.existsSync("./tsconfig.json")).toBe(false);
313
751
  expect(fs.existsSync("../../tsconfig.json")).toBe(true);
314
752
 
@@ -318,105 +756,228 @@ describe("wrangler", () => {
318
756
  expect(tsconfigJson.compilerOptions).toEqual({});
319
757
  });
320
758
 
321
- it("should error if `--type` is used", async () => {
322
- const noValue = await w("init --type");
323
- expect(noValue.stderr).toMatchInlineSnapshot(
324
- `"The --type option is no longer supported."`
759
+ it("should initialize with no interactive prompts if `--yes` is used", async () => {
760
+ await runWrangler("init --yes");
761
+
762
+ expect(fs.existsSync("./src/index.js")).toBe(false);
763
+ expect(fs.existsSync("./src/index.ts")).toBe(true);
764
+ expect(fs.existsSync("./tsconfig.json")).toBe(true);
765
+ expect(fs.existsSync("./package.json")).toBe(true);
766
+ expect(fs.existsSync("./wrangler.toml")).toBe(true);
767
+ expect(std.out).toMatchInlineSnapshot(`
768
+ "✨ Successfully created wrangler.toml
769
+ ✨ Created package.json
770
+ ✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies
771
+ ✨ Created src/index.ts
772
+
773
+ To start developing your Worker, run \`npm start\`
774
+ To publish your Worker to the Internet, run \`npm run publish\`"
775
+ `);
776
+ expect(std.err).toMatchInlineSnapshot(`""`);
777
+ expect(std.warn).toMatchInlineSnapshot(`""`);
778
+ });
779
+
780
+ it("should initialize with no interactive prompts if `--yes` is used (named worker)", async () => {
781
+ await runWrangler("init my-worker --yes");
782
+
783
+ expect(fs.existsSync("./my-worker/src/index.js")).toBe(false);
784
+ expect(fs.existsSync("./my-worker/src/index.ts")).toBe(true);
785
+ expect(fs.existsSync("./my-worker/tsconfig.json")).toBe(true);
786
+ expect(fs.existsSync("./my-worker/package.json")).toBe(true);
787
+ expect(fs.existsSync("./my-worker/wrangler.toml")).toBe(true);
788
+ const parsedWranglerToml = TOML.parse(
789
+ fs.readFileSync("./my-worker/wrangler.toml", "utf-8")
325
790
  );
791
+ expect(parsedWranglerToml.main).toEqual("src/index.ts");
792
+ expect(std.out).toMatchInlineSnapshot(`
793
+ "✨ Successfully created wrangler.toml
794
+ ✨ Created package.json
795
+ ✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies
796
+ ✨ Created src/index.ts
797
+
798
+ To start developing your Worker, run \`cd my-worker && npm start\`
799
+ To publish your Worker to the Internet, run \`npm run publish\`"
800
+ `);
801
+ expect(std.err).toMatchInlineSnapshot(`""`);
802
+ expect(std.warn).toMatchInlineSnapshot(`""`);
803
+ });
804
+
805
+ it("should initialize with no interactive prompts if `-y` is used", async () => {
806
+ await runWrangler("init -y");
807
+
808
+ expect(fs.existsSync("./src/index.js")).toBe(false);
809
+ expect(fs.existsSync("./src/index.ts")).toBe(true);
810
+ expect(fs.existsSync("./tsconfig.json")).toBe(true);
811
+ expect(fs.existsSync("./package.json")).toBe(true);
812
+ expect(fs.existsSync("./wrangler.toml")).toBe(true);
326
813
  });
327
814
 
328
815
  it("should error if `--type javascript` is used", async () => {
329
- const javascriptValue = await w("init --type javascript");
330
- expect(javascriptValue.stderr).toMatchInlineSnapshot(
816
+ await expect(
817
+ runWrangler("init --type javascript")
818
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
331
819
  `"The --type option is no longer supported."`
332
820
  );
333
821
  });
334
822
 
335
823
  it("should error if `--type rust` is used", async () => {
336
- const rustValue = await w("init --type rust");
337
- expect(rustValue.stderr).toMatchInlineSnapshot(
824
+ await expect(
825
+ runWrangler("init --type rust")
826
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
338
827
  `"The --type option is no longer supported."`
339
828
  );
340
829
  });
341
830
 
342
831
  it("should error if `--type webpack` is used", async () => {
343
- const webpackValue = await w("init --type webpack");
344
- expect(webpackValue.stderr).toMatchInlineSnapshot(`
345
- "The --type option is no longer supported.
346
- If you wish to use webpack then you will need to create a custom build."
347
- `);
832
+ await expect(runWrangler("init --type webpack")).rejects
833
+ .toThrowErrorMatchingInlineSnapshot(`
834
+ "The --type option is no longer supported.
835
+ If you wish to use webpack then you will need to create a custom build."
836
+ `);
348
837
  });
349
838
  });
350
839
 
351
- describe("kv:namespace", () => {
352
- afterEach(() => {
353
- unsetAllMocks();
840
+ describe("preview", () => {
841
+ it("should throw an error if the deprecated command is used with positional arguments", async () => {
842
+ await expect(runWrangler("preview GET")).rejects
843
+ .toThrowErrorMatchingInlineSnapshot(`
844
+ "DEPRECATION WARNING:
845
+ The \`wrangler preview\` command has been deprecated.
846
+ Try using \`wrangler dev\` to to try out a worker during development.
847
+ "
848
+ `);
849
+ await expect(runWrangler(`preview GET "SomeBody"`)).rejects
850
+ .toThrowErrorMatchingInlineSnapshot(`
851
+ "DEPRECATION WARNING:
852
+ The \`wrangler preview\` command has been deprecated.
853
+ Try using \`wrangler dev\` to to try out a worker during development.
854
+ "
855
+ `);
354
856
  });
857
+ });
355
858
 
356
- it("can create a namespace", async () => {
357
- const KVNamespaces: { title: string; id: string }[] = [];
358
- setMock("/accounts/:accountId/storage/kv/namespaces", (uri, init) => {
359
- expect(init.method === "POST");
360
- expect(uri[0]).toEqual(
361
- "/accounts/some-account-id/storage/kv/namespaces"
362
- );
363
- const { title } = JSON.parse(init.body);
364
- expect(title).toEqual("worker-UnitTestNamespace");
365
- KVNamespaces.push({ title, id: "some-namespace-id" });
366
- return { id: "some-namespace-id" };
367
- });
859
+ describe("subcommand implicit help ran on imcomplete command execution", () => {
860
+ function endEventLoop() {
861
+ return new Promise((resolve) => setImmediate(resolve));
862
+ }
863
+ it("no subcommand for 'secret' should display a list of available subcommands", async () => {
864
+ await runWrangler("secret");
865
+ await endEventLoop();
866
+ expect(std.out).toMatchInlineSnapshot(`
867
+ "wrangler secret
368
868
 
369
- await w("kv:namespace create UnitTestNamespace");
869
+ 🤫 Generate a secret that can be referenced in the worker script
370
870
 
371
- expect(KVNamespaces).toEqual([
372
- {
373
- title: "worker-UnitTestNamespace",
374
- id: "some-namespace-id",
375
- },
376
- ]);
871
+ Commands:
872
+ wrangler secret put <key> Create or update a secret variable for a script
873
+ wrangler secret delete <key> Delete a secret variable from a script
874
+ wrangler secret list List all secrets for a script
875
+
876
+ Flags:
877
+ -c, --config Path to .toml configuration file [string]
878
+ -h, --help Show help [boolean]
879
+ -v, --version Show version number [boolean]
880
+ --legacy-env Use legacy environments [boolean]"
881
+ `);
377
882
  });
378
883
 
379
- it("can list namespaces", async () => {
380
- const KVNamespaces: { title: string; id: string }[] = [
381
- { title: "title-1", id: "id-1" },
382
- { title: "title-2", id: "id-2" },
383
- ];
384
- setMock(
385
- "/accounts/:accountId/storage/kv/namespaces\\?:qs",
386
- (uri, init) => {
387
- expect(uri[0]).toContain(
388
- "/accounts/some-account-id/storage/kv/namespaces"
389
- );
390
- expect(uri[2]).toContain("per_page=100");
391
- expect(uri[2]).toContain("order=title");
392
- expect(uri[2]).toContain("direction=asc");
393
- expect(uri[2]).toContain("page=1");
394
- expect(init).toBe(undefined);
395
- return KVNamespaces;
396
- }
397
- );
398
- const { stdout } = await w("kv:namespace list");
399
- const namespaces = JSON.parse(stdout) as { id: string; title: string }[];
400
- expect(namespaces).toEqual(KVNamespaces);
401
- });
402
-
403
- it("can delete a namespace", async () => {
404
- let accountId = "";
405
- let namespaceId = "";
406
- setMock(
407
- "/accounts/:accountId/storage/kv/namespaces/:namespaceId",
408
- (uri, init) => {
409
- accountId = uri[1];
410
- namespaceId = uri[2];
411
- expect(uri[0]).toEqual(
412
- "/accounts/some-account-id/storage/kv/namespaces/some-namespace-id"
413
- );
414
- expect(init.method).toBe("DELETE");
415
- }
416
- );
417
- await w(`kv:namespace delete --namespace-id some-namespace-id`);
418
- expect(accountId).toEqual("some-account-id");
419
- expect(namespaceId).toEqual("some-namespace-id");
884
+ it("no subcommand 'kv:namespace' should display a list of available subcommands", async () => {
885
+ await runWrangler("kv:namespace");
886
+ await endEventLoop();
887
+ expect(std.out).toMatchInlineSnapshot(`
888
+ "wrangler kv:namespace
889
+
890
+ 🗂️ Interact with your Workers KV Namespaces
891
+
892
+ Commands:
893
+ wrangler kv:namespace create <namespace> Create a new namespace
894
+ wrangler kv:namespace list Outputs a list of all KV namespaces associated with your account id.
895
+ wrangler kv:namespace delete Deletes a given namespace.
896
+
897
+ Flags:
898
+ -c, --config Path to .toml configuration file [string]
899
+ -h, --help Show help [boolean]
900
+ -v, --version Show version number [boolean]
901
+ --legacy-env Use legacy environments [boolean]"
902
+ `);
903
+ });
904
+
905
+ it("no subcommand 'kv:key' should display a list of available subcommands", async () => {
906
+ await runWrangler("kv:key");
907
+ await endEventLoop();
908
+ expect(std.out).toMatchInlineSnapshot(`
909
+ "wrangler kv:key
910
+
911
+ 🔑 Individually manage Workers KV key-value pairs
912
+
913
+ Commands:
914
+ wrangler kv:key put <key> [value] Writes a single key/value pair to the given namespace.
915
+ wrangler kv:key list Outputs a list of all keys in a given namespace.
916
+ wrangler kv:key get <key> Reads a single value by key from the given namespace.
917
+ wrangler kv:key delete <key> Removes a single key value pair from the given namespace.
918
+
919
+ Flags:
920
+ -c, --config Path to .toml configuration file [string]
921
+ -h, --help Show help [boolean]
922
+ -v, --version Show version number [boolean]
923
+ --legacy-env Use legacy environments [boolean]"
924
+ `);
925
+ });
926
+
927
+ it("no subcommand 'kv:bulk' should display a list of available subcommands", async () => {
928
+ await runWrangler("kv:bulk");
929
+ await endEventLoop();
930
+ expect(std.out).toMatchInlineSnapshot(`
931
+ "wrangler kv:bulk
932
+
933
+ 💪 Interact with multiple Workers KV key-value pairs at once
934
+
935
+ Commands:
936
+ wrangler kv:bulk put <filename> Upload multiple key-value pairs to a namespace
937
+ wrangler kv:bulk delete <filename> Delete multiple key-value pairs from a namespace
938
+
939
+ Flags:
940
+ -c, --config Path to .toml configuration file [string]
941
+ -h, --help Show help [boolean]
942
+ -v, --version Show version number [boolean]
943
+ --legacy-env Use legacy environments [boolean]"
944
+ `);
945
+ });
946
+ it("no subcommand 'r2' should display a list of available subcommands", async () => {
947
+ await runWrangler("r2");
948
+ await endEventLoop();
949
+ expect(std.out).toMatchInlineSnapshot(`
950
+ "wrangler r2
951
+
952
+ 📦 Interact with an R2 store
953
+
954
+ Commands:
955
+ wrangler r2 bucket Manage R2 buckets
956
+
957
+ Flags:
958
+ -c, --config Path to .toml configuration file [string]
959
+ -h, --help Show help [boolean]
960
+ -v, --version Show version number [boolean]
961
+ --legacy-env Use legacy environments [boolean]"
962
+ `);
963
+ });
964
+ });
965
+ describe("Deprecated commands", () => {
966
+ it("should print a deprecation message for 'generate'", async () => {
967
+ await runWrangler("generate").catch((err) => {
968
+ expect(err.message).toMatchInlineSnapshot(`
969
+ "DEPRECATION WARNING:
970
+ \`wrangler generate\` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#generate for alternatives"
971
+ `);
972
+ });
973
+ });
974
+ it("should print a deprecation message for 'build'", async () => {
975
+ await runWrangler("build").catch((err) => {
976
+ expect(err.message).toMatchInlineSnapshot(`
977
+ "DEPRECATION WARNING:
978
+ \`wrangler build\` has been deprecated, please refer to https://github.com/cloudflare/wrangler2/blob/main/docs/deprecations.md#build for alternatives"
979
+ `);
980
+ });
420
981
  });
421
982
  });
422
983
  });