Skip to content

Commit

Permalink
[Docs Site] Add WranglerCommand component
Browse files Browse the repository at this point in the history
  • Loading branch information
KianNH committed Oct 18, 2024
1 parent 0d8a917 commit 9ad3cab
Show file tree
Hide file tree
Showing 17 changed files with 4,009 additions and 1,501 deletions.
195 changes: 195 additions & 0 deletions scripts/wrangler-commands-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import { execSync } from "child_process";
import { writeFileSync } from "fs";

const TWO_OR_MORE_SPACES_REGEX = /[^\S\r\n]{2,}/;
const WORDS_IN_BRACKETS_REGEX = /\[([\s\S]+?)\]|\{([\s\S]+?)\}|<([\s\S]+?)>/g;
const COMMANDS_REGEX = /(?:\r?\n){2}COMMANDS\r?\n/;
const POSITIONALS_REGEX = /(?:\r?\n){2}POSITIONALS\r?\n/;
const GLOBAL_FLAGS_REGEX = /(?:\r?\n){2}GLOBAL FLAGS\r?\n/;
const OPTIONS_REGEX = /(?:\r?\n){2}OPTIONS\r?\n/;
const EXAMPLES_REGEX = /(?:\r?\n){2}EXAMPLES\r?\n/;
const HELP_END =
"Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose";

function run(cmd: string) {
return execSync(cmd).toString();
}

function removePositionalsFromCommand(str: string) {
const matches = str.matchAll(WORDS_IN_BRACKETS_REGEX);

if (matches) {
let line = str;

for (const match of matches) {
const start = line.indexOf(match[0]);
const end = start + match[0].length;

line = (line.substring(0, start) + line.substring(end)).trim();
}

return line;
}

return str;
}

function handlePositionals(str: string) {
const start = str.match(POSITIONALS_REGEX);
const end = str.match(GLOBAL_FLAGS_REGEX);

if (!start || !end) {
throw new Error("Oops");
}

const output = str.substring(
str.indexOf(start[0]) + start[0].length,
str.indexOf(end[0]),
);

let lines = output.split("\n");

lines = lines.filter(Boolean);
lines = lines.map((x) => x.trim());

return lines.map((x) => {
const [name, description, type] = x.split(TWO_OR_MORE_SPACES_REGEX);

return {
name,
description,
type,
};
});
}

function handleOptions(str: string) {
const start = str.match(OPTIONS_REGEX);
const end = str.match(EXAMPLES_REGEX) ?? str.length;

if (!start || !end) {
throw new Error("Oops");
}

const output = str.substring(
str.indexOf(start[0]) + start[0].length,
typeof end === "number" ? end : str.indexOf(end[0]),
);

let lines = output.split("\n");

lines = lines.filter(Boolean);
lines = lines.map((x) => x.trim());

const options: string[] = [];
let multiLineBuffer: string[] = [];

for (let i = 0; i < lines.length; i++) {
const line = lines[i];

const isOptionLine = line.startsWith("-");
const isLastLine = i + 1 === lines.length;

if (isOptionLine || isLastLine) {
if (isLastLine) {
options.push([...multiLineBuffer, line].join("\n"));
} else {
const nextLineIsOptionLine = lines[i + 1].startsWith("-");

if (nextLineIsOptionLine) {
options.push(line);
continue;
}
}
}

multiLineBuffer.push(line);
}

return options
.filter((x) => !x.includes("--------------------"))
.map((x) => {
let [flags, ...rest] = x.split(/[^\S\r\n]{2,}/);
let description = rest.join("\n");

const match = description.match(/\[.*\]/g);

let type;
if (match) {
[type] = match;

const start = description.indexOf(type);
const end = start + type.length;

description =
description.substring(0, start) + description.substring(end);
}

return {
flags,
description,
type,
};
});
}

function handleSubcommands(str: string) {
const start = str.match(COMMANDS_REGEX);
const end = str.match(GLOBAL_FLAGS_REGEX);

const isNamespace = start && end;

if (isNamespace) {
const output = str.substring(
str.indexOf(start[0]) + start[0].length,
str.indexOf(end[0]),
);

let lines = output.split("\n");

lines = lines.filter(Boolean);
lines = lines.map((x) => x.trim());
lines = lines.map((x) => x.split(TWO_OR_MORE_SPACES_REGEX).at(0) as string);
lines = lines.map(removePositionalsFromCommand);

if (lines) {
for (const line of lines) {
handleSubcommands(run(`${line} --help`));
}
}
} else {
const [example, _, description] = str.split("\n");
const command = removePositionalsFromCommand(example);

json[command] = {
example,
description,
};

const hasPositionals = str.indexOf("POSITIONALS") !== -1;
const hasOptions = str.indexOf("OPTIONS") !== -1;

if (hasPositionals) {
json[command]["positionals"] = handlePositionals(str);
}

if (hasOptions) {
json[command]["options"] = handleOptions(str);
}
}
}

