@devdogsuga/backstage 0.1.10 → 0.1.11

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.
@@ -1,7 +1,6 @@
1
- import { A as YES, D as DRY_RUN, O as JSON_FLAG, j as createCatalog, k as SCOPES, v as noteRan, w as findRepoRoot } from "./telemetry-Be_lbB5c.js";
2
- import { n as isDryRun } from "./dry-run-CFCZUpjb.js";
3
- import { o as unwrap } from "./ui-Bb69ZfVv.js";
4
- import { n as positionals } from "./args-Cjr_Iqts.js";
1
+ import { A as YES, D as DRY_RUN, N as positionals, O as JSON_FLAG, j as createCatalog, k as SCOPES, v as noteRan, w as findRepoRoot } from "./telemetry-RNK5Wu74.js";
2
+ import { n as isDryRun } from "./dry-run-OzO0jUhK.js";
3
+ import { o as unwrap } from "./ui-RFZyr6k_.js";
5
4
  import { t as EXPORTS } from "./queries-D3mTchag.js";
6
5
  import { r as qrCatalogOptions } from "./options-DCaqm8BI.js";
7
6
  import { existsSync, readFileSync } from "node:fs";
@@ -80,15 +79,28 @@ function scopedBody(commands) {
80
79
  open = command.scope;
81
80
  lines.push(`${INDENT}${SCOPES[open].help}:`);
82
81
  }
83
- lines.push(`${INDENT.repeat(2)}${command.name.padEnd(width)} ${command.summary}`);
82
+ lines.push(`${INDENT.repeat(2)}${command.name.padEnd(width)} ${describe(command)}`);
84
83
  }
85
84
  return lines;
86
85
  }
87
86
  function optionRows(options) {
88
87
  return options.map((option) => [optionLabel(option), option.summary]);
89
88
  }
89
+ /** A command's summary as a list prints it, with what else it answers to. */
90
+ function describe(command) {
91
+ const aliases = (command.aliases ?? []).map((alias) => alias.name);
92
+ const also = aliases.length > 0 ? ` (also: ${aliases.join(", ")})` : "";
93
+ const deprecated = command.deprecated ? " (deprecated)" : "";
94
+ return `${command.summary}${also}${deprecated}`;
95
+ }
90
96
  function childRows(children) {
91
- return children.map((child) => [child.name, child.deprecated ? `${child.summary} (deprecated)` : child.summary]);
97
+ return children.map((child) => [child.name, describe(child)]);
98
+ }
99
+ /** `cron` is `jobs --kind sync`, for a command page's alias line. */
100
+ function aliasLine(node) {
101
+ const aliases = node.aliases ?? [];
102
+ if (aliases.length === 0) return void 0;
103
+ return `Also typed as ${aliases.map((alias) => alias.implies?.length ? `${alias.name} (${node.name} … ${alias.implies.join(" ")})` : alias.name).join(", ")}.`;
92
104
  }
93
105
  /** `pnpm devtools --help`: the groups, and nothing below them. */
