sproutboat 0.4.2 → 0.4.3
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/SURFACE.md +4 -4
- package/package.json +1 -1
- package/src/main.ts +10 -2
- package/src/surface.ts +79 -16
package/SURFACE.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Generated by `src/surface.test.ts` from `src/surface.ts` + the pinned
|
|
4
4
|
> toolchain constants. Do not edit by hand — run `UPDATE_SURFACE=1 bun test`.
|
|
5
5
|
|
|
6
|
-
**Package:** `sproutboat` 0.4.
|
|
6
|
+
**Package:** `sproutboat` 0.4.3 · runs on Bun (use `bunx`, not `npx`)
|
|
7
7
|
|
|
8
8
|
## Commands
|
|
9
9
|
|
|
@@ -13,16 +13,16 @@
|
|
|
13
13
|
| `check` | `[project-dir]` | Validate the config and entry point without building. |
|
|
14
14
|
| `build` | `[project-dir]` | Cross-compile the native-fetch sprout (Porffor + Zig). |
|
|
15
15
|
| `deploy` | `[project-dir] [--dry-run] [--artifact <dir>] [--no-wait]` | Build (unless --artifact), print the report, upload, wait until the URL serves. --dry-run stops before upload; --no-wait skips the health check. |
|
|
16
|
-
| `login` | `[--api-url <url>] [--token <token>]` | Device-code browser flow, or store <token> for <url> directly. |
|
|
17
|
-
| `tail` | `[project-dir] [--sprout]` | Print recent request logs; --sprout prints the running sprout + broker stdout/stderr instead. |
|
|
18
16
|
| `versions` | `list [project-dir]` | List the project's deployed versions. |
|
|
19
17
|
| `rollback` | `<version-id> [project-dir]` | Re-activate a previous version. |
|
|
18
|
+
| `tail` | `[project-dir] [--sprout]` | Print recent request logs; --sprout prints the running sprout + broker stdout/stderr instead. |
|
|
20
19
|
| `domains` | `[list | add <host> | verify <host> | rm <host>] [project-dir]` | Attach a custom domain to the project (TXT-verified). No sub-command lists. |
|
|
21
20
|
| `secrets` | `[list | set <NAME> [value] | rm <NAME>] [project-dir]` | Manage encrypted project secrets (read as env.NAME). `set` takes the value from the arg or stdin; applies on next deploy. |
|
|
22
21
|
| `delete` | `[project-dir] [--name <project>] --yes` | Delete the project, every version, and its route. |
|
|
22
|
+
| `login` | `[--api-url <url>] [--token <token>]` | Device-code browser flow, or store <token> for <url> directly. |
|
|
23
23
|
|
|
24
24
|
```
|
|
25
|
-
usage: sproutboat <init [name] | check [project-dir] | build [project-dir] | deploy [project-dir] [--dry-run] [--artifact <dir>] [--no-wait] |
|
|
25
|
+
usage: sproutboat <init [name] | check [project-dir] | build [project-dir] | deploy [project-dir] [--dry-run] [--artifact <dir>] [--no-wait] | versions list [project-dir] | rollback <version-id> [project-dir] | tail [project-dir] [--sprout] | domains [list | add <host> | verify <host> | rm <host>] [project-dir] | secrets [list | set <NAME> [value] | rm <NAME>] [project-dir] | delete [project-dir] [--name <project>] --yes | login [--api-url <url>] [--token <token>]>
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Environment variables
|
package/package.json
CHANGED
package/src/main.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { buildArtifact } from "./build";
|
|
|
7
7
|
import { validateManifest, type ArtifactManifest } from "./manifest";
|
|
8
8
|
import { printDeployReport } from "./report";
|
|
9
9
|
import { activeApiUrl, savedToken, saveToken } from "./credentials";
|
|
10
|
-
import { usageLine } from "./surface";
|
|
10
|
+
import { helpText, usageLine } from "./surface";
|
|
11
11
|
import { amber, bold, dim, leaf, ok, rose } from "./style";
|
|
12
12
|
|
|
13
13
|
const defaultApiUrl = "https://dashboard.sproutboat.com";
|
|
@@ -473,12 +473,20 @@ async function deleteProject(args: string[]) {
|
|
|
473
473
|
if (failed.length) console.log(` ! ${failed.length} artifact file(s) left on disk — remove them manually`);
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
/** `sproutboat` alone or with -h/--help/help: the friendly grouped list, exit 0. */
|
|
477
|
+
function help(): never {
|
|
478
|
+
console.log(helpText());
|
|
479
|
+
process.exit(0);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/** An unrecognised command: a short pointer on stderr, exit 1. */
|
|
476
483
|
function usage(): never {
|
|
477
|
-
console.error(usageLine());
|
|
484
|
+
console.error(`unknown command "${command}"\n${usageLine()}\nrun \`sproutboat\` with no arguments for the grouped command list`);
|
|
478
485
|
process.exit(1);
|
|
479
486
|
}
|
|
480
487
|
|
|
481
488
|
const [command, ...args] = process.argv.slice(2);
|
|
489
|
+
if (command === undefined || command === "help" || command === "-h" || command === "--help") help();
|
|
482
490
|
switch (command) {
|
|
483
491
|
case "init": await init(args[0]); break;
|
|
484
492
|
case "check": await check(args[0]); break;
|
package/src/surface.ts
CHANGED
|
@@ -1,24 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The CLI's public surface, as data. `main.ts` builds its usage
|
|
3
|
-
* this, and `surface.test.ts` renders it to `SURFACE.md` and checks that
|
|
4
|
-
* command switch, the referenced env vars, and the doc can't drift apart.
|
|
2
|
+
* The CLI's public surface, as data. `main.ts` builds its help + usage strings
|
|
3
|
+
* from this, and `surface.test.ts` renders it to `SURFACE.md` and checks that
|
|
4
|
+
* the command switch, the referenced env vars, and the doc can't drift apart.
|
|
5
5
|
*/
|
|
6
|
+
import { bold, dim, leaf } from "./style";
|
|
7
|
+
|
|
6
8
|
export const CLI_NAME = "sproutboat";
|
|
9
|
+
export const TAGLINE = "Deploy JavaScript handlers as tiny native binaries on your own VPS.";
|
|
10
|
+
export const REPO_URL = "https://github.com/baronunread/sproutboat";
|
|
11
|
+
|
|
12
|
+
export type Group = "Develop" | "Ship" | "Configure" | "Account";
|
|
7
13
|
|
|
8
|
-
export type Command = {
|
|
14
|
+
export type Command = {
|
|
15
|
+
name: string;
|
|
16
|
+
/** Full argument grammar — used by SURFACE.md and the one-line usage string. */
|
|
17
|
+
args: string;
|
|
18
|
+
/** Short argument hint shown in the grouped help list (falls back to `args`). */
|
|
19
|
+
brief?: string;
|
|
20
|
+
group: Group;
|
|
21
|
+
emoji: string;
|
|
22
|
+
summary: string;
|
|
23
|
+
};
|
|
9
24
|
|
|
10
25
|
export const COMMANDS: readonly Command[] = [
|
|
11
|
-
{ name: "init",
|
|
12
|
-
|
|
13
|
-
{ name: "
|
|
14
|
-
|
|
15
|
-
{ name: "
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
{ name: "
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
{ name: "
|
|
26
|
+
{ name: "init", group: "Develop", emoji: "🌱", args: "[name]",
|
|
27
|
+
summary: "Scaffold sproutboat.jsonc + src/index.js in ./<name>." },
|
|
28
|
+
{ name: "check", group: "Develop", emoji: "🔍", args: "[project-dir]",
|
|
29
|
+
summary: "Validate the config and entry point without building." },
|
|
30
|
+
{ name: "build", group: "Develop", emoji: "🔨", args: "[project-dir]",
|
|
31
|
+
summary: "Cross-compile the native-fetch sprout (Porffor + Zig)." },
|
|
32
|
+
|
|
33
|
+
{ name: "deploy", group: "Ship", emoji: "🚀",
|
|
34
|
+
args: "[project-dir] [--dry-run] [--artifact <dir>] [--no-wait]", brief: "[project-dir] [--dry-run]",
|
|
35
|
+
summary: "Build (unless --artifact), print the report, upload, wait until the URL serves. --dry-run stops before upload; --no-wait skips the health check." },
|
|
36
|
+
{ name: "versions", group: "Ship", emoji: "📜", args: "list [project-dir]",
|
|
37
|
+
summary: "List the project's deployed versions." },
|
|
38
|
+
{ name: "rollback", group: "Ship", emoji: "⏮", args: "<version-id> [project-dir]", brief: "<version-id>",
|
|
39
|
+
summary: "Re-activate a previous version." },
|
|
40
|
+
{ name: "tail", group: "Ship", emoji: "📡", args: "[project-dir] [--sprout]",
|
|
41
|
+
summary: "Print recent request logs; --sprout prints the running sprout + broker stdout/stderr instead." },
|
|
42
|
+
|
|
43
|
+
{ name: "domains", group: "Configure", emoji: "🌐",
|
|
44
|
+
args: "[list | add <host> | verify <host> | rm <host>] [project-dir]", brief: "[list | add | verify | rm]",
|
|
45
|
+
summary: "Attach a custom domain to the project (TXT-verified). No sub-command lists." },
|
|
46
|
+
{ name: "secrets", group: "Configure", emoji: "🔑",
|
|
47
|
+
args: "[list | set <NAME> [value] | rm <NAME>] [project-dir]", brief: "[list | set | rm]",
|
|
48
|
+
summary: "Manage encrypted project secrets (read as env.NAME). `set` takes the value from the arg or stdin; applies on next deploy." },
|
|
49
|
+
{ name: "delete", group: "Configure", emoji: "🗑",
|
|
50
|
+
args: "[project-dir] [--name <project>] --yes", brief: "[project-dir] --yes",
|
|
51
|
+
summary: "Delete the project, every version, and its route." },
|
|
52
|
+
|
|
53
|
+
{ name: "login", group: "Account", emoji: "🔓", args: "[--api-url <url>] [--token <token>]", brief: "[--token <token>]",
|
|
54
|
+
summary: "Device-code browser flow, or store <token> for <url> directly." },
|
|
22
55
|
];
|
|
23
56
|
|
|
24
57
|
export type EnvVar = { name: string; purpose: string };
|
|
@@ -40,8 +73,38 @@ export const ENV_VARS: readonly EnvVar[] = [
|
|
|
40
73
|
{ name: "SB_SPROUT_URL", purpose: "http://127.0.0.1:<PORT> of the sprout; when set, `src/broker.ts` runs the cron scheduler and queue consumer and delivers triggers to it." },
|
|
41
74
|
];
|
|
42
75
|
|
|
43
|
-
|
|
76
|
+
const GROUP_ORDER: readonly Group[] = ["Develop", "Ship", "Configure", "Account"];
|
|
77
|
+
|
|
78
|
+
/** One-line usage string, e.g. for `usage()` and SURFACE.md. */
|
|
44
79
|
export function usageLine(): string {
|
|
45
80
|
const parts = COMMANDS.map((c) => (c.args ? `${c.name} ${c.args}` : c.name));
|
|
46
81
|
return `usage: ${CLI_NAME} <${parts.join(" | ")}>`;
|
|
47
82
|
}
|
|
83
|
+
|
|
84
|
+
/** First sentence of a summary — enough for the at-a-glance command list. */
|
|
85
|
+
function firstSentence(text: string): string {
|
|
86
|
+
const end = text.indexOf(". ");
|
|
87
|
+
return end === -1 ? text.replace(/\.$/, "") : text.slice(0, end);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Wrangler-style grouped help: `sproutboat` with no command, or `--help`. */
|
|
91
|
+
export function helpText(): string {
|
|
92
|
+
const invocations = COMMANDS.map((c) => `${c.name} ${c.brief ?? c.args}`.trim());
|
|
93
|
+
const width = Math.max(...invocations.map((s) => s.length));
|
|
94
|
+
const lines: string[] = [`${bold(CLI_NAME)} — ${TAGLINE}`, "", leaf("USAGE"), ` ${CLI_NAME} <command> [options]`];
|
|
95
|
+
|
|
96
|
+
for (const group of GROUP_ORDER) {
|
|
97
|
+
lines.push("", leaf(group.toUpperCase()));
|
|
98
|
+
for (const command of COMMANDS.filter((c) => c.group === group)) {
|
|
99
|
+
const invocation = `${command.name} ${command.brief ?? command.args}`.trim();
|
|
100
|
+
lines.push(` ${invocation.padEnd(width)} ${command.emoji} ${firstSentence(command.summary)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
lines.push(
|
|
105
|
+
"",
|
|
106
|
+
dim(`Run \`${CLI_NAME} <command>\` with no/invalid args to see that command's full usage.`),
|
|
107
|
+
dim(`Docs: ${REPO_URL} · runs on Bun — use \`bunx\`, not \`npx\`.`),
|
|
108
|
+
);
|
|
109
|
+
return lines.join("\n");
|
|
110
|
+
}
|