wrangler 0.0.0-df6fea02 → 0.0.0-df9d5550

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "0.0.0-df6fea02",
3
+ "version": "0.0.0-df9d5550",
4
4
  "description": "Command-line interface for all things Cloudflare Workers",
5
5
  "keywords": [
6
6
  "wrangler",
@@ -1,5 +1,7 @@
1
1
  // import * as fs from "fs";
2
2
  // import * as TOML from "@iarna/toml";
3
+ import * as fs from "node:fs";
4
+ import * as TOML from "@iarna/toml";
3
5
  import { rest } from "msw";
4
6
  import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
5
7
  import { mockConsoleMethods } from "./helpers/mock-console";
@@ -26,11 +28,7 @@ describe("deployments", () => {
26
28
  ...mswSuccessUserHandlers,
27
29
  rest.get(
28
30
  "*/accounts/:accountId/workers/services/:scriptName",
29
- (request, response, context) => {
30
- expect(["undefined", "somethingElse"]).toContain(
31
- request.params.scriptName
32
- );
33
-
31
+ (_, response, context) => {
34
32
  return response.once(
35
33
  context.status(200),
36
34
  context.json({
@@ -52,6 +50,16 @@ describe("deployments", () => {
52
50
  });
53
51
 
54
52
  it("should log deployments", async () => {
53
+ fs.writeFileSync(
54
+ "./wrangler.toml",
55
+ TOML.stringify({
56
+ compatibility_date: "2022-01-12",
57
+ name: "test-script-name",
58
+ first_party_worker: true,
59
+ }),
60
+ "utf-8"
61
+ );
62
+
55
63
  await runWrangler("deployments");
56
64
  expect(std.out).toMatchInlineSnapshot(`
57
65
  "🚧\`wrangler deployments\` is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
@@ -71,7 +79,7 @@ describe("deployments", () => {
71
79
  });
72
80
 
73
81
  it("should log deployments for script with passed in name option", async () => {
74
- await runWrangler("deployments --name somethingElse");
82
+ await runWrangler("deployments --name something-else");
75
83
  expect(std.out).toMatchInlineSnapshot(`
76
84
  "🚧\`wrangler deployments\` is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose
77
85
 
@@ -88,4 +96,10 @@ describe("deployments", () => {
88
96
  🟩 Active"
89
97
  `);
90
98
  });
99
+
100
+ it("should error on missing script name", async () => {
101
+ await expect(runWrangler("deployments")).rejects.toMatchInlineSnapshot(
102
+ `[Error: Required Worker name missing. Please specify the Worker name in wrangler.toml, or pass it as an argument with \`--name\`]`
103
+ );
104
+ });
91
105
  });
@@ -31,28 +31,29 @@ describe("wrangler", () => {
31
31
  "wrangler
32
32
 
33
33
  Commands:
34
- wrangler docs 📚 Open wrangler's docs in your browser
35
- wrangler init [name] 📥 Create a wrangler.toml configuration file
36
- wrangler dev [script] 👂 Start a local server for developing your worker
37
- wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
38
- wrangler delete [script] 🗑 Delete your Worker from Cloudflare.
39
- wrangler tail [worker] 🦚 Starts a log tailing session for a published Worker.
40
- wrangler secret 🤫 Generate a secret that can be referenced in a Worker
41
- wrangler secret:bulk <json> 🗄️ Bulk upload secrets for a Worker
42
- wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
43
- wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
44
- wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
45
- wrangler pages ⚡️ Configure Cloudflare Pages
46
- wrangler queues 🇶 Configure Workers Queues
47
- wrangler r2 📦 Interact with an R2 store
48
- wrangler dispatch-namespace 📦 Interact with a dispatch namespace
49
- wrangler d1 🗄 Interact with a D1 database
50
- wrangler pubsub 📮 Interact and manage Pub/Sub Brokers
51
- wrangler login 🔓 Login to Cloudflare
52
- wrangler logout 🚪 Logout from Cloudflare
53
- wrangler whoami 🕵️ Retrieve your user info and test your auth config
54
- wrangler types 📝 Generate types from bindings & module rules in config
55
- wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
34
+ wrangler docs [command] 📚 Open wrangler's docs in your browser
35
+ wrangler init [name] 📥 Initialize a basic Worker project, including a wrangler.toml file
36
+ wrangler generate [name] [template] ✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
37
+ wrangler dev [script] 👂 Start a local server for developing your worker
38
+ wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
39
+ wrangler delete [script] 🗑 Delete your Worker from Cloudflare.
40
+ wrangler tail [worker] 🦚 Starts a log tailing session for a published Worker.
41
+ wrangler secret 🤫 Generate a secret that can be referenced in a Worker
42
+ wrangler secret:bulk <json> 🗄️ Bulk upload secrets for a Worker
43
+ wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
44
+ wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
45
+ wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
46
+ wrangler pages ⚡️ Configure Cloudflare Pages
47
+ wrangler queues 🇶 Configure Workers Queues
48
+ wrangler r2 📦 Interact with an R2 store
49
+ wrangler dispatch-namespace 📦 Interact with a dispatch namespace
50
+ wrangler d1 🗄 Interact with a D1 database
51
+ wrangler pubsub 📮 Interact and manage Pub/Sub Brokers
52
+ wrangler login 🔓 Login to Cloudflare
53
+ wrangler logout 🚪 Logout from Cloudflare
54
+ wrangler whoami 🕵️ Retrieve your user info and test your auth config
55
+ wrangler types 📝 Generate types from bindings & module rules in config
56
+ wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
56
57
 
57
58
  Flags:
58
59
  -c, --config Path to .toml configuration file [string]
@@ -78,28 +79,29 @@ describe("wrangler", () => {
78
79
  wrangler
79
80
 
80
81
  Commands:
81
- wrangler docs 📚 Open wrangler's docs in your browser
82
- wrangler init [name] 📥 Create a wrangler.toml configuration file
83
- wrangler dev [script] 👂 Start a local server for developing your worker
84
- wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
85
- wrangler delete [script] 🗑 Delete your Worker from Cloudflare.
86
- wrangler tail [worker] 🦚 Starts a log tailing session for a published Worker.
87
- wrangler secret 🤫 Generate a secret that can be referenced in a Worker
88
- wrangler secret:bulk <json> 🗄️ Bulk upload secrets for a Worker
89
- wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
90
- wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
91
- wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
92
- wrangler pages ⚡️ Configure Cloudflare Pages
93
- wrangler queues 🇶 Configure Workers Queues
94
- wrangler r2 📦 Interact with an R2 store
95
- wrangler dispatch-namespace 📦 Interact with a dispatch namespace
96
- wrangler d1 🗄 Interact with a D1 database
97
- wrangler pubsub 📮 Interact and manage Pub/Sub Brokers
98
- wrangler login 🔓 Login to Cloudflare
99
- wrangler logout 🚪 Logout from Cloudflare
100
- wrangler whoami 🕵️ Retrieve your user info and test your auth config
101
- wrangler types 📝 Generate types from bindings & module rules in config
102
- wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
82
+ wrangler docs [command] 📚 Open wrangler's docs in your browser
83
+ wrangler init [name] 📥 Initialize a basic Worker project, including a wrangler.toml file
84
+ wrangler generate [name] [template] ✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
85
+ wrangler dev [script] 👂 Start a local server for developing your worker
86
+ wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
87
+ wrangler delete [script] 🗑 Delete your Worker from Cloudflare.
88
+ wrangler tail [worker] 🦚 Starts a log tailing session for a published Worker.
89
+ wrangler secret 🤫 Generate a secret that can be referenced in a Worker
90
+ wrangler secret:bulk <json> 🗄️ Bulk upload secrets for a Worker
91
+ wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
92
+ wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
93
+ wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
94
+ wrangler pages ⚡️ Configure Cloudflare Pages
95
+ wrangler queues 🇶 Configure Workers Queues
96
+ wrangler r2 📦 Interact with an R2 store
97
+ wrangler dispatch-namespace 📦 Interact with a dispatch namespace
98
+ wrangler d1 🗄 Interact with a D1 database
99
+ wrangler pubsub 📮 Interact and manage Pub/Sub Brokers
100
+ wrangler login 🔓 Login to Cloudflare
101
+ wrangler logout 🚪 Logout from Cloudflare
102
+ wrangler whoami 🕵️ Retrieve your user info and test your auth config
103
+ wrangler types 📝 Generate types from bindings & module rules in config
104
+ wrangler deployments 🚢 Displays the 10 most recent deployments for a worker
103
105
 
104
106
  Flags:
105
107
  -c, --config Path to .toml configuration file [string]
@@ -2400,6 +2400,42 @@ describe("init", () => {
2400
2400
  });
2401
2401
  });
2402
2402
 
2403
+ it("should fail on init --from-dash on non-existent worker name", async () => {
2404
+ setMockResponse(
2405
+ `/accounts/:accountId/workers/services/:scriptName`,
2406
+ "GET",
2407
+ () => mockServiceMetadata
2408
+ );
2409
+ setMockFetchDashScript({
2410
+ accountId: "LCARS",
2411
+ fromDashScriptName: "memory-crystal",
2412
+ environment: mockServiceMetadata.default_environment.environment,
2413
+ mockResponse: mockDashboardScript,
2414
+ });
2415
+ mockConfirm(
2416
+ {
2417
+ text: "Would you like to use git to manage this Worker?",
2418
+ result: false,
2419
+ },
2420
+ {
2421
+ text: "Would you like to use TypeScript?",
2422
+ result: true,
2423
+ },
2424
+ {
2425
+ text: "No package.json found. Would you like to create one?",
2426
+ result: true,
2427
+ },
2428
+ {
2429
+ text: "Would you like to install the type definitions for Workers into your package.json?",
2430
+ result: true,
2431
+ }
2432
+ );
2433
+
2434
+ await expect(
2435
+ runWrangler("init isolinear-optical-chip --from-dash i-dont-exist")
2436
+ ).rejects.toThrowError();
2437
+ });
2438
+
2403
2439
  it("should download source script from dashboard w/ out positional <name>", async () => {
2404
2440
  mockSupportingDashRequests({
2405
2441
  expectedAccountId: "LCARS",
@@ -2795,7 +2831,7 @@ describe("init", () => {
2795
2831
  await expect(
2796
2832
  runWrangler("init --from-dash")
2797
2833
  ).rejects.toMatchInlineSnapshot(
2798
- `[YError: Not enough arguments following: from-dash]`
2834
+ `[Error: Not enough arguments following: from-dash]`
2799
2835
  );
2800
2836
  checkFiles({
2801
2837
  items: {
@@ -36,6 +36,12 @@ export async function deployments(
36
36
  accountId: string,
37
37
  scriptName: string | undefined
38
38
  ) {
39
+ if (!scriptName) {
40
+ throw new Error(
41
+ "Required Worker name missing. Please specify the Worker name in wrangler.toml, or pass it as an argument with `--name`"
42
+ );
43
+ }
44
+
39
45
  const scriptMetadata = await fetchResult<ServiceMetadataRes>(
40
46
  `/accounts/${accountId}/workers/services/${scriptName}`
41
47
  );
@@ -1,305 +1,12 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
1
  import { DeprecationError } from "../errors";
4
- import { cloneIntoDirectory, initializeGit } from "../git-client";
5
- import {
6
- CommandLineArgsError,
7
- createCLIParser,
8
- printWranglerBanner,
9
- } from "../index";
10
- import { initHandler } from "../init";
2
+ import { createCLIParser } from "../index";
11
3
  import { logger } from "../logger";
12
4
  import { formatMessage } from "../parse";
13
5
  import type {
14
6
  CommonYargsOptions,
15
7
  YargsOptionsToInterface,
16
8
  } from "../yargs-types";
17
- import type { Argv, ArgumentsCamelCase, BuilderCallback } from "yargs";
18
-
19
- // https://github.com/cloudflare/wrangler/blob/master/src/cli/mod.rs#L106-L123
20
- interface GenerateArgs {
21
- name?: string;
22
- template?: string;
23
- type?: string;
24
- site?: boolean;
25
- }
26
-
27
- export function generateOptions(yargs: Argv<CommonYargsOptions>) {
28
- return yargs
29
- .positional("name", {
30
- describe: "Name of the Workers project",
31
- type: "string",
32
- })
33
- .positional("template", {
34
- type: "string",
35
- describe: "The URL of a GitHub template",
36
- })
37
- .option("type", {
38
- alias: "t",
39
- type: "string",
40
- hidden: true,
41
- deprecated: true,
42
- })
43
- .option("site", {
44
- alias: "s",
45
- type: "boolean",
46
- hidden: true,
47
- deprecated: true,
48
- });
49
- }
50
-
51
- export async function generateHandler({
52
- // somehow, `init` marks name as required but then also runs fine
53
- // with the name omitted, and then substitutes it at runtime with ""
54
- name = "",
55
- template,
56
- type,
57
- site,
58
- ...args
59
- }: ArgumentsCamelCase<GenerateArgs>) {
60
- // delegate to `wrangler init` if no template is specified
61
- if (template === undefined) {
62
- return initHandler({ name, ...args });
63
- }
64
-
65
- // print down here cuz `init` prints it own its own
66
- await printWranglerBanner();
67
-
68
- if (type) {
69
- let message = "The --type option is no longer supported.";
70
- if (args.type === "webpack") {
71
- message +=
72
- "\nIf you wish to use webpack then you will need to create a custom build.";
73
- // TODO: Add a link to docs
74
- }
75
- throw new CommandLineArgsError(message);
76
- }
77
-
78
- if (isRemote(name)) {
79
- [template, name] = [name, template];
80
- }
81
-
82
- const creationDirectory = generateWorkerDirectoryName(name);
83
-
84
- if (site) {
85
- const gitDirectory =
86
- creationDirectory !== process.cwd()
87
- ? path.basename(creationDirectory)
88
- : "my-site";
89
- const message =
90
- "The --site option is no longer supported.\n" +
91
- "If you wish to create a brand new Worker Sites project then clone the `worker-sites-template` starter repository:\n\n" +
92
- "```\n" +
93
- `git clone --depth=1 --branch=wrangler2 https://github.com/cloudflare/worker-sites-template ${gitDirectory}\n` +
94
- `cd ${gitDirectory}\n` +
95
- "```\n\n" +
96
- "Find out more about how to create and maintain Sites projects at https://developers.cloudflare.com/workers/platform/sites.\n" +
97
- "Have you considered using Cloudflare Pages instead? See https://pages.cloudflare.com/.";
98
- throw new CommandLineArgsError(message);
99
- }
100
-
101
- logger.log(
102
- `Creating a worker in ${path.basename(creationDirectory)} from ${template}`
103
- );
104
-
105
- const { remote, subdirectory } = parseTemplatePath(template);
106
-
107
- await cloneIntoDirectory(remote, creationDirectory, subdirectory);
108
- await initializeGit(creationDirectory);
109
-
110
- logger.log("✨ Success!");
111
- }
112
-
113
- /**
114
- * Creates a path based on the current working directory and a worker name.
115
- * Automatically increments a counter when searching for an available directory.
116
- *
117
- * Running `wrangler generate worker https://some-git-repo` in a directory
118
- * with the structure:
119
- * ```
120
- * - workers
121
- * |
122
- * | - worker
123
- * | | - wrangler.toml
124
- * | | ...
125
- * |
126
- * | - worker-1
127
- * | | - wrangler.toml
128
- * | | ...
129
- * ```
130
- *
131
- * will result in a new worker called `worker-2` being generated.
132
- *
133
- * @param workerName the name of the generated worker
134
- * @returns an absolute path to the directory to generate the worker into
135
- */
136
- function generateWorkerDirectoryName(workerName: string): string {
137
- let workerDirectoryPath = path.resolve(process.cwd(), workerName);
138
- let i = 1;
139
-
140
- while (fs.existsSync(workerDirectoryPath)) {
141
- workerDirectoryPath = path.resolve(process.cwd(), `${workerName}-${i}`);
142
- i++;
143
- }
144
-
145
- return workerDirectoryPath;
146
- }
147
-
148
- /**
149
- * Checks if an arg is a template, which can be useful if the order
150
- * of template & worker name args is switched
151
- *
152
- * @param arg a template to generate from, or a folder to generate into
153
- * @returns true if the given arg was remote (a template)
154
- */
155
- function isRemote(arg: string) {
156
- return /^(https?|ftps?|file|git|ssh):\/\//.test(arg) || arg.includes(":");
157
- }
158
-
159
- /**
160
- * unreadable regex basically copied from degit. i put some named capture groups in,
161
- * but uhh...there's not much to do short of using pomsky or some other tool.
162
- *
163
- * notably: this only supports `https://` and `git@` urls,
164
- * and is missing support for:
165
- * - `http`
166
- * - `ftp(s)`
167
- * - `file`
168
- * - `ssh`
169
- */
170
- const TEMPLATE_REGEX =
171
- /^(?:(?:https:\/\/)?(?<httpsUrl>[^:/]+\.[^:/]+)\/|git@(?<gitUrl>[^:/]+)[:/]|(?<shorthandUrl>[^/]+):)?(?<user>[^/\s]+)\/(?<repository>[^/\s#]+)(?:(?<subdirectoryPath>(?:\/[^/\s#]+)+))?(?:\/)?(?:#(?<tag>.+))?/;
172
-
173
- // there are a few URL formats we support:
174
- // - `user/repo` -> assume github, use "https://github.com/user/repo.git"
175
- // - `https://<httpsUrl>
176
- // - `git@<gitUrl>`
177
- // - `(bb|bitbucket|gh|github|gl|gitlab):user/repo` -> parse shorthand into https url
178
-
179
- /**
180
- * There's no URL, so assume a github repo
181
- */
182
- type NoUrl = {
183
- httpsUrl: undefined;
184
- gitUrl: undefined;
185
- shorthandUrl: undefined;
186
- };
187
-
188
- /**
189
- * A https url (e.g. https://bitbucket.org/user/repo)
190
- */
191
- type HttpsUrl = Omit<NoUrl, "httpsUrl"> & { httpsUrl: string };
192
-
193
- /**
194
- * A git url (e.g. git@gitlab.com:user/repo)
195
- */
196
- type GitUrl = Omit<NoUrl, "gitUrl"> & { gitUrl: string };
197
-
198
- /**
199
- * A shorthand url (e.g. github:user/repo)
200
- */
201
- type ShorthandUrl = Omit<NoUrl, "shorthandUrl"> & { shorthandUrl: string };
202
-
203
- /**
204
- * Union of all possible URL groups. Exactly one will be present, the rest
205
- * will be `undefined`.
206
- */
207
- type TemplateRegexUrlGroup = NoUrl | HttpsUrl | GitUrl | ShorthandUrl;
208
-
209
- /**
210
- * Possible matches of `TEMPLATE_REGEX` against a passed-in template arg
211
- */
212
- type TemplateRegexGroups = {
213
- /** The user the repo is under */
214
- user: string;
215
-
216
- /** The repo name */
217
- repository: string;
218
-
219
- /** Optional, path to subdirectory containing template. Begins with `/` */
220
- subdirectoryPath?: string;
221
-
222
- /** Optional tag (or branch, etc.) to clone */
223
- tag?: string;
224
- } & TemplateRegexUrlGroup;
225
-
226
- /**
227
- * Parses a regex match on any of the URL groups into a URL base
228
- *
229
- * @param urlGroup a regex hit for a URL of any sort
230
- * @returns the protocol and domain name of the url to clone from
231
- */
232
- function toUrlBase({ httpsUrl, gitUrl, shorthandUrl }: TemplateRegexUrlGroup) {
233
- if (httpsUrl !== undefined) {
234
- return `https://${httpsUrl}`;
235
- }
236
-
237
- if (gitUrl !== undefined) {
238
- return `git@${gitUrl}`;
239
- }
240
-
241
- if (shorthandUrl !== undefined) {
242
- switch (shorthandUrl) {
243
- case "github":
244
- case "gh":
245
- return "https://github.com";
246
- case "gitlab":
247
- case "gl":
248
- return "https://gitlab.com";
249
- case "bitbucket":
250
- case "bb":
251
- return "https://bitbucket.org";
252
- default:
253
- throw new Error(
254
- `Unable to parse shorthand ${shorthandUrl}. Supported options are "bitbucket" ("bb"), "github" ("gh"), and "gitlab" ("gl")`
255
- );
256
- }
257
- }
258
-
259
- return "https://github.com";
260
- }
261
-
262
- /**
263
- * Parses a template string (e.g. "user/repo", "github:user/repo/path/to/subdirectory")
264
- * into a remote URL to clone from and an optional subdirectory to filter for
265
- *
266
- * @param templatePath the template string to parse
267
- * @returns an object containing the remote url and an optional subdirectory to clone
268
- */
269
- function parseTemplatePath(templatePath: string): {
270
- remote: string;
271
- subdirectory?: string;
272
- } {
273
- if (!templatePath.includes("/")) {
274
- // template is a cloudflare canonical template, it doesn't include a slash in the name
275
- return {
276
- remote: "https://github.com/cloudflare/templates.git",
277
- subdirectory: templatePath,
278
- };
279
- }
280
-
281
- const groups = TEMPLATE_REGEX.exec(templatePath)?.groups as unknown as
282
- | TemplateRegexGroups
283
- | undefined;
284
-
285
- if (!groups) {
286
- throw new Error(`Unable to parse ${templatePath} as a template`);
287
- }
288
-
289
- const { user, repository, subdirectoryPath, tag, ...urlGroups } = groups;
290
-
291
- const urlBase = toUrlBase(urlGroups);
292
- const isHttp = urlBase.startsWith("http");
293
-
294
- const remote = `${urlBase}${isHttp ? "/" : ":"}${user}/${repository}.git${
295
- tag ? `#${tag}` : ""
296
- }`;
297
-
298
- // remove starting /
299
- const subdirectory = subdirectoryPath?.slice(1);
300
-
301
- return { remote, subdirectory };
302
- }
9
+ import type { Argv, BuilderCallback } from "yargs";
303
10
 
304
11
  export function buildOptions(yargs: Argv<CommonYargsOptions>) {
305
12
  return yargs;
package/src/dev.tsx CHANGED
@@ -328,7 +328,7 @@ export function devOptions(yargs: Argv<CommonYargsOptions>): Argv<DevArgs> {
328
328
  }
329
329
 
330
330
  export async function devHandler(args: ArgumentsCamelCase<DevArgs>) {
331
- if (!args.local) {
331
+ if (!(args.local || args.experimentalLocal)) {
332
332
  const isLoggedIn = await loginOrRefreshIfRequired();
333
333
  if (!isLoggedIn) {
334
334
  throw new Error(
@@ -0,0 +1,97 @@
1
+ import { printWranglerBanner } from "..";
2
+ import { readConfig } from "../config";
3
+ import { logger } from "../logger";
4
+ import * as metrics from "../metrics";
5
+ import openInBrowser from "../open-in-browser";
6
+
7
+ import type {
8
+ CommonYargsOptions,
9
+ YargsOptionsToInterface,
10
+ } from "../yargs-types";
11
+ import type { ArgumentsCamelCase, Argv } from "yargs";
12
+
13
+ const argToUrlHash = {
14
+ docs: "docs",
15
+ init: "init",
16
+ generate: "generate",
17
+ dev: "dev",
18
+ publish: "publish",
19
+ delete: "delete",
20
+ "kv:namespace": "kvnamespace",
21
+ "kv:key": "kvkey",
22
+ "kv:bulk": "kvbulk",
23
+ "r2 bucket": "r2-bucket",
24
+ "r2 object": "r2-object",
25
+ secret: "secret",
26
+ "secret:bulk": "secretbulk",
27
+ tail: "tail",
28
+ pages: "pages",
29
+ login: "login",
30
+ logout: "logout",
31
+ whoami: "whoami",
32
+ types: "types",
33
+ deployments: "deployments",
34
+ };
35
+
36
+ export function docsOptions(yargs: Argv<CommonYargsOptions>) {
37
+ return yargs.positional("command", {
38
+ describe: "Enter the wrangler command you want to know more about",
39
+ type: "string",
40
+ // requiresArg: true,
41
+ choices: [
42
+ "docs",
43
+ "init",
44
+ "generate",
45
+ "dev",
46
+ "publish",
47
+ "delete",
48
+ "tail",
49
+ "secret",
50
+ "secret:bulk",
51
+ "kv:namespace",
52
+ "kv:key",
53
+ "kv:bulk",
54
+ "pages",
55
+ // "queues", //TODO: Undocumented
56
+ "r2 object",
57
+ "r2 bucket",
58
+ // "dispatch-namespace", // TODO: Undocumented - Workers for Platforms
59
+ // "d1", //TODO: Undocumented
60
+ // "pubsub", //TODO: Undocumented
61
+ "login",
62
+ "logout",
63
+ "whoami",
64
+ "types",
65
+ "deployments",
66
+ "api",
67
+ ],
68
+ });
69
+ }
70
+
71
+ type DocsArgs = YargsOptionsToInterface<typeof docsOptions>;
72
+
73
+ function isValidParam(k: string): k is keyof typeof argToUrlHash {
74
+ return k in argToUrlHash;
75
+ }
76
+
77
+ export async function docsHandler(args: ArgumentsCamelCase<DocsArgs>) {
78
+ let urlToOpen =
79
+ "https://developers.cloudflare.com/workers/wrangler/commands/";
80
+
81
+ if (args.command === "api") {
82
+ //if api, take them to the API docs
83
+ urlToOpen = "https://developers.cloudflare.com/workers/wrangler/api/";
84
+ } else if (args.command && isValidParam(args.command)) {
85
+ //otherwise, they get the wrangler commands page
86
+ urlToOpen += `#${argToUrlHash[args.command]}`;
87
+ }
88
+
89
+ await printWranglerBanner();
90
+
91
+ logger.log(`Opening a link in your default browser: ${urlToOpen}`);
92
+ await openInBrowser(urlToOpen);
93
+ const config = readConfig(undefined, {});
94
+ await metrics.sendMetricsEvent("view docs", {
95
+ sendMetrics: config.send_metrics,
96
+ });
97
+ }