Skip to content

Commit

Permalink
[wrangler] teach wrangler to search docs (#3004)
Browse files Browse the repository at this point in the history
  • Loading branch information
rozenmd committed Apr 19, 2023
1 parent 590e4d3 commit 6d5000a
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 72 deletions.
15 changes: 15 additions & 0 deletions .changeset/six-toes-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
"wrangler": minor
---

feat: teach `wrangler docs` to use algolia search index

This PR lets you search Cloudflare's entire docs via `wrangler docs [search term here]`.

By default, if the search fails to find what you're looking for, you'll get an error like this:

```
✘ [ERROR] Could not find docs for: <search term goes here>. Please try again with another search term.
```

If you provide the `--yes` or `-y` flag, wrangler will open the docs to https://developers.cloudflare.com/workers/wrangler/commands/, even if the search fails.
2 changes: 2 additions & 0 deletions .github/workflows/create-pullrequest-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ jobs:
run: npm run build
env:
NODE_ENV: "production"
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}

- name: Pack wrangler
run: npm pack
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/prereleases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ jobs:
run: npm run build
env:
NODE_ENV: "production"
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}

- name: Build & Publish Prerelease Registry
run: npm run publish
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }}
ALGOLIA_PUBLIC_KEY: ${{ secrets.ALGOLIA_PUBLIC_KEY }}
NODE_ENV: "production"
# This is the "production" key for sparrow analytics.
# Include this here because this step will rebuild Wrangler and needs to have this available
Expand Down
6 changes: 6 additions & 0 deletions packages/wrangler/scripts/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ async function buildMain(flags: BuildFlags = {}) {
...(process.env.SPARROW_SOURCE_KEY
? { SPARROW_SOURCE_KEY: `"${process.env.SPARROW_SOURCE_KEY}"` }
: {}),
...(process.env.ALGOLIA_APP_ID
? { ALGOLIA_APP_ID: `"${process.env.ALGOLIA_APP_ID}"` }
: {}),
...(process.env.ALGOLIA_PUBLIC_KEY
? { ALGOLIA_PUBLIC_KEY: `"${process.env.ALGOLIA_PUBLIC_KEY}"` }
: {}),
},
watch: flags.watch ? watchLogger("./wrangler-dist") : false,
});
Expand Down
4 changes: 2 additions & 2 deletions packages/wrangler/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe("wrangler", () => {
"wrangler
Commands:
wrangler docs [command] 📚 Open wrangler's docs in your browser
wrangler docs [command..] 📚 Open wrangler's docs in your browser
wrangler init [name] 📥 Initialize a basic Worker project, including a wrangler.toml file
wrangler generate [name] [template] ✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
wrangler dev [script] 👂 Start a local server for developing your worker
Expand Down Expand Up @@ -85,7 +85,7 @@ describe("wrangler", () => {
wrangler
Commands:
wrangler docs [command] 📚 Open wrangler's docs in your browser
wrangler docs [command..] 📚 Open wrangler's docs in your browser
wrangler init [name] 📥 Initialize a basic Worker project, including a wrangler.toml file
wrangler generate [name] [template] ✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
wrangler dev [script] 👂 Start a local server for developing your worker
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/__tests__/mtls-certificates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ describe("wrangler", () => {
"wrangler
Commands:
wrangler docs [command] 📚 Open wrangler's docs in your browser
wrangler docs [command..] 📚 Open wrangler's docs in your browser
wrangler init [name] 📥 Initialize a basic Worker project, including a wrangler.toml file
wrangler generate [name] [template] ✨ Generate a new Worker project from an existing Worker template. See https://github.com/cloudflare/templates
wrangler dev [script] 👂 Start a local server for developing your worker
Expand Down
50 changes: 50 additions & 0 deletions packages/wrangler/src/docs/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import assert from "node:assert";
import { fetch } from "undici";
import { logger } from "../logger";

// The ALGOLIA_APP_ID and ALGOLIA_PUBLIC_KEY are provided at esbuild time as a `define` for production and beta releases.
// Otherwise it is left undefined, which disables search.
declare const ALGOLIA_APP_ID: string;
declare const ALGOLIA_PUBLIC_KEY: string;

export async function runSearch(searchTerm: string) {
const id = ALGOLIA_APP_ID;
const index = "developers-cloudflare2";
const key = ALGOLIA_PUBLIC_KEY;
const params = new URLSearchParams({
query: searchTerm,
hitsPerPage: "1",
getRankingInfo: "0",
});

assert(id, "Missing Algolia App ID");
assert(key, "Missing Algolia Key");

const searchResp = await fetch(
`https://${id}-dsn.algolia.net/1/indexes/${index}/query`,
{
method: "POST",
body: JSON.stringify({
params: params.toString(),
}),
headers: {
"X-Algolia-API-Key": key,
"X-Algolia-Application-Id": id,
},
}
);
if (!searchResp.ok) {
logger.error(`Could not search the docs. Please try again later.`);
return;
}
const searchData = (await searchResp.json()) as { hits: { url: string }[] };
logger.debug("searchData: ", searchData);
if (searchData.hits[0]) {
return searchData.hits[0].url;
} else {
logger.error(
`Could not find docs for: ${searchTerm}. Please try again with another search term.`
);
return;
}
}
93 changes: 25 additions & 68 deletions packages/wrangler/src/docs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,89 +3,46 @@ import { readConfig } from "../config";
import { logger } from "../logger";
import * as metrics from "../metrics";
import openInBrowser from "../open-in-browser";

import { runSearch } from "./helpers";
import type {
CommonYargsArgv,
StrictYargsOptionsToInterface,
} from "../yargs-types";

const argToUrlHash = {
d1: "d1",
docs: "docs",
init: "init",
generate: "generate",
dev: "dev",
publish: "publish",
delete: "delete",
"kv:namespace": "kvnamespace",
"kv:key": "kvkey",
"kv:bulk": "kvbulk",
"r2 bucket": "r2-bucket",
"r2 object": "r2-object",
secret: "secret",
"secret:bulk": "secretbulk",
tail: "tail",
pages: "pages",
login: "login",
logout: "logout",
whoami: "whoami",
types: "types",
deployments: "deployments",
};

export function docsOptions(yargs: CommonYargsArgv) {
return yargs.positional("command", {
describe: "Enter the wrangler command you want to know more about",
type: "string",
// requiresArg: true,
choices: [
"docs",
"init",
"generate",
"dev",
"publish",
"delete",
"tail",
"secret",
"secret:bulk",
"kv:namespace",
"kv:key",
"kv:bulk",
"pages",
// "queues", //TODO: Undocumented
"r2 object",
"r2 bucket",
// "dispatch-namespace", // TODO: Undocumented - Workers for Platforms
"d1",
// "pubsub", //TODO: Undocumented
"login",
"logout",
"whoami",
"types",
"deployments",
"api",
],
});
}

function isValidParam(k: string): k is keyof typeof argToUrlHash {
return k in argToUrlHash;
return yargs
.positional("command", {
describe: "Enter the wrangler command you want to know more about",
type: "string",
array: true,
})
.option("yes", {
alias: "y",
type: "boolean",
description: "Takes you to the docs, even if search fails",
});
}

export async function docsHandler(
args: StrictYargsOptionsToInterface<typeof docsOptions>
) {
//if no command is provided, open the docs homepage
//or, if a command IS provided, but we can't find anything, open the docs homepage
let urlToOpen =
"https://developers.cloudflare.com/workers/wrangler/commands/";
args.yes || !args.command || args.command.length === 0
? "https://developers.cloudflare.com/workers/wrangler/commands/"
: "";

if (args.command && args.command.length > 0) {
const searchTerm = args.command.join(" ");
const searchResult = await runSearch(searchTerm);

if (args.command === "api") {
//if api, take them to the API docs
urlToOpen = "https://developers.cloudflare.com/workers/wrangler/api/";
} else if (args.command && isValidParam(args.command)) {
//otherwise, they get the wrangler commands page
urlToOpen += `#${argToUrlHash[args.command]}`;
urlToOpen = searchResult ?? urlToOpen;
}

if (!urlToOpen) {
return;
}
await printWranglerBanner();

logger.log(`Opening a link in your default browser: ${urlToOpen}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/wrangler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export function createCLIParser(argv: string[]) {

// docs
wrangler.command(
"docs [command]",
"docs [command..]",
"📚 Open wrangler's docs in your browser",
docsOptions,
docsHandler
Expand Down

0 comments on commit 6d5000a

Please sign in to comment.