@devdogsuga/devtools 0.1.0

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.
Files changed (253) hide show
  1. package/README.md +44 -0
  2. package/bin/devtools-ci-bare.mjs +48 -0
  3. package/bin/devtools-ci.mjs +17 -0
  4. package/bin/devtools.mjs +27 -0
  5. package/dist/args.d.ts +26 -0
  6. package/dist/args.js +78 -0
  7. package/dist/bws/bw.d.ts +9 -0
  8. package/dist/bws/bw.js +49 -0
  9. package/dist/bws/client.d.ts +43 -0
  10. package/dist/bws/client.js +363 -0
  11. package/dist/bws/environments.d.ts +96 -0
  12. package/dist/bws/environments.js +111 -0
  13. package/dist/bws/pace.d.ts +27 -0
  14. package/dist/bws/pace.js +43 -0
  15. package/dist/bws/retry.d.ts +12 -0
  16. package/dist/bws/retry.js +39 -0
  17. package/dist/bws/store.d.ts +1 -0
  18. package/dist/bws/store.js +32 -0
  19. package/dist/bws/token.d.ts +31 -0
  20. package/dist/bws/token.js +88 -0
  21. package/dist/bws/vault.d.ts +29 -0
  22. package/dist/bws/vault.js +200 -0
  23. package/dist/catalog.d.ts +55 -0
  24. package/dist/catalog.js +81 -0
  25. package/dist/cf/commands.d.ts +1 -0
  26. package/dist/cf/commands.js +182 -0
  27. package/dist/cf/local-env.d.ts +44 -0
  28. package/dist/cf/local-env.js +148 -0
  29. package/dist/ci.d.ts +1 -0
  30. package/dist/ci.js +319 -0
  31. package/dist/cli.d.ts +11 -0
  32. package/dist/cli.js +1077 -0
  33. package/dist/commands.d.ts +255 -0
  34. package/dist/commands.js +1279 -0
  35. package/dist/completions.d.ts +4 -0
  36. package/dist/completions.js +110 -0
  37. package/dist/cron/commands.d.ts +47 -0
  38. package/dist/cron/commands.js +372 -0
  39. package/dist/cron/discovery.d.ts +55 -0
  40. package/dist/cron/discovery.js +85 -0
  41. package/dist/cron/schema.d.ts +45 -0
  42. package/dist/cron/schema.js +35 -0
  43. package/dist/db/config-push.d.ts +8 -0
  44. package/dist/db/config-push.js +11 -0
  45. package/dist/db/connection.d.ts +79 -0
  46. package/dist/db/connection.js +114 -0
  47. package/dist/db/exec.d.ts +1 -0
  48. package/dist/db/exec.js +11 -0
  49. package/dist/db/generate-migration.d.ts +1 -0
  50. package/dist/db/generate-migration.js +67 -0
  51. package/dist/db/generate-types.d.ts +1 -0
  52. package/dist/db/generate-types.js +4 -0
  53. package/dist/db/introspect.d.ts +1 -0
  54. package/dist/db/introspect.js +113 -0
  55. package/dist/db/local-env.d.ts +65 -0
  56. package/dist/db/local-env.js +23 -0
  57. package/dist/db/new-migration.d.ts +1 -0
  58. package/dist/db/new-migration.js +8 -0
  59. package/dist/db/run.d.ts +70 -0
  60. package/dist/db/run.js +158 -0
  61. package/dist/db/seed-buckets.d.ts +2 -0
  62. package/dist/db/seed-buckets.js +4 -0
  63. package/dist/db/seed-production.d.ts +8 -0
  64. package/dist/db/seed-production.js +73 -0
  65. package/dist/db/seed-roles.d.ts +7 -0
  66. package/dist/db/seed-roles.js +31 -0
  67. package/dist/db/session-refresh.d.ts +43 -0
  68. package/dist/db/session-refresh.js +40 -0
  69. package/dist/deploy/migrations.d.ts +20 -0
  70. package/dist/deploy/migrations.js +68 -0
  71. package/dist/deploy/orphans.d.ts +20 -0
  72. package/dist/deploy/orphans.js +177 -0
  73. package/dist/deploy/preflight.d.ts +53 -0
  74. package/dist/deploy/preflight.js +189 -0
  75. package/dist/deploy/report.d.ts +26 -0
  76. package/dist/deploy/report.js +70 -0
  77. package/dist/deploy/require-planner.d.ts +2 -0
  78. package/dist/deploy/require-planner.js +60 -0
  79. package/dist/deploy/require-token.d.ts +15 -0
  80. package/dist/deploy/require-token.js +78 -0
  81. package/dist/deploy/secrets-file.d.ts +17 -0
  82. package/dist/deploy/secrets-file.js +167 -0
  83. package/dist/deploy/write-env.d.ts +40 -0
  84. package/dist/deploy/write-env.js +393 -0
  85. package/dist/docs/index-pages.d.ts +36 -0
  86. package/dist/docs/index-pages.js +184 -0
  87. package/dist/doctor.d.ts +62 -0
  88. package/dist/doctor.js +225 -0
  89. package/dist/emails/commands.d.ts +15 -0
  90. package/dist/emails/commands.js +130 -0
  91. package/dist/emails/email-types.d.ts +13 -0
  92. package/dist/emails/email-types.js +1 -0
  93. package/dist/emails/fixtures.d.ts +20 -0
  94. package/dist/emails/fixtures.js +20 -0
  95. package/dist/env/audit.d.ts +206 -0
  96. package/dist/env/audit.js +436 -0
  97. package/dist/env/cloudflare.d.ts +21 -0
  98. package/dist/env/cloudflare.js +61 -0
  99. package/dist/env/commands.d.ts +99 -0
  100. package/dist/env/commands.js +612 -0
  101. package/dist/env/discovery.d.ts +15 -0
  102. package/dist/env/discovery.js +226 -0
  103. package/dist/env/document.d.ts +119 -0
  104. package/dist/env/document.js +323 -0
  105. package/dist/env/example.d.ts +68 -0
  106. package/dist/env/example.js +603 -0
  107. package/dist/env/selection.d.ts +105 -0
  108. package/dist/env/selection.js +226 -0
  109. package/dist/environment.d.ts +92 -0
  110. package/dist/environment.js +206 -0
  111. package/dist/fingerprint.d.ts +10 -0
  112. package/dist/fingerprint.js +18 -0
  113. package/dist/gen/campus-map.d.ts +1 -0
  114. package/dist/gen/campus-map.js +473 -0
  115. package/dist/gen/commands.d.ts +1 -0
  116. package/dist/gen/commands.js +25 -0
  117. package/dist/gen/hypno.d.ts +1 -0
  118. package/dist/gen/hypno.js +134 -0
  119. package/dist/gh/client.d.ts +80 -0
  120. package/dist/gh/client.js +258 -0
  121. package/dist/gh/environments.d.ts +83 -0
  122. package/dist/gh/environments.js +178 -0
  123. package/dist/gh/rulesets/actors.d.ts +14 -0
  124. package/dist/gh/rulesets/actors.js +68 -0
  125. package/dist/gh/rulesets/api.d.ts +15 -0
  126. package/dist/gh/rulesets/api.js +99 -0
  127. package/dist/gh/rulesets/commands.d.ts +3 -0
  128. package/dist/gh/rulesets/commands.js +203 -0
  129. package/dist/gh/rulesets/desired.d.ts +112 -0
  130. package/dist/gh/rulesets/desired.js +247 -0
  131. package/dist/gh/rulesets/diff.d.ts +65 -0
  132. package/dist/gh/rulesets/diff.js +134 -0
  133. package/dist/gh/rulesets/types.d.ts +76 -0
  134. package/dist/gh/rulesets/types.js +13 -0
  135. package/dist/gh/settings/api.d.ts +40 -0
  136. package/dist/gh/settings/api.js +172 -0
  137. package/dist/gh/settings/commands.d.ts +1 -0
  138. package/dist/gh/settings/commands.js +245 -0
  139. package/dist/gh/settings/desired.d.ts +53 -0
  140. package/dist/gh/settings/desired.js +39 -0
  141. package/dist/gh/settings/diff.d.ts +57 -0
  142. package/dist/gh/settings/diff.js +156 -0
  143. package/dist/gh/settings/types.d.ts +92 -0
  144. package/dist/gh/settings/types.js +11 -0
  145. package/dist/gh/settings/workflows.d.ts +41 -0
  146. package/dist/gh/settings/workflows.js +124 -0
  147. package/dist/grantRoot.d.ts +42 -0
  148. package/dist/grantRoot.js +89 -0
  149. package/dist/help.d.ts +18 -0
  150. package/dist/help.js +169 -0
  151. package/dist/images/commands.d.ts +35 -0
  152. package/dist/images/commands.js +233 -0
  153. package/dist/images/events.d.ts +36 -0
  154. package/dist/images/events.js +152 -0
  155. package/dist/images/graphics.d.ts +70 -0
  156. package/dist/images/graphics.js +233 -0
  157. package/dist/images/open-graph-types.d.ts +75 -0
  158. package/dist/images/open-graph-types.js +1 -0
  159. package/dist/images/prompts.d.ts +34 -0
  160. package/dist/images/prompts.js +100 -0
  161. package/dist/images/render.d.ts +21 -0
  162. package/dist/images/render.js +57 -0
  163. package/dist/images/select.d.ts +64 -0
  164. package/dist/images/select.js +96 -0
  165. package/dist/instance.d.ts +67 -0
  166. package/dist/instance.js +129 -0
  167. package/dist/invocation.d.ts +49 -0
  168. package/dist/invocation.js +78 -0
  169. package/dist/launch-ci.d.ts +1 -0
  170. package/dist/launch-ci.js +86 -0
  171. package/dist/launch.d.ts +29 -0
  172. package/dist/launch.js +371 -0
  173. package/dist/menu.d.ts +31 -0
  174. package/dist/menu.js +277 -0
  175. package/dist/newsletter/commands.d.ts +16 -0
  176. package/dist/newsletter/commands.js +311 -0
  177. package/dist/newsletter/imap.d.ts +17 -0
  178. package/dist/newsletter/imap.js +127 -0
  179. package/dist/newsletter/loopback.d.ts +24 -0
  180. package/dist/newsletter/loopback.js +100 -0
  181. package/dist/newsletter/oauth.d.ts +26 -0
  182. package/dist/newsletter/oauth.js +130 -0
  183. package/dist/newsletter/smtp.d.ts +23 -0
  184. package/dist/newsletter/smtp.js +133 -0
  185. package/dist/oauth/browser.d.ts +1 -0
  186. package/dist/oauth/browser.js +13 -0
  187. package/dist/oauth/config.d.ts +24 -0
  188. package/dist/oauth/config.js +24 -0
  189. package/dist/oauth/connect-url.d.ts +17 -0
  190. package/dist/oauth/connect-url.js +23 -0
  191. package/dist/oauth/db.d.ts +37 -0
  192. package/dist/oauth/db.js +108 -0
  193. package/dist/oauth/device.d.ts +93 -0
  194. package/dist/oauth/device.js +190 -0
  195. package/dist/oauth/discovery.d.ts +28 -0
  196. package/dist/oauth/discovery.js +54 -0
  197. package/dist/oauth/env-file.d.ts +6 -0
  198. package/dist/oauth/env-file.js +35 -0
  199. package/dist/oauth/exchange.d.ts +43 -0
  200. package/dist/oauth/exchange.js +87 -0
  201. package/dist/oauth/label.d.ts +1 -0
  202. package/dist/oauth/label.js +25 -0
  203. package/dist/oauth/loopback.d.ts +52 -0
  204. package/dist/oauth/loopback.js +162 -0
  205. package/dist/oauth/pkce.d.ts +6 -0
  206. package/dist/oauth/pkce.js +34 -0
  207. package/dist/oauth/target.d.ts +54 -0
  208. package/dist/oauth/target.js +102 -0
  209. package/dist/oauth/transport.d.ts +41 -0
  210. package/dist/oauth/transport.js +32 -0
  211. package/dist/oauth/wizard.d.ts +33 -0
  212. package/dist/oauth/wizard.js +571 -0
  213. package/dist/pick.d.ts +6 -0
  214. package/dist/pick.js +64 -0
  215. package/dist/planner/checks.d.ts +26 -0
  216. package/dist/planner/checks.js +104 -0
  217. package/dist/planner/commands.d.ts +10 -0
  218. package/dist/planner/commands.js +367 -0
  219. package/dist/planner/db.d.ts +15 -0
  220. package/dist/planner/db.js +33 -0
  221. package/dist/planner/role.d.ts +33 -0
  222. package/dist/planner/role.js +68 -0
  223. package/dist/repo/peers.d.ts +24 -0
  224. package/dist/repo/peers.js +114 -0
  225. package/dist/repo/preflight.d.ts +109 -0
  226. package/dist/repo/preflight.js +266 -0
  227. package/dist/repo/resolve.d.ts +41 -0
  228. package/dist/repo/resolve.js +152 -0
  229. package/dist/repo/root.d.ts +23 -0
  230. package/dist/repo/root.js +91 -0
  231. package/dist/repo/source.d.ts +14 -0
  232. package/dist/repo/source.js +54 -0
  233. package/dist/repo/tsx-loader.d.ts +6 -0
  234. package/dist/repo/tsx-loader.js +41 -0
  235. package/dist/run/pick.d.ts +60 -0
  236. package/dist/run/pick.js +559 -0
  237. package/dist/setup.d.ts +1 -0
  238. package/dist/setup.js +152 -0
  239. package/dist/stack.d.ts +48 -0
  240. package/dist/stack.js +290 -0
  241. package/dist/telemetry.d.ts +34 -0
  242. package/dist/telemetry.js +93 -0
  243. package/dist/tier.d.ts +40 -0
  244. package/dist/tier.js +93 -0
  245. package/dist/tsconfig.typecheck.tsbuildinfo +1 -0
  246. package/dist/ui.d.ts +25 -0
  247. package/dist/ui.js +51 -0
  248. package/dist/workers.d.ts +5 -0
  249. package/dist/workers.js +35 -0
  250. package/dist/workflows/commands.d.ts +44 -0
  251. package/dist/workflows/commands.js +668 -0
  252. package/env.ts +158 -0
  253. package/package.json +80 -0
