wrangler 0.0.0-e2a26a0 → 0.0.0-e2b3306e1

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 (136) hide show
  1. package/README.md +44 -25
  2. package/bin/wrangler.js +95 -32
  3. package/config-schema.json +3370 -0
  4. package/kv-asset-handler.js +1 -0
  5. package/package.json +146 -92
  6. package/templates/__tests__/pages-dev-util.test.ts +128 -0
  7. package/templates/__tests__/tsconfig-sanity.ts +12 -0
  8. package/templates/__tests__/tsconfig.json +8 -0
  9. package/templates/checked-fetch.js +30 -0
  10. package/templates/facade.d.ts +19 -0
  11. package/templates/gitignore +170 -0
  12. package/templates/init-tests/test-jest-new-worker.js +23 -0
  13. package/templates/init-tests/test-vitest-new-worker.js +24 -0
  14. package/templates/init-tests/test-vitest-new-worker.ts +25 -0
  15. package/templates/middleware/common.ts +67 -0
  16. package/templates/middleware/loader-modules.ts +134 -0
  17. package/templates/middleware/loader-sw.ts +229 -0
  18. package/templates/middleware/middleware-ensure-req-body-drained.ts +18 -0
  19. package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
  20. package/templates/middleware/middleware-mock-analytics-engine.d.ts +3 -0
  21. package/templates/middleware/middleware-mock-analytics-engine.ts +30 -0
  22. package/templates/middleware/middleware-patch-console-prefix.d.ts +3 -0
  23. package/templates/middleware/middleware-patch-console-prefix.ts +21 -0
  24. package/templates/middleware/middleware-pretty-error.ts +40 -0
  25. package/templates/middleware/middleware-scheduled.ts +29 -0
  26. package/templates/middleware/middleware-serve-static-assets.d.ts +6 -0
  27. package/templates/middleware/middleware-serve-static-assets.ts +56 -0
  28. package/templates/modules-watch-stub.js +4 -0
  29. package/templates/new-worker-scheduled.js +17 -0
  30. package/templates/new-worker-scheduled.ts +32 -0
  31. package/templates/new-worker.js +4 -4
  32. package/templates/new-worker.ts +22 -4
  33. package/templates/no-op-worker.js +10 -0
  34. package/templates/pages-dev-pipeline.ts +32 -0
  35. package/templates/pages-dev-util.ts +55 -0
  36. package/templates/pages-shim.ts +9 -0
  37. package/templates/pages-template-plugin.ts +190 -0
  38. package/templates/pages-template-worker.ts +198 -0
  39. package/templates/startDevWorker/InspectorProxyWorker.ts +664 -0
  40. package/templates/startDevWorker/ProxyWorker.ts +336 -0
  41. package/templates/tsconfig-sanity.ts +11 -0
  42. package/templates/tsconfig.init.json +22 -0
  43. package/templates/tsconfig.json +8 -0
  44. package/wrangler-dist/InspectorProxyWorker.js +464 -0
  45. package/wrangler-dist/InspectorProxyWorker.js.map +6 -0
  46. package/wrangler-dist/ProxyWorker.js +241 -0
  47. package/wrangler-dist/ProxyWorker.js.map +6 -0
  48. package/wrangler-dist/cli.d.ts +26730 -0
  49. package/wrangler-dist/cli.js +165374 -118597
  50. package/import_meta_url.js +0 -3
  51. package/miniflare-config-stubs/.env.empty +0 -0
  52. package/miniflare-config-stubs/package.empty.json +0 -1
  53. package/miniflare-config-stubs/wrangler.empty.toml +0 -0
  54. package/pages/functions/buildWorker.ts +0 -62
  55. package/pages/functions/filepath-routing.test.ts +0 -47
  56. package/pages/functions/filepath-routing.ts +0 -231
  57. package/pages/functions/identifiers.ts +0 -78
  58. package/pages/functions/routes.ts +0 -160
  59. package/pages/functions/template-worker.ts +0 -136
  60. package/src/__tests__/dev.test.tsx +0 -71
  61. package/src/__tests__/helpers/clipboardy-mock.js +0 -4
  62. package/src/__tests__/helpers/cmd-shim.d.ts +0 -11
  63. package/src/__tests__/helpers/mock-account-id.ts +0 -30
  64. package/src/__tests__/helpers/mock-bin.ts +0 -33
  65. package/src/__tests__/helpers/mock-cfetch.ts +0 -207
  66. package/src/__tests__/helpers/mock-console.ts +0 -56
  67. package/src/__tests__/helpers/mock-dialogs.ts +0 -65
  68. package/src/__tests__/helpers/mock-kv.ts +0 -40
  69. package/src/__tests__/helpers/mock-user.ts +0 -27
  70. package/src/__tests__/helpers/run-in-tmp.ts +0 -29
  71. package/src/__tests__/helpers/run-wrangler.ts +0 -14
  72. package/src/__tests__/index.test.ts +0 -543
  73. package/src/__tests__/jest.setup.ts +0 -37
  74. package/src/__tests__/kv.test.ts +0 -1139
  75. package/src/__tests__/logout.test.ts +0 -50
  76. package/src/__tests__/package-manager.test.ts +0 -206
  77. package/src/__tests__/publish.test.ts +0 -1222
  78. package/src/__tests__/secret.test.ts +0 -210
  79. package/src/__tests__/whoami.test.tsx +0 -86
  80. package/src/api/form_data.ts +0 -134
  81. package/src/api/preview.ts +0 -128
  82. package/src/api/worker.ts +0 -155
  83. package/src/cfetch/index.ts +0 -102
  84. package/src/cfetch/internal.ts +0 -101
  85. package/src/cli.ts +0 -9
  86. package/src/config.ts +0 -641
  87. package/src/dev.tsx +0 -834
  88. package/src/dialogs.tsx +0 -77
  89. package/src/index.tsx +0 -2101
  90. package/src/inspect.ts +0 -596
  91. package/src/kv.tsx +0 -284
  92. package/src/module-collection.ts +0 -63
  93. package/src/package-manager.ts +0 -120
  94. package/src/pages.tsx +0 -1046
  95. package/src/paths.ts +0 -26
  96. package/src/proxy.ts +0 -370
  97. package/src/publish.ts +0 -410
  98. package/src/sites.tsx +0 -240
  99. package/src/tail.tsx +0 -73
  100. package/src/user.tsx +0 -1019
  101. package/src/whoami.tsx +0 -69
  102. package/templates/static-asset-facade.js +0 -47
  103. package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
  104. package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
  105. package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
  106. package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
  107. package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
  108. package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
  109. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
  110. package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
  111. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
  112. package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
  113. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
  114. package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
  115. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
  116. package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
  117. package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
  118. package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
  119. package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
  120. package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
  121. package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
  122. package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
  123. package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
  124. package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
  125. package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
  126. package/vendor/wrangler-mime/CHANGELOG.md +0 -289
  127. package/vendor/wrangler-mime/LICENSE +0 -21
  128. package/vendor/wrangler-mime/Mime.js +0 -97
  129. package/vendor/wrangler-mime/README.md +0 -187
  130. package/vendor/wrangler-mime/cli.js +0 -46
  131. package/vendor/wrangler-mime/index.js +0 -4
  132. package/vendor/wrangler-mime/lite.js +0 -4
  133. package/vendor/wrangler-mime/package.json +0 -52
  134. package/vendor/wrangler-mime/types/other.js +0 -1
  135. package/vendor/wrangler-mime/types/standard.js +0 -1
  136. package/wrangler-dist/cli.js.map +0 -7