94
106
  function renderRoot(catalog) {
@@ -123,6 +135,8 @@ function renderCommand(catalog, path, node) {
123
135
  "",
124
136
  node.summary
125
137
  ];
138
+ const also = aliasLine(node);
139
+ if (also) lines.push("", also);
126
140
  if (node.deprecated) lines.push("", `Deprecated. ${node.deprecated}`);
127
141
  if (children.length > 0) lines.push("", "Subcommands:", ...scopedBody(children));
128
142
  if (options.length > 0) lines.push("", "Options:", ...columns(optionRows(options)));
@@ -139,8 +153,9 @@ function renderCommand(catalog, path, node) {
139
153
  function renderHelp(catalog, path = []) {
140
154
  if (path.length === 0) return renderRoot(catalog);
141
155
  const node = catalog.findCommand(path);
142
- if (!node) return renderRoot(catalog);
143
- return renderCommand(catalog, path, node);
156
+ const canonical = catalog.canonicalPath(path);
157
+ if (!node || !canonical) return renderRoot(catalog);
158
+ return renderCommand(catalog, canonical, node);
144
159
  }
145
160
  /**
146
161
  * The command names in `argv` that precede any flag.
@@ -177,7 +192,8 @@ function commandList(catalog) {
177
192
  path: path.join(" "),
178
193
  summary: node.summary,
179
194
  surface: cliOnly ? "cli-only" : "interactive",
180
- ...node.deprecated ? { deprecated: node.deprecated } : {}
195
+ ...node.deprecated ? { deprecated: node.deprecated } : {},
196
+ ...node.aliases?.length ? { aliases: node.aliases.map((alias) => alias.name) } : {}
181
197
  });
182
198
  visit(node.subcommands ?? [], path, cliOnly);
183
199
  }
@@ -606,7 +622,7 @@ function describeEnvironment(env) {
606
622
  * A command's inputs arrive from two places that never meet: the wizard walks
607
623
  * `commands.ts` and gathers the *declared* options into the argv it dispatches
608
624
  * (see `menu.ts`), while a runner resolves anything it prompts for *itself* —
609
- * `workflows run` picking a tier, `env init` picking projects — deep inside its
625
+ * `jobs run` picking a tier, `env init` picking projects — deep inside its
610
626
  * own call stack, where the dispatched argv is long out of reach. Threading a
611
627
  * return value back up through every runner would touch each one's signature;
612
628
  * a recorder every layer can reach touches only the layers that actually
@@ -662,13 +678,22 @@ function recordResolved(...fragment) {
662
678
  interactive = true;
663
679
  }
664
680
  /**
681
+ * One argv token as a POSIX shell reads it back. A cron expression is the case
682
+ * that forced this: `--cron 0 0 * * *` pasted unquoted is three stray words
683
+ * and two globs.
684
+ */
685
+ function shellQuote(token) {
686
+ if (/^[\w@%+=:,./-]+$/.test(token)) return token;
687
+ return `'${token.replaceAll("'", `'\\''`)}'`;
688
+ }
689
+ /**
665
690
  * The command to print, or `null` when there is nothing worth printing —
666
691
  * either no invocation ran, or the user typed a complete command and answered
667
692
  * no prompts, so echoing it back would be noise.
668
693
  */
669
694
  function reproducibleCommand() {
670
695
  if (argv === null || !interactive || argv.length === 0) return null;
671
- return `pnpm devtools ${[...enteredTier ? ["--tier", enteredTier] : [], ...argv].join(" ")}`;
696
+ return `pnpm devtools ${[...enteredTier ? ["--tier", enteredTier] : [], ...argv].map(shellQuote).join(" ")}`;
672
697
  }
673
698
  //#endregion
674
699
  //#region ../cli-core/src/menu.ts
@@ -688,6 +713,16 @@ function reproducibleCommand() {
688
713
  *
689
714
  * Walking the catalog means an interactive command added there is in the
690
715
  * menu the same day, with its options. Commands marked `cli-only` do not appear here.
716
+ *
717
+ * ## One flat first screen
718
+ *
719
+ * The first screen lists every top-level command, in the catalog's order,
720
+ * under its `title`: "Restart local Supabase" rather than `restart-stack`.
721
+ * There used to be a screen of groups above it, which put a door between the
722
+ * reader and every command and named the doors after how the CLI is built
723
+ * rather than what the reader came to do. The command's real name rides in
724
+ * the hint (`restart-stack · …`), so a walk still teaches what to type next
725
+ * time. Aliases are never drawn: the menu builds an argv for a real command.
691
726
  */
692
727
  /** Chosen when a submenu should return to the screen above it. */
693
728
  const BACK = Symbol("back");
@@ -712,39 +747,38 @@ function hintFor(node) {
712
747
  const said = node.hint ?? node.summary;
713
748
  return node.scope ? `${SCOPES[node.scope].menu} · ${said}` : said;
714
749
  }
715
- async function pickGroup(catalog, env) {
716
- const groups = catalog.groups.filter((group) => offered(group.commands, env).length > 0);
750
+ /**
751
+ * One command's entry on a screen: its title, with its real name leading the
752
+ * hint so the reader learns what to type. A command with no title is labelled
753
+ * by its name, which then has no reason to appear twice.
754
+ */
755
+ function entryFor(node) {
756
+ return node.title ? {
757
+ label: node.title,
758
+ hint: `${node.name} · ${hintFor(node)}`
759
+ } : {
760
+ label: node.name,
761
+ hint: hintFor(node)
762
+ };
763
+ }
764
+ async function pickTopLevel(catalog, env) {
717
765
  return unwrap(await select({
718
766
  message: "What would you like to do?",
719
- options: [...groups.map((group) => ({
720
- value: group,
721
- label: group.title,
722
- hint: offered(group.commands, env).map((command) => command.name).join(", ")
767
+ options: [...offered(catalog.topLevel, env).map((command) => ({
768
+ value: command,
769
+ ...entryFor(command)
723
770
  })), {
724
771
  value: null,
725
772
  label: "Quit"
726
773
  }]
727
774
  }));
728
775
  }
729
- async function pickCommand(group, env) {
730
- const commands = offered(group.commands, env);
731
- if (commands.length === 1) return commands[0];
732
- return unwrap(await select({
733
- message: `${group.title}:`,
734
- options: [...commands.map((command) => ({
735
- value: command,
736
- label: command.name,
737
- hint: hintFor(command)
738
- })), BACK_OPTION]
739
- }));
740
- }
741
776
  async function pickSubcommand(node, env) {
742
777
  return unwrap(await select({
743
- message: `${node.name}:`,
778
+ message: `${node.title ?? node.name}:`,
744
779
  options: [...offered(node.subcommands ?? [], env).map((child) => ({
745
780
  value: child,
746
- label: child.name,
747
- hint: hintFor(child)
781
+ ...entryFor(child)
748
782
  })), BACK_OPTION]
749
783
  }));
750
784
  }
@@ -790,7 +824,7 @@ async function askOptions(node) {
790
824
  * that leaf's options.
791
825
  *
792
826
  * Shared by both entries into a walk: the top-of-tree loop below, which calls
793
- * this once a group and its first command are chosen, and a resumed walk
827
+ * this once a top-level command is chosen, and a resumed walk
794
828
  * (`walk`'s `startPath` branch), which calls it directly on a node the caller
795
829
  * already picked by argv. `while` rather than a single step because the tree
796
830
  * is two deep today and this does not care. The condition counts the OFFERED
@@ -798,7 +832,7 @@ async function askOptions(node) {
798
832
  * hidden is treated as the leaf it has become instead of opening a screen
799
833
  * holding only "Back".
800
834
  */
801
- async function descendFrom(start, pathNames, env) {
835
+ async function descendFrom(start, pathNames, env, carried = []) {
802
836
  let node = start;
803
837
  const path = [...pathNames];
804
838
  while (offered(node.subcommands ?? [], env).length > 0) {
@@ -809,7 +843,11 @@ async function descendFrom(start, pathNames, env) {
809
843
  }
810
844
  return {
811
845
  node,
812
- argv: [...path, ...await askOptions(node)]
846
+ argv: [
847
+ ...path,
848
+ ...await askOptions(node),
849
+ ...carried
850
+ ]
813
851
  };
814
852
  }
815
853
  /**
@@ -817,24 +855,24 @@ async function descendFrom(start, pathNames, env) {
817
855
  * a known group.
818
856
  *
819
857
  * `startPath`, when given, is a path to a group node from `bareGroupStartPath`
820
- * — `["db"]` for `devtools db` — and lands here instead of at `pickGroup`.
821
- * There is no group screen above a resumed node (the caller already named it
822
- * by typing `db`), so BACK on its first subcommand screen has nowhere to
858
+ * — `["jobs"]` for `devtools jobs` — and lands here instead of at the first
859
+ * screen. There is no screen above a resumed node (the caller already named
860
+ * it by typing `jobs`), so BACK on its first subcommand screen has nowhere to
823
861
  * return to but out, unlike BACK from the top of the tree, which returns to
824
- * `pickGroup`.
862
+ * the first screen. `startFlags` are the flags typed beside it, carried onto
863
+ * the end of the argv the walk builds.
825
864
  */
826
- async function walk(catalog, env, startPath) {
865
+ async function walk(catalog, env, startPath, startFlags = []) {
827
866
  if (startPath) {
828
867
  const start = catalog.findCommand(startPath);
829
- if (!start) return null;
830
- const chosen = await descendFrom(start, [...startPath], env);
868
+ const path = catalog.canonicalPath(startPath);
869
+ if (!start || !path) return null;
870
+ const chosen = await descendFrom(start, path, env, startFlags);
831
871
  return chosen === BACK ? null : chosen;
832
872
  }
833
873
  for (;;) {
834
- const group = await pickGroup(catalog, env);
835
- if (!group) return null;
836
- const first = await pickCommand(group, env);
837
- if (first === BACK) continue;
874
+ const first = await pickTopLevel(catalog, env);
875
+ if (!first) return null;
838
876
  const chosen = await descendFrom(first, [first.name], env);
839
877
  if (chosen === BACK) continue;
840
878
  return chosen;
@@ -865,7 +903,8 @@ function bareGroupStartPath(catalog, argv) {
865
903
  * from the command line.
866
904
  *
867
905
  * `options.startPath`, from `bareGroupStartPath`, skips straight to that
868
- * node's subcommand screen — see `walk`'s `startPath` branch.
906
+ * node's subcommand screen — see `walk`'s `startPath` branch — and
907
+ * `options.startFlags` (from `bareGroupStartFlags`) rides along to the end.
869
908
  *
870
909
  * The deploy tier is NOT asked here any more. `src/launch.ts` resolves it
871
910
  * before `cli.ts` — and therefore this module — is even imported, and
@@ -887,7 +926,7 @@ function bareGroupStartPath(catalog, argv) {
887
926
  */
888
927
  async function runMenu(catalog, dispatch, env = probeEnvironment(), options = {}) {
889
928
  note(describeEnvironment(env), "This machine");
890
- const chosen = await walk(catalog, env, options.startPath);
929
+ const chosen = await walk(catalog, env, options.startPath, options.startFlags);
891
930
  if (!chosen) return null;
892
931
  beginInvocation(chosen.argv, true);
893
932
  const enteredTier = process.env.DEPLOY_ENV ?? "development";
@@ -1,6 +1,6 @@
1
- import { C as discoverRepoRoot, p as isNonInteractive } from "./telemetry-Be_lbB5c.js";
1
+ import { C as discoverRepoRoot, p as isNonInteractive } from "./telemetry-RNK5Wu74.js";
2
2
  import { t as nonEmpty } from "./connection-D3XsOE3S.js";
3
- import { a as explainError, i as explain, o as unwrap, t as UsageError } from "./ui-Bb69ZfVv.js";
3
+ import { a as explainError, i as explain, o as unwrap, t as UsageError } from "./ui-RFZyr6k_.js";
4
4
  import { t as EnvDocument } from "./document-DumoZXoO.js";
5
5
  import { resolve } from "node:path";
6
6
  import { confirm, log, text } from "@clack/prompts";
@@ -31,7 +31,7 @@ async function readProductionKey(key) {
31
31
  const value = nonEmpty(EnvDocument.parse(text).get(key));
32
32
  if (value) return value;
33
33
  } catch {}
34
- const { listSecrets, projectIdFor } = await import("./client-A6pJcxSE.js");
34
+ const { listSecrets, projectIdFor } = await import("./client-DCRfKvpP.js");
35
35
  const secrets = await listSecrets(await projectIdFor(PRODUCTION_PROJECT));
36
36
  return nonEmpty(secrets.find((s) => s.key === key)?.value);
37
37
  }
@@ -1,13 +1,12 @@
1
- import { C as discoverRepoRoot, T as cliName, b as ownPackageDir, c as reportDevtoolsError, f as isNoEnv, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive, w as findRepoRoot, x as ownVersion } from "./telemetry-Be_lbB5c.js";
2
- import { a as recordEnteredTier, f as helpPath, i as beginInvocation, l as dbPush, m as renderHelp, n as bareGroupStartPath, o as recordResolved, p as renderCommandList, r as runMenu, s as reproducibleCommand, t as catalog, u as dbPushDryRun } from "./catalog-CaTnrGVr.js";
3
- import { a as repoPeerUrl, n as loadEnv, r as loadEnvLoad, t as getEnvSync } from "./peers-u1zxe-Ub.js";
1
+ import { C as discoverRepoRoot, M as flagValue, N as positionals, T as cliName, b as ownPackageDir, c as reportDevtoolsError, f as isNoEnv, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive, w as findRepoRoot, x as ownVersion } from "./telemetry-RNK5Wu74.js";
2
+ import { a as recordEnteredTier, f as helpPath, i as beginInvocation, l as dbPush, m as renderHelp, n as bareGroupStartPath, o as recordResolved, p as renderCommandList, r as runMenu, s as reproducibleCommand, t as catalog, u as dbPushDryRun } from "./catalog-BLgY4knB.js";
3
+ import { a as repoPeerUrl, n as loadEnv, r as loadEnvLoad, t as getEnvSync } from "./peers-DE07w6nT.js";
4
4
  import { t as nonEmpty } from "./connection-D3XsOE3S.js";
5
- import { a as wouldRunLine, n as isDryRun, t as dryRunKind } from "./dry-run-CFCZUpjb.js";
6
- import { a as explainError, i as explain, n as bail, o as unwrap, r as errorMessage } from "./ui-Bb69ZfVv.js";
7
- import { n as positionals, t as flagValue } from "./args-Cjr_Iqts.js";
5
+ import { a as wouldRunLine, n as isDryRun, t as dryRunKind } from "./dry-run-OzO0jUhK.js";
6
+ import { a as explainError, i as explain, n as bail, o as unwrap, r as errorMessage } from "./ui-RFZyr6k_.js";
8
7
  import { t as DONE } from "./dispatch-D048O65I.js";
9
8
  import { t as EnvDocument } from "./document-DumoZXoO.js";
10
- import { a as listSecrets$1, c as updateSecret, i as createSecret, o as projectIdFor, r as byKey, s as setExplicitAccessToken } from "./client-NuoKMQmV.js";
9
+ import { a as listSecrets$1, c as updateSecret, i as createSecret, o as projectIdFor, r as byKey, s as setExplicitAccessToken } from "./client-Djo8fRdS.js";
11
10
  import { register } from "node:module";
12
11
  import { pathToFileURL } from "node:url";
13
12
  import { appendFileSync, existsSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
@@ -24,17 +23,24 @@ import { randomBytes } from "node:crypto";
24
23
  /**
25
24
  * Groups all paths by their parent prefix to build per-parent completion lists.
26
25
  *
27
- * e.g. ["env", "pull"] contributes "pull" to the group keyed "env".
26
+ * e.g. ["env", "pull"] contributes "pull" to the group keyed "env". Aliases
27
+ * complete too, after the name they stand for, and the children under an
28
+ * alias are its command's: `cron <TAB>` offers what `jobs <TAB>` does.
28
29
  */
29
30
  function buildGroups(catalog) {
30
31
  const groups = /* @__PURE__ */ new Map();
31
- for (const path of catalog.allPaths()) {
32
- const parent = path.slice(0, -1).join(" ");
33
- const name = path[path.length - 1];
34
- const existing = groups.get(parent) ?? [];
35
- existing.push(name);
36
- groups.set(parent, existing);
37
- }
32
+ const visit = (nodes, parents) => {
33
+ for (const node of nodes) {
34
+ const names = [node.name, ...(node.aliases ?? []).map((a) => a.name)];
35
+ for (const parent of parents) {
36
+ const existing = groups.get(parent) ?? [];
37
+ existing.push(...names);
38
+ groups.set(parent, existing);
39
+ }
40
+ visit(node.subcommands ?? [], parents.flatMap((parent) => names.map((name) => parent ? `${parent} ${name}` : name)));
41
+ }
42
+ };
43
+ visit(catalog.topLevel, [""]);
38
44
  return groups;
39
45
  }
40
46
  function generateBash(catalog) {
@@ -985,7 +991,7 @@ function toPath(location) {
985
991
  }
986
992
  }
987
993
  /**
988
- * `GET /cron/config-reconcile`, authenticated. Unlike `devtools cron run`
994
+ * `GET /cron/config-reconcile`, authenticated. Unlike `devtools jobs run`
989
995
  * (which only checks the HTTP status), this reads the JSON body: the route
990
996
  * answers 200 even when the reconcile itself failed
991
997
  * (`{ success: false, reason: … }`, see
@@ -5380,12 +5386,12 @@ const HANDLERS = {
5380
5386
  },
5381
5387
  completions: handleCompletions,
5382
5388
  github: handleGithub,
5383
- graphics: async (rest) => (await import("./commands-jJcS7D2a.js")).handleGraphics(rest),
5384
- qr: async (rest) => (await import("./commands-DQYH_m6i.js")).handleQr(rest),
5385
- newsletter: async (rest) => (await import("./commands-35rBJ1R0.js")).handleNewsletter(rest),
5386
- creds: async (rest) => (await import("./commands-BF5eptEi.js")).handleCreds(rest),
5387
- import: async (rest) => (await import("./commands-Ye0G_5bZ.js")).handleImport(rest),
5388
- export: async (rest) => (await import("./commands-C8pXvbv1.js")).handleExport(rest)
5389
+ graphics: async (rest) => (await import("./commands-BAh2_Nds.js")).handleGraphics(rest),
5390
+ qr: async (rest) => (await import("./commands-DILvdMc2.js")).handleQr(rest),
5391
+ newsletter: async (rest) => (await import("./commands-C3_hAcZS.js")).handleNewsletter(rest),
5392
+ creds: async (rest) => (await import("./commands-C6w8jm6a.js")).handleCreds(rest),
5393
+ import: async (rest) => (await import("./commands-DfWNSPra.js")).handleImport(rest),
5394
+ export: async (rest) => (await import("./commands-3HvxDq-2.js")).handleExport(rest)
5389
5395
  };
5390
5396
  /**
5391
5397
  * Names that were commands of the contributor CLI, refused with where they
@@ -0,0 +1,2 @@
1
+ import { a as listSecrets, o as projectIdFor } from "./client-Djo8fRdS.js";
2
+ export { listSecrets, projectIdFor };
@@ -1,8 +1,8 @@
1
- import { w as findRepoRoot } from "./telemetry-Be_lbB5c.js";
2
- import { n as loadEnv } from "./peers-u1zxe-Ub.js";
3
- import { o as unwrap } from "./ui-Bb69ZfVv.js";
1
+ import { w as findRepoRoot } from "./telemetry-RNK5Wu74.js";
2
+ import { n as loadEnv } from "./peers-DE07w6nT.js";
3
+ import { o as unwrap } from "./ui-RFZyr6k_.js";
4
4
  import { t as EnvDocument } from "./document-DumoZXoO.js";
5
- import { a as readTokenFromVault, o as saveTokenToVault, t as VAULT_ITEM_NAME } from "./vault-DFV0zjbT.js";
5
+ import { a as readTokenFromVault, o as saveTokenToVault, t as VAULT_ITEM_NAME } from "./vault-BpYSYcuT.js";
6
6
  import { dirname, join, resolve } from "node:path";
7
7
  import { log, password, select, text } from "@clack/prompts";
8
8
  import { mkdir, readFile, writeFile } from "node:fs/promises";
@@ -1,9 +1,9 @@
1
- import { n as isDryRun } from "./dry-run-CFCZUpjb.js";
2
- import { o as unwrap, r as errorMessage, t as UsageError } from "./ui-Bb69ZfVv.js";
1
+ import { n as isDryRun } from "./dry-run-OzO0jUhK.js";
2
+ import { o as unwrap, r as errorMessage, t as UsageError } from "./ui-RFZyr6k_.js";
3
3
  import { i as exportParams, n as EXPORT_KINDS, r as auditFilters, t as EXPORTS } from "./queries-D3mTchag.js";
4
4
  import { t as DONE } from "./dispatch-D048O65I.js";
5
- import { c as ProductionError, d as requireProductionKey, i as plural, l as connect, o as reportFailure, r as expandHome, s as say, t as canPrompt, u as dbError } from "./cli-DjIwbjnx.js";
6
- import { i as parseBound, n as findMeetingsWith, r as pickMeeting, t as describeMeeting } from "./meetings-Du5asTAj.js";
5
+ import { c as ProductionError, d as requireProductionKey, i as plural, l as connect, o as reportFailure, r as expandHome, s as say, t as canPrompt, u as dbError } from "./cli-B7W_-WdD.js";
6
+ import { i as parseBound, n as findMeetingsWith, r as pickMeeting, t as describeMeeting } from "./meetings-BAX4Sils.js";
7
7
  import { existsSync, readdirSync, statSync } from "node:fs";
8
8
  import { basename, dirname, join } from "node:path";
9
9
  import { autocomplete, confirm, multiselect, text } from "@clack/prompts";
@@ -1,8 +1,8 @@
1
- import { n as isDryRun } from "./dry-run-CFCZUpjb.js";
2
- import { r as errorMessage, t as UsageError } from "./ui-Bb69ZfVv.js";
1
+ import { n as isDryRun } from "./dry-run-OzO0jUhK.js";
2
+ import { r as errorMessage, t as UsageError } from "./ui-RFZyr6k_.js";
3
3
  import { t as DONE } from "./dispatch-D048O65I.js";
4
- import { a as readInputFile, d as requireProductionKey, f as withConnection, i as plural, n as confirmWrite, o as reportFailure, s as say, t as canPrompt } from "./cli-DjIwbjnx.js";
5
- import { a as createAccounts, i as createAccountFor, n as accountFinder, o as readAccounts, t as parseCsv } from "./read-B8DSwYfB.js";
4
+ import { a as readInputFile, d as requireProductionKey, f as withConnection, i as plural, n as confirmWrite, o as reportFailure, s as say, t as canPrompt } from "./cli-B7W_-WdD.js";
5
+ import { a as createAccounts, i as createAccountFor, n as accountFinder, o as readAccounts, t as parseCsv } from "./read-Dd388anq.js";
6
6
  import { parseArgs } from "node:util";
7
7
  //#region src/involvement/csv.ts
8
8
  /**
@@ -1,6 +1,5 @@
1
- import { p as isNonInteractive } from "./telemetry-Be_lbB5c.js";
2
- import { a as explainError, o as unwrap, r as errorMessage, t as UsageError } from "./ui-Bb69ZfVv.js";
3
- import { n as positionals } from "./args-Cjr_Iqts.js";
1
+ import { N as positionals, p as isNonInteractive } from "./telemetry-RNK5Wu74.js";
2
+ import { a as explainError, o as unwrap, r as errorMessage, t as UsageError } from "./ui-RFZyr6k_.js";
4
3
  import { t as DONE } from "./dispatch-D048O65I.js";
5
4
  import { dirname, relative, resolve } from "node:path";
6
5
  import { autocompleteMultiselect, log, multiselect, note } from "@clack/prompts";
@@ -1,5 +1,5 @@
1
- import { p as isNonInteractive } from "./telemetry-Be_lbB5c.js";
2
- import { a as explainError, o as unwrap, r as errorMessage, t as UsageError } from "./ui-Bb69ZfVv.js";
1
+ import { p as isNonInteractive } from "./telemetry-RNK5Wu74.js";
2
+ import { a as explainError, o as unwrap, r as errorMessage, t as UsageError } from "./ui-RFZyr6k_.js";
3
3
  import { t as DONE } from "./dispatch-D048O65I.js";
4
4
  import { dirname, join, resolve } from "node:path";
5
5
  import { confirm, log, multiselect, spinner, text } from "@clack/prompts";
@@ -1,9 +1,9 @@
1
- import { C as discoverRepoRoot, p as isNonInteractive } from "./telemetry-Be_lbB5c.js";
1
+ import { C as discoverRepoRoot, p as isNonInteractive } from "./telemetry-RNK5Wu74.js";
2
2
  import { t as nonEmpty } from "./connection-D3XsOE3S.js";
3
- import { a as explainError, i as explain, o as unwrap, r as errorMessage, t as UsageError } from "./ui-Bb69ZfVv.js";
3
+ import { a as explainError, i as explain, o as unwrap, r as errorMessage, t as UsageError } from "./ui-RFZyr6k_.js";
4
4
  import { t as DONE } from "./dispatch-D048O65I.js";
5
5
  import { t as EnvDocument } from "./document-DumoZXoO.js";
6
- import { i as readPasswordFromVault, n as bwArgs, r as openVault, s as bwCommand } from "./vault-DFV0zjbT.js";
6
+ import { i as readPasswordFromVault, n as bwArgs, r as openVault, s as bwCommand } from "./vault-BpYSYcuT.js";
7
7
  import { resolve } from "node:path";
8
8
  import { confirm, log, multiselect, note, password, select, text } from "@clack/prompts";
9
9
  import { readFile } from "node:fs/promises";
@@ -632,7 +632,7 @@ async function readCheckoutDbUrl() {
632
632
  }
633
633
  }
634
634
  async function readSecretsManagerDbUrl() {
635
- const { listSecrets, projectIdFor } = await import("./client-A6pJcxSE.js");
635
+ const { listSecrets, projectIdFor } = await import("./client-DCRfKvpP.js");
636
636
  const secrets = await listSecrets(await projectIdFor(PRODUCTION_PROJECT));
637
637
  return nonEmpty(secrets.find((s) => s.key === "DB_URL")?.value);
638
638
  }
@@ -1,9 +1,9 @@
1
- import { n as isDryRun } from "./dry-run-CFCZUpjb.js";
2
- import { o as unwrap, r as errorMessage, t as UsageError } from "./ui-Bb69ZfVv.js";
1
+ import { n as isDryRun } from "./dry-run-OzO0jUhK.js";
2
+ import { o as unwrap, r as errorMessage, t as UsageError } from "./ui-RFZyr6k_.js";
3
3
  import { t as DONE } from "./dispatch-D048O65I.js";
4
- import { a as readInputFile, c as ProductionError, d as requireProductionKey, f as withConnection, i as plural, l as connect, n as confirmWrite, o as reportFailure, s as say, t as canPrompt } from "./cli-DjIwbjnx.js";
5
- import { a as createAccounts, i as createAccountFor, n as accountFinder, r as accountsWith, t as parseCsv } from "./read-B8DSwYfB.js";
6
- import { n as findMeetingsWith, r as pickMeeting, t as describeMeeting } from "./meetings-Du5asTAj.js";
4
+ import { a as readInputFile, c as ProductionError, d as requireProductionKey, f as withConnection, i as plural, l as connect, n as confirmWrite, o as reportFailure, s as say, t as canPrompt } from "./cli-B7W_-WdD.js";
5
+ import { a as createAccounts, i as createAccountFor, n as accountFinder, r as accountsWith, t as parseCsv } from "./read-Dd388anq.js";
6
+ import { n as findMeetingsWith, r as pickMeeting, t as describeMeeting } from "./meetings-BAX4Sils.js";
7
7
  import { text } from "@clack/prompts";
8
8
  import { parseArgs } from "node:util";
9
9
  //#region src/attendance/plan.ts
@@ -1,6 +1,6 @@
1
- import { p as isNonInteractive } from "./telemetry-Be_lbB5c.js";
2
- import { n as isDryRun } from "./dry-run-CFCZUpjb.js";
3
- import { a as explainError, o as unwrap, t as UsageError } from "./ui-Bb69ZfVv.js";
1
+ import { p as isNonInteractive } from "./telemetry-RNK5Wu74.js";
2
+ import { n as isDryRun } from "./dry-run-OzO0jUhK.js";
3
+ import { a as explainError, o as unwrap, t as UsageError } from "./ui-RFZyr6k_.js";
4
4
  import { i as qrParseOptions, n as QR_FLAGS, t as QR_EXTRA_FLAGS } from "./options-DCaqm8BI.js";
5
5
  import { t as DONE } from "./dispatch-D048O65I.js";
6
6
  import { dirname, extname, relative, resolve } from "node:path";
@@ -1,9 +1,9 @@
1
- import { i as explain } from "./ui-Bb69ZfVv.js";
1
+ import { i as explain } from "./ui-RFZyr6k_.js";
2
2
  //#region src/import/commands.ts
3
3
  const handleImport = async (rest) => {
4
4
  const [what, ...args] = rest;
5
- if (what === "involvement") return (await import("./commands-KY-9X1Rh.js")).handleInvolvement(args);
6
- if (what === "attendance") return (await import("./commands-CD1v_-6y.js")).handleAttendance(args);
5
+ if (what === "involvement") return (await import("./commands-B25Vafxz.js")).handleInvolvement(args);
6
+ if (what === "attendance") return (await import("./commands-D-Vvufb0.js")).handleAttendance(args);
7
7
  explain(what ? `Unknown import "${what}". Try involvement or attendance.` : "Name the import: involvement or attendance.", "");
8
8
  process.exitCode = 1;
9
9
  return null;
@@ -1,4 +1,4 @@
1
- import { T as cliName } from "./telemetry-Be_lbB5c.js";
1
+ import { T as cliName } from "./telemetry-RNK5Wu74.js";
2
2
  //#region ../cli-core/src/dry-run.ts
3
3
  const DRY_RUN_FLAG = "--dry-run";
4
4
  /** Commands that forward everything after their name to another tool. */
package/dist/launch.js CHANGED
@@ -1,9 +1,9 @@
1
- import { C as discoverRepoRoot, E as setCliName, S as RepoNotFoundError, T as cliName, _ as installFailureLog, d as hasYes, g as stripTierFlag, h as stripNoEnvFlag, m as setNoEnv, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive, s as lastSentryEventId } from "./telemetry-Be_lbB5c.js";
2
- import { c as setMenuEnvHook, d as formatCommand, f as helpPath, n as bareGroupStartPath, t as catalog } from "./catalog-CaTnrGVr.js";
3
- import { i as loadEnvSession, r as loadEnvLoad } from "./peers-u1zxe-Ub.js";
1
+ import { C as discoverRepoRoot, E as setCliName, S as RepoNotFoundError, T as cliName, _ as installFailureLog, d as hasYes, g as stripTierFlag, h as stripNoEnvFlag, m as setNoEnv, n as captureDevtoolsError, o as initDevtoolsTelemetry, p as isNonInteractive, s as lastSentryEventId } from "./telemetry-RNK5Wu74.js";
2
+ import { c as setMenuEnvHook, d as formatCommand, f as helpPath, n as bareGroupStartPath, t as catalog } from "./catalog-BLgY4knB.js";
3
+ import { i as loadEnvSession, r as loadEnvLoad } from "./peers-DE07w6nT.js";
4
4
  import { t as nonEmpty } from "./connection-D3XsOE3S.js";
5
- import { i as setDryRun, n as isDryRun, r as resolveDryRun } from "./dry-run-CFCZUpjb.js";
6
- import { o as unwrap, r as errorMessage } from "./ui-Bb69ZfVv.js";
5
+ import { i as setDryRun, n as isDryRun, r as resolveDryRun } from "./dry-run-OzO0jUhK.js";
6
+ import { o as unwrap, r as errorMessage } from "./ui-RFZyr6k_.js";
7
7
  import { confirm } from "@clack/prompts";
8
8
  //#region ../cli-core/src/pipes.ts
9
9
  /**
@@ -322,7 +322,7 @@ async function launchWith(argv, options) {
322
322
  */
323
323
  async function launch(argv) {
324
324
  await launchWith(argv, { dispatch: async (args) => {
325
- const { main } = await import("./cli-feRmGaGi.js");
325
+ const { main } = await import("./cli-B8Lshscc.js");
326
326
  await main(args);
327
327
  } });
328
328
  }
@@ -1,5 +1,5 @@
1
- import { t as UsageError } from "./ui-Bb69ZfVv.js";
2
- import "./cli-DjIwbjnx.js";
1
+ import { t as UsageError } from "./ui-RFZyr6k_.js";
2
+ import "./cli-B7W_-WdD.js";
3
3
  //#region src/production/time.ts
4
4
  /**
5
5
  * Dates as officers type them. Meetings happen in Athens, so a bare
@@ -1,4 +1,4 @@
1
- import { S as RepoNotFoundError, w as findRepoRoot } from "./telemetry-Be_lbB5c.js";
1
+ import { S as RepoNotFoundError, w as findRepoRoot } from "./telemetry-RNK5Wu74.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { existsSync, readFileSync, readdirSync } from "node:fs";
@@ -1,5 +1,5 @@
1
- import { r as errorMessage } from "./ui-Bb69ZfVv.js";
2
- import { c as ProductionError, f as withConnection } from "./cli-DjIwbjnx.js";
1
+ import { r as errorMessage } from "./ui-RFZyr6k_.js";
2
+ import { c as ProductionError, f as withConnection } from "./cli-B7W_-WdD.js";
3
3
  //#region src/production/accounts.ts
4
4
  /**
5
5
  * Production accounts: reading them, finding one by email, and creating the
@@ -4,8 +4,103 @@ import { dirname, join } from "node:path";
4
4
  import { homedir, platform, release } from "node:os";
5
5
  import * as Sentry from "@sentry/node";
6
6
  import { buildSentryOptions } from "@devdogsuga/telemetry";
7
+ //#region ../cli-core/src/args.ts
8
+ /**
9
+ * Positional arguments, with flag values excluded.
10
+ *
11
+ * Its own module because of one bug it prevents. The first positional is the
12
+ * subcommand, and `pull`, `push` and `audit` do very different things to live
13
+ * credentials. A naive `filter((a) => !a.startsWith("--"))` reads a flag's
14
+ * VALUE as a positional, so `env --file notes.env audit` fails loudly:
15
+ * `notes.env` is not a subcommand and the command refuses. The quiet version
16
+ * is the one that matters:
17
+ *
18
+ * env --file push audit
19
+ *
20
+ * which runs `push`, writing to Bitwarden and GitHub, when the caller asked
21
+ * for `audit`, which writes nothing at all.
22
+ */
23
+ /**
24
+ * Flags that consume the token after them.
25
+ */
26
+ const VALUE_FLAGS = /* @__PURE__ */ new Set([
27
+ "--access-token",
28
+ "--format",
29
+ "--out",
30
+ "--version",
31
+ "--app",
32
+ "--apps",
33
+ "--base-url",
34
+ "--file",
35
+ "--source",
36
+ "--target",
37
+ "--tier",
38
+ "--cron",
39
+ "--kind",
40
+ "--workflow",
41
+ "--params",
42
+ "--port",
43
+ "--preview-url",
44
+ "--db-url",
45
+ "--user",
46
+ "--filter",
47
+ "--shell"
48
+ ]);
49
+ function positionals(argv) {
50
+ const found = [];
51
+ for (let i = 0; i < argv.length; i += 1) {
52
+ const arg = argv[i];
53
+ if (!arg.startsWith("-")) {
54
+ found.push(arg);
55
+ continue;
56
+ }
57
+ const next = argv[i + 1];
58
+ if (VALUE_FLAGS.has(arg) && next !== void 0 && !next.startsWith("-")) i += 1;
59
+ }
60
+ return found;
61
+ }
62
+ /**
63
+ * The value after `flag`, or `undefined` when the flag is absent or is
64
+ * followed by another flag instead of a value.
65
+ */
66
+ function flagValue(rest, flag) {
67
+ const index = rest.indexOf(flag);
68
+ if (index === -1) return void 0;
69
+ const value = rest[index + 1];
70
+ return value && !value.startsWith("--") ? value : void 0;
71
+ }
72
+ //#endregion
7
73
  //#region ../cli-core/src/catalog.ts
8
74
  /**
75
+ * The command catalog: types, shared option shapes and the lookups over a
76
+ * composed tree.
77
+ *
78
+ * A CLI's command tree is data. Each domain declares its own commands in its
79
+ * `catalog.ts` (names, summaries and option shapes, nothing that runs), the
80
+ * CLI's `src/catalog.ts` composes those into groups, and `createCatalog`
81
+ * wraps the result. Three readers consume it:
82
+ *
83
+ * * `help.ts` renders it, one level at a time.
84
+ * * `menu.ts` walks its interactive commands and options without a second
85
+ * list to keep in step.
86
+ * * `completions.ts` enumerates it, and contributor documentation uses the
87
+ * same group and command vocabulary.
88
+ *
89
+ * It is deliberately inert: no imports of anything that runs (`args.ts` is
90
+ * data too), so the launcher can read it (for `envFree`) before the session's
91
+ * environment is entered.
92
+ * The CLI's dispatcher owns the handlers, and the wizard turns a walk of this
93
+ * tree into an argv and hands it to that same dispatcher, which keeps menu and
94
+ * CLI behavior aligned by construction rather than by review.
95
+ *
96
+ * ## What a summary is for
97
+ *
98
+ * Every `summary` is one line and is the ONLY thing `--help` prints for a
99
+ * command at the level above it. Rationale, target tables, credential lookup
100
+ * order and deploy internals live in `docs/`, not here: `--help` is a map, and
101
+ * a map that reprints the territory is the thing this replaced.
102
+ */
103
+ /**
9
104
  * How each scope reads, in the two places that draw it.
10
105
  *
11
106
  * `menu` sits inline in a hint, so it is one word. `help` heads a block of
@@ -51,22 +146,54 @@ const YES = {
51
146
  flag: "--yes",
52
147
  summary: "Skip the confirmations."
53
148
  };
54
- function walk(roots, path) {
149
+ /** The node a typed token names among `nodes`, by its name or an alias. */
150
+ function named(nodes, token) {
151
+ for (const node of nodes) {
152
+ if (node.name === token) return { node };
153
+ const alias = node.aliases?.find((candidate) => candidate.name === token);
154
+ if (alias) return {
155
+ node,
156
+ alias
157
+ };
158
+ }
159
+ }
160
+ /** Each step of a path, resolved through aliases; `null` at the first miss. */
161
+ function resolve$1(roots, path) {
55
162
  let nodes = roots;
56
- let found = null;
57
- for (const name of path) {
58
- const next = nodes.find((node) => node.name === name);
59
- if (!next) return null;
60
- found = next;
61
- nodes = next.subcommands ?? [];
163
+ const steps = [];
164
+ for (const token of path) {
165
+ const step = named(nodes, token);
166
+ if (!step) return null;
167
+ steps.push(step);
168
+ nodes = step.node.subcommands ?? [];
169
+ }
170
+ return steps;
171
+ }
172
+ function walk(roots, path) {
173
+ return resolve$1(roots, path)?.at(-1)?.node ?? null;
174
+ }
175
+ /**
176
+ * Refuses a tree where one token could name two siblings. An alias that
177
+ * shadowed another command would make which one runs depend on declaration
178
+ * order, the kind of thing nobody finds until it has run the wrong one.
179
+ */
180
+ function assertUnambiguous(nodes, prefix) {
181
+ const seen = /* @__PURE__ */ new Set();
182
+ for (const node of nodes) {
183
+ for (const token of [node.name, ...(node.aliases ?? []).map((a) => a.name)]) {
184
+ if (seen.has(token)) throw new Error(`Command tree: "${[...prefix, token].join(" ")}" names two commands.`);
185
+ seen.add(token);
186
+ }
187
+ assertUnambiguous(node.subcommands ?? [], [...prefix, node.name]);
62
188
  }
63
- return found;
64
189
  }
65
190
  function createCatalog(trees) {
66
191
  const groups = trees.groups;
67
192
  const ciGroups = trees.ciGroups ?? [];
68
193
  const topLevel = groups.flatMap((group) => group.commands);
69
194
  const ciTopLevel = ciGroups.flatMap((group) => group.commands);
195
+ assertUnambiguous(topLevel, []);
196
+ assertUnambiguous(ciTopLevel, []);
70
197
  const subcommandNames = (path) => (walk(topLevel, path)?.subcommands ?? []).map((node) => node.name);
71
198
  return {
72
199
  usage: trees.usage,
@@ -78,6 +205,26 @@ function createCatalog(trees) {
78
205
  findCommand: (path) => walk(topLevel, path),
79
206
  findCiCommand: (path) => walk(ciTopLevel, path),
80
207
  groupOf: (name) => groups.find((group) => group.commands.some((command) => command.name === name)),
208
+ canonicalPath: (path) => resolve$1(topLevel, path)?.map((step) => step.node.name) ?? null,
209
+ canonicalArgv: (argv) => {
210
+ const out = [...argv];
211
+ const implied = [];
212
+ let nodes = topLevel;
213
+ for (let i = 0; i < out.length; i += 1) {
214
+ const arg = out[i];
215
+ if (arg.startsWith("-")) {
216
+ const next = out[i + 1];
217
+ if (VALUE_FLAGS.has(arg) && next !== void 0 && !next.startsWith("-")) i += 1;
218
+ continue;
219
+ }
220
+ const step = named(nodes, arg);
221
+ if (!step) break;
222
+ out[i] = step.node.name;
223
+ implied.push(...step.alias?.implies ?? []);
224
+ nodes = step.node.subcommands ?? [];
225
+ }
226
+ return [...out, ...implied];
227
+ },
81
228
  subcommandNames,
82
229
  subcommandCiNames: (path) => (walk(ciTopLevel, path)?.subcommands ?? []).map((node) => node.name),
83
230
  subcommandList: (path) => {
@@ -606,4 +753,4 @@ async function captureDevtoolsDeprecation(message, fingerprint, tags) {
606
753
  await Sentry.flush(1e3);
607
754
  }
608
755
  //#endregion
609
- export { YES as A, discoverRepoRoot as C, DRY_RUN as D, setCliName as E, JSON_FLAG as O, RepoNotFoundError as S, cliName as T, installFailureLog as _, hasRealCaller as a, ownPackageDir as b, reportDevtoolsError as c, hasYes as d, isNoEnv as f, stripTierFlag as g, stripNoEnvFlag as h, devtoolsTelemetryEnabled as i, createCatalog as j, SCOPES as k, reportDevtoolsFailure as l, setNoEnv as m, captureDevtoolsError as n, initDevtoolsTelemetry as o, isNonInteractive as p, devtoolsEnvironment as r, lastSentryEventId as s, captureDevtoolsDeprecation as t, resolveDevtoolsDsn as u, noteRan as v, findRepoRoot as w, ownVersion as x, suppressFailureLog as y };
756
+ export { YES as A, discoverRepoRoot as C, DRY_RUN as D, setCliName as E, flagValue as M, positionals as N, JSON_FLAG as O, RepoNotFoundError as S, cliName as T, installFailureLog as _, hasRealCaller as a, ownPackageDir as b, reportDevtoolsError as c, hasYes as d, isNoEnv as f, stripTierFlag as g, stripNoEnvFlag as h, devtoolsTelemetryEnabled as i, createCatalog as j, SCOPES as k, reportDevtoolsFailure as l, setNoEnv as m, captureDevtoolsError as n, initDevtoolsTelemetry as o, isNonInteractive as p, devtoolsEnvironment as r, lastSentryEventId as s, captureDevtoolsDeprecation as t, resolveDevtoolsDsn as u, noteRan as v, findRepoRoot as w, ownVersion as x, suppressFailureLog as y };
package/dist/telemetry.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as hasRealCaller, c as reportDevtoolsError, i as devtoolsTelemetryEnabled, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, s as lastSentryEventId, t as captureDevtoolsDeprecation, u as resolveDevtoolsDsn } from "./telemetry-Be_lbB5c.js";
1
+ import { a as hasRealCaller, c as reportDevtoolsError, i as devtoolsTelemetryEnabled, l as reportDevtoolsFailure, n as captureDevtoolsError, o as initDevtoolsTelemetry, r as devtoolsEnvironment, s as lastSentryEventId, t as captureDevtoolsDeprecation, u as resolveDevtoolsDsn } from "./telemetry-RNK5Wu74.js";
2
2
  export { captureDevtoolsDeprecation, captureDevtoolsError, devtoolsEnvironment, devtoolsTelemetryEnabled, hasRealCaller, initDevtoolsTelemetry, lastSentryEventId, reportDevtoolsError, reportDevtoolsFailure, resolveDevtoolsDsn };
@@ -1,4 +1,4 @@
1
- import { c as reportDevtoolsError, p as isNonInteractive, y as suppressFailureLog } from "./telemetry-Be_lbB5c.js";
1
+ import { c as reportDevtoolsError, p as isNonInteractive, y as suppressFailureLog } from "./telemetry-RNK5Wu74.js";
2
2
  import { cancel, isCancel, log, note } from "@clack/prompts";
3
3
  //#region ../cli-core/src/ui.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { o as unwrap } from "./ui-Bb69ZfVv.js";
1
+ import { o as unwrap } from "./ui-RFZyr6k_.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { dirname, join } from "node:path";
4
4
  import { confirm, log, spinner } from "@clack/prompts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devdogsuga/backstage",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Officer and production CLI for DevDogsUGA: deploys, env sync with Bitwarden and GitHub, the migration planner role, club graphics and QR codes, GitHub rulesets and settings, and the newsletter. Ships built JS; run it anywhere with `pnpm dlx @devdogsuga/backstage` (no checkout needed to start; commands that read a checkout say so).",
@@ -41,9 +41,9 @@
41
41
  "typescript": "^6.0.3",
42
42
  "zod": "4.4.3",
43
43
  "@devdogsuga/brand": "0.1.6",
44
- "@devdogsuga/telemetry": "0.1.4",
45
44
  "@devdogsuga/events": "0.1.7",
46
- "@devdogsuga/newsletter": "0.1.12"
45
+ "@devdogsuga/newsletter": "0.1.13",
46
+ "@devdogsuga/telemetry": "0.1.4"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@devdogsuga/db": "*",
@@ -65,9 +65,9 @@
65
65
  "tsdown": "^0.23.0",
66
66
  "vitest": "^4.1.11",
67
67
  "@devdogsuga/cli-core": "0.0.0",
68
- "@devdogsuga/config": "0.1.2",
69
68
  "@devdogsuga/db": "0.1.3",
70
- "@devdogsuga/env": "0.1.5"
69
+ "@devdogsuga/env": "0.1.5",
70
+ "@devdogsuga/config": "0.1.2"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "tsdown && node scripts/write-build-info.mjs && node ../../scripts/check-bundle-imports.mjs",
@@ -1,66 +0,0 @@
1
- //#region ../cli-core/src/args.ts
2
- /**
3
- * Positional arguments, with flag values excluded.
4
- *
5
- * Its own module because of one bug it prevents. The first positional is the
6
- * subcommand, and `pull`, `push` and `audit` do very different things to live
7
- * credentials. A naive `filter((a) => !a.startsWith("--"))` reads a flag's
8
- * VALUE as a positional, so `env --file notes.env audit` fails loudly:
9
- * `notes.env` is not a subcommand and the command refuses. The quiet version
10
- * is the one that matters:
11
- *
12
- * env --file push audit
13
- *
14
- * which runs `push`, writing to Bitwarden and GitHub, when the caller asked
15
- * for `audit`, which writes nothing at all.
16
- */
17
- /**
18
- * Flags that consume the token after them.
19
- */
20
- const VALUE_FLAGS = /* @__PURE__ */ new Set([
21
- "--access-token",
22
- "--format",
23
- "--out",
24
- "--version",
25
- "--app",
26
- "--apps",
27
- "--base-url",
28
- "--file",
29
- "--source",
30
- "--target",
31
- "--tier",
32
- "--cron",
33
- "--workflow",
34
- "--params",
35
- "--port",
36
- "--preview-url",
37
- "--db-url",
38
- "--user",
39
- "--filter",
40
- "--shell"
41
- ]);
42
- function positionals(argv) {
43
- const found = [];
44
- for (let i = 0; i < argv.length; i += 1) {
45
- const arg = argv[i];
46
- if (!arg.startsWith("-")) {
47
- found.push(arg);
48
- continue;
49
- }
50
- const next = argv[i + 1];
51
- if (VALUE_FLAGS.has(arg) && next !== void 0 && !next.startsWith("-")) i += 1;
52
- }
53
- return found;
54
- }
55
- /**
56
- * The value after `flag`, or `undefined` when the flag is absent or is
57
- * followed by another flag instead of a value.
58
- */
59
- function flagValue(rest, flag) {
60
- const index = rest.indexOf(flag);
61
- if (index === -1) return void 0;
62
- const value = rest[index + 1];
63
- return value && !value.startsWith("--") ? value : void 0;
64
- }
65
- //#endregion
66
- export { positionals as n, flagValue as t };
@@ -1,2 +0,0 @@
1
- import { a as listSecrets, o as projectIdFor } from "./client-NuoKMQmV.js";
2
- export { listSecrets, projectIdFor };