@@ -0,0 +1,23 @@
1
+ export declare class RepoNotFoundError extends Error {
2
+ constructor();
3
+ }
4
+ /**
5
+ * Walks up from `startDir` (default `process.cwd()`) looking for the repo
6
+ * marker. Returns `null` rather than throwing — `findRepoRoot()` below is
7
+ * the throwing convenience most callers want; this is exported for callers
8
+ * (like `setup`) that need to know without failing.
9
+ */
10
+ export declare function discoverRepoRoot(startDir?: string): string | null;
11
+ /**
12
+ * The memoized, throwing repo-root lookup. Lazy on purpose: importing this
13
+ * module must never fail just because nothing has called it yet (`setup`
14
+ * and `completions` in `launch.ts` never need a repo at all, and must stay
15
+ * that way — see that file's header comment on why).
16
+ *
17
+ * Resolved once per process: `process.cwd()` does not change mid-invocation
18
+ * for this CLI, and re-walking the filesystem on every call would be pure
19
+ * waste.
20
+ */
21
+ export declare function findRepoRoot(): string;
22
+ /** Test-only: clears the memoized root so a test can point `process.cwd()` elsewhere. */
23
+ export declare function resetRepoRootCacheForTests(): void;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Where devtools finds the DevDogsUGA checkout it is running against.
3
+ *
4
+ * devtools used to live inside `packages/devtools` of that repo, so its own
5
+ * `import.meta.url` WAS a path into the repo (`PROJECT_ROOT` /
6
+ * `REPO_ROOT` walked up a fixed number of `..` segments from this file).
7
+ * Published as its own package and run through `pnpm dlx`, that assumption
8
+ * breaks: this file's `import.meta.url` points into a dlx cache directory
9
+ * or an isolated `node_modules` tree that has nothing to do with the repo
10
+ * the contributor is standing in.
11
+ *
12
+ * So repo discovery walks up from `process.cwd()` instead, looking for the
13
+ * marker validated in the `devtools-dlx` prototype
14
+ * (`/home/sloan/scratchpad/devdogs/prototypes/devtools-dlx/FINDINGS.md`,
15
+ * experiment 1): a directory containing `pnpm-workspace.yaml` AND whose
16
+ * `package.json` has `"name": "devdogs-monorepo"`. The name check is not
17
+ * redundant — a bare `pnpm-workspace.yaml` also matches a Backstage
18
+ * checkout (a separate pnpm workspace), which devtools should refuse
19
+ * rather than silently "find".
20
+ */
21
+ import { existsSync, readFileSync } from "node:fs";
22
+ import { dirname, join } from "node:path";
23
+ /** The `package.json` name every real DevDogsUGA checkout carries at its root. */
24
+ const REPO_MARKER_NAME = "devdogs-monorepo";
25
+ export class RepoNotFoundError extends Error {
26
+ constructor() {
27
+ super("run this from inside a DevDogsUGA clone");
28
+ this.name = "RepoNotFoundError";
29
+ }
30
+ }
31
+ function looksLikeRepoRoot(dir) {
32
+ if (!existsSync(join(dir, "pnpm-workspace.yaml")))
33
+ return false;
34
+ try {
35
+ const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
36
+ return pkg.name === REPO_MARKER_NAME;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ /**
43
+ * Walks up from `startDir` (default `process.cwd()`) looking for the repo
44
+ * marker. Returns `null` rather than throwing — `findRepoRoot()` below is
45
+ * the throwing convenience most callers want; this is exported for callers
46
+ * (like `setup`) that need to know without failing.
47
+ */
48
+ export function discoverRepoRoot(startDir = process.cwd()) {
49
+ let dir = startDir;
50
+ for (;;) {
51
+ if (looksLikeRepoRoot(dir))
52
+ return dir;
53
+ const parent = dirname(dir);
54
+ if (parent === dir)
55
+ return null;
56
+ dir = parent;
57
+ }
58
+ }
59
+ let cachedRoot;
60
+ /**
61
+ * The memoized, throwing repo-root lookup. Lazy on purpose: importing this
62
+ * module must never fail just because nothing has called it yet (`setup`
63
+ * and `completions` in `launch.ts` never need a repo at all, and must stay
64
+ * that way — see that file's header comment on why).
65
+ *
66
+ * Resolved once per process: `process.cwd()` does not change mid-invocation
67
+ * for this CLI, and re-walking the filesystem on every call would be pure
68
+ * waste.
69
+ */
70
+ export function findRepoRoot() {
71
+ if (cachedRoot === undefined) {
72
+ // Backstage's own test suite has no DevDogsUGA checkout to discover —
73
+ // it IS a different pnpm workspace — but most of devtools' unit tests
74
+ // exercise code that calls `findRepoRoot()` only to build a path string
75
+ // that a mocked `node:fs/promises` never actually reads. Rather than
76
+ // adding a `vi.mock("../repo/root.js", ...)` to every one of those
77
+ // files, `vitest.config.ts` sets this one env var for the whole run so
78
+ // `findRepoRoot()` resolves to a stable fake path instead of throwing.
79
+ // A test that specifically wants the real "not in a repo" refusal
80
+ // (`RepoNotFoundError`) unsets it locally — see `root.test.ts`.
81
+ cachedRoot = process.env.DEVTOOLS_TEST_REPO_ROOT ?? discoverRepoRoot();
82
+ }
83
+ if (cachedRoot === null) {
84
+ throw new RepoNotFoundError();
85
+ }
86
+ return cachedRoot;
87
+ }
88
+ /** Test-only: clears the memoized root so a test can point `process.cwd()` elsewhere. */
89
+ export function resetRepoRootCacheForTests() {
90
+ cachedRoot = undefined;
91
+ }
@@ -0,0 +1,14 @@
1
+ /** Test-only: clears the memoized source modules. */
2
+ export declare function resetSourceCacheForTests(): void;
3
+ import type { OpenGraphModule } from "../images/open-graph-types.js";
4
+ export declare function loadOpenGraph(): Promise<OpenGraphModule>;
5
+ import type { EmailTemplates } from "../emails/email-types.js";
6
+ export interface EmailModule {
7
+ render<K extends keyof EmailTemplates>(name: K, props: EmailTemplates[K]): {
8
+ subject: string;
9
+ html: string;
10
+ text: string;
11
+ };
12
+ }
13
+ export declare function loadEmail(): Promise<EmailModule>;
14
+ export declare function loadDocs(): Promise<unknown>;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Loads the repo-local, never-published `@devdogsuga/*` packages devtools
3
+ * needs at runtime: `open-graph`, `email`, `docs`. Unlike the
4
+ * `peers.ts` set, these are `"private": true` in the target repo and never
5
+ * reach npm — devtools resolves them straight out of the repo's own
6
+ * `node_modules` (a pnpm workspace symlink) using the `devdogs-source`
7
+ * export condition, picked by hand (see `resolve.ts`'s header and
8
+ * FINDINGS.md experiment 4 for why this can't go through
9
+ * `require.resolve`/tsx's `register({ conditions })`).
10
+ *
11
+ * `open-graph` and `email` both declare a `"devdogs-source"` entry in their
12
+ * `exports["."]` map, pointing at TS source. `docs` does not (its `default`
13
+ * points straight at a built `dist/index.js`, produced by
14
+ * `docs-compiler`) — `resolveFromRepo` falls back to `.default` for it,
15
+ * and routing the result through the same tsx-backed import as the other
16
+ * two is harmless: tsx passes plain `.js` through unchanged.
17
+ */
18
+ import { findRepoRoot } from "./root.js";
19
+ import { findDependent, resolveFromRepo } from "./resolve.js";
20
+ import { importRepoTs } from "./tsx-loader.js";
21
+ const CONDITION = "devdogs-source";
22
+ const cache = new Map();
23
+ function loadSource(specifier) {
24
+ const cached = cache.get(specifier);
25
+ if (cached)
26
+ return cached;
27
+ const promise = (async () => {
28
+ const repoRoot = findRepoRoot();
29
+ const resolutionBase = findDependent(repoRoot, specifier);
30
+ if (!resolutionBase) {
31
+ throw new Error(`Nothing in this repo depends on ${specifier} — expected an app or package under apps/*` +
32
+ ` or packages/* to declare it.`);
33
+ }
34
+ const { resolvedPath } = resolveFromRepo(repoRoot, resolutionBase, specifier, {
35
+ condition: CONDITION,
36
+ });
37
+ return importRepoTs(resolvedPath);
38
+ })();
39
+ cache.set(specifier, promise);
40
+ return promise;
41
+ }
42
+ /** Test-only: clears the memoized source modules. */
43
+ export function resetSourceCacheForTests() {
44
+ cache.clear();
45
+ }
46
+ export function loadOpenGraph() {
47
+ return loadSource("@devdogsuga/open-graph");
48
+ }
49
+ export function loadEmail() {
50
+ return loadSource("@devdogsuga/email");
51
+ }
52
+ export function loadDocs() {
53
+ return loadSource("@devdogsuga/docs");
54
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Imports a repo TypeScript file at an absolute path, loaded through tsx.
3
+ * Returns the module namespace, typed as `T` by the caller (there is no way
4
+ * to know the shape of an arbitrary repo file's exports statically here).
5
+ */
6
+ export declare function importRepoTs<T>(absolutePath: string): Promise<T>;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Loads the repo's own TypeScript at runtime: env manifests
3
+ * (each app's `src/env.ts` and friends), cron contracts
4
+ * (each app's `cloudflare/scheduled.ts`), and — via `source.ts` — the
5
+ * `devdogs-source` condition packages (`open-graph`, `email`, `docs`).
6
+ *
7
+ * Uses `tsx`'s programmatic API (`register()` from `tsx/esm/api`), NOT the
8
+ * `--conditions=devdogs-source` CLI flag the old in-repo devtools used —
9
+ * this package ships built JS and runs from `dist/`, so there is no `tsx`
10
+ * process wrapping it anymore (see the package README / CUTOVER note on
11
+ * "built JS, tsx only for repo TS").
12
+ *
13
+ * Gotcha (FINDINGS.md experiments 3 and 4, gotcha C): do NOT pass a
14
+ * `namespace` to `register()`. It silently breaks tsx's own relative
15
+ * `./foo.js` → `./foo.ts` extension-fallback resolution for files loaded
16
+ * under that registration — exactly the convention `open-graph`, `email`,
17
+ * and any future `devdogs-source` package use for their internal relative
18
+ * imports. `register({})` (no options) is the only form validated.
19
+ */
20
+ import { pathToFileURL } from "node:url";
21
+ let registered = false;
22
+ /** Idempotent: registers tsx's ESM loader hooks once per process. */
23
+ async function ensureRegistered() {
24
+ if (registered)
25
+ return;
26
+ const { register } = await import("tsx/esm/api");
27
+ // `register()`'s return value is an unregister callback (`() => Promise<void>`),
28
+ // not something this process ever calls: the hooks stay installed for the
29
+ // CLI's whole lifetime.
30
+ register();
31
+ registered = true;
32
+ }
33
+ /**
34
+ * Imports a repo TypeScript file at an absolute path, loaded through tsx.
35
+ * Returns the module namespace, typed as `T` by the caller (there is no way
36
+ * to know the shape of an arbitrary repo file's exports statically here).
37
+ */
38
+ export async function importRepoTs(absolutePath) {
39
+ await ensureRegistered();
40
+ return import(pathToFileURL(absolutePath).href);
41
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Whether to ask at all.
3
+ *
4
+ * Every one of these is a case where a prompt is either impossible or wrong:
5
+ *
6
+ * * `CI`, set by GitHub Actions and every other runner. No workflow reaches
7
+ * this today (see the header), but a workflow that blocked on a
8
+ * multiselect would hang until its timeout with no output saying why, and
9
+ * that failure is bad enough to keep guarding against.
10
+ * * No TTY: a pipe, a `pnpm` invoked by a script, an editor task runner.
11
+ * Nobody is there to answer. Every other picker in this repo checks the
12
+ * same thing.
13
+ * * An explicit filter. The caller has already said which packages, and
14
+ * asking again would be asking them to repeat themselves.
15
+ * * `DEVDOGS_PICK=0`, the escape hatch and the recursion guard above.
16
+ */
17
+ export declare function shouldAsk(args: string[]): boolean;
18
+ /**
19
+ * Pulls every `--filter`/`-F`/`--scope` value out of `args`, returning the
20
+ * package patterns named and the remaining args with those flags removed.
21
+ *
22
+ * `--scope` is folded into the same bucket as `--filter` here: pnpm has no
23
+ * `--scope` flag of its own, so a caller who still types the turbo-era name
24
+ * gets it translated into a real `--filter` value rather than passed through
25
+ * to a `pnpm` invocation that would reject it outright.
26
+ *
27
+ * Exported for the same reason `parseTierArg` is: pure, no `process.exit`, so
28
+ * it is unit-testable without going through `passthrough`.
29
+ */
30
+ export declare function extractFilters(args: readonly string[]): {
31
+ filters: string[];
32
+ rest: string[];
33
+ };
34
+ export interface TierArgResult {
35
+ /** The validated tier, or absent when `--tier` was not passed. */
36
+ tier?: string;
37
+ /** `args` with `--tier` and its value removed, so pnpm never sees them. */
38
+ rest: string[];
39
+ /** Set instead of `tier` when parsing failed; `rest` is unchanged on error. */
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Parses and strips `--tier <value>` from pnpm-bound args, mirroring the
44
+ * `--all` strip above.
45
+ *
46
+ * Pure on purpose — no `process.exit` — so this is unit-testable without
47
+ * going through `passthrough`, which every other path in this file ends at
48
+ * and which a test cannot observe return from. `runTask` is the one caller,
49
+ * and it is the one that turns `error` into an exit.
50
+ */
51
+ export declare function parseTierArg(args: readonly string[]): TierArgResult;
52
+ /**
53
+ * Runs one root task, asking which apps first where that makes sense.
54
+ *
55
+ * Never returns: every path ends in `passthrough`, which exits with the
56
+ * underlying `pnpm` invocation's own status. That is why `cli.ts` dispatches
57
+ * this before `intro()`. There is no `outro()` to reach, and a banner would
58
+ * land on the stream a dev server is about to take over.
59
+ */
60
+ export declare function runTask(argv: string[]): Promise<never>;