package/src/index.tsx DELETED
@@ -1,2101 +0,0 @@
1
- import * as fs from "node:fs";
2
- import { readFile, writeFile, mkdir } from "node:fs/promises";
3
- import path from "node:path";
4
- import { setTimeout } from "node:timers/promises";
5
- import TOML from "@iarna/toml";
6
- import { findUp } from "find-up";
7
- import { render } from "ink";
8
- import React from "react";
9
- import onExit from "signal-exit";
10
- import makeCLI from "yargs";
11
- import { version as wranglerVersion } from "../package.json";
12
- import { toFormData } from "./api/form_data";
13
- import { fetchResult } from "./cfetch";
14
- import { normaliseAndValidateEnvironmentsConfig } from "./config";
15
- import Dev from "./dev";
16
- import { confirm, prompt } from "./dialogs";
17
- import {
18
- getNamespaceId,
19
- listNamespaces,
20
- listNamespaceKeys,
21
- putKeyValue,
22
- putBulkKeyValue,
23
- deleteBulkKeyValue,
24
- createNamespace,
25
- isValidNamespaceBinding,
26
- getKeyValue,
27
- } from "./kv";
28
- import { getPackageManager } from "./package-manager";
29
- import { pages } from "./pages";
30
- import publish from "./publish";
31
- import { getAssetPaths } from "./sites";
32
- import { createTail } from "./tail";
33
- import {
34
- login,
35
- logout,
36
- listScopes,
37
- initialise as initialiseUserConfig,
38
- loginOrRefreshIfRequired,
39
- getAccountId,
40
- validateScopeKeys,
41
- } from "./user";
42
- import { whoami } from "./whoami";
43
-
44
- import type { Config } from "./config";
45
- import type Yargs from "yargs";
46
-
47
- const resetColor = "\x1b[0m";
48
- const fgGreenColor = "\x1b[32m";
49
-
50
- async function readConfig(configPath?: string): Promise<Config> {
51
- const config: Config = {};
52
- if (!configPath) {
53
- configPath = await findUp("wrangler.toml");
54
- // TODO - terminate this early instead of going all the way to the root
55
- }
56
-
57
- if (configPath) {
58
- const tml: string = await readFile(configPath, "utf-8");
59
- const parsed = TOML.parse(tml) as Config;
60
- Object.assign(config, parsed);
61
- }
62
-
63
- normaliseAndValidateEnvironmentsConfig(config);
64
-
65
- if ("experimental_services" in config) {
66
- console.warn(
67
- "The experimental_services field is only for cloudflare internal usage right now, and is subject to change. Please do not use this on production projects"
68
- );
69
- }
70
-
71
- // todo: validate, add defaults
72
- // let's just do some basics for now
73
-
74
- // @ts-expect-error we're being sneaky here for now
75
- config.__path__ = configPath;
76
-
77
- return config;
78
- }
79
-
80
- // a helper to demand one of a set of options
81
- // via https://github.com/yargs/yargs/issues/1093#issuecomment-491299261
82
- function demandOneOfOption(...options: string[]) {
83
- return function (argv: Yargs.Arguments) {
84
- const count = options.filter((option) => argv[option]).length;
85
- const lastOption = options.pop();
86
-
87
- if (count === 0) {
88
- throw new CommandLineArgsError(
89
- `Exactly one of the arguments ${options.join(
90
- ", "
91
- )} and ${lastOption} is required`
92
- );
93
- } else if (count > 1) {
94
- throw new CommandLineArgsError(
95
- `Arguments ${options.join(
96
- ", "
97
- )} and ${lastOption} are mutually exclusive`
98
- );
99
- }
100
-
101
- return true;
102
- };
103
- }
104
-
105
- class CommandLineArgsError extends Error {}
106
- class DeprecationError extends Error {}
107
- class NotImplementedError extends Error {}
108
-
109
- export async function main(argv: string[]): Promise<void> {
110
- const wrangler = makeCLI(argv)
111
- // We handle errors ourselves in a try-catch around `yargs.parse`.
112
- // If you want the "help info" to be displayed then throw an instance of `CommandLineArgsError`.
113
- // Otherwise we just log the error that was thrown without any "help info".
114
- .showHelpOnFail(false)
115
- .fail((msg, error) => {
116
- if (!error) {
117
- // If there is only a `msg` then this came from yargs own validation, so wrap in a `CommandLineArgsError`.
118
- error = new CommandLineArgsError(msg);
119
- }
120
- throw error;
121
- })
122
- .scriptName("wrangler")
123
- .wrap(null);
124
-
125
- // the default is to simply print the help menu
126
- wrangler.command(
127
- ["*"],
128
- false,
129
- () => {},
130
- (args) => {
131
- if (args._.length > 0) {
132
- throw new CommandLineArgsError(`Unknown command: ${args._}.`);
133
- } else {
134
- wrangler.showHelp("log");
135
- }
136
- }
137
- );
138
-
139
- // You will note that we use the form for all commands where we use the builder function
140
- // to define options and subcommands.
141
- // Further we return the result of this builder even though it's not completely necessary.
142
- // The reason is that it's required for type inference of the args in the handle function.
143
- // I wish we could enforce this pattern, but this comment will have to do for now.
144
- // (It's also annoying that choices[] doesn't get inferred as an enum. 🤷‍♂.)
145
-
146
- // [DEPRECATED] generate
147
- wrangler.command(
148
- // we definitely want to move away from us cloning github templates
149
- // we can do something better here, let's see
150
- "generate [name] [template]",
151
- false,
152
- (yargs) => {
153
- return yargs
154
- .positional("name", {
155
- describe: "Name of the Workers project",
156
- default: "worker",
157
- })
158
- .positional("template", {
159
- describe: "a link to a GitHub template",
160
- default: "https://github.com/cloudflare/worker-template",
161
- });
162
- },
163
- () => {
164
- // "👯 [DEPRECATED]. Scaffold a Cloudflare Workers project from a public GitHub repository.",
165
- throw new DeprecationError(
166
- "`wrangler generate` has been deprecated, please refer to TODO://some/path for alternatives"
167
- );
168
- }
169
- );
170
-
171
- // init
172
- wrangler.command(
173
- "init [name]",
174
- "📥 Create a wrangler.toml configuration file",
175
- (yargs) => {
176
- return yargs.positional("name", {
177
- describe: "The name of your worker.",
178
- type: "string",
179
- });
180
- },
181
- async (args) => {
182
- if ("type" in args) {
183
- let message = "The --type option is no longer supported.";
184
- if (args.type === "webpack") {
185
- message +=
186
- "\nIf you wish to use webpack then you will need to create a custom build.";
187
- // TODO: Add a link to docs
188
- }
189
- throw new CommandLineArgsError(message);
190
- }
191
-
192
- const packageManager = await getPackageManager(process.cwd());
193
-
194
- const destination = "./wrangler.toml";
195
- if (fs.existsSync(destination)) {
196
- console.warn(`${destination} file already exists!`);
197
- const shouldContinue = await confirm(
198
- "Do you want to continue initializing this project?"
199
- );
200
- if (!shouldContinue) {
201
- return;
202
- }
203
- } else {
204
- const compatibilityDate = new Date().toISOString().substring(0, 10);
205
- try {
206
- await writeFile(
207
- destination,
208
- `compatibility_date = "${compatibilityDate}"` + "\n"
209
- );
210
- console.log(`✨ Successfully created wrangler.toml`);
211
- // TODO: suggest next steps?
212
- } catch (err) {
213
- throw new Error(
214
- `Failed to create wrangler.toml.\n${err.message ?? err}`
215
- );
216
- }
217
- }
218
-
219
- let pathToPackageJson = await findUp("package.json");
220
- if (!pathToPackageJson) {
221
- // If no package.json exists, ask to create one
222
- const shouldCreatePackageJson = await confirm(
223
- "No package.json found. Would you like to create one?"
224
- );
225
- if (shouldCreatePackageJson) {
226
- await writeFile(
227
- "./package.json",
228
- JSON.stringify(
229
- {
230
- name: "worker",
231
- version: "0.0.0",
232
- devDependencies: {
233
- wrangler: wranglerVersion,
234
- },
235
- private: true,
236
- },
237
- null,
238
- " "
239
- ) + "\n"
240
- );
241
- await packageManager.install();
242
- console.log(`✨ Created package.json`);
243
- pathToPackageJson = path.join(process.cwd(), "package.json");
244
- } else {
245
- return;
246
- }
247
- } else {
248
- // If package.json exists and wrangler isn't installed,
249
- // then ask to add wrangler to devDependencies
250
- const packageJson = JSON.parse(
251
- await readFile(pathToPackageJson, "utf-8")
252
- );
253
- if (
254
- !(
255
- packageJson.devDependencies?.wrangler ||
256
- packageJson.dependencies?.wrangler
257
- )
258
- ) {
259
- const shouldInstall = await confirm(
260
- "Would you like to install wrangler into your package.json?"
261
- );
262
- if (shouldInstall) {
263
- await packageManager.addDevDeps(`wrangler@${wranglerVersion}`);
264
- console.log(`✨ Installed wrangler`);
265
- }
266
- }
267
- }
268
-
269
- let isTypescriptProject = false;
270
- let pathToTSConfig = await findUp("tsconfig.json");
271
- if (!pathToTSConfig) {
272
- // If there's no tsconfig, offer to create one
273
- // and install @cloudflare/workers-types
274
- if (await confirm("Would you like to use TypeScript?")) {
275
- isTypescriptProject = true;
276
- await writeFile(
277
- "./tsconfig.json",
278
- JSON.stringify(
279
- {
280
- compilerOptions: {
281
- target: "es2021",
282
- module: "es2022",
283
- moduleResolution: "node",
284
- allowJs: true,
285
- allowSyntheticDefaultImports: true,
286
- isolatedModules: true,
287
- noEmit: true,
288
- lib: ["es2021"],
289
- resolveJsonModule: true,
290
- types: ["@cloudflare/workers-types"],
291
- },
292
- },
293
- null,
294
- " "
295
- ) + "\n"
296
- );
297
- await packageManager.addDevDeps(
298
- "@cloudflare/workers-types",
299
- "typescript"
300
- );
301
-
302
- console.log(
303
- `✨ Created tsconfig.json, installed @cloudflare/workers-types into devDependencies`
304
- );
305
- pathToTSConfig = path.join(process.cwd(), "tsconfig.json");
306
- }
307
- } else {
308
- isTypescriptProject = true;
309
- // If there's a tsconfig, check if @cloudflare/workers-types
310
- // is already installed, and offer to install it if not
311
- const packageJson = JSON.parse(
312
- await readFile(pathToPackageJson, "utf-8")
313
- );
314
- if (
315
- !(
316
- packageJson.devDependencies?.["@cloudflare/workers-types"] ||
317
- packageJson.dependencies?.["@cloudflare/workers-types"]
318
- )
319
- ) {
320
- const shouldInstall = await confirm(
321
- "Would you like to install the type definitions for Workers into your package.json?"
322
- );
323
- if (shouldInstall) {
324
- await packageManager.addDevDeps("@cloudflare/workers-types");
325
- // We don't update the tsconfig.json because
326
- // it could be complicated in existing projects
327
- // and we don't want to break them. Instead, we simply
328
- // tell the user that they need to update their tsconfig.json
329
- console.log(
330
- `✨ Installed @cloudflare/workers-types.\nPlease add "@cloudflare/workers-types" to compilerOptions.types in your tsconfig.json`
331
- );
332
- }
333
- }
334
- }
335
-
336
- if (isTypescriptProject) {
337
- if (!fs.existsSync("./src/index.ts")) {
338
- const shouldCreateSource = await confirm(
339
- `Would you like to create a Worker at src/index.ts?`
340
- );
341
- if (shouldCreateSource) {
342
- await mkdir("./src", { recursive: true });
343
- await writeFile(
344
- "./src/index.ts",
345
- await readFile(
346
- path.join(__dirname, "../templates/new-worker.ts"),
347
- "utf-8"
348
- )
349
- );
350
- console.log(`✨ Created src/index.ts`);
351
- }
352
- }
353
- } else {
354
- if (!fs.existsSync("./src/index.js")) {
355
- const shouldCreateSource = await confirm(
356
- `Would you like to create a Worker at src/index.js?`
357
- );
358
- if (shouldCreateSource) {
359
- await mkdir("./src", { recursive: true });
360
- await writeFile(
361
- path.join("./src/index.js"),
362
- await readFile(
363
- path.join(__dirname, "../templates/new-worker.js"),
364
- "utf-8"
365
- )
366
- );
367
- console.log(`✨ Created src/index.js`);
368
- }
369
- }
370
- }
371
- }
372
- );
373
-
374
- // build
375
- wrangler.command(
376
- "build",
377
- false,
378
- (yargs) => {
379
- return yargs.option("env", {
380
- describe: "Perform on a specific environment",
381
- });
382
- },
383
- () => {
384
- // "[DEPRECATED] 🦀 Build your project (if applicable)",
385
- throw new DeprecationError(
386
- "`wrangler build` has been deprecated, please refer to TODO://some/path for alternatives"
387
- );
388
- }
389
- );
390
-
391
- // login
392
- wrangler.command(
393
- // this needs scopes as an option?
394
- "login",
395
- false, // we don't need to show this in the menu
396
- // "🔓 Login to Cloudflare",
397
- (yargs) => {
398
- // TODO: This needs some copy editing
399
- // I mean, this entire app does, but this too.
400
- return yargs
401
- .option("scopes-list", {
402
- describe: "list all the available OAuth scopes with descriptions.",
403
- })
404
- .option("scopes", {
405
- describe: "allows to choose your set of OAuth scopes.",
406
- array: true,
407
- type: "string",
408
- });
409
-
410
- // TODO: scopes
411
- },
412
- async (args) => {
413
- if (args["scopes-list"]) {
414
- listScopes();
415
- return;
416
- }
417
- if (args.scopes) {
418
- if (args.scopes.length === 0) {
419
- // don't allow no scopes to be passed, that would be weird
420
- listScopes();
421
- return;
422
- }
423
- if (!validateScopeKeys(args.scopes)) {
424
- throw new CommandLineArgsError(
425
- `One of ${args.scopes} is not a valid authentication scope. Run "wrangler login --list-scopes" to see the valid scopes.`
426
- );
427
- }
428
- await login({ scopes: args.scopes });
429
- return;
430
- }
431
- await login();
432
-
433
- // TODO: would be nice if it optionally saved login
434
- // credentials inside node_modules/.cache or something
435
- // this way you could have multiple users on a single machine
436
- }
437
- );
438
-
439
- // logout
440
- wrangler.command(
441
- // this needs scopes as an option?
442
- "logout",
443
- false, // we don't need to show this in the menu
444
- // "🚪 Logout from Cloudflare",
445
- () => {},
446
- async () => {
447
- await logout();
448
- }
449
- );
450
-
451
- // whoami
452
- wrangler.command(
453
- "whoami",
454
- "🕵️ Retrieve your user info and test your auth config",
455
- () => {},
456
- async () => {
457
- await whoami();
458
- }
459
- );
460
-
461
- // config
462
- wrangler.command(
463
- "config",
464
- false,
465
- () => {},
466
- () => {
467
- // "🕵️ Authenticate Wrangler with a Cloudflare API Token",
468
- throw new DeprecationError(
469
- "`wrangler config` has been deprecated, please refer to TODO://some/path for alternatives"
470
- );
471
- }
472
- );
473
-
474
- // dev
475
- wrangler.command(
476
- "dev <filename>",
477
- "👂 Start a local server for developing your worker",
478
- (yargs) => {
479
- return yargs
480
- .positional("filename", {
481
- describe: "entry point",
482
- type: "string",
483
- demandOption: true,
484
- })
485
- .option("name", {
486
- describe: "name of the script",
487
- type: "string",
488
- })
489
- .option("format", {
490
- choices: ["modules", "service-worker"] as const,
491
- describe: "Choose an entry type",
492
- })
493
- .option("env", {
494
- describe: "Perform on a specific environment",
495
- type: "string",
496
- // TODO: get choices for the toml file?
497
- })
498
- .option("compatibility-date", {
499
- describe: "Date to use for compatibility checks",
500
- type: "string",
501
- })
502
- .option("compatibility-flags", {
503
- describe: "Flags to use for compatibility checks",
504
- type: "array",
505
- alias: "compatibility-flag",
506
- })
507
- .option("latest", {
508
- describe: "Use the latest version of the worker runtime",
509
- type: "boolean",
510
- default: true,
511
- })
512
- .option("ip", {
513
- describe: "IP address to listen on",
514
- type: "string",
515
- default: "127.0.0.1",
516
- })
517
- .option("port", {
518
- describe: "Port to listen on, defaults to 8787",
519
- type: "number",
520
- default: 8787,
521
- })
522
- .option("host", {
523
- type: "string",
524
- describe:
525
- "Host to forward requests to, defaults to the zone of project",
526
- })
527
- .option("local-protocol", {
528
- default: "http",
529
- describe: "Protocol to listen to requests on, defaults to http.",
530
- choices: ["http", "https"],
531
- })
532
- .option("experimental-public", {
533
- describe: "Static assets to be served",
534
- type: "string",
535
- })
536
- .option("site", {
537
- describe: "Root folder of static assets for Workers Sites",
538
- type: "string",
539
- })
540
- .option("site-include", {
541
- describe:
542
- "Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
543
- type: "string",
544
- array: true,
545
- })
546
- .option("site-exclude", {
547
- describe:
548
- "Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
549
- type: "string",
550
- array: true,
551
- })
552
- .option("upstream-protocol", {
553
- default: "https",
554
- describe:
555
- "Protocol to forward requests to host on, defaults to https.",
556
- choices: ["http", "https"],
557
- })
558
- .option("jsx-factory", {
559
- describe: "The function that is called for each JSX element",
560
- type: "string",
561
- })
562
- .option("jsx-fragment", {
563
- describe: "The function that is called for each JSX fragment",
564
- type: "string",
565
- })
566
- .option("experimental-enable-local-persistence", {
567
- describe: "Enable persistence for this session (only for local mode)",
568
- type: "boolean",
569
- });
570
- },
571
- async (args) => {
572
- const { filename, format } = args;
573
- const config = args.config as Config;
574
-
575
- if (args["experimental-public"]) {
576
- console.warn(
577
- "🚨 The --experimental-public field is experimental and will change in the future."
578
- );
579
- }
580
-
581
- if (args.public) {
582
- throw new Error(
583
- "🚨 The --public field has been renamed to --experimental-public, and will change behaviour in the future."
584
- );
585
- }
586
-
587
- if (config.site?.["entry-point"]) {
588
- console.warn(
589
- "Deprecation notice: The `site.entry-point` config field is no longer used.\n" +
590
- "The entry-point is specified via the command line (e.g. `wrangler dev path/to/script`).\n" +
591
- "Please remove the `site.entry-point` field from the `wrangler.toml` file."
592
- );
593
- }
594
-
595
- if (!args.local) {
596
- // -- snip, extract --
597
- const loggedIn = await loginOrRefreshIfRequired();
598
- if (!loggedIn) {
599
- // didn't login, let's just quit
600
- console.log("Did not login, quitting...");
601
- return;
602
- }
603
-
604
- if (!config.account_id) {
605
- config.account_id = await getAccountId();
606
- if (!config.account_id) {
607
- throw new Error("No account id found, quitting...");
608
- }
609
- }
610
- // -- snip, end --
611
- }
612
-
613
- const environments = config.env ?? {};
614
- const envRootObj = args.env ? environments[args.env] || {} : config;
615
-
616
- // TODO: this error shouldn't actually happen,
617
- // but we haven't fixed it internally yet
618
- if ("durable_objects" in envRootObj) {
619
- if (!(args.name || config.name)) {
620
- console.warn(
621
- 'A worker with durable objects needs to be named, or it may not work as expected. Add a "name" into wrangler.toml, or pass it in the command line with --name.'
622
- );
623
- }
624
- // TODO: if not already published, publish a draft worker
625
- }
626
-
627
- const { waitUntilExit } = render(
628
- <Dev
629
- name={args.name || config.name}
630
- entry={path.relative(process.cwd(), filename)}
631
- env={args.env}
632
- buildCommand={config.build || {}}
633
- format={format}
634
- initialMode={args.local ? "local" : "remote"}
635
- jsxFactory={args["jsx-factory"] || envRootObj?.jsx_factory}
636
- jsxFragment={args["jsx-fragment"] || envRootObj?.jsx_fragment}
637
- enableLocalPersistence={
638
- args["experimental-enable-local-persistence"] || false
639
- }
640
- accountId={config.account_id}
641
- assetPaths={getAssetPaths(
642
- config,
643
- args.site,
644
- args.siteInclude,
645
- args.siteExclude
646
- )}
647
- port={args.port || config.dev?.port}
648
- public={args["experimental-public"]}
649
- compatibilityDate={
650
- args["compatibility-date"] ||
651
- config.compatibility_date ||
652
- new Date().toISOString().substring(0, 10)
653
- }
654
- compatibilityFlags={
655
- (args["compatibility-flags"] as string[]) ||
656
- config.compatibility_flags
657
- }
658
- usageModel={config.usage_model}
659
- bindings={{
660
- kv_namespaces: envRootObj.kv_namespaces?.map(
661
- ({ binding, preview_id, id: _id }) => {
662
- // In `dev`, we make folks use a separate kv namespace called
663
- // `preview_id` instead of `id` so that they don't
664
- // break production data. So here we check that a `preview_id`
665
- // has actually been configured.
666
- // This whole block of code will be obsoleted in the future
667
- // when we have copy-on-write for previews on edge workers.
668
- if (!preview_id) {
669
- // TODO: This error has to be a _lot_ better, ideally just asking
670
- // to create a preview namespace for the user automatically
671
- throw new Error(
672
- `In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create <name> --preview" and add its id as preview_id to the kv_namespace "${binding}" in your wrangler.toml`
673
- ); // Ugh, I really don't like this message very much
674
- }
675
- return {
676
- binding,
677
- id: preview_id,
678
- };
679
- }
680
- ),
681
- vars: envRootObj.vars,
682
- durable_objects: envRootObj.durable_objects,
683
- services: envRootObj.experimental_services,
684
- }}
685
- />
686
- );
687
- await waitUntilExit();
688
- }
689
- );
690
-
691
- // publish
692
- wrangler.command(
693
- "publish [script]",
694
- "🆙 Publish your Worker to Cloudflare.",
695
- (yargs) => {
696
- return yargs
697
- .option("env", {
698
- type: "string",
699
- describe: "Perform on a specific environment",
700
- })
701
- .positional("script", {
702
- describe: "script to upload",
703
- type: "string",
704
- })
705
- .option("name", {
706
- describe: "name to use when uploading",
707
- type: "string",
708
- })
709
- .option("compatibility-date", {
710
- describe: "Date to use for compatibility checks",
711
- type: "string",
712
- })
713
- .option("compatibility-flags", {
714
- describe: "Flags to use for compatibility checks",
715
- type: "array",
716
- alias: "compatibility-flag",
717
- })
718
- .option("latest", {
719
- describe: "Use the latest version of the worker runtime",
720
- type: "boolean",
721
- default: false,
722
- })
723
- .option("experimental-public", {
724
- describe: "Static assets to be served",
725
- type: "string",
726
- })
727
- .option("site", {
728
- describe: "Root folder of static assets for Workers Sites",
729
- type: "string",
730
- })
731
- .option("site-include", {
732
- describe:
733
- "Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded.",
734
- type: "string",
735
- array: true,
736
- })
737
- .option("site-exclude", {
738
- describe:
739
- "Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded.",
740
- type: "string",
741
- array: true,
742
- })
743
- .option("triggers", {
744
- describe: "cron schedules to attach",
745
- alias: ["schedule", "schedules"],
746
- type: "array",
747
- })
748
- .option("routes", {
749
- describe: "routes to upload",
750
- alias: "route",
751
- type: "array",
752
- })
753
- .option("services", {
754
- describe: "experimental support for services",
755
- type: "boolean",
756
- default: "false",
757
- hidden: true,
758
- })
759
- .option("jsx-factory", {
760
- describe: "The function that is called for each JSX element",
761
- type: "string",
762
- })
763
- .option("jsx-fragment", {
764
- describe: "The function that is called for each JSX fragment",
765
- type: "string",
766
- });
767
- },
768
- async (args) => {
769
- if (args.local) {
770
- throw new NotImplementedError(
771
- "🚫 Local publishing is not yet supported"
772
- );
773
- }
774
-
775
- if (args["experimental-public"]) {
776
- console.warn(
777
- "🚨 The --experimental-public field is experimental and will change in the future."
778
- );
779
- }
780
- if (args.public) {
781
- throw new Error(
782
- "🚨 The --public field has been renamed to --experimental-public, and will change behaviour in the future."
783
- );
784
- }
785
-
786
- const config = args.config as Config;
787
-
788
- if (args.latest) {
789
- console.warn(
790
- "⚠️ Using the latest version of the Workers runtime. To silence this warning, please choose a specific version of the runtime with --compatibility-date, or add a compatibility_date to your wrangler.toml.\n"
791
- );
792
- }
793
-
794
- if (!args.local) {
795
- // -- snip, extract --
796
- const loggedIn = await loginOrRefreshIfRequired();
797
- if (!loggedIn) {
798
- // didn't login, let's just quit
799
- console.log("Did not login, quitting...");
800
- return;
801
- }
802
-
803
- if (!config.account_id) {
804
- config.account_id = await getAccountId();
805
- if (!config.account_id) {
806
- throw new Error("No account id found, quitting...");
807
- }
808
- }
809
- // -- snip, end --
810
- }
811
-
812
- const assetPaths = getAssetPaths(
813
- config,
814
- args["experimental-public"] || args.site,
815
- args.siteInclude,
816
- args.siteExclude
817
- );
818
- await publish({
819
- config: args.config as Config,
820
- name: args.name,
821
- script: args.script,
822
- env: args.env,
823
- compatibilityDate: args.latest
824
- ? new Date().toISOString().substring(0, 10)
825
- : args["compatibility-date"],
826
- compatibilityFlags: args["compatibility-flags"] as string[],
827
- triggers: args.triggers,
828
- jsxFactory: args["jsx-factory"],
829
- jsxFragment: args["jsx-fragment"],
830
- routes: args.routes,
831
- assetPaths,
832
- format: undefined, // TODO: add args for this
833
- legacyEnv: undefined, // TODO: get this from somewhere... config?
834
- experimentalPublic: args["experimental-public"] !== undefined,
835
- });
836
- }
837
- );
838
-
839
- // tail
840
- wrangler.command(
841
- "tail [name]",
842
- "🦚 Starts a log tailing session for a deployed Worker.",
843
- (yargs) => {
844
- return (
845
- yargs
846
- .positional("name", {
847
- describe: "name of the worker",
848
- type: "string",
849
- })
850
- // TODO: auto-detect if this should be json or pretty based on atty
851
- .option("format", {
852
- default: "json",
853
- choices: ["json", "pretty"],
854
- describe: "The format of log entries",
855
- })
856
- .option("status", {
857
- choices: ["ok", "error", "canceled"],
858
- describe: "Filter by invocation status",
859
- })
860
- .option("header", {
861
- type: "string",
862
- describe: "Filter by HTTP header",
863
- })
864
- .option("method", {
865
- type: "string",
866
- describe: "Filter by HTTP method",
867
- })
868
- .option("sampling-rate", {
869
- type: "number",
870
- describe: "Adds a percentage of requests to log sampling rate",
871
- })
872
- .option("search", {
873
- type: "string",
874
- describe: "Filter by a text match in console.log messages",
875
- })
876
- .option("env", {
877
- type: "string",
878
- describe: "Perform on a specific environment",
879
- })
880
- );
881
- // TODO: filter by client ip, which can be 'self' or an ip address
882
- },
883
- async (args) => {
884
- if (args.local) {
885
- throw new NotImplementedError(
886
- `local mode is not yet supported for this command`
887
- );
888
- }
889
-
890
- const config = args.config as Config;
891
-
892
- if (!(args.name || config.name)) {
893
- throw new Error("Missing script name");
894
- }
895
- const scriptName = `${args.name || config.name}${
896
- args.env ? `-${args.env}` : ""
897
- }`;
898
-
899
- // -- snip, extract --
900
- const loggedIn = await loginOrRefreshIfRequired();
901
- if (!loggedIn) {
902
- // didn't login, let's just quit
903
- console.log("Did not login, quitting...");
904
- return;
905
- }
906
-
907
- if (!config.account_id) {
908
- config.account_id = await getAccountId();
909
- if (!config.account_id) {
910
- throw new Error("No account id found, quitting...");
911
- }
912
- }
913
- // -- snip, end --
914
-
915
- const accountId = config.account_id;
916
-
917
- const filters = {
918
- status: args.status as "ok" | "error" | "canceled",
919
- header: args.header,
920
- method: args.method,
921
- "sampling-rate": args["sampling-rate"],
922
- search: args.search,
923
- };
924
-
925
- const { tail, expiration, /* sendHeartbeat, */ deleteTail } =
926
- await createTail(accountId, scriptName, filters);
927
-
928
- console.log(
929
- `successfully created tail, expires at ${expiration.toLocaleString()}`
930
- );
931
-
932
- onExit(async () => {
933
- tail.terminate();
934
- await deleteTail();
935
- });
936
-
937
- tail.on("message", (data) => {
938
- console.log(JSON.stringify(JSON.parse(data.toString()), null, " "));
939
- });
940
-
941
- while (tail.readyState !== tail.OPEN) {
942
- switch (tail.readyState) {
943
- case tail.CONNECTING:
944
- await setTimeout(1000);
945
- break;
946
- case tail.CLOSING:
947
- await setTimeout(1000);
948
- break;
949
- case tail.CLOSED:
950
- process.exit(1);
951
- }
952
- }
953
-
954
- console.log(`Connected to ${scriptName}, waiting for logs...`);
955
- }
956
- );
957
-
958
- // preview
959
- wrangler.command(
960
- "preview [method] [body]",
961
- false,
962
- (yargs) => {
963
- return yargs
964
- .positional("method", {
965
- describe: "Type of request to preview your worker",
966
- choices: ["GET", "POST"],
967
- default: ["GET"],
968
- })
969
- .positional("body", {
970
- type: "string",
971
- describe: "Body string to post to your preview worker request.",
972
- default: "Null",
973
- })
974
- .option("env", {
975
- type: "string",
976
- describe: "Perform on a specific environment",
977
- })
978
- .option("watch", {
979
- default: true,
980
- describe: "Enable live preview",
981
- type: "boolean",
982
- });
983
- },
984
- () => {
985
- // "🔬 [DEPRECATED] Preview your code temporarily on https://cloudflareworkers.com"
986
- throw new DeprecationError(
987
- "`wrangler preview` has been deprecated, please refer to TODO://some/path for alternatives"
988
- );
989
- }
990
- );
991
-
992
- // route
993
- wrangler.command(
994
- "route",
995
- false, // I think we want to hide this command
996
- // "➡️ List or delete worker routes",
997
- (routeYargs) => {
998
- return routeYargs
999
- .command(
1000
- "list",
1001
- "List a route associated with a zone",
1002
- (yargs) => {
1003
- return yargs
1004
- .option("env", {
1005
- type: "string",
1006
- describe: "Perform on a specific environment",
1007
- })
1008
- .option("zone", {
1009
- type: "string",
1010
- describe: "zone id",
1011
- })
1012
- .positional("zone", {
1013
- describe: "zone id",
1014
- type: "string",
1015
- });
1016
- },
1017
- async (args) => {
1018
- console.log(":route list", args);
1019
- // TODO: use environment (current wrangler doesn't do so?)
1020
- const zone = args.zone || (args.config as Config).zone_id;
1021
- if (!zone) {
1022
- throw new Error("missing zone id");
1023
- }
1024
-
1025
- console.log(await fetchResult(`/zones/${zone}/workers/routes`));
1026
- }
1027
- )
1028
- .command(
1029
- "delete <id>",
1030
- "Delete a route associated with a zone",
1031
- (yargs) => {
1032
- return yargs
1033
- .positional("id", {
1034
- describe: "The hash of the route ID to delete.",
1035
- type: "string",
1036
- })
1037
- .option("zone", {
1038
- type: "string",
1039
- describe: "zone id",
1040
- })
1041
- .option("env", {
1042
- type: "string",
1043
- describe: "Perform on a specific environment",
1044
- });
1045
- },
1046
- async (args) => {
1047
- console.log(":route delete", args);
1048
- // TODO: use environment (current wrangler doesn't do so?)
1049
- const zone = args.zone || (args.config as Config).zone_id;
1050
- if (!zone) {
1051
- throw new Error("missing zone id");
1052
- }
1053
-
1054
- console.log(
1055
- await fetchResult(`/zones/${zone}/workers/routes/${args.id}`, {
1056
- method: "DELETE",
1057
- })
1058
- );
1059
- }
1060
- );
1061
- }
1062
- );
1063
-
1064
- // subdomain
1065
- wrangler.command(
1066
- "subdomain [name]",
1067
- false,
1068
- // "👷 Create or change your workers.dev subdomain.",
1069
- (yargs) => {
1070
- return yargs.positional("name", { type: "string" });
1071
- },
1072
- () => {
1073
- throw new DeprecationError(
1074
- "`wrangler subdomain` has been deprecated, please refer to TODO://some/path for alternatives"
1075
- );
1076
- }
1077
- );
1078
-
1079
- // secret
1080
- wrangler.command(
1081
- "secret",
1082
- "🤫 Generate a secret that can be referenced in the worker script",
1083
- (secretYargs) => {
1084
- return secretYargs
1085
- .command(
1086
- "put <key>",
1087
- "Create or update a secret variable for a script",
1088
- (yargs) => {
1089
- return yargs
1090
- .positional("key", {
1091
- describe: "The variable name to be accessible in the script.",
1092
- type: "string",
1093
- })
1094
- .option("name", {
1095
- describe: "name of the script",
1096
- type: "string",
1097
- })
1098
- .option("env", {
1099
- type: "string",
1100
- describe:
1101
- "Binds the secret to the script of the specific environment.",
1102
- });
1103
- },
1104
- async (args) => {
1105
- const config = args.config as Config;
1106
-
1107
- // TODO: use environment (how does current wrangler do it?)
1108
- const scriptName = args.name || config.name;
1109
- if (!scriptName) {
1110
- throw new Error("Missing script name");
1111
- }
1112
-
1113
- if (args.local) {
1114
- console.warn("`wrangler secret put` is a no-op in --local mode");
1115
- }
1116
-
1117
- if (!args.local) {
1118
- // -- snip, extract --
1119
- const loggedIn = await loginOrRefreshIfRequired();
1120
- if (!loggedIn) {
1121
- // didn't login, let's just quit
1122
- console.log("Did not login, quitting...");
1123
- return;
1124
- }
1125
-
1126
- if (!config.account_id) {
1127
- config.account_id = await getAccountId();
1128
- if (!config.account_id) {
1129
- throw new Error("No account id found, quitting...");
1130
- }
1131
- }
1132
- // -- snip, end --
1133
- }
1134
-
1135
- const secretValue = await prompt(
1136
- "Enter a secret value:",
1137
- "password"
1138
- );
1139
-
1140
- if (args.local) {
1141
- return;
1142
- }
1143
-
1144
- console.log(`🌀 Creating the secret for script ${scriptName}`);
1145
-
1146
- async function submitSecret() {
1147
- return await fetchResult(
1148
- `/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/`,
1149
- {
1150
- method: "PUT",
1151
- headers: { "Content-Type": "application/json" },
1152
- body: JSON.stringify({
1153
- name: args.key,
1154
- text: secretValue,
1155
- type: "secret_text",
1156
- }),
1157
- }
1158
- );
1159
- }
1160
-
1161
- try {
1162
- await submitSecret();
1163
- } catch (e) {
1164
- if (e.code === 10007) {
1165
- // upload a draft worker
1166
- await fetchResult(
1167
- `/accounts/${config.account_id}/workers/scripts/${scriptName}`,
1168
- {
1169
- method: "PUT",
1170
- body: toFormData({
1171
- name: scriptName,
1172
- main: {
1173
- name: scriptName,
1174
- content: `export default { fetch() {} }`,
1175
- type: "esm",
1176
- },
1177
- bindings: {
1178
- kv_namespaces: [],
1179
- vars: {},
1180
- durable_objects: { bindings: [] },
1181
- },
1182
- modules: [],
1183
- migrations: undefined,
1184
- compatibility_date: undefined,
1185
- compatibility_flags: undefined,
1186
- usage_model: undefined,
1187
- }),
1188
- }
1189
- );
1190
-
1191
- // and then try again
1192
- await submitSecret();
1193
- // TODO: delete the draft worker if this failed too?
1194
- }
1195
- }
1196
- console.log(`✨ Success! Uploaded secret ${args.key}`);
1197
- }
1198
- )
1199
- .command(
1200
- "delete <key>",
1201
- "Delete a secret variable from a script",
1202
- (yargs) => {
1203
- return yargs
1204
- .positional("key", {
1205
- describe: "The variable name to be accessible in the script.",
1206
- type: "string",
1207
- })
1208
- .option("name", {
1209
- describe: "name of the script",
1210
- type: "string",
1211
- })
1212
- .option("env", {
1213
- type: "string",
1214
- describe:
1215
- "Binds the secret to the script of the specific environment.",
1216
- });
1217
- },
1218
- async (args) => {
1219
- const config = args.config as Config;
1220
-
1221
- // TODO: use environment (how does current wrangler do it?)
1222
- const scriptName = args.name || config.name;
1223
- if (!scriptName) {
1224
- throw new Error("Missing script name");
1225
- }
1226
-
1227
- if (args.local) {
1228
- console.warn(
1229
- "`wrangler secret delete` is a no-op in --local mode"
1230
- );
1231
- }
1232
-
1233
- if (!args.local) {
1234
- // -- snip, extract --
1235
- const loggedIn = await loginOrRefreshIfRequired();
1236
- if (!loggedIn) {
1237
- // didn't login, let's just quit
1238
- console.log("Did not login, quitting...");
1239
- return;
1240
- }
1241
-
1242
- if (!config.account_id) {
1243
- config.account_id = await getAccountId();
1244
- if (!config.account_id) {
1245
- throw new Error("No account id found, quitting...");
1246
- }
1247
- }
1248
- // -- snip, end --
1249
- }
1250
-
1251
- if (
1252
- await confirm(
1253
- `Are you sure you want to permanently delete the variable ${args.key} on the script ${scriptName}?`
1254
- )
1255
- ) {
1256
- console.log(
1257
- `🌀 Deleting the secret ${args.key} on script ${scriptName}.`
1258
- );
1259
-
1260
- if (args.local) {
1261
- return;
1262
- }
1263
-
1264
- await fetchResult(
1265
- `/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets/${args.key}`,
1266
- { method: "DELETE" }
1267
- );
1268
- console.log(`✨ Success! Deleted secret ${args.key}`);
1269
- }
1270
- }
1271
- )
1272
- .command(
1273
- "list",
1274
- "List all secrets for a script",
1275
- (yargs) => {
1276
- return yargs
1277
- .option("name", {
1278
- describe: "name of the script",
1279
- type: "string",
1280
- })
1281
- .option("env", {
1282
- type: "string",
1283
- describe:
1284
- "Binds the secret to the script of the specific environment.",
1285
- });
1286
- },
1287
- async (args) => {
1288
- const config = args.config as Config;
1289
-
1290
- // TODO: use environment (how does current wrangler do it?)
1291
- const scriptName = args.name || config.name;
1292
- if (!scriptName) {
1293
- throw new Error("Missing script name");
1294
- }
1295
-
1296
- if (args.local) {
1297
- console.warn("`wrangler secret list` is a no-op in --local mode");
1298
- }
1299
-
1300
- if (!args.local) {
1301
- // -- snip, extract --
1302
- const loggedIn = await loginOrRefreshIfRequired();
1303
- if (!loggedIn) {
1304
- // didn't login, let's just quit
1305
- console.log("Did not login, quitting...");
1306
- return;
1307
- }
1308
-
1309
- if (!config.account_id) {
1310
- config.account_id = await getAccountId();
1311
- if (!config.account_id) {
1312
- throw new Error("No account id found, quitting...");
1313
- }
1314
- }
1315
- // -- snip, end --
1316
- }
1317
-
1318
- if (args.local) {
1319
- return;
1320
- }
1321
-
1322
- console.log(
1323
- JSON.stringify(
1324
- await fetchResult(
1325
- `/accounts/${config.account_id}/workers/scripts/${scriptName}/secrets`
1326
- ),
1327
- null,
1328
- " "
1329
- )
1330
- );
1331
- }
1332
- );
1333
- }
1334
- );
1335
-
1336
- // kv
1337
- // :namespace
1338
- wrangler.command(
1339
- "kv:namespace",
1340
- "🗂️ Interact with your Workers KV Namespaces",
1341
- (namespaceYargs) => {
1342
- return namespaceYargs
1343
- .command(
1344
- "create <namespace>",
1345
- "Create a new namespace",
1346
- (yargs) => {
1347
- return yargs
1348
- .positional("namespace", {
1349
- describe: "The name of the new namespace",
1350
- type: "string",
1351
- demandOption: true,
1352
- })
1353
- .option("env", {
1354
- type: "string",
1355
- describe: "Perform on a specific environment",
1356
- })
1357
- .option("preview", {
1358
- type: "boolean",
1359
- describe: "Interact with a preview namespace",
1360
- });
1361
- },
1362
- async (args) => {
1363
- if (args._.length > 2) {
1364
- const extraArgs = args._.slice(2).join(" ");
1365
- throw new CommandLineArgsError(
1366
- `Unexpected additional positional arguments "${extraArgs}".`
1367
- );
1368
- }
1369
-
1370
- if (!isValidNamespaceBinding(args.namespace)) {
1371
- throw new CommandLineArgsError(
1372
- `The namespace binding name "${args.namespace}" is invalid. It can only have alphanumeric and _ characters, and cannot begin with a number.`
1373
- );
1374
- }
1375
-
1376
- const config = args.config as Config;
1377
- if (!config.name) {
1378
- console.warn(
1379
- "No configured name present, using `worker` as a prefix for the title"
1380
- );
1381
- }
1382
-
1383
- const name = config.name || "worker";
1384
- const environment = args.env ? `-${args.env}` : "";
1385
- const preview = args.preview ? "_preview" : "";
1386
- const title = `${name}${environment}-${args.namespace}${preview}`;
1387
-
1388
- if (args.local) {
1389
- const { Miniflare } = await import("miniflare");
1390
- const mf = new Miniflare({
1391
- kvPersist: (args.kvPersist as string) || true,
1392
- // TODO: these options shouldn't be required
1393
- script: ` `, // has to be a string with at least one char
1394
- });
1395
- await mf.getKVNamespace(title); // this should "create" the namespace
1396
- console.log(`✨ Success! Created KV namespace ${title}`);
1397
- } else {
1398
- // -- snip, extract --
1399
- const loggedIn = await loginOrRefreshIfRequired();
1400
- if (!loggedIn) {
1401
- // didn't login, let's just quit
1402
- console.log("Did not login, quitting...");
1403
- return;
1404
- }
1405
-
1406
- if (!config.account_id) {
1407
- config.account_id = await getAccountId();
1408
- if (!config.account_id) {
1409
- throw new Error("No account id found, quitting...");
1410
- }
1411
- }
1412
- // -- snip, end --
1413
-
1414
- // TODO: generate a binding name stripping non alphanumeric chars
1415
-
1416
- console.log(`🌀 Creating namespace with title "${title}"`);
1417
- const namespaceId = await createNamespace(
1418
- config.account_id,
1419
- title
1420
- );
1421
-
1422
- console.log("✨ Success!");
1423
- const envString = args.env ? ` under [env.${args.env}]` : "";
1424
- const previewString = args.preview ? "preview_" : "";
1425
- console.log(
1426
- `Add the following to your configuration file in your kv_namespaces array${envString}:`
1427
- );
1428
- console.log(
1429
- `{ binding = "${args.namespace}", ${previewString}id = "${namespaceId}" }`
1430
- );
1431
-
1432
- // TODO: automatically write this block to the wrangler.toml config file??
1433
- }
1434
- }
1435
- )
1436
- .command(
1437
- "list",
1438
- "Outputs a list of all KV namespaces associated with your account id.",
1439
- {},
1440
- async (args) => {
1441
- const config = args.config as Config;
1442
-
1443
- if (args.local) {
1444
- throw new NotImplementedError(
1445
- `local mode is not yet supported for this command`
1446
- );
1447
- } else {
1448
- // -- snip, extract --
1449
- const loggedIn = await loginOrRefreshIfRequired();
1450
- if (!loggedIn) {
1451
- // didn't login, let's just quit
1452
- console.log("Did not login, quitting...");
1453
- return;
1454
- }
1455
-
1456
- if (!config.account_id) {
1457
- config.account_id = await getAccountId();
1458
- if (!config.account_id) {
1459
- throw new Error("No account id found, quitting...");
1460
- }
1461
- }
1462
- // -- snip, end --
1463
-
1464
- // TODO: we should show bindings if they exist for given ids
1465
-
1466
- console.log(
1467
- JSON.stringify(
1468
- await listNamespaces(config.account_id),
1469
- null,
1470
- " "
1471
- )
1472
- );
1473
- }
1474
- }
1475
- )
1476
- .command(
1477
- "delete",
1478
- "Deletes a given namespace.",
1479
- (yargs) => {
1480
- return yargs
1481
- .option("binding", {
1482
- type: "string",
1483
- describe: "The name of the namespace to delete",
1484
- })
1485
- .option("namespace-id", {
1486
- type: "string",
1487
- describe: "The id of the namespace to delete",
1488
- })
1489
- .check(demandOneOfOption("binding", "namespace-id"))
1490
- .option("env", {
1491
- type: "string",
1492
- describe: "Perform on a specific environment",
1493
- })
1494
- .option("preview", {
1495
- type: "boolean",
1496
- describe: "Interact with a preview namespace",
1497
- });
1498
- },
1499
- async (args) => {
1500
- const config = args.config as Config;
1501
-
1502
- if (args.local) {
1503
- throw new NotImplementedError(
1504
- `local mode is not yet supported for this command`
1505
- );
1506
- } else {
1507
- let id;
1508
- try {
1509
- id = getNamespaceId(args);
1510
- } catch (e) {
1511
- throw new CommandLineArgsError(
1512
- "Not able to delete namespace.\n" + e.message
1513
- );
1514
- }
1515
-
1516
- // -- snip, extract --
1517
- const loggedIn = await loginOrRefreshIfRequired();
1518
- if (!loggedIn) {
1519
- // didn't login, let's just quit
1520
- console.log("Did not login, quitting...");
1521
- return;
1522
- }
1523
-
1524
- if (!config.account_id) {
1525
- config.account_id = await getAccountId();
1526
- if (!config.account_id) {
1527
- throw new Error("No account id found, quitting...");
1528
- }
1529
- }
1530
- // -- snip, end --
1531
-
1532
- await fetchResult<{ id: string }>(
1533
- `/accounts/${config.account_id}/storage/kv/namespaces/${id}`,
1534
- { method: "DELETE" }
1535
- );
1536
-
1537
- // TODO: recommend they remove it from wrangler.toml
1538
-
1539
- // test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
1540
- // Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
1541
- // n
1542
- // 💁 Not deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
1543
- // ➜ test-mf wrangler kv:namespace delete --namespace-id 2a7d3d8b23fc4159b5afa489d6cfd388
1544
- // Are you sure you want to delete namespace 2a7d3d8b23fc4159b5afa489d6cfd388? [y/n]
1545
- // y
1546
- // 🌀 Deleting namespace 2a7d3d8b23fc4159b5afa489d6cfd388
1547
- // ✨ Success
1548
- // ⚠️ Make sure to remove this "kv-namespace" entry from your configuration file!
1549
- // ➜ test-mf
1550
-
1551
- // TODO: do it automatically
1552
-
1553
- // TODO: delete the preview namespace as well?
1554
- }
1555
- }
1556
- );
1557
- }
1558
- );
1559
-
1560
- // :key
1561
- wrangler.command(
1562
- "kv:key",
1563
- "🔑 Individually manage Workers KV key-value pairs",
1564
- (kvKeyYargs) => {
1565
- return kvKeyYargs
1566
- .command(
1567
- "put <key> [value]",
1568
- "Writes a single key/value pair to the given namespace.",
1569
- (yargs) => {
1570
- return yargs
1571
- .positional("key", {
1572
- type: "string",
1573
- describe: "The key to write to.",
1574
- demandOption: true,
1575
- })
1576
- .positional("value", {
1577
- type: "string",
1578
- describe: "The value to write.",
1579
- })
1580
- .option("binding", {
1581
- type: "string",
1582
- describe: "The binding of the namespace to write to.",
1583
- })
1584
- .option("namespace-id", {
1585
- type: "string",
1586
- describe: "The id of the namespace to write to.",
1587
- })
1588
- .check(demandOneOfOption("binding", "namespace-id"))
1589
- .option("env", {
1590
- type: "string",
1591
- describe: "Perform on a specific environment",
1592
- })
1593
- .option("preview", {
1594
- type: "boolean",
1595
- describe: "Interact with a preview namespace",
1596
- })
1597
- .option("ttl", {
1598
- type: "number",
1599
- describe: "Time for which the entries should be visible.",
1600
- })
1601
- .option("expiration", {
1602
- type: "number",
1603
- describe:
1604
- "Time since the UNIX epoch after which the entry expires",
1605
- })
1606
- .option("path", {
1607
- type: "string",
1608
- describe: "Read value from the file at a given path.",
1609
- })
1610
- .check(demandOneOfOption("value", "path"));
1611
- },
1612
- async ({ key, ttl, expiration, ...args }) => {
1613
- const namespaceId = getNamespaceId(args);
1614
- // One of `args.path` and `args.value` must be defined
1615
- const value = args.path
1616
- ? await readFile(args.path, "utf-8")
1617
- : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1618
- args.value!;
1619
- const config = args.config as Config;
1620
-
1621
- if (args.path) {
1622
- console.log(
1623
- `writing the contents of ${args.path} to the key "${key}" on namespace ${namespaceId}`
1624
- );
1625
- } else {
1626
- console.log(
1627
- `writing the value "${value}" to key "${key}" on namespace ${namespaceId}`
1628
- );
1629
- }
1630
-
1631
- if (args.local) {
1632
- const { Miniflare } = await import("miniflare");
1633
- const mf = new Miniflare({
1634
- kvPersist: (args.kvPersist as string) || true,
1635
- // TODO: these options shouldn't be required
1636
- script: ` `, // has to be a string with at least one char
1637
- });
1638
- const ns = await mf.getKVNamespace(namespaceId);
1639
- await ns.put(key, value, { expiration, expirationTtl: ttl });
1640
- } else {
1641
- // -- snip, extract --
1642
- const loggedIn = await loginOrRefreshIfRequired();
1643
- if (!loggedIn) {
1644
- // didn't login, let's just quit
1645
- console.log("Did not login, quitting...");
1646
- return;
1647
- }
1648
-
1649
- if (!config.account_id) {
1650
- config.account_id = await getAccountId();
1651
- if (!config.account_id) {
1652
- throw new Error("No account id found, quitting...");
1653
- }
1654
- }
1655
- // -- snip, end --
1656
-
1657
- await putKeyValue(config.account_id, namespaceId, key, value, {
1658
- expiration,
1659
- expiration_ttl: ttl,
1660
- });
1661
- }
1662
- }
1663
- )
1664
- .command(
1665
- "list",
1666
- "Outputs a list of all keys in a given namespace.",
1667
- (yargs) => {
1668
- return yargs
1669
- .option("binding", {
1670
- type: "string",
1671
- describe: "The name of the namespace to list",
1672
- })
1673
- .option("namespace-id", {
1674
- type: "string",
1675
- describe: "The id of the namespace to list",
1676
- })
1677
- .check(demandOneOfOption("binding", "namespace-id"))
1678
- .option("env", {
1679
- type: "string",
1680
- describe: "Perform on a specific environment",
1681
- })
1682
- .option("preview", {
1683
- type: "boolean",
1684
- // In the case of listing keys we will default to non-preview mode
1685
- default: false,
1686
- describe: "Interact with a preview namespace",
1687
- })
1688
- .option("prefix", {
1689
- type: "string",
1690
- describe: "A prefix to filter listed keys",
1691
- });
1692
- },
1693
- async ({ prefix, ...args }) => {
1694
- // TODO: support for limit+cursor (pagination)
1695
-
1696
- const namespaceId = getNamespaceId(args);
1697
- const config = args.config as Config;
1698
-
1699
- if (args.local) {
1700
- const { Miniflare } = await import("miniflare");
1701
- const mf = new Miniflare({
1702
- kvPersist: (args.kvPersist as string) || true,
1703
- // TODO: these options shouldn't be required
1704
- script: ` `, // has to be a string with at least one char
1705
- });
1706
- const ns = await mf.getKVNamespace(namespaceId);
1707
- const listResponse = await ns.list({ prefix });
1708
- console.log(JSON.stringify(listResponse.keys, null, " ")); // TODO: paginate, collate
1709
- } else {
1710
- // -- snip, extract --
1711
- const loggedIn = await loginOrRefreshIfRequired();
1712
- if (!loggedIn) {
1713
- // didn't login, let's just quit
1714
- console.log("Did not login, quitting...");
1715
- return;
1716
- }
1717
-
1718
- if (!config.account_id) {
1719
- config.account_id = await getAccountId();
1720
- if (!config.account_id) {
1721
- throw new Error("No account id found, quitting...");
1722
- }
1723
- }
1724
- // -- snip, end --
1725
-
1726
- const results = await listNamespaceKeys(
1727
- config.account_id,
1728
- namespaceId,
1729
- prefix
1730
- );
1731
- console.log(JSON.stringify(results, undefined, 2));
1732
- }
1733
- }
1734
- )
1735
- .command(
1736
- "get <key>",
1737
- "Reads a single value by key from the given namespace.",
1738
- (yargs) => {
1739
- return yargs
1740
- .positional("key", {
1741
- describe: "The key value to get.",
1742
- type: "string",
1743
- demandOption: true,
1744
- })
1745
- .option("binding", {
1746
- type: "string",
1747
- describe: "The name of the namespace to get from",
1748
- })
1749
- .option("namespace-id", {
1750
- type: "string",
1751
- describe: "The id of the namespace to get from",
1752
- })
1753
- .check(demandOneOfOption("binding", "namespace-id"))
1754
- .option("env", {
1755
- type: "string",
1756
- describe: "Perform on a specific environment",
1757
- })
1758
- .option("preview", {
1759
- type: "boolean",
1760
- describe: "Interact with a preview namespace",
1761
- })
1762
- .option("preview", {
1763
- type: "boolean",
1764
- // In the case of getting key values we will default to non-preview mode
1765
- default: false,
1766
- describe: "Interact with a preview namespace",
1767
- });
1768
- },
1769
- async ({ key, ...args }) => {
1770
- const namespaceId = getNamespaceId(args);
1771
- const config = args.config as Config;
1772
-
1773
- if (args.local) {
1774
- const { Miniflare } = await import("miniflare");
1775
- const mf = new Miniflare({
1776
- kvPersist: (args.kvPersist as string) || true,
1777
- // TODO: these options shouldn't be required
1778
- script: ` `, // has to be a string with at least one char
1779
- });
1780
- const ns = await mf.getKVNamespace(namespaceId);
1781
- console.log(await ns.get(key));
1782
- return;
1783
- }
1784
-
1785
- if (!args.local) {
1786
- // -- snip, extract --
1787
- const loggedIn = await loginOrRefreshIfRequired();
1788
- if (!loggedIn) {
1789
- // didn't login, let's just quit
1790
- console.log("Did not login, quitting...");
1791
- return;
1792
- }
1793
-
1794
- if (!config.account_id) {
1795
- config.account_id = await getAccountId();
1796
- if (!config.account_id) {
1797
- throw new Error("No account id found, quitting...");
1798
- }
1799
- }
1800
- // -- snip, end --
1801
-
1802
- console.log(
1803
- await getKeyValue(config.account_id, namespaceId, key)
1804
- );
1805
- }
1806
- }
1807
- )
1808
- .command(
1809
- "delete <key>",
1810
- "Removes a single key value pair from the given namespace.",
1811
- (yargs) => {
1812
- return yargs
1813
- .positional("key", {
1814
- describe: "The key value to delete",
1815
- type: "string",
1816
- demandOption: true,
1817
- })
1818
- .option("binding", {
1819
- type: "string",
1820
- describe: "The name of the namespace to delete from",
1821
- })
1822
- .option("namespace-id", {
1823
- type: "string",
1824
- describe: "The id of the namespace to delete from",
1825
- })
1826
- .check(demandOneOfOption("binding", "namespace-id"))
1827
- .option("env", {
1828
- type: "string",
1829
- describe: "Perform on a specific environment",
1830
- })
1831
- .option("preview", {
1832
- type: "boolean",
1833
- describe: "Interact with a preview namespace",
1834
- });
1835
- },
1836
- async ({ key, ...args }) => {
1837
- const namespaceId = getNamespaceId(args);
1838
-
1839
- console.log(
1840
- `deleting the key "${key}" on namespace ${namespaceId}`
1841
- );
1842
-
1843
- if (args.local) {
1844
- const { Miniflare } = await import("miniflare");
1845
- const mf = new Miniflare({
1846
- kvPersist: (args.kvPersist as string) || true,
1847
- // TODO: these options shouldn't be required
1848
- script: ` `, // has to be a string with at least one char
1849
- });
1850
- const ns = await mf.getKVNamespace(namespaceId);
1851
- console.log(await ns.delete(key));
1852
- return;
1853
- }
1854
-
1855
- const config = args.config as Config;
1856
-
1857
- if (!args.local) {
1858
- // -- snip, extract --
1859
- const loggedIn = await loginOrRefreshIfRequired();
1860
- if (!loggedIn) {
1861
- // didn't login, let's just quit
1862
- console.log("Did not login, quitting...");
1863
- return;
1864
- }
1865
-
1866
- if (!config.account_id) {
1867
- config.account_id = await getAccountId();
1868
- if (!config.account_id) {
1869
- throw new Error("No account id found, quitting...");
1870
- }
1871
- }
1872
- // -- snip, end --
1873
- }
1874
-
1875
- await fetchResult(
1876
- `/accounts/${config.account_id}/storage/kv/namespaces/${namespaceId}/values/${key}`,
1877
- { method: "DELETE" }
1878
- );
1879
- }
1880
- );
1881
- }
1882
- );
1883
-
1884
- // :bulk
1885
- wrangler.command(
1886
- "kv:bulk",
1887
- "💪 Interact with multiple Workers KV key-value pairs at once",
1888
- (kvBulkYargs) => {
1889
- return kvBulkYargs
1890
- .command(
1891
- "put <filename>",
1892
- "Upload multiple key-value pairs to a namespace",
1893
- (yargs) => {
1894
- return yargs
1895
- .positional("filename", {
1896
- describe: `The JSON file of key-value pairs to upload, in form [{"key":..., "value":...}"...]`,
1897
- type: "string",
1898
- demandOption: true,
1899
- })
1900
- .option("binding", {
1901
- type: "string",
1902
- describe: "The name of the namespace to put to",
1903
- })
1904
- .option("namespace-id", {
1905
- type: "string",
1906
- describe: "The id of the namespace to put to",
1907
- })
1908
- .check(demandOneOfOption("binding", "namespace-id"))
1909
- .option("env", {
1910
- type: "string",
1911
- describe: "Perform on a specific environment",
1912
- })
1913
- .option("preview", {
1914
- type: "boolean",
1915
- describe: "Interact with a preview namespace",
1916
- });
1917
- },
1918
- async ({ filename, ...args }) => {
1919
- // The simplest implementation I could think of.
1920
- // This could be made more efficient with a streaming parser/uploader
1921
- // but we'll do that in the future if needed.
1922
-
1923
- const namespaceId = getNamespaceId(args);
1924
- const config = args.config as Config;
1925
- const content = await readFile(filename, "utf-8");
1926
- let parsedContent;
1927
- try {
1928
- parsedContent = JSON.parse(content);
1929
- } catch (err) {
1930
- throw new Error(
1931
- `Could not parse json from ${filename}.\n${err.message ?? err}`
1932
- );
1933
- }
1934
-
1935
- if (args.local) {
1936
- const { Miniflare } = await import("miniflare");
1937
- const mf = new Miniflare({
1938
- kvPersist: (args.kvPersist as string) || true,
1939
- // TODO: these options shouldn't be required
1940
- script: ` `, // has to be a string with at least one char
1941
- });
1942
- const ns = await mf.getKVNamespace(namespaceId);
1943
- for (const {
1944
- key,
1945
- value,
1946
- expiration,
1947
- expiration_ttl,
1948
- } of parsedContent) {
1949
- await ns.put(key, value, {
1950
- expiration,
1951
- expirationTtl: expiration_ttl,
1952
- });
1953
- }
1954
- } else {
1955
- // -- snip, extract --
1956
- const loggedIn = await loginOrRefreshIfRequired();
1957
- if (!loggedIn) {
1958
- // didn't login, let's just quit
1959
- console.log("Did not login, quitting...");
1960
- return;
1961
- }
1962
-
1963
- if (!config.account_id) {
1964
- config.account_id = await getAccountId();
1965
- if (!config.account_id) {
1966
- throw new Error("No account id found, quitting...");
1967
- }
1968
- }
1969
- // -- snip, end --
1970
-
1971
- console.log(
1972
- await putBulkKeyValue(config.account_id, namespaceId, content)
1973
- );
1974
- }
1975
- }
1976
- )
1977
- .command(
1978
- "delete <filename>",
1979
- "Delete multiple key-value pairs from a namespace",
1980
- (yargs) => {
1981
- return yargs
1982
- .positional("filename", {
1983
- describe: `The JSON file of keys to delete, in the form ["key1", "key2", ...]`,
1984
- type: "string",
1985
- demandOption: true,
1986
- })
1987
- .option("binding", {
1988
- type: "string",
1989
- describe: "The name of the namespace to delete from",
1990
- })
1991
- .option("namespace-id", {
1992
- type: "string",
1993
- describe: "The id of the namespace to delete from",
1994
- })
1995
- .check(demandOneOfOption("binding", "namespace-id"))
1996
- .option("env", {
1997
- type: "string",
1998
- describe: "Perform on a specific environment",
1999
- })
2000
- .option("preview", {
2001
- type: "boolean",
2002
- describe: "Interact with a preview namespace",
2003
- });
2004
- },
2005
- async ({ filename, ...args }) => {
2006
- const namespaceId = getNamespaceId(args);
2007
- const config = args.config as Config;
2008
- const content = await readFile(filename, "utf-8");
2009
- let parsedContent;
2010
- try {
2011
- parsedContent = JSON.parse(content);
2012
- } catch (err) {
2013
- throw new Error(
2014
- `Could not parse json from ${filename}.\n${err.message ?? err}`
2015
- );
2016
- }
2017
-
2018
- if (args.local) {
2019
- const { Miniflare } = await import("miniflare");
2020
- const mf = new Miniflare({
2021
- kvPersist: (args.kvPersist as string) || true,
2022
- // TODO: these options shouldn't be required
2023
- script: ` `, // has to be a string with at least one char
2024
- });
2025
- const ns = await mf.getKVNamespace(namespaceId);
2026
- for (const key of parsedContent) {
2027
- await ns.delete(key);
2028
- }
2029
- } else {
2030
- // -- snip, extract --
2031
- const loggedIn = await loginOrRefreshIfRequired();
2032
- if (!loggedIn) {
2033
- // didn't login, let's just quit
2034
- console.log("Did not login, quitting...");
2035
- return;
2036
- }
2037
-
2038
- if (!config.account_id) {
2039
- config.account_id = await getAccountId();
2040
- if (!config.account_id) {
2041
- throw new Error("No account id found, quitting...");
2042
- }
2043
- }
2044
- // -- snip, end --
2045
-
2046
- console.log(
2047
- await deleteBulkKeyValue(
2048
- config.account_id,
2049
- namespaceId,
2050
- content
2051
- )
2052
- );
2053
- }
2054
- }
2055
- );
2056
- }
2057
- );
2058
-
2059
- wrangler.command("pages", "⚡️ Configure Cloudflare Pages", pages);
2060
-
2061
- wrangler
2062
- .option("config", {
2063
- alias: "c",
2064
- describe: "Path to .toml configuration file",
2065
- type: "string",
2066
- async coerce(arg) {
2067
- return await readConfig(arg);
2068
- },
2069
- })
2070
- .option("local", {
2071
- alias: "l",
2072
- describe: "Run on my machine",
2073
- type: "boolean",
2074
- default: false, // I bet this will a point of contention. We'll revisit it.
2075
- });
2076
-
2077
- wrangler.group(["config", "help", "version"], "Flags:");
2078
- wrangler.help().alias("h", "help");
2079
- wrangler.version(wranglerVersion).alias("v", "version");
2080
- wrangler.exitProcess(false);
2081
-
2082
- await initialiseUserConfig();
2083
-
2084
- try {
2085
- await wrangler.parse();
2086
- } catch (e) {
2087
- if (e instanceof CommandLineArgsError) {
2088
- wrangler.showHelp("error");
2089
- console.error(""); // Just adds a bit of space
2090
- console.error(e.message);
2091
- } else {
2092
- console.error(e.message);
2093
- console.error(""); // Just adds a bit of space
2094
- console.error(
2095
- `${fgGreenColor}%s${resetColor}`,
2096
- "If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
2097
- );
2098
- }
2099
- throw e;
2100
- }
2101
- }