const json: Record<string, any> = {};

function main() {
const topLevelHelp = run("wrangler --help");

handleSubcommands(topLevelHelp);

writeFileSync(
"./src/content/wrangler-commands/index.json",
JSON.stringify(json, null, "\t"),
);
}

await main();
70 changes: 70 additions & 0 deletions src/components/WranglerCommand.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
import { z } from "astro:schema";
import { Code } from "@astrojs/starlight/components";
import Type from "./Type.astro";
import AnchorHeading from "./AnchorHeading.astro";
import { marked } from "marked";
import { getEntry } from "astro:content";
import MetaInfo from "./MetaInfo.astro";
type Props = z.infer<typeof props>;
const props = z.object({
cmd: z.string(),
});
const { cmd } = props.parse(Astro.props);
const depth = cmd.split(" ").length > 1 ? 3 : 2;
const command = (await getEntry("wrangler-commands", "index")).data[
`wrangler ${cmd}`
];
if (!command) {
throw new Error(`Unable to find info for ${cmd}`);
}
---

<AnchorHeading depth={depth} title={cmd} />

<p>{command.description}</p>

<Code lang="sh" code={command.example} />

{
command["positionals"]?.length && (
<>
<h3>Positionals</h3>
<ul>
{command["positionals"].map((x) => (
<li>
<strong>{x.name}</strong>
<Type text={x.type} />
<p>{x.description}</p>
</li>
))}
</ul>
</>
)
}

{
command["options"]?.length && (
<>
<h3>Options</h3>
<ul>
{command["options"].map((x) => (
<li>
<strong>{x.flags}</strong>
<Type text={x.type} />
<Fragment
set:html={marked.parse(x.description, { breaks: true })}
/>
{x.meta && <MetaInfo text={x.meta} />}
</li>
))}
</ul>
</>
)
}
3 changes: 2 additions & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ export { default as ThreeCardGrid } from "./ThreeCardGrid.astro";
export { default as TroubleshootingList } from "./TroubleshootingList.astro";
export { default as TunnelCalculator } from "./TunnelCalculator.astro";
export { default as Type } from "./Type.astro";
export { default as TypeScriptExample } from "./TypeScriptExample.astro"
export { default as TypeScriptExample } from "./TypeScriptExample.astro";
export { default as WorkersArchitectureDiagram } from "./WorkersArchitectureDiagram.astro";
export { default as WorkersIsolateDiagram } from "./WorkersIsolateDiagram.astro";
export { default as WorkerStarter } from "./WorkerStarter.astro";
export { default as WranglerCommand } from "./WranglerCommand.astro";
export { default as YouTube } from "./YouTube.astro";

// Taken from Astro
Expand Down
5 changes: 5 additions & 0 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
learningPathsSchema,
videosSchema,
workersAiSchema,
wranglerCommandsSchema,
} from "~/schemas";

const partialSchema = z.object({
Expand Down Expand Up @@ -74,4 +75,8 @@ export const collections = {
schema: appsSchema,
type: "data",
}),
"wrangler-commands": defineCollection({
schema: wranglerCommandsSchema,
type: "data",
}),
};
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default {
};
```

To make this work, you need to use [`wrangler secret put`](/workers/wrangler/commands/#put-3) to set your `OPENAI_API_KEY`. This will save the API key to your environment so your Worker can access it when deployed. This key is the API key you created earlier in the OpenAI dashboard:
To make this work, you need to use [`wrangler secret put`](/workers/wrangler/commands/#secret-put) to set your `OPENAI_API_KEY`. This will save the API key to your environment so your Worker can access it when deployed. This key is the API key you created earlier in the OpenAI dashboard:

```sh title="Save your API key to your Workers env"
npx wrangler secret put OPENAI_API_KEY
Expand Down
11 changes: 11 additions & 0 deletions src/content/docs/style-guide/components/wrangler-command.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: Wrangler command
---

This component reads from a JSON file that is created by parsing the `--help` output of Wrangler commands.

```mdx live
import { WranglerCommand } from "~/components";

<WranglerCommand cmd="r2 bucket create" />
```
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ For the remainder of this tutorial you will complete each task, iterating on you

To begin, you need to understand how to populate your todo list with actual data. To do this, use [Cloudflare Workers KV](/kv/) — a key-value store that you can access inside of your Worker to read and write data.

