@devdogsuga/devtools 0.1.35 → 0.1.37

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.
@@ -2,8 +2,103 @@ import { a as ownVersion } from "./root-C2OmZDwD.js";
2
2
  import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { homedir, platform, release } from "node:os";
5
+ //#region ../cli-core/src/args.ts
6
+ /**
7
+ * Positional arguments, with flag values excluded.
8
+ *
9
+ * Its own module because of one bug it prevents. The first positional is the
10
+ * subcommand, and `pull`, `push` and `audit` do very different things to live
11
+ * credentials. A naive `filter((a) => !a.startsWith("--"))` reads a flag's
12
+ * VALUE as a positional, so `env --file notes.env audit` fails loudly:
13
+ * `notes.env` is not a subcommand and the command refuses. The quiet version
14
+ * is the one that matters:
15
+ *
16
+ * env --file push audit
17
+ *
18
+ * which runs `push`, writing to Bitwarden and GitHub, when the caller asked
19
+ * for `audit`, which writes nothing at all.
20
+ */
21
+ /**
22
+ * Flags that consume the token after them.
23
+ */
24
+ const VALUE_FLAGS = /* @__PURE__ */ new Set([
25
+ "--access-token",
26
+ "--format",
27
+ "--out",
28
+ "--version",
29
+ "--app",
30
+ "--apps",
31
+ "--base-url",
32
+ "--file",
33
+ "--source",
34
+ "--target",
35
+ "--tier",
36
+ "--cron",
37
+ "--kind",
38
+ "--workflow",
39
+ "--params",
40
+ "--port",
41
+ "--preview-url",
42
+ "--db-url",
43
+ "--user",
44
+ "--filter",
45
+ "--shell"
46
+ ]);
47
+ function positionals(argv) {
48
+ const found = [];
49
+ for (let i = 0; i < argv.length; i += 1) {
50
+ const arg = argv[i];
51
+ if (!arg.startsWith("-")) {
52
+ found.push(arg);
53
+ continue;
54
+ }
55
+ const next = argv[i + 1];
56
+ if (VALUE_FLAGS.has(arg) && next !== void 0 && !next.startsWith("-")) i += 1;
57
+ }
58
+ return found;
59
+ }
60
+ /**
61
+ * The value after `flag`, or `undefined` when the flag is absent or is
62
+ * followed by another flag instead of a value.
63
+ */
64
+ function flagValue(rest, flag) {
65
+ const index = rest.indexOf(flag);
66
+ if (index === -1) return void 0;
67
+ const value = rest[index + 1];
68
+ return value && !value.startsWith("--") ? value : void 0;
69
+ }
70
+ //#endregion
5
71
  //#region ../cli-core/src/catalog.ts
