@devdogsuga/devtools 0.1.26 → 0.1.28
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/README.md +72 -11
- package/bin/devtools.mjs +4 -4
- package/dist/cli-CZKkNHK5.js +6619 -0
- package/dist/failure-log-BBPGejQv.js +256 -0
- package/dist/launch.js +267 -281
- package/dist/local-env-D8HC2JK_.js +351 -0
- package/dist/local-env-DrBCXqD8.js +2 -0
- package/dist/menu-CQBsQRgH.js +1684 -0
- package/dist/peer-redirect-hooks.js +15 -0
- package/dist/peers-RBplwovA.js +229 -0
- package/dist/root-C2OmZDwD.js +94 -0
- package/dist/stack-Bx-55oi_.js +2 -0
- package/dist/stack-BynCgRVS.js +181 -0
- package/dist/supabase-project-0knM0mqd.js +426 -0
- package/dist/telemetry-C4foD8MD.js +249 -0
- package/dist/telemetry.js +2 -148
- package/package.json +10 -29
- package/bin/devtools-ci-bare.mjs +0 -48
- package/bin/devtools-ci.mjs +0 -31
- package/dist/args.d.ts +0 -26
- package/dist/args.js +0 -78
- package/dist/bws/bw.d.ts +0 -18
- package/dist/bws/bw.js +0 -70
- package/dist/bws/client.d.ts +0 -43
- package/dist/bws/client.js +0 -363
- package/dist/bws/environments.d.ts +0 -96
- package/dist/bws/environments.js +0 -111
- package/dist/bws/pace.d.ts +0 -25
- package/dist/bws/pace.js +0 -43
- package/dist/bws/retry.d.ts +0 -12
- package/dist/bws/retry.js +0 -39
- package/dist/bws/store.d.ts +0 -1
- package/dist/bws/store.js +0 -32
- package/dist/bws/token.d.ts +0 -31
- package/dist/bws/token.js +0 -88
- package/dist/bws/vault.d.ts +0 -29
- package/dist/bws/vault.js +0 -200
- package/dist/catalog.d.ts +0 -57
- package/dist/catalog.js +0 -57
- package/dist/cf/build.d.ts +0 -13
- package/dist/cf/build.js +0 -65
- package/dist/cf/commands.d.ts +0 -1
- package/dist/cf/commands.js +0 -172
- package/dist/cf/local-env.d.ts +0 -58
- package/dist/cf/local-env.js +0 -177
- package/dist/ci.d.ts +0 -1
- package/dist/ci.js +0 -328
- package/dist/cli.d.ts +0 -11
- package/dist/cli.js +0 -1094
- package/dist/commands.d.ts +0 -261
- package/dist/commands.js +0 -1318
- package/dist/completions.d.ts +0 -4
- package/dist/completions.js +0 -110
- package/dist/cron/commands.d.ts +0 -47
- package/dist/cron/commands.js +0 -372
- package/dist/cron/discovery.d.ts +0 -55
- package/dist/cron/discovery.js +0 -85
- package/dist/cron/schema.d.ts +0 -45
- package/dist/cron/schema.js +0 -35
- package/dist/db/config-push.d.ts +0 -8
- package/dist/db/config-push.js +0 -11
- package/dist/db/connection.d.ts +0 -79
- package/dist/db/connection.js +0 -114
- package/dist/db/exec.d.ts +0 -1
- package/dist/db/exec.js +0 -11
- package/dist/db/generate-types.d.ts +0 -1
- package/dist/db/generate-types.js +0 -4
- package/dist/db/generated-env.d.ts +0 -69
- package/dist/db/generated-env.js +0 -113
- package/dist/db/introspect.d.ts +0 -1
- package/dist/db/introspect.js +0 -122
- package/dist/db/local-env.d.ts +0 -65
- package/dist/db/local-env.js +0 -23
- package/dist/db/new-migration.d.ts +0 -8
- package/dist/db/new-migration.js +0 -69
- package/dist/db/pooler.d.ts +0 -23
- package/dist/db/pooler.js +0 -55
- package/dist/db/run.d.ts +0 -68
- package/dist/db/run.js +0 -156
- package/dist/db/seed-buckets.d.ts +0 -2
- package/dist/db/seed-buckets.js +0 -4
- package/dist/db/seed-production.d.ts +0 -8
- package/dist/db/seed-production.js +0 -79
- package/dist/db/seed-roles.d.ts +0 -7
- package/dist/db/seed-roles.js +0 -33
- package/dist/db/session-refresh.d.ts +0 -43
- package/dist/db/session-refresh.js +0 -40
- package/dist/deploy/migrations.d.ts +0 -20
- package/dist/deploy/migrations.js +0 -68
- package/dist/deploy/orphans.d.ts +0 -20
- package/dist/deploy/orphans.js +0 -177
- package/dist/deploy/preflight.d.ts +0 -53
- package/dist/deploy/preflight.js +0 -189
- package/dist/deploy/report.d.ts +0 -26
- package/dist/deploy/report.js +0 -70
- package/dist/deploy/require-planner.d.ts +0 -2
- package/dist/deploy/require-planner.js +0 -60
- package/dist/deploy/require-token.d.ts +0 -15
- package/dist/deploy/require-token.js +0 -78
- package/dist/deploy/secrets-file.d.ts +0 -17
- package/dist/deploy/secrets-file.js +0 -166
- package/dist/deploy/write-env.d.ts +0 -40
- package/dist/deploy/write-env.js +0 -395
- package/dist/docs/index-pages.d.ts +0 -38
- package/dist/docs/index-pages.js +0 -186
- package/dist/emails/commands.d.ts +0 -15
- package/dist/emails/commands.js +0 -130
- package/dist/emails/email-types.d.ts +0 -13
- package/dist/emails/email-types.js +0 -1
- package/dist/emails/fixtures.d.ts +0 -20
- package/dist/emails/fixtures.js +0 -20
- package/dist/env/audit.d.ts +0 -206
- package/dist/env/audit.js +0 -436
- package/dist/env/cloudflare.d.ts +0 -21
- package/dist/env/cloudflare.js +0 -61
- package/dist/env/commands.d.ts +0 -99
- package/dist/env/commands.js +0 -613
- package/dist/env/discovery.d.ts +0 -15
- package/dist/env/discovery.js +0 -239
- package/dist/env/document.d.ts +0 -119
- package/dist/env/document.js +0 -323
- package/dist/env/example.d.ts +0 -68
- package/dist/env/example.js +0 -605
- package/dist/env/selection.d.ts +0 -105
- package/dist/env/selection.js +0 -228
- package/dist/env-entry.d.ts +0 -49
- package/dist/env-entry.js +0 -204
- package/dist/environment-doctor.d.ts +0 -45
- package/dist/environment-doctor.js +0 -429
- package/dist/environment.d.ts +0 -92
- package/dist/environment.js +0 -185
- package/dist/fingerprint.d.ts +0 -10
- package/dist/fingerprint.js +0 -18
- package/dist/gen/campus-map.d.ts +0 -1
- package/dist/gen/campus-map.js +0 -473
- package/dist/gen/commands.d.ts +0 -1
- package/dist/gen/commands.js +0 -25
- package/dist/gen/hypno.d.ts +0 -1
- package/dist/gen/hypno.js +0 -134
- package/dist/gh/client.d.ts +0 -80
- package/dist/gh/client.js +0 -259
- package/dist/gh/environments.d.ts +0 -83
- package/dist/gh/environments.js +0 -178
- package/dist/gh/rulesets/actors.d.ts +0 -14
- package/dist/gh/rulesets/actors.js +0 -69
- package/dist/gh/rulesets/api.d.ts +0 -15
- package/dist/gh/rulesets/api.js +0 -104
- package/dist/gh/rulesets/commands.d.ts +0 -3
- package/dist/gh/rulesets/commands.js +0 -203
- package/dist/gh/rulesets/desired.d.ts +0 -112
- package/dist/gh/rulesets/desired.js +0 -271
- package/dist/gh/rulesets/diff.d.ts +0 -65
- package/dist/gh/rulesets/diff.js +0 -170
- package/dist/gh/rulesets/types.d.ts +0 -76
- package/dist/gh/rulesets/types.js +0 -13
- package/dist/gh/settings/api.d.ts +0 -40
- package/dist/gh/settings/api.js +0 -180
- package/dist/gh/settings/commands.d.ts +0 -1
- package/dist/gh/settings/commands.js +0 -254
- package/dist/gh/settings/desired.d.ts +0 -53
- package/dist/gh/settings/desired.js +0 -43
- package/dist/gh/settings/diff.d.ts +0 -57
- package/dist/gh/settings/diff.js +0 -161
- package/dist/gh/settings/types.d.ts +0 -92
- package/dist/gh/settings/types.js +0 -11
- package/dist/gh/settings/workflows.d.ts +0 -41
- package/dist/gh/settings/workflows.js +0 -128
- package/dist/grantRoot.d.ts +0 -42
- package/dist/grantRoot.js +0 -89
- package/dist/help.d.ts +0 -18
- package/dist/help.js +0 -169
- package/dist/images/commands.d.ts +0 -32
- package/dist/images/commands.js +0 -231
- package/dist/images/events.d.ts +0 -47
- package/dist/images/events.js +0 -116
- package/dist/images/graphics.d.ts +0 -70
- package/dist/images/graphics.js +0 -234
- package/dist/images/open-graph-types.d.ts +0 -75
- package/dist/images/open-graph-types.js +0 -1
- package/dist/images/prompts.d.ts +0 -34
- package/dist/images/prompts.js +0 -100
- package/dist/images/render.d.ts +0 -21
- package/dist/images/render.js +0 -61
- package/dist/images/select.d.ts +0 -64
- package/dist/images/select.js +0 -96
- package/dist/instance.d.ts +0 -69
- package/dist/instance.js +0 -102
- package/dist/invocation.d.ts +0 -49
- package/dist/invocation.js +0 -78
- package/dist/launch-ci.d.ts +0 -1
- package/dist/launch-ci.js +0 -90
- package/dist/launch.d.ts +0 -18
- package/dist/menu.d.ts +0 -43
- package/dist/menu.js +0 -300
- package/dist/moderation.d.ts +0 -70
- package/dist/moderation.js +0 -128
- package/dist/oauth/browser.d.ts +0 -1
- package/dist/oauth/browser.js +0 -13
- package/dist/oauth/config.d.ts +0 -24
- package/dist/oauth/config.js +0 -24
- package/dist/oauth/connect-url.d.ts +0 -17
- package/dist/oauth/connect-url.js +0 -23
- package/dist/oauth/db.d.ts +0 -37
- package/dist/oauth/db.js +0 -108
- package/dist/oauth/device.d.ts +0 -93
- package/dist/oauth/device.js +0 -198
- package/dist/oauth/discovery.d.ts +0 -28
- package/dist/oauth/discovery.js +0 -54
- package/dist/oauth/env-file.d.ts +0 -6
- package/dist/oauth/env-file.js +0 -35
- package/dist/oauth/exchange.d.ts +0 -43
- package/dist/oauth/exchange.js +0 -93
- package/dist/oauth/label.d.ts +0 -1
- package/dist/oauth/label.js +0 -25
- package/dist/oauth/loopback.d.ts +0 -52
- package/dist/oauth/loopback.js +0 -168
- package/dist/oauth/pkce.d.ts +0 -6
- package/dist/oauth/pkce.js +0 -34
- package/dist/oauth/target.d.ts +0 -54
- package/dist/oauth/target.js +0 -102
- package/dist/oauth/transport.d.ts +0 -41
- package/dist/oauth/transport.js +0 -32
- package/dist/oauth/wizard.d.ts +0 -40
- package/dist/oauth/wizard.js +0 -578
- package/dist/persona.d.ts +0 -18
- package/dist/persona.js +0 -221
- package/dist/pick.d.ts +0 -6
- package/dist/pick.js +0 -64
- package/dist/pipes.d.ts +0 -1
- package/dist/pipes.js +0 -25
- package/dist/planner/checks.d.ts +0 -26
- package/dist/planner/checks.js +0 -104
- package/dist/planner/commands.d.ts +0 -10
- package/dist/planner/commands.js +0 -367
- package/dist/planner/db.d.ts +0 -15
- package/dist/planner/db.js +0 -33
- package/dist/planner/role.d.ts +0 -33
- package/dist/planner/role.js +0 -68
- package/dist/repo/peer-redirect-hooks.d.ts +0 -16
- package/dist/repo/peer-redirect-hooks.js +0 -10
- package/dist/repo/peer-redirect.d.ts +0 -4
- package/dist/repo/peer-redirect.js +0 -26
- package/dist/repo/peers.d.ts +0 -39
- package/dist/repo/peers.js +0 -139
- package/dist/repo/resolve.d.ts +0 -41
- package/dist/repo/resolve.js +0 -152
- package/dist/repo/root.d.ts +0 -23
- package/dist/repo/root.js +0 -91
- package/dist/repo/source.d.ts +0 -14
- package/dist/repo/source.js +0 -54
- package/dist/repo/supabase-project.d.ts +0 -60
- package/dist/repo/supabase-project.js +0 -124
- package/dist/repo/tsx-loader.d.ts +0 -6
- package/dist/repo/tsx-loader.js +0 -41
- package/dist/run/pick.d.ts +0 -90
- package/dist/run/pick.js +0 -664
- package/dist/setup.d.ts +0 -1
- package/dist/setup.js +0 -280
- package/dist/stack.d.ts +0 -48
- package/dist/stack.js +0 -403
- package/dist/telemetry.d.ts +0 -59
- package/dist/tier.d.ts +0 -40
- package/dist/tier.js +0 -96
- package/dist/ui.d.ts +0 -40
- package/dist/ui.js +0 -71
- package/dist/version.d.ts +0 -7
- package/dist/version.js +0 -17
- package/dist/workers.d.ts +0 -5
- package/dist/workers.js +0 -33
- package/dist/workflows/commands.d.ts +0 -54
- package/dist/workflows/commands.js +0 -763
package/dist/commands.js
DELETED
|
@@ -1,1318 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The command tree, as data.
|
|
3
|
-
*
|
|
4
|
-
* One declaration, three readers:
|
|
5
|
-
*
|
|
6
|
-
* * `help.ts` renders it, one level at a time.
|
|
7
|
-
* * `menu.ts` walks its interactive commands and options without a second
|
|
8
|
-
* list to keep in step.
|
|
9
|
-
* * contributor documentation uses the same group and command vocabulary.
|
|
10
|
-
*
|
|
11
|
-
* It is deliberately inert: names, summaries and option shapes, no imports of
|
|
12
|
-
* anything that runs. `cli.ts` owns dispatch; the wizard turns a walk of this
|
|
13
|
-
* tree into an argv and hands it to that same dispatcher, which keeps menu and
|
|
14
|
-
* CLI behavior aligned by construction rather than by review.
|
|
15
|
-
*
|
|
16
|
-
* One exception: `WORKER_APP_CHOICES` imports the shared `WORKER_APPS` list
|
|
17
|
-
* (root `workers.json`) so `cf preview`/`typegen`/`build`'s `--app` choices
|
|
18
|
-
* cannot drift from the six-site source of truth. It is data — a string
|
|
19
|
-
* array read from a JSON file — not a function this file calls.
|
|
20
|
-
*
|
|
21
|
-
* ## What a summary is for
|
|
22
|
-
*
|
|
23
|
-
* Every `summary` is one line and is the ONLY thing `--help` prints for a
|
|
24
|
-
* command at the level above it. Rationale, target tables, credential lookup
|
|
25
|
-
* order and deploy internals live in `docs/`, not here: `--help` is a map, and
|
|
26
|
-
* a map that reprints the territory is the thing this replaced.
|
|
27
|
-
*/
|
|
28
|
-
import { workerApps } from "./workers.js";
|
|
29
|
-
/**
|
|
30
|
-
* The `--app <slug>` choices shared by `cf preview`/`typegen`/`build`.
|
|
31
|
-
*
|
|
32
|
-
* `workerApps()` reads `workers.json` via `findRepoRoot()`, which throws
|
|
33
|
-
* outside a DevDogsUGA checkout — and this module (via `help.ts`/`menu.ts`)
|
|
34
|
-
* is imported for `devtools --help`, which must work from anywhere,
|
|
35
|
-
* `/tmp` included (see `workers.ts`'s header). The tree below is built once
|
|
36
|
-
* at import time regardless, so this falls back to an empty choice list
|
|
37
|
-
* rather than propagating the throw: `--help` still renders the command
|
|
38
|
-
* shape with no `--app` values listed, and any actual `cf preview --app …`
|
|
39
|
-
* invocation outside a repo fails with the same clear `RepoNotFoundError`
|
|
40
|
-
* it always would have, just a little further downstream.
|
|
41
|
-
*/
|
|
42
|
-
const WORKER_APP_CHOICES = (() => {
|
|
43
|
-
try {
|
|
44
|
-
return workerApps().map((app) => ({ value: app, label: app }));
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return [];
|
|
48
|
-
}
|
|
49
|
-
})();
|
|
50
|
-
/**
|
|
51
|
-
* How each scope reads, in the two places that draw it.
|
|
52
|
-
*
|
|
53
|
-
* `menu` sits inline in a hint, so it is one word. `help` heads a block of
|
|
54
|
-
* commands, so it can be a phrase. Both live here rather than in the renderers
|
|
55
|
-
* because they are labels, the same kind of data as a group title.
|
|
56
|
-
*/
|
|
57
|
-
export const SCOPES = {
|
|
58
|
-
machine: { menu: "This machine", help: "Supabase on this machine" },
|
|
59
|
-
repo: { menu: "Repo", help: "files in the repo" },
|
|
60
|
-
endpoint: { menu: "Database", help: "the session's database (--tier)" },
|
|
61
|
-
infra: {
|
|
62
|
-
menu: "Hosted",
|
|
63
|
-
help: "hosted infrastructure, each naming its own connection",
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
// ── Exit codes ───────────────────────────────────────────────────────────────
|
|
67
|
-
/** Standard success. */
|
|
68
|
-
export const EXIT_OK = 0;
|
|
69
|
-
/** Command failed. */
|
|
70
|
-
export const EXIT_FAIL = 1;
|
|
71
|
-
/** `--check` found drift. Distinct from failure so scripts can tell them apart. */
|
|
72
|
-
export const EXIT_DRIFT = 2;
|
|
73
|
-
// ── Shared option shapes ─────────────────────────────────────────────────────
|
|
74
|
-
/**
|
|
75
|
-
* `docs index`'s delete acknowledgment — NOT a database selector.
|
|
76
|
-
*
|
|
77
|
-
* The db namespace's old `--target local|remote` flag is retired outright
|
|
78
|
-
* (the SESSION names the database now — see `db/connection.ts`), but `docs
|
|
79
|
-
* index` keeps this spelling for a different job: its prune deletes rows,
|
|
80
|
-
* and running that against a non-local `DB_URL` requires saying so out
|
|
81
|
-
* loud. The database itself still comes from the session's env.
|
|
82
|
-
*/
|
|
83
|
-
export const DOCS_TARGET = {
|
|
84
|
-
flag: "--target",
|
|
85
|
-
value: "<local|remote>",
|
|
86
|
-
summary: "Acknowledge indexing a non-local DB_URL. Defaults to local-only.",
|
|
87
|
-
prompt: {
|
|
88
|
-
kind: "select",
|
|
89
|
-
message: "May this prune a non-local database?",
|
|
90
|
-
choices: [
|
|
91
|
-
{ value: "local", label: "Local only", hint: "the default" },
|
|
92
|
-
{ value: "remote", label: "Yes — the session's remote DB_URL" },
|
|
93
|
-
],
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
/**
|
|
97
|
-
* The deployment-tier selector, for the commands that resolve a tier of
|
|
98
|
-
* their OWN (cron/workflows run against a chosen tier's env). The session's
|
|
99
|
-
* global `--tier` — `development:local|development:remote|staging|production`,
|
|
100
|
-
* stripped by the launcher before dispatch — is a superset of this
|
|
101
|
-
* vocabulary; this per-command flag still reads plain tiers.
|
|
102
|
-
*/
|
|
103
|
-
export const TIER = {
|
|
104
|
-
flag: "--tier",
|
|
105
|
-
value: "<t>",
|
|
106
|
-
summary: "Which deployment tier. Asked for when absent.",
|
|
107
|
-
};
|
|
108
|
-
/** Print what would change; write nothing; exit 0. On every command that writes. */
|
|
109
|
-
export const DRY_RUN = {
|
|
110
|
-
flag: "--dry-run",
|
|
111
|
-
summary: "Print what would change, write nothing, exit 0.",
|
|
112
|
-
};
|
|
113
|
-
/** Verify correctness; write nothing; exit 2 on drift. */
|
|
114
|
-
export const CHECK = {
|
|
115
|
-
flag: "--check",
|
|
116
|
-
summary: "Verify, write nothing, exit 2 on drift.",
|
|
117
|
-
};
|
|
118
|
-
/**
|
|
119
|
-
* Machine-readable output to stdout.
|
|
120
|
-
*
|
|
121
|
-
* Promptless by design: the wizard is already interactive; a flag that switches
|
|
122
|
-
* its output format has no meaning there. `commands.test.ts` pins the promptless
|
|
123
|
-
* set with a "scripting-only" category for exactly this kind of flag.
|
|
124
|
-
*/
|
|
125
|
-
export const JSON_FLAG = {
|
|
126
|
-
flag: "--json",
|
|
127
|
-
summary: "Print machine-readable JSON to stdout.",
|
|
128
|
-
};
|
|
129
|
-
const VAULT_TARGET = {
|
|
130
|
-
flag: "--target",
|
|
131
|
-
value: "<t>",
|
|
132
|
-
summary: "preflight, staging or production. Asked for when absent.",
|
|
133
|
-
// No prompt: `pick.ts` already owns this question, and it orders the list
|
|
134
|
-
// least- to most-dangerous so a reflexive Enter cannot select production.
|
|
135
|
-
// Duplicating it here would put production one keystroke closer.
|
|
136
|
-
};
|
|
137
|
-
/**
|
|
138
|
-
* The three flags every `run` task takes.
|
|
139
|
-
*
|
|
140
|
-
* None carries a `prompt`, and that is the point rather than an omission.
|
|
141
|
-
* `run` opens a multiselect of the apps defining the task, so a wizard that
|
|
142
|
-
* asked "every package?", "which filter?" and "which tier?" up front would
|
|
143
|
-
* ask the same question three times and let the answers disagree. `--tier`
|
|
144
|
-
* is promptless for a different reason than `--filter`/`--all`, though: it is
|
|
145
|
-
* not a question `run` asks itself elsewhere (unlike `cron run`'s own
|
|
146
|
-
* `--tier`, which opens a live picker) — it is a scripting input with no
|
|
147
|
-
* wizard equivalent, the same category `--json` sits in. `--help` still
|
|
148
|
-
* documents all three, which is where someone scripting this will look.
|
|
149
|
-
*
|
|
150
|
-
* Same reasoning as `VAULT_TARGET` above: the command owns the question, so the
|
|
151
|
-
* tree declares the flag and stays quiet.
|
|
152
|
-
*/
|
|
153
|
-
const RUN_OPTIONS = [
|
|
154
|
-
{
|
|
155
|
-
flag: "--filter",
|
|
156
|
-
value: "<pkg>",
|
|
157
|
-
summary: "Limit to a package. pnpm's own flag; skips the question.",
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
flag: "--all",
|
|
161
|
-
summary: "Every package, unfiltered, with nothing asked.",
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
flag: "--tier",
|
|
165
|
-
value: "<t>",
|
|
166
|
-
summary: "Load a tier's env into the run. CLI-only; never prompted.",
|
|
167
|
-
},
|
|
168
|
-
];
|
|
169
|
-
const ENV_FILE = {
|
|
170
|
-
flag: "--file",
|
|
171
|
-
value: "<path>",
|
|
172
|
-
summary: "Read and write this file instead of the target's own.",
|
|
173
|
-
};
|
|
174
|
-
/** Skip every interactive confirmation prompt. On every destructive command. */
|
|
175
|
-
export const YES = {
|
|
176
|
-
flag: "--yes",
|
|
177
|
-
summary: "Skip the confirmations.",
|
|
178
|
-
};
|
|
179
|
-
const ACCESS_TOKEN = {
|
|
180
|
-
flag: "--access-token",
|
|
181
|
-
value: "<token>",
|
|
182
|
-
summary: "Bitwarden Secrets Manager token. Prefer the vault or the env var.",
|
|
183
|
-
};
|
|
184
|
-
const DB_URL = {
|
|
185
|
-
flag: "--db-url",
|
|
186
|
-
value: "<url>",
|
|
187
|
-
summary: "Privileged connection. Defaults to .env.production's DB_URL.",
|
|
188
|
-
prompt: {
|
|
189
|
-
kind: "text",
|
|
190
|
-
message: "Connection URL? (blank uses .env.production's DB_URL)",
|
|
191
|
-
optional: true,
|
|
192
|
-
},
|
|
193
|
-
};
|
|
194
|
-
// ── The tree ─────────────────────────────────────────────────────────────────
|
|
195
|
-
const DECLARED_GROUPS = [
|
|
196
|
-
{
|
|
197
|
-
title: "Start here",
|
|
198
|
-
commands: [
|
|
199
|
-
{
|
|
200
|
-
name: "setup",
|
|
201
|
-
summary: "Check prerequisites and seed .env.",
|
|
202
|
-
hint: "run this first",
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
name: "completions",
|
|
206
|
-
summary: "Output a shell completion script for devtools.",
|
|
207
|
-
hint: "pipe to source or write to a file",
|
|
208
|
-
surface: "cli-only",
|
|
209
|
-
options: [
|
|
210
|
-
{
|
|
211
|
-
flag: "--shell",
|
|
212
|
-
value: "<bash|zsh>",
|
|
213
|
-
summary: "Target shell. Asked for when absent.",
|
|
214
|
-
prompt: {
|
|
215
|
-
kind: "select",
|
|
216
|
-
message: "Which shell?",
|
|
217
|
-
choices: [{ value: "bash" }, { value: "zsh" }],
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
],
|
|
221
|
-
},
|
|
222
|
-
],
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
title: "Workspace",
|
|
226
|
-
commands: [
|
|
227
|
-
{
|
|
228
|
-
name: "run",
|
|
229
|
-
summary: "Run a pnpm workspace task, asking which apps first.",
|
|
230
|
-
hint: "build, dev, lint…",
|
|
231
|
-
// The six with a root alias, which are the six a contributor types.
|
|
232
|
-
// NOT an exhaustive list of every package script: `run` forwards
|
|
233
|
-
// whatever name it is given, so `test:coverage` works without being
|
|
234
|
-
// listed here, and this CLI's own unrelated `deploy` command group
|
|
235
|
-
// stays out of a menu where a same-named package script would sit
|
|
236
|
-
// one line away from it.
|
|
237
|
-
subcommands: [
|
|
238
|
-
{
|
|
239
|
-
name: "build",
|
|
240
|
-
summary: "Compile every package an app needs.",
|
|
241
|
-
options: RUN_OPTIONS,
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
name: "dev",
|
|
245
|
-
summary: "Start the development servers.",
|
|
246
|
-
options: RUN_OPTIONS,
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
name: "typecheck",
|
|
250
|
-
summary: "Run tsc across the workspace.",
|
|
251
|
-
options: RUN_OPTIONS,
|
|
252
|
-
},
|
|
253
|
-
{
|
|
254
|
-
name: "lint",
|
|
255
|
-
summary: "Run ESLint across the workspace.",
|
|
256
|
-
options: RUN_OPTIONS,
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
name: "lint:fix",
|
|
260
|
-
summary: "Run ESLint and write what it can fix.",
|
|
261
|
-
options: RUN_OPTIONS,
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
name: "test",
|
|
265
|
-
summary: "Run the unit tests.",
|
|
266
|
-
options: RUN_OPTIONS,
|
|
267
|
-
},
|
|
268
|
-
],
|
|
269
|
-
},
|
|
270
|
-
],
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
title: "Brand",
|
|
274
|
-
commands: [
|
|
275
|
-
{
|
|
276
|
-
name: "emails",
|
|
277
|
-
summary: "Render populated transactional email previews.",
|
|
278
|
-
hint: "HTML or plain text, one template or all",
|
|
279
|
-
// Like `images`, this command owns its dependent questions: formats
|
|
280
|
-
// and output only make sense after the templates have been selected.
|
|
281
|
-
options: [
|
|
282
|
-
{
|
|
283
|
-
flag: "--format",
|
|
284
|
-
value: "<html,text>",
|
|
285
|
-
summary: "Outputs to write. Defaults to html.",
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
flag: "--out",
|
|
289
|
-
value: "<dir>",
|
|
290
|
-
summary: "Output directory. Defaults to ./email-previews.",
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
flag: "--dry-run",
|
|
294
|
-
summary: "List subjects and destination files without writing.",
|
|
295
|
-
},
|
|
296
|
-
],
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
name: "images",
|
|
300
|
-
summary: "Render a club image at one or more sizes.",
|
|
301
|
-
hint: "brand/*, page/*, app/*, event/*, or * for all",
|
|
302
|
-
// No subcommands: graphics are positional, and several can be named at
|
|
303
|
-
// once. The command owns its interactive path because it can ask in CLI
|
|
304
|
-
// order — graphic, format, output — and derive each question from the
|
|
305
|
-
// previous answer. The outer wizard therefore dispatches bare `images`;
|
|
306
|
-
// these options remain here for help and scripted invocations.
|
|
307
|
-
options: [
|
|
308
|
-
{
|
|
309
|
-
flag: "--format",
|
|
310
|
-
value: "<a,b,…>",
|
|
311
|
-
summary: "Sizes to render: og, gdgc-wide, gdgc-square, savvycal, email-*, icon-*.",
|
|
312
|
-
// Not prompted here: the command asks itself, from the formats the
|
|
313
|
-
// chosen graphics actually support, which a static list cannot know.
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
flag: "--all-formats",
|
|
317
|
-
summary: "Every size the named graphics support.",
|
|
318
|
-
},
|
|
319
|
-
{
|
|
320
|
-
flag: "--out",
|
|
321
|
-
value: "<dir>",
|
|
322
|
-
summary: "Write everything into one directory, flat.",
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
flag: "--default-out",
|
|
326
|
-
summary: "Write each image where it belongs in the repo.",
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
flag: "--dry-run",
|
|
330
|
-
summary: "List what would be written, and what each size is for.",
|
|
331
|
-
},
|
|
332
|
-
],
|
|
333
|
-
},
|
|
334
|
-
],
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
title: "Moderation",
|
|
338
|
-
commands: [
|
|
339
|
-
{
|
|
340
|
-
name: "moderation",
|
|
341
|
-
summary: "An app's moderation integration: the catalog and its wiring.",
|
|
342
|
-
hint: "check",
|
|
343
|
-
subcommands: [
|
|
344
|
-
{
|
|
345
|
-
name: "check",
|
|
346
|
-
summary: "List the catalog, or check one app's moderation integration.",
|
|
347
|
-
hint: "reasons and content types with no --app; per-app wiring with one",
|
|
348
|
-
// No `needs: "instance-running"` any more — this resolves through
|
|
349
|
-
// the session system now (`resolveInstance`, `instance.ts`), the
|
|
350
|
-
// same as `db migrate`/`db reset`, so it works against a hosted
|
|
351
|
-
// development database with no local stack at all. Refuses
|
|
352
|
-
// staging/production itself, with its own message, rather than a
|
|
353
|
-
// menu-only hint.
|
|
354
|
-
options: [
|
|
355
|
-
{
|
|
356
|
-
flag: "--app",
|
|
357
|
-
value: "<slug>",
|
|
358
|
-
summary: "App to check. Prints the catalog when absent.",
|
|
359
|
-
},
|
|
360
|
-
JSON_FLAG,
|
|
361
|
-
],
|
|
362
|
-
},
|
|
363
|
-
],
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
name: "grant-root",
|
|
367
|
-
summary: "Give an account every permission on your own database.",
|
|
368
|
-
// Also on the session system now — every tier, not just local. See
|
|
369
|
-
// `check`'s note above; production additionally gets `YES`'s stern
|
|
370
|
-
// confirmation, the same treatment `db reset` gives it.
|
|
371
|
-
options: [
|
|
372
|
-
{
|
|
373
|
-
flag: "--user",
|
|
374
|
-
value: "<email>",
|
|
375
|
-
summary: "Account to grant Root to. Asked for when absent.",
|
|
376
|
-
},
|
|
377
|
-
YES,
|
|
378
|
-
],
|
|
379
|
-
},
|
|
380
|
-
],
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
title: "Personas",
|
|
384
|
-
commands: [
|
|
385
|
-
{
|
|
386
|
-
name: "persona",
|
|
387
|
-
summary: "A throwaway member or moderator account for development.",
|
|
388
|
-
hint: "member, moderator, or --clean",
|
|
389
|
-
options: [
|
|
390
|
-
{
|
|
391
|
-
flag: "--clean",
|
|
392
|
-
summary: "Delete every account this command has created, instead of making one.",
|
|
393
|
-
prompt: {
|
|
394
|
-
kind: "confirm",
|
|
395
|
-
message: "Clean up every persona this command created, instead of making one?",
|
|
396
|
-
initial: false,
|
|
397
|
-
},
|
|
398
|
-
},
|
|
399
|
-
],
|
|
400
|
-
},
|
|
401
|
-
],
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
title: "Environment",
|
|
405
|
-
commands: [
|
|
406
|
-
{
|
|
407
|
-
name: "doctor",
|
|
408
|
-
summary: "Check this machine's environment against what the repo needs.",
|
|
409
|
-
hint: "node, pnpm, Docker, .env, hosted Supabase, OAuth — read-only",
|
|
410
|
-
options: [
|
|
411
|
-
{
|
|
412
|
-
flag: "--app",
|
|
413
|
-
value: "<slug>",
|
|
414
|
-
summary: "Scope checks to one app. Defaults to every app you have env for.",
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
flag: "--report",
|
|
418
|
-
summary: "Print a redacted, paste-able block (versions, OS, results — no secrets).",
|
|
419
|
-
},
|
|
420
|
-
],
|
|
421
|
-
},
|
|
422
|
-
],
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
title: "Generate",
|
|
426
|
-
commands: [
|
|
427
|
-
{
|
|
428
|
-
name: "gen",
|
|
429
|
-
summary: "Regenerate committed, generated source.",
|
|
430
|
-
hint: "refresh a tracked artifact",
|
|
431
|
-
subcommands: [
|
|
432
|
-
{
|
|
433
|
-
name: "campus-map",
|
|
434
|
-
summary: "Rebuild the FindUs campus map from OpenStreetMap.",
|
|
435
|
-
hint: "occasional — rerun when OSM improves the area",
|
|
436
|
-
},
|
|
437
|
-
{
|
|
438
|
-
name: "hypno",
|
|
439
|
-
summary: "Bake the hero spiral into a pre-blurred raster.",
|
|
440
|
-
hint: "needs Playwright",
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
name: "og-assets",
|
|
444
|
-
summary: "Re-embed OG fonts, icons and brand art.",
|
|
445
|
-
hint: "after a brand, font or Phosphor bump",
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
name: "email-templates",
|
|
449
|
-
summary: "Recompile the transactional email chunks.",
|
|
450
|
-
hint: "render → tokenize → emit",
|
|
451
|
-
},
|
|
452
|
-
],
|
|
453
|
-
},
|
|
454
|
-
],
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
title: "Cron",
|
|
458
|
-
commands: [
|
|
459
|
-
{
|
|
460
|
-
name: "cron",
|
|
461
|
-
summary: "Cloudflare cron triggers: list schedules or fire one now.",
|
|
462
|
-
hint: "list schedules, run a job",
|
|
463
|
-
subcommands: [
|
|
464
|
-
{
|
|
465
|
-
name: "list",
|
|
466
|
-
summary: "Every registered cron: schedule, English description, routes.",
|
|
467
|
-
hint: "the audit view",
|
|
468
|
-
options: [
|
|
469
|
-
{
|
|
470
|
-
flag: "--app",
|
|
471
|
-
value: "<slug>",
|
|
472
|
-
summary: "Limit to one app. All apps if omitted.",
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
flag: "--tier",
|
|
476
|
-
value: "<t>",
|
|
477
|
-
summary: "Whose wrangler schedules to read. All tiers if omitted.",
|
|
478
|
-
prompt: {
|
|
479
|
-
kind: "select",
|
|
480
|
-
message: "Which tier's wrangler schedules?",
|
|
481
|
-
choices: [
|
|
482
|
-
{ value: "development", hint: "the default" },
|
|
483
|
-
{ value: "staging" },
|
|
484
|
-
{ value: "production" },
|
|
485
|
-
],
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
JSON_FLAG,
|
|
489
|
-
],
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
name: "run",
|
|
493
|
-
summary: "Choose and fire a configured cron schedule now.",
|
|
494
|
-
hint: "pick a job from the Worker configuration",
|
|
495
|
-
options: [
|
|
496
|
-
{
|
|
497
|
-
flag: "--app",
|
|
498
|
-
value: "<slug>",
|
|
499
|
-
summary: "Limit the discovered jobs to one app.",
|
|
500
|
-
},
|
|
501
|
-
{
|
|
502
|
-
flag: "--tier",
|
|
503
|
-
value: "<t>",
|
|
504
|
-
summary: "development, staging or production. Asked when absent.",
|
|
505
|
-
},
|
|
506
|
-
{
|
|
507
|
-
flag: "--cron",
|
|
508
|
-
value: "<expr>",
|
|
509
|
-
summary: "Fire this schedule without opening the picker.",
|
|
510
|
-
},
|
|
511
|
-
YES,
|
|
512
|
-
],
|
|
513
|
-
},
|
|
514
|
-
],
|
|
515
|
-
},
|
|
516
|
-
{
|
|
517
|
-
name: "workflows",
|
|
518
|
-
summary: "Cloudflare Workflows: list configured bindings or trigger one.",
|
|
519
|
-
hint: "pick a workflow from wrangler.jsonc",
|
|
520
|
-
subcommands: [
|
|
521
|
-
{
|
|
522
|
-
name: "list",
|
|
523
|
-
summary: "List every Workflow binding declared by each Wrangler tier.",
|
|
524
|
-
options: [
|
|
525
|
-
{
|
|
526
|
-
flag: "--app",
|
|
527
|
-
value: "<slug>",
|
|
528
|
-
summary: "Limit to one app.",
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
flag: "--tier",
|
|
532
|
-
value: "<t>",
|
|
533
|
-
summary: "Limit to development, staging or production.",
|
|
534
|
-
},
|
|
535
|
-
JSON_FLAG,
|
|
536
|
-
],
|
|
537
|
-
},
|
|
538
|
-
{
|
|
539
|
-
name: "run",
|
|
540
|
-
summary: "Choose and trigger a Workflow through Wrangler.",
|
|
541
|
-
hint: "local session or a deployed tier",
|
|
542
|
-
options: [
|
|
543
|
-
{
|
|
544
|
-
flag: "--app",
|
|
545
|
-
value: "<slug>",
|
|
546
|
-
summary: "Limit the discovered Workflows to one app.",
|
|
547
|
-
},
|
|
548
|
-
{
|
|
549
|
-
flag: "--tier",
|
|
550
|
-
value: "<t>",
|
|
551
|
-
summary: "development, staging or production. Asked when absent.",
|
|
552
|
-
},
|
|
553
|
-
{
|
|
554
|
-
flag: "--workflow",
|
|
555
|
-
value: "<name>",
|
|
556
|
-
summary: "Trigger this configured name without opening the picker.",
|
|
557
|
-
},
|
|
558
|
-
{
|
|
559
|
-
flag: "--params",
|
|
560
|
-
value: "<json>",
|
|
561
|
-
summary: "JSON parameters passed to the Workflow instance.",
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
flag: "--port",
|
|
565
|
-
value: "<n>",
|
|
566
|
-
summary: "Local Wrangler session port. Defaults to 8787.",
|
|
567
|
-
},
|
|
568
|
-
YES,
|
|
569
|
-
],
|
|
570
|
-
},
|
|
571
|
-
{
|
|
572
|
-
name: "serve",
|
|
573
|
-
summary: "Start an app-scoped local Wrangler runtime until Ctrl+C.",
|
|
574
|
-
hint: "secure alternative to bare wrangler dev",
|
|
575
|
-
options: [
|
|
576
|
-
{
|
|
577
|
-
flag: "--app",
|
|
578
|
-
value: "<slug>",
|
|
579
|
-
summary: "Serve the development Workflow for this app.",
|
|
580
|
-
},
|
|
581
|
-
{
|
|
582
|
-
flag: "--port",
|
|
583
|
-
value: "<n>",
|
|
584
|
-
summary: "Local Wrangler session port. Defaults to 8787.",
|
|
585
|
-
},
|
|
586
|
-
],
|
|
587
|
-
},
|
|
588
|
-
],
|
|
589
|
-
},
|
|
590
|
-
],
|
|
591
|
-
},
|
|
592
|
-
{
|
|
593
|
-
title: "GitHub",
|
|
594
|
-
commands: [
|
|
595
|
-
{
|
|
596
|
-
name: "github",
|
|
597
|
-
summary: "Reconcile the repository's rulesets and settings.",
|
|
598
|
-
hint: "rulesets: main, production, ~ALL, team/**, tags; settings: security, Actions, environments",
|
|
599
|
-
subcommands: [
|
|
600
|
-
{
|
|
601
|
-
name: "rulesets",
|
|
602
|
-
summary: "Diff the fixed rulesets against live GitHub; --apply to write.",
|
|
603
|
-
hint: "dry-run plan by default",
|
|
604
|
-
envFree: true,
|
|
605
|
-
options: [
|
|
606
|
-
{
|
|
607
|
-
flag: "--org",
|
|
608
|
-
value: "<org>",
|
|
609
|
-
summary: "GitHub org. Defaults to DevDogsUGA.",
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
flag: "--repo",
|
|
613
|
-
value: "<repo>",
|
|
614
|
-
summary: "Repository name. Defaults to DevDogsUGA.",
|
|
615
|
-
},
|
|
616
|
-
{
|
|
617
|
-
flag: "--app-slug",
|
|
618
|
-
value: "<slug>",
|
|
619
|
-
summary: "The GitHub App whose id bypasses team/** creation. Defaults to devdogs-platform.",
|
|
620
|
-
},
|
|
621
|
-
{
|
|
622
|
-
flag: "--apply",
|
|
623
|
-
summary: "Write the plan instead of only printing it.",
|
|
624
|
-
},
|
|
625
|
-
YES,
|
|
626
|
-
JSON_FLAG,
|
|
627
|
-
],
|
|
628
|
-
},
|
|
629
|
-
{
|
|
630
|
-
name: "settings",
|
|
631
|
-
summary: "Diff security/Actions/environment settings vs live GitHub.",
|
|
632
|
-
hint: "dry-run plan by default",
|
|
633
|
-
envFree: true,
|
|
634
|
-
options: [
|
|
635
|
-
{
|
|
636
|
-
flag: "--org",
|
|
637
|
-
value: "<org>",
|
|
638
|
-
summary: "GitHub org. Defaults to DevDogsUGA.",
|
|
639
|
-
},
|
|
640
|
-
{
|
|
641
|
-
flag: "--repo",
|
|
642
|
-
value: "<repo>",
|
|
643
|
-
summary: "Repository name. Defaults to DevDogsUGA.",
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
flag: "--apply",
|
|
647
|
-
summary: "Write fixable drift instead of only printing it.",
|
|
648
|
-
},
|
|
649
|
-
YES,
|
|
650
|
-
JSON_FLAG,
|
|
651
|
-
],
|
|
652
|
-
},
|
|
653
|
-
],
|
|
654
|
-
},
|
|
655
|
-
],
|
|
656
|
-
},
|
|
657
|
-
{
|
|
658
|
-
title: "Project setup",
|
|
659
|
-
commands: [
|
|
660
|
-
{
|
|
661
|
-
name: "oauth",
|
|
662
|
-
summary: 'Configure "Sign in with DevDogs" for this directory.',
|
|
663
|
-
hint: "works outside a DevDogsUGA checkout too",
|
|
664
|
-
// Talks only to whatever local Supabase project is running in `cwd`
|
|
665
|
-
// (see `oauth/db.ts`'s `detectLocalSupabase`) and, for a hosted
|
|
666
|
-
// target, to the platform's own OAuth endpoints — never a
|
|
667
|
-
// DevDogsUGA env file, database, or `DEPLOY_ENV`. TASK-345: a
|
|
668
|
-
// workshop repo with no DevDogsUGA checkout at all must still be
|
|
669
|
-
// able to run `pnpm dlx @devdogsuga/devtools oauth`, so this joins
|
|
670
|
-
// `github rulesets`/`github settings` in the catalog-driven bypass
|
|
671
|
-
// rather than the hardcoded `setup`/`completions` check — see
|
|
672
|
-
// `launch.ts`'s `isEnvFreeCommand`. Inside a checkout, the command's
|
|
673
|
-
// own hosted-target path still resolves a tier itself, lazily, only
|
|
674
|
-
// when a hosted target is actually chosen (see `oauth/wizard.ts`).
|
|
675
|
-
envFree: true,
|
|
676
|
-
options: [
|
|
677
|
-
{
|
|
678
|
-
flag: "--base-url",
|
|
679
|
-
value: "<url>",
|
|
680
|
-
summary: 'DevDogs API URL for "Paste credentials instead". Defaults to https://api.devdogsuga.org.',
|
|
681
|
-
},
|
|
682
|
-
{
|
|
683
|
-
flag: "--platform-url",
|
|
684
|
-
value: "<url>",
|
|
685
|
-
summary: "Platform URL for one-click connect. Defaults to https://devdogsuga.org.",
|
|
686
|
-
},
|
|
687
|
-
{
|
|
688
|
-
flag: "--device",
|
|
689
|
-
summary: "Force the device-code flow instead of the local loopback listener.",
|
|
690
|
-
},
|
|
691
|
-
{
|
|
692
|
-
flag: "--loopback",
|
|
693
|
-
summary: "Force the local loopback listener even over SSH/Codespaces/a dev container.",
|
|
694
|
-
},
|
|
695
|
-
],
|
|
696
|
-
},
|
|
697
|
-
{
|
|
698
|
-
name: "docs",
|
|
699
|
-
summary: "The documentation search index.",
|
|
700
|
-
subcommands: [
|
|
701
|
-
{
|
|
702
|
-
name: "index",
|
|
703
|
-
summary: "Push the built docs artifact into the search index.",
|
|
704
|
-
hint: "prunes stale rows in the target database",
|
|
705
|
-
scope: "endpoint",
|
|
706
|
-
options: [DOCS_TARGET],
|
|
707
|
-
},
|
|
708
|
-
],
|
|
709
|
-
},
|
|
710
|
-
],
|
|
711
|
-
},
|
|
712
|
-
{
|
|
713
|
-
title: "Env files",
|
|
714
|
-
commands: [
|
|
715
|
-
{
|
|
716
|
-
name: "env",
|
|
717
|
-
summary: "One env file per target, synced to Bitwarden and GitHub.",
|
|
718
|
-
subcommands: [
|
|
719
|
-
{
|
|
720
|
-
name: "pull",
|
|
721
|
-
summary: "Bitwarden → the target's file, in place.",
|
|
722
|
-
options: [VAULT_TARGET, ENV_FILE, YES, ACCESS_TOKEN],
|
|
723
|
-
},
|
|
724
|
-
{
|
|
725
|
-
name: "push",
|
|
726
|
-
summary: "The target's file → Bitwarden and GitHub.",
|
|
727
|
-
options: [VAULT_TARGET, ENV_FILE, YES, ACCESS_TOKEN],
|
|
728
|
-
},
|
|
729
|
-
{
|
|
730
|
-
name: "audit",
|
|
731
|
-
summary: "Compare the file, Bitwarden, GitHub and Cloudflare.",
|
|
732
|
-
hint: "reads only",
|
|
733
|
-
options: [VAULT_TARGET, ENV_FILE, YES, ACCESS_TOKEN, JSON_FLAG],
|
|
734
|
-
},
|
|
735
|
-
{
|
|
736
|
-
name: "init",
|
|
737
|
-
summary: "Create a target file, or append newly declared keys.",
|
|
738
|
-
hint: "existing lines are never changed",
|
|
739
|
-
options: [
|
|
740
|
-
{
|
|
741
|
-
flag: "--target",
|
|
742
|
-
value: "<t>",
|
|
743
|
-
summary: "Which file to create. Defaults to development.",
|
|
744
|
-
prompt: {
|
|
745
|
-
kind: "select",
|
|
746
|
-
message: "Create a file for which target?",
|
|
747
|
-
choices: [
|
|
748
|
-
{ value: "development", hint: ".env — the default" },
|
|
749
|
-
{ value: "preflight", hint: ".env.preflight" },
|
|
750
|
-
{ value: "staging", hint: ".env.staging" },
|
|
751
|
-
{ value: "production", hint: "⚠️ .env.production" },
|
|
752
|
-
],
|
|
753
|
-
},
|
|
754
|
-
},
|
|
755
|
-
{
|
|
756
|
-
flag: "--apps",
|
|
757
|
-
value: "<a,b,…>",
|
|
758
|
-
summary: "Which sections to render. Development only; asks.",
|
|
759
|
-
},
|
|
760
|
-
],
|
|
761
|
-
},
|
|
762
|
-
{
|
|
763
|
-
name: "example",
|
|
764
|
-
summary: "Regenerate .env.example from the manifests.",
|
|
765
|
-
options: [
|
|
766
|
-
{
|
|
767
|
-
flag: "--check",
|
|
768
|
-
summary: "Verify it is current, as CI does. Writes nothing.",
|
|
769
|
-
prompt: {
|
|
770
|
-
kind: "confirm",
|
|
771
|
-
message: "Check only, without rewriting .env.example?",
|
|
772
|
-
initial: true,
|
|
773
|
-
},
|
|
774
|
-
},
|
|
775
|
-
],
|
|
776
|
-
},
|
|
777
|
-
{
|
|
778
|
-
name: "reset",
|
|
779
|
-
summary: "Blank every value in .env, keeping each commented out.",
|
|
780
|
-
hint: "local only, no target",
|
|
781
|
-
options: [ENV_FILE, YES],
|
|
782
|
-
},
|
|
783
|
-
],
|
|
784
|
-
},
|
|
785
|
-
{
|
|
786
|
-
// The Bitwarden CLI, not a command of this one: everything after `bw`
|
|
787
|
-
// is handed to it untouched. It is here because it is the login that
|
|
788
|
-
// `env pull` depends on, it ships as a devtools dependency, and the
|
|
789
|
-
// root `bw` alias it replaces was the last thing at the workspace root
|
|
790
|
-
// reaching into this package. Declaring no subcommands is deliberate:
|
|
791
|
-
// Bitwarden's commands are its own to document, and mirroring a slice
|
|
792
|
-
// of them here would go stale on their release schedule, not ours.
|
|
793
|
-
name: "bw",
|
|
794
|
-
summary: "Run the Bitwarden CLI. `bw login` is the one you want.",
|
|
795
|
-
hint: "passes everything through",
|
|
796
|
-
},
|
|
797
|
-
],
|
|
798
|
-
},
|
|
799
|
-
{
|
|
800
|
-
title: "Database",
|
|
801
|
-
// One command, `db`. Its OWN subcommands carry the scopes — see the
|
|
802
|
-
// header comment on `Scope` and `db`'s `hint` below. Declared in scope
|
|
803
|
-
// order (machine, repo, endpoint, infra, then the unscoped escape hatch)
|
|
804
|
-
// so `--help` and the wizard render one contiguous block per scope
|
|
805
|
-
// instead of several.
|
|
806
|
-
commands: [
|
|
807
|
-
{
|
|
808
|
-
name: "db",
|
|
809
|
-
summary: "Supabase endpoints, and the databases inside them.",
|
|
810
|
-
hint: "start, migrate, reset, types…",
|
|
811
|
-
subcommands: [
|
|
812
|
-
// ── machine — Supabase on this machine ─────────────────────────
|
|
813
|
-
{
|
|
814
|
-
name: "start",
|
|
815
|
-
summary: "Start Supabase on this machine.",
|
|
816
|
-
hint: "boots the Docker containers",
|
|
817
|
-
scope: "machine",
|
|
818
|
-
when: "instance-stopped",
|
|
819
|
-
},
|
|
820
|
-
{
|
|
821
|
-
name: "connect",
|
|
822
|
-
summary: "Run `supabase link` against a hosted project ref.",
|
|
823
|
-
hint: "for driving the bare supabase CLI by hand",
|
|
824
|
-
scope: "machine",
|
|
825
|
-
},
|
|
826
|
-
{
|
|
827
|
-
name: "stop",
|
|
828
|
-
summary: "Shut it down, freeing its containers.",
|
|
829
|
-
hint: "your data survives",
|
|
830
|
-
scope: "machine",
|
|
831
|
-
// Not offered while nothing is running: "stop" against a stopped
|
|
832
|
-
// stack is the one shape of question a menu should never ask.
|
|
833
|
-
when: "instance-running",
|
|
834
|
-
},
|
|
835
|
-
{
|
|
836
|
-
name: "restart",
|
|
837
|
-
summary: "Stop it, then start it again.",
|
|
838
|
-
// The reason this exists rather than being a footnote on `reset`:
|
|
839
|
-
// `config.toml` is read at `supabase start`, so a reset replays
|
|
840
|
-
// migrations into containers still holding the old settings.
|
|
841
|
-
hint: "the only way to pick up config.toml — reset will not",
|
|
842
|
-
scope: "machine",
|
|
843
|
-
when: "instance-running",
|
|
844
|
-
},
|
|
845
|
-
// ── repo — files in the repo, no live connection ───────────────
|
|
846
|
-
{
|
|
847
|
-
name: "migration",
|
|
848
|
-
summary: "Empty timestamped migration files, hand-authored.",
|
|
849
|
-
scope: "repo",
|
|
850
|
-
subcommands: [
|
|
851
|
-
{
|
|
852
|
-
name: "new",
|
|
853
|
-
summary: "Create an empty timestamped migration file.",
|
|
854
|
-
hint: "<timestamp>_<schema>_<description>.sql",
|
|
855
|
-
options: [
|
|
856
|
-
{
|
|
857
|
-
flag: "--app",
|
|
858
|
-
value: "<slug>",
|
|
859
|
-
summary: "Whose schema. Asked for when absent.",
|
|
860
|
-
},
|
|
861
|
-
],
|
|
862
|
-
},
|
|
863
|
-
],
|
|
864
|
-
},
|
|
865
|
-
// ── endpoint — the session's database ──────────────────────────
|
|
866
|
-
{
|
|
867
|
-
name: "status",
|
|
868
|
-
summary: "Report the session database's health, URLs and keys.",
|
|
869
|
-
hint: "reads only",
|
|
870
|
-
scope: "endpoint",
|
|
871
|
-
options: [JSON_FLAG],
|
|
872
|
-
},
|
|
873
|
-
{
|
|
874
|
-
name: "migrate",
|
|
875
|
-
summary: "Apply new migrations to the database.",
|
|
876
|
-
hint: "without erasing anything",
|
|
877
|
-
scope: "endpoint",
|
|
878
|
-
options: [YES],
|
|
879
|
-
},
|
|
880
|
-
{
|
|
881
|
-
name: "reset",
|
|
882
|
-
summary: "Rebuild the database: migrations, seeds, types, buckets.",
|
|
883
|
-
hint: "⚠️ erases the database first",
|
|
884
|
-
scope: "endpoint",
|
|
885
|
-
options: [YES],
|
|
886
|
-
},
|
|
887
|
-
{
|
|
888
|
-
name: "types",
|
|
889
|
-
summary: "Regenerate database.types.ts, format it, rebuild the package.",
|
|
890
|
-
hint: "after any schema change",
|
|
891
|
-
scope: "endpoint",
|
|
892
|
-
options: [],
|
|
893
|
-
},
|
|
894
|
-
{
|
|
895
|
-
name: "seed",
|
|
896
|
-
summary: "Seed storage buckets or the platform's role catalogue.",
|
|
897
|
-
scope: "endpoint",
|
|
898
|
-
subcommands: [
|
|
899
|
-
{
|
|
900
|
-
name: "buckets",
|
|
901
|
-
summary: "Create the storage buckets config.toml declares.",
|
|
902
|
-
options: [],
|
|
903
|
-
},
|
|
904
|
-
{
|
|
905
|
-
name: "roles",
|
|
906
|
-
summary: "Reconcile the platform's role catalogue.",
|
|
907
|
-
options: [],
|
|
908
|
-
},
|
|
909
|
-
{
|
|
910
|
-
name: "production",
|
|
911
|
-
summary: "Apply supabase/seed/production/*.sql — roles and officers.",
|
|
912
|
-
hint: "confirms before writing to a hosted database",
|
|
913
|
-
options: [YES],
|
|
914
|
-
},
|
|
915
|
-
],
|
|
916
|
-
},
|
|
917
|
-
{
|
|
918
|
-
name: "introspect",
|
|
919
|
-
summary: "Pull an app's live schema into its generated Drizzle files.",
|
|
920
|
-
scope: "endpoint",
|
|
921
|
-
options: [
|
|
922
|
-
{
|
|
923
|
-
flag: "--app",
|
|
924
|
-
value: "<slug>",
|
|
925
|
-
summary: "App whose schema to pull. Asked for when absent.",
|
|
926
|
-
},
|
|
927
|
-
],
|
|
928
|
-
},
|
|
929
|
-
{
|
|
930
|
-
name: "config",
|
|
931
|
-
summary: "The Supabase config.toml, pushed to the session's project.",
|
|
932
|
-
scope: "endpoint",
|
|
933
|
-
subcommands: [
|
|
934
|
-
{
|
|
935
|
-
name: "push",
|
|
936
|
-
summary: "Push config.toml to the session's hosted project.",
|
|
937
|
-
hint: "hosted sessions only",
|
|
938
|
-
options: [],
|
|
939
|
-
},
|
|
940
|
-
],
|
|
941
|
-
},
|
|
942
|
-
// ── infra — hosted infrastructure, each naming its own connection
|
|
943
|
-
{
|
|
944
|
-
name: "planner",
|
|
945
|
-
summary: "The migration_planner role the preflight tier may hold.",
|
|
946
|
-
scope: "infra",
|
|
947
|
-
subcommands: [
|
|
948
|
-
{
|
|
949
|
-
name: "status",
|
|
950
|
-
summary: "Does the role exist, hold its two grants, and no more.",
|
|
951
|
-
hint: "reads only — start here",
|
|
952
|
-
options: [DB_URL, JSON_FLAG],
|
|
953
|
-
},
|
|
954
|
-
{
|
|
955
|
-
name: "create",
|
|
956
|
-
summary: "Mint the role, verify it live, write .env.preflight.",
|
|
957
|
-
options: [DB_URL],
|
|
958
|
-
},
|
|
959
|
-
{
|
|
960
|
-
name: "reset-password",
|
|
961
|
-
summary: "Rotate the password. There is no retrieve.",
|
|
962
|
-
options: [DB_URL, YES],
|
|
963
|
-
},
|
|
964
|
-
{
|
|
965
|
-
name: "drop",
|
|
966
|
-
summary: "Remove the role and blank the dead URL.",
|
|
967
|
-
hint: "the recovery path",
|
|
968
|
-
options: [DB_URL, YES],
|
|
969
|
-
},
|
|
970
|
-
],
|
|
971
|
-
},
|
|
972
|
-
// ── unscoped — the escape hatch ─────────────────────────────────
|
|
973
|
-
{
|
|
974
|
-
name: "exec",
|
|
975
|
-
summary: "Run the Supabase CLI. Everything after -- passes through.",
|
|
976
|
-
hint: "the escape hatch",
|
|
977
|
-
},
|
|
978
|
-
],
|
|
979
|
-
},
|
|
980
|
-
],
|
|
981
|
-
},
|
|
982
|
-
{
|
|
983
|
-
title: "Cloudflare",
|
|
984
|
-
commands: [
|
|
985
|
-
{
|
|
986
|
-
name: "cf",
|
|
987
|
-
summary: "Develop and build an app on the Workers runtime.",
|
|
988
|
-
hint: "preview, typegen — deploys live in CI",
|
|
989
|
-
subcommands: [
|
|
990
|
-
{
|
|
991
|
-
name: "preview",
|
|
992
|
-
summary: "Build and serve an app on the Workers runtime.",
|
|
993
|
-
options: [
|
|
994
|
-
{
|
|
995
|
-
flag: "--app",
|
|
996
|
-
value: "<slug>",
|
|
997
|
-
summary: "App to preview. Asked for when absent.",
|
|
998
|
-
prompt: {
|
|
999
|
-
kind: "select",
|
|
1000
|
-
message: "Which app?",
|
|
1001
|
-
choices: WORKER_APP_CHOICES,
|
|
1002
|
-
},
|
|
1003
|
-
},
|
|
1004
|
-
{
|
|
1005
|
-
flag: "--tier",
|
|
1006
|
-
value: "<t>",
|
|
1007
|
-
summary: "Preview against a tier's env. Defaults to development.",
|
|
1008
|
-
// No prompt: the runtime resolver (`tier.ts`) asks this
|
|
1009
|
-
// itself, conditionally, for both the wizard and a direct
|
|
1010
|
-
// CLI invocation — a `prompt` here would ask it twice, once
|
|
1011
|
-
// on this screen and once when the command actually runs.
|
|
1012
|
-
},
|
|
1013
|
-
YES,
|
|
1014
|
-
],
|
|
1015
|
-
},
|
|
1016
|
-
{
|
|
1017
|
-
name: "typegen",
|
|
1018
|
-
summary: "Regenerate cloudflare-env.d.ts from the wrangler config.",
|
|
1019
|
-
options: [
|
|
1020
|
-
{
|
|
1021
|
-
flag: "--app",
|
|
1022
|
-
value: "<slug>",
|
|
1023
|
-
summary: "App to run typegen for. Asked for when absent.",
|
|
1024
|
-
prompt: {
|
|
1025
|
-
kind: "select",
|
|
1026
|
-
message: "Which app?",
|
|
1027
|
-
choices: WORKER_APP_CHOICES,
|
|
1028
|
-
},
|
|
1029
|
-
},
|
|
1030
|
-
{
|
|
1031
|
-
flag: "--check",
|
|
1032
|
-
summary: "Check types only — do not write.",
|
|
1033
|
-
prompt: {
|
|
1034
|
-
kind: "confirm",
|
|
1035
|
-
message: "Check only (do not write)?",
|
|
1036
|
-
initial: true,
|
|
1037
|
-
},
|
|
1038
|
-
},
|
|
1039
|
-
],
|
|
1040
|
-
},
|
|
1041
|
-
{
|
|
1042
|
-
name: "build",
|
|
1043
|
-
summary: "Build an app's Worker bundle for a tier.",
|
|
1044
|
-
options: [
|
|
1045
|
-
{
|
|
1046
|
-
flag: "--app",
|
|
1047
|
-
value: "<slug>",
|
|
1048
|
-
summary: "App to build. Asked for when absent.",
|
|
1049
|
-
prompt: {
|
|
1050
|
-
kind: "select",
|
|
1051
|
-
message: "Which app?",
|
|
1052
|
-
choices: WORKER_APP_CHOICES,
|
|
1053
|
-
},
|
|
1054
|
-
},
|
|
1055
|
-
{
|
|
1056
|
-
flag: "--tier",
|
|
1057
|
-
value: "<t>",
|
|
1058
|
-
summary: "Which deployment tier to build for.",
|
|
1059
|
-
prompt: {
|
|
1060
|
-
kind: "select",
|
|
1061
|
-
message: "Which tier?",
|
|
1062
|
-
choices: [
|
|
1063
|
-
{ value: "staging" },
|
|
1064
|
-
{ value: "production", hint: "⚠️ live bundle" },
|
|
1065
|
-
],
|
|
1066
|
-
},
|
|
1067
|
-
},
|
|
1068
|
-
],
|
|
1069
|
-
},
|
|
1070
|
-
{
|
|
1071
|
-
name: "exec",
|
|
1072
|
-
summary: "Run wrangler. Everything after -- passes through.",
|
|
1073
|
-
hint: "the escape hatch",
|
|
1074
|
-
},
|
|
1075
|
-
],
|
|
1076
|
-
},
|
|
1077
|
-
],
|
|
1078
|
-
},
|
|
1079
|
-
];
|
|
1080
|
-
/**
|
|
1081
|
-
* The contributor-facing navigation, grouped by the job somebody is doing.
|
|
1082
|
-
*
|
|
1083
|
-
* Command declarations stay close to their domain-specific option data above;
|
|
1084
|
-
* this projection is the one place that decides how the root help and menu
|
|
1085
|
-
* read. Paths do not change when a command moves between groups.
|
|
1086
|
-
*/
|
|
1087
|
-
const declaredByName = new Map(DECLARED_GROUPS.flatMap((group) => group.commands).map((command) => [
|
|
1088
|
-
command.name,
|
|
1089
|
-
command,
|
|
1090
|
-
]));
|
|
1091
|
-
function commands(...names) {
|
|
1092
|
-
return names.map((name) => {
|
|
1093
|
-
const command = declaredByName.get(name);
|
|
1094
|
-
if (!command)
|
|
1095
|
-
throw new Error(`Command "${name}" is not declared.`);
|
|
1096
|
-
return command;
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
export const GROUPS = [
|
|
1100
|
-
{
|
|
1101
|
-
title: "Workspace",
|
|
1102
|
-
commands: commands("setup", "oauth", "run", "gen", "docs"),
|
|
1103
|
-
},
|
|
1104
|
-
{
|
|
1105
|
-
title: "Runtime & infrastructure",
|
|
1106
|
-
commands: commands("db", "cf", "cron", "workflows"),
|
|
1107
|
-
},
|
|
1108
|
-
{
|
|
1109
|
-
title: "Content & communications",
|
|
1110
|
-
commands: commands("images", "emails"),
|
|
1111
|
-
},
|
|
1112
|
-
{
|
|
1113
|
-
title: "Configuration & integrations",
|
|
1114
|
-
commands: commands("env", "bw"),
|
|
1115
|
-
},
|
|
1116
|
-
{
|
|
1117
|
-
title: "Moderation",
|
|
1118
|
-
commands: commands("moderation", "grant-root"),
|
|
1119
|
-
},
|
|
1120
|
-
{
|
|
1121
|
-
title: "Personas",
|
|
1122
|
-
commands: commands("persona"),
|
|
1123
|
-
},
|
|
1124
|
-
{
|
|
1125
|
-
title: "Environment",
|
|
1126
|
-
commands: commands("doctor"),
|
|
1127
|
-
},
|
|
1128
|
-
{
|
|
1129
|
-
title: "GitHub",
|
|
1130
|
-
commands: commands("github"),
|
|
1131
|
-
},
|
|
1132
|
-
{
|
|
1133
|
-
title: "CLI utilities",
|
|
1134
|
-
commands: commands("completions"),
|
|
1135
|
-
},
|
|
1136
|
-
];
|
|
1137
|
-
// ── CI command tree ───────────────────────────────────────────────────────────
|
|
1138
|
-
/**
|
|
1139
|
-
* The commands the `devtools-ci` bin exposes.
|
|
1140
|
-
*
|
|
1141
|
-
* Kept separate from `GROUPS` because CI commands are never reached from the
|
|
1142
|
-
* wizard and never rendered in `--help`. They live here so the docs build can
|
|
1143
|
-
* render a CI reference page from the same declaration, and so the tests that
|
|
1144
|
-
* guard the style guide can cover both trees without duplicating the pins.
|
|
1145
|
-
*/
|
|
1146
|
-
export const CI_GROUPS = [
|
|
1147
|
-
{
|
|
1148
|
-
title: "Deploy",
|
|
1149
|
-
commands: [
|
|
1150
|
-
{
|
|
1151
|
-
name: "deploy",
|
|
1152
|
-
summary: "Deploy an app: token gate, per-app steps, upload.",
|
|
1153
|
-
options: [TIER, DRY_RUN],
|
|
1154
|
-
subcommands: [
|
|
1155
|
-
// ── App orchestrators ────────────────────────────────────────────
|
|
1156
|
-
{
|
|
1157
|
-
name: "platform",
|
|
1158
|
-
summary: "Deploy the platform app.",
|
|
1159
|
-
options: [TIER, DRY_RUN],
|
|
1160
|
-
},
|
|
1161
|
-
{
|
|
1162
|
-
name: "schedule-builder",
|
|
1163
|
-
summary: "Deploy the schedule-builder app.",
|
|
1164
|
-
options: [TIER, DRY_RUN],
|
|
1165
|
-
},
|
|
1166
|
-
{
|
|
1167
|
-
name: "sandbox",
|
|
1168
|
-
summary: "Deploy the sandbox app.",
|
|
1169
|
-
options: [TIER, DRY_RUN],
|
|
1170
|
-
},
|
|
1171
|
-
// ── Step commands ────────────────────────────────────────────────
|
|
1172
|
-
{
|
|
1173
|
-
name: "write-env",
|
|
1174
|
-
summary: "Compose .env.<DEPLOY_ENV> from the GitHub environment.",
|
|
1175
|
-
options: [
|
|
1176
|
-
{
|
|
1177
|
-
flag: "--source",
|
|
1178
|
-
value: "<manifest>",
|
|
1179
|
-
summary: "Compose one manifest's slice instead of all.",
|
|
1180
|
-
},
|
|
1181
|
-
],
|
|
1182
|
-
},
|
|
1183
|
-
{
|
|
1184
|
-
name: "secrets-file",
|
|
1185
|
-
summary: "Write the --secrets-file wrangler uploads with a Worker.",
|
|
1186
|
-
options: [
|
|
1187
|
-
{
|
|
1188
|
-
flag: "--app",
|
|
1189
|
-
value: "<app>",
|
|
1190
|
-
summary: "Whose manifest declares the Worker's secrets.",
|
|
1191
|
-
},
|
|
1192
|
-
],
|
|
1193
|
-
},
|
|
1194
|
-
{
|
|
1195
|
-
name: "orphans",
|
|
1196
|
-
summary: "Report Worker secrets nothing declares.",
|
|
1197
|
-
options: [
|
|
1198
|
-
{
|
|
1199
|
-
flag: "--prune",
|
|
1200
|
-
summary: "Delete them. production-apply only.",
|
|
1201
|
-
},
|
|
1202
|
-
],
|
|
1203
|
-
},
|
|
1204
|
-
{
|
|
1205
|
-
name: "preflight",
|
|
1206
|
-
summary: "Classify the project: paused (skip) vs broken (fail).",
|
|
1207
|
-
},
|
|
1208
|
-
{
|
|
1209
|
-
name: "require-token",
|
|
1210
|
-
summary: "Refuse to deploy without CLOUDFLARE_API_TOKEN.",
|
|
1211
|
-
},
|
|
1212
|
-
{
|
|
1213
|
-
name: "require-planner",
|
|
1214
|
-
summary: "Refuse to plan unless DB_URL is the planner role.",
|
|
1215
|
-
},
|
|
1216
|
-
{
|
|
1217
|
-
name: "plan",
|
|
1218
|
-
summary: "Dry-run the migrations into the job summary.",
|
|
1219
|
-
options: [
|
|
1220
|
-
{
|
|
1221
|
-
flag: "--label",
|
|
1222
|
-
value: "<title>",
|
|
1223
|
-
summary: "Heading for the summary section.",
|
|
1224
|
-
},
|
|
1225
|
-
],
|
|
1226
|
-
},
|
|
1227
|
-
{
|
|
1228
|
-
name: "migrate",
|
|
1229
|
-
summary: "Apply the migrations to DB_URL.",
|
|
1230
|
-
},
|
|
1231
|
-
],
|
|
1232
|
-
},
|
|
1233
|
-
],
|
|
1234
|
-
},
|
|
1235
|
-
];
|
|
1236
|
-
// ── Lookup ───────────────────────────────────────────────────────────────────
|
|
1237
|
-
/** Every top-level command, in group order. */
|
|
1238
|
-
export const TOP_LEVEL = GROUPS.flatMap((group) => group.commands);
|
|
1239
|
-
/** Every top-level CI command, in group order. */
|
|
1240
|
-
export const CI_TOP_LEVEL = CI_GROUPS.flatMap((group) => group.commands);
|
|
1241
|
-
/**
|
|
1242
|
-
* Walks a path in the CI tree, returning `null` at the first miss.
|
|
1243
|
-
*
|
|
1244
|
-
* Identical to `findCommand` but over `CI_TOP_LEVEL` rather than `TOP_LEVEL`.
|
|
1245
|
-
*/
|
|
1246
|
-
export function findCiCommand(path) {
|
|
1247
|
-
let nodes = CI_TOP_LEVEL;
|
|
1248
|
-
let found = null;
|
|
1249
|
-
for (const name of path) {
|
|
1250
|
-
const next = nodes.find((node) => node.name === name);
|
|
1251
|
-
if (!next)
|
|
1252
|
-
return null;
|
|
1253
|
-
found = next;
|
|
1254
|
-
nodes = next.subcommands ?? [];
|
|
1255
|
-
}
|
|
1256
|
-
return found;
|
|
1257
|
-
}
|
|
1258
|
-
/** The subcommand names under a CI path. */
|
|
1259
|
-
export function subcommandCiNames(path) {
|
|
1260
|
-
return (findCiCommand(path)?.subcommands ?? []).map((node) => node.name);
|
|
1261
|
-
}
|
|
1262
|
-
/**
|
|
1263
|
-
* Walks a path like `["env", "pull"]`, returning `null` at the first miss.
|
|
1264
|
-
*
|
|
1265
|
-
* Callers use `null` to mean "not a command", which is the same answer the
|
|
1266
|
-
* dispatcher gives, so an unknown name reads the same whichever notices first.
|
|
1267
|
-
*/
|
|
1268
|
-
export function findCommand(path) {
|
|
1269
|
-
let nodes = TOP_LEVEL;
|
|
1270
|
-
let found = null;
|
|
1271
|
-
for (const name of path) {
|
|
1272
|
-
const next = nodes.find((node) => node.name === name);
|
|
1273
|
-
if (!next)
|
|
1274
|
-
return null;
|
|
1275
|
-
found = next;
|
|
1276
|
-
nodes = next.subcommands ?? [];
|
|
1277
|
-
}
|
|
1278
|
-
return found;
|
|
1279
|
-
}
|
|
1280
|
-
/** The group a top-level command sits in, for the wizard's first screen. */
|
|
1281
|
-
export function groupOf(name) {
|
|
1282
|
-
return GROUPS.find((group) => group.commands.some((command) => command.name === name));
|
|
1283
|
-
}
|
|
1284
|
-
/**
|
|
1285
|
-
* The subcommand names under a path, in the order they are declared.
|
|
1286
|
-
*
|
|
1287
|
-
* This is what the dispatchers in `cli.ts` validate against. A subcommand the
|
|
1288
|
-
* tree does not declare is refused by the CLI, and an interactive one it does
|
|
1289
|
-
* declare is in the menu. There is one list, and this reads it.
|
|
1290
|
-
*/
|
|
1291
|
-
export function subcommandNames(path) {
|
|
1292
|
-
return (findCommand(path)?.subcommands ?? []).map((node) => node.name);
|
|
1293
|
-
}
|
|
1294
|
-
/** `pull, push, audit, init, example or reset`, for a refusal message. */
|
|
1295
|
-
export function subcommandList(path) {
|
|
1296
|
-
const names = subcommandNames(path);
|
|
1297
|
-
if (names.length <= 1)
|
|
1298
|
-
return names.join("");
|
|
1299
|
-
return `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}`;
|
|
1300
|
-
}
|
|
1301
|
-
/**
|
|
1302
|
-
* Every command path in the tree, deepest names included.
|
|
1303
|
-
*
|
|
1304
|
-
* Used by the coverage test, and by anything that wants to enumerate the CLI
|
|
1305
|
-
* (the docs build's reference page is the intended second caller).
|
|
1306
|
-
*/
|
|
1307
|
-
export function allPaths() {
|
|
1308
|
-
const paths = [];
|
|
1309
|
-
const visit = (nodes, prefix) => {
|
|
1310
|
-
for (const node of nodes) {
|
|
1311
|
-
const path = [...prefix, node.name];
|
|
1312
|
-
paths.push(path);
|
|
1313
|
-
visit(node.subcommands ?? [], path);
|
|
1314
|
-
}
|
|
1315
|
-
};
|
|
1316
|
-
visit(TOP_LEVEL, []);
|
|
1317
|
-
return paths;
|
|
1318
|
-
}
|