To get started with KV, set up a namespace. All of your cached data will be stored inside that namespace and, with configuration, you can access that namespace inside the Worker with a predefined variable. Use Wrangler to create a new namespace called `TODOS` with the [`kv:namespace create` command](/workers/wrangler/commands/#create-3) and get the associated namespace ID by running the following command in your terminal:
To get started with KV, set up a namespace. All of your cached data will be stored inside that namespace and, with configuration, you can access that namespace inside the Worker with a predefined variable. Use Wrangler to create a new namespace called `TODOS` with the [`kv:namespace create` command](/workers/wrangler/commands/#kv-namespace-create) and get the associated namespace ID by running the following command in your terminal:

```sh title="Create a new KV namespace"
npx wrangler kv:namespace create "TODOS" --preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ cd finetune-chatgpt-model

Next, upload the fine-tune document to R2. R2 is a key-value store that allows you to store and retrieve files from within your Workers application. You will use [Wrangler](/workers/wrangler) to create a new R2 bucket.

To create a new R2 bucket use the [`wrangler r2 bucket create`](/workers/wrangler/commands/#create-2) command. Note that you are logged in with your Cloudflare account. If not logged in via Wrangler, use the [`wrangler login`](/workers/wrangler/commands/#login) command.
To create a new R2 bucket use the [`wrangler r2 bucket create`](/workers/wrangler/commands/#r2-bucket-create) command. Note that you are logged in with your Cloudflare account. If not logged in via Wrangler, use the [`wrangler login`](/workers/wrangler/commands/#login) command.

```sh
npx wrangler r2 bucket create <BUCKET_NAME>
```

Replace `<BUCKET_NAME>` with your desired bucket name. Note that bucket names must be lowercase and can only contain dashes.

Next, upload a file using the [`wrangler r2 object put`](/workers/wrangler/commands/#put-2) command.
Next, upload a file using the [`wrangler r2 object put`](/workers/wrangler/commands/#r2-object-put) command.

```sh
npx wrangler r2 object put <PATH> -f <FILE_NAME>
Expand Down Expand Up @@ -233,7 +233,7 @@ app.get("/jobs", async (c) => {

After you have created your Worker application and added the required functions, deploy the application.

Before you deploy, you must set the `OPENAI_API_KEY` [secret](/workers/configuration/secrets/) for your application. Do this by running the [`wrangler secret put`](/workers/wrangler/commands/#put-3) command:
Before you deploy, you must set the `OPENAI_API_KEY` [secret](/workers/configuration/secrets/) for your application. Do this by running the [`wrangler secret put`](/workers/wrangler/commands/#secret-put) command:

```sh
npx wrangler secret put OPENAI_API_KEY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ function checkSignature(text, headers, githubSecretToken) {
}
```

To make this work, you need to use [`wrangler secret put`](/workers/wrangler/commands/#put-3) to set your `GITHUB_SECRET_TOKEN`. This token is the secret you picked earlier when configuring you GitHub webhook:
To make this work, you need to use [`wrangler secret put`](/workers/wrangler/commands/#secret-put) to set your `GITHUB_SECRET_TOKEN`. This token is the secret you picked earlier when configuring you GitHub webhook:

```sh
npx wrangler secret put GITHUB_SECRET_TOKEN
Expand Down Expand Up @@ -197,7 +197,7 @@ async function sendText(accountSid, authToken, message) {
}
```

To make this work, you need to set some secrets to hide your `ACCOUNT_SID` and `AUTH_TOKEN` from the source code. You can set secrets with [`wrangler secret put`](/workers/wrangler/commands/#put-3) in your command line.
To make this work, you need to set some secrets to hide your `ACCOUNT_SID` and `AUTH_TOKEN` from the source code. You can set secrets with [`wrangler secret put`](/workers/wrangler/commands/#secret-put) in your command line.

```sh
npx wrangler secret put TWILIO_ACCOUNT_SID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ async fetch(request, env, ctx) {
},
```

Use [`wrangler secret put`](/workers/wrangler/commands/#put-3) to set `OPENAI_API_KEY`. This [secret's](/workers/configuration/secrets/) value is the API key you created earlier in the OpenAI dashboard:
Use [`wrangler secret put`](/workers/wrangler/commands/#secret-put) to set `OPENAI_API_KEY`. This [secret's](/workers/configuration/secrets/) value is the API key you created earlier in the OpenAI dashboard:

```sh
npx wrangler secret put <OPENAI_API_KEY>
Expand Down
Loading

0 comments on commit 9ad3cab

Please sign in to comment.