6
72
  /**
73
+ * The command catalog: types, shared option shapes and the lookups over a
74
+ * composed tree.
75
+ *
76
+ * A CLI's command tree is data. Each domain declares its own commands in its
77
+ * `catalog.ts` (names, summaries and option shapes, nothing that runs), the
78
+ * CLI's `src/catalog.ts` composes those into groups, and `createCatalog`
79
+ * wraps the result. Three readers consume it:
80
+ *
81
+ * * `help.ts` renders it, one level at a time.
82
+ * * `menu.ts` walks its interactive commands and options without a second
83
+ * list to keep in step.
84
+ * * `completions.ts` enumerates it, and contributor documentation uses the
85
+ * same group and command vocabulary.
86
+ *
87
+ * It is deliberately inert: no imports of anything that runs (`args.ts` is
88
+ * data too), so the launcher can read it (for `envFree`) before the session's
89
+ * environment is entered.
90
+ * The CLI's dispatcher owns the handlers, and the wizard turns a walk of this
91
+ * tree into an argv and hands it to that same dispatcher, which keeps menu and
92
+ * CLI behavior aligned by construction rather than by review.
93
+ *
94
+ * ## What a summary is for
95
+ *
96
+ * Every `summary` is one line and is the ONLY thing `--help` prints for a
97
+ * command at the level above it. Rationale, target tables, credential lookup
98
+ * order and deploy internals live in `docs/`, not here: `--help` is a map, and
99
+ * a map that reprints the territory is the thing this replaced.
100
+ */
101
+ /**
7
102
  * How each scope reads, in the two places that draw it.
8
103
  *
9
104
  * `menu` sits inline in a hint, so it is one word. `help` heads a block of
@@ -44,22 +139,54 @@ const YES = {
44
139
  flag: "--yes",
45
140
  summary: "Skip the confirmations."
46
141
  };
47
- function walk(roots, path) {
142
+ /** The node a typed token names among `nodes`, by its name or an alias. */
143
+ function named(nodes, token) {
144
+ for (const node of nodes) {
145
+ if (node.name === token) return { node };
146
+ const alias = node.aliases?.find((candidate) => candidate.name === token);
147
+ if (alias) return {
148
+ node,
149
+ alias
150
+ };
151
+ }
152
+ }
153
+ /** Each step of a path, resolved through aliases; `null` at the first miss. */
154
+ function resolve$1(roots, path) {
48
155
  let nodes = roots;
49
- let found = null;
50
- for (const name of path) {
51
- const next = nodes.find((node) => node.name === name);
52
- if (!next) return null;
53
- found = next;
54
- nodes = next.subcommands ?? [];
156
+ const steps = [];
157
+ for (const token of path) {
158
+ const step = named(nodes, token);
159
+ if (!step) return null;
160
+ steps.push(step);
161
+ nodes = step.node.subcommands ?? [];
162
+ }
163
+ return steps;
164
+ }
165
+ function walk(roots, path) {
166
+ return resolve$1(roots, path)?.at(-1)?.node ?? null;
167
+ }
168
+ /**
169
+ * Refuses a tree where one token could name two siblings. An alias that
170
+ * shadowed another command would make which one runs depend on declaration
171
+ * order, the kind of thing nobody finds until it has run the wrong one.
172
+ */
173
+ function assertUnambiguous(nodes, prefix) {
174
+ const seen = /* @__PURE__ */ new Set();
175
+ for (const node of nodes) {
176
+ for (const token of [node.name, ...(node.aliases ?? []).map((a) => a.name)]) {
177
+ if (seen.has(token)) throw new Error(`Command tree: "${[...prefix, token].join(" ")}" names two commands.`);
178
+ seen.add(token);
179
+ }
180
+ assertUnambiguous(node.subcommands ?? [], [...prefix, node.name]);
55
181
  }
56
- return found;
57
182
  }
58
183
  function createCatalog(trees) {
59
184
  const groups = trees.groups;
60
185
  const ciGroups = trees.ciGroups ?? [];
61
186
  const topLevel = groups.flatMap((group) => group.commands);
62
187
  const ciTopLevel = ciGroups.flatMap((group) => group.commands);
188
+ assertUnambiguous(topLevel, []);
189
+ assertUnambiguous(ciTopLevel, []);
63
190
  const subcommandNames = (path) => (walk(topLevel, path)?.subcommands ?? []).map((node) => node.name);
64
191
  return {
65
192
  usage: trees.usage,
@@ -71,6 +198,26 @@ function createCatalog(trees) {
71
198
  findCommand: (path) => walk(topLevel, path),
72
199
  findCiCommand: (path) => walk(ciTopLevel, path),
73
200
  groupOf: (name) => groups.find((group) => group.commands.some((command) => command.name === name)),
201
+ canonicalPath: (path) => resolve$1(topLevel, path)?.map((step) => step.node.name) ?? null,
202
+ canonicalArgv: (argv) => {
203
+ const out = [...argv];
204
+ const implied = [];
205
+ let nodes = topLevel;
206
+ for (let i = 0; i < out.length; i += 1) {
207
+ const arg = out[i];
208
+ if (arg.startsWith("-")) {
209
+ const next = out[i + 1];
210
+ if (VALUE_FLAGS.has(arg) && next !== void 0 && !next.startsWith("-")) i += 1;
211
+ continue;
212
+ }
213
+ const step = named(nodes, arg);
214
+ if (!step) break;
215
+ out[i] = step.node.name;
216
+ implied.push(...step.alias?.implies ?? []);
217
+ nodes = step.node.subcommands ?? [];
218
+ }
219
+ return [...out, ...implied];
220
+ },
74
221
  subcommandNames,
75
222
  subcommandCiNames: (path) => (walk(ciTopLevel, path)?.subcommands ?? []).map((node) => node.name),
76
223
  subcommandList: (path) => {
@@ -253,4 +400,4 @@ function installFailureLog(options) {
253
400
  });
254
401
  }
255
402
  //#endregion
256
- export { cliName as a, YES as c, suppressFailureLog as i, createCatalog as l, noteError as n, JSON_FLAG as o, noteRan as r, SCOPES as s, installFailureLog as t };
403
+ export { cliName as a, YES as c, positionals as d, suppressFailureLog as i, createCatalog as l, noteError as n, JSON_FLAG as o, noteRan as r, SCOPES as s, installFailureLog as t, flagValue as u };
package/dist/launch.js CHANGED
@@ -1,9 +1,9 @@
1
- import { a as cliName, t as installFailureLog } from "./failure-log-BBPGejQv.js";
2
- import { C as catalog, S as unwrap, _ as setMenuEnvHook, d as nonEmpty, g as realEnvEntryDeps, h as enterSessionEnvironment, t as bareGroupStartPath, w as helpPath, y as errorMessage } from "./menu-DnqlX22U.js";
3
- import { b as setDryRun, m as formatCommand, v as isDryRun, y as resolveDryRun } from "./supabase-project-0knM0mqd.js";
1
+ import { a as cliName, t as installFailureLog } from "./failure-log-B5GG_8T1.js";
2
+ import { C as helpPath, S as catalog, g as setMenuEnvHook, h as realEnvEntryDeps, m as enterSessionEnvironment, n as bareGroupStartPath, u as nonEmpty, v as errorMessage, x as unwrap } from "./menu-C7gh8v-s.js";
3
+ import { b as setDryRun, m as formatCommand, v as isDryRun, y as resolveDryRun } from "./supabase-project-B7JMicl-.js";
4
4
  import { n as discoverRepoRoot, r as findRepoRoot, t as RepoNotFoundError } from "./root-C2OmZDwD.js";
5
5
  import { i as loadEnvSession, r as loadEnvLoad } from "./peers-RBplwovA.js";
6
- import { d as hasYes, f as isNonInteractive, m as stripTierFlag, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as stripNoEnvFlag, s as lastSentryEventId } from "./telemetry-El7OainP.js";
6
+ import { d as hasYes, f as isNonInteractive, m as stripTierFlag, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as stripNoEnvFlag, s as lastSentryEventId } from "./telemetry-Do13RFhc.js";
7
7
  import { confirm, select } from "@clack/prompts";
8
8
  //#region ../cli-core/src/session.ts
9
9
  /**
@@ -155,7 +155,7 @@ function skipsEnvEntry(rest) {
155
155
  /** The offer's stack start (`env-entry.ts` holds the TTY prompt, this holds
156
156
  * the lifecycle command), imported lazily like the rest of the commands. */
157
157
  async function startStack() {
158
- const { runStackCommand } = await import("./stack-Bx-55oi_.js");
158
+ const { runStackCommand } = await import("./stack-CKiRU68w.js");
159
159
  return runStackCommand("start");
160
160
  }
161
161
  /**
@@ -166,7 +166,7 @@ async function startStack() {
166
166
  * post-tier-resolution path.
167
167
  */
168
168
  async function dispatch(argv) {
169
- const { main } = await import("./cli-Bb-Lzg-l.js");
169
+ const { main } = await import("./cli-DvADNoml.js");
170
170
  try {
171
171
  await main(argv);
172
172
  } catch (err) {