@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.
Files changed (271) hide show
  1. package/README.md +72 -11
  2. package/bin/devtools.mjs +4 -4
  3. package/dist/cli-CZKkNHK5.js +6619 -0
  4. package/dist/failure-log-BBPGejQv.js +256 -0
  5. package/dist/launch.js +267 -281
  6. package/dist/local-env-D8HC2JK_.js +351 -0
  7. package/dist/local-env-DrBCXqD8.js +2 -0
  8. package/dist/menu-CQBsQRgH.js +1684 -0
  9. package/dist/peer-redirect-hooks.js +15 -0
  10. package/dist/peers-RBplwovA.js +229 -0
  11. package/dist/root-C2OmZDwD.js +94 -0
  12. package/dist/stack-Bx-55oi_.js +2 -0
  13. package/dist/stack-BynCgRVS.js +181 -0
  14. package/dist/supabase-project-0knM0mqd.js +426 -0
  15. package/dist/telemetry-C4foD8MD.js +249 -0
  16. package/dist/telemetry.js +2 -148
  17. package/package.json +10 -29
  18. package/bin/devtools-ci-bare.mjs +0 -48
  19. package/bin/devtools-ci.mjs +0 -31
  20. package/dist/args.d.ts +0 -26
  21. package/dist/args.js +0 -78
  22. package/dist/bws/bw.d.ts +0 -18
  23. package/dist/bws/bw.js +0 -70
  24. package/dist/bws/client.d.ts +0 -43
  25. package/dist/bws/client.js +0 -363
  26. package/dist/bws/environments.d.ts +0 -96
  27. package/dist/bws/environments.js +0 -111
  28. package/dist/bws/pace.d.ts +0 -25
  29. package/dist/bws/pace.js +0 -43
  30. package/dist/bws/retry.d.ts +0 -12
  31. package/dist/bws/retry.js +0 -39
  32. package/dist/bws/store.d.ts +0 -1
  33. package/dist/bws/store.js +0 -32
  34. package/dist/bws/token.d.ts +0 -31
  35. package/dist/bws/token.js +0 -88
  36. package/dist/bws/vault.d.ts +0 -29
  37. package/dist/bws/vault.js +0 -200
  38. package/dist/catalog.d.ts +0 -57
  39. package/dist/catalog.js +0 -57
  40. package/dist/cf/build.d.ts +0 -13
  41. package/dist/cf/build.js +0 -65
  42. package/dist/cf/commands.d.ts +0 -1
  43. package/dist/cf/commands.js +0 -172
  44. package/dist/cf/local-env.d.ts +0 -58
  45. package/dist/cf/local-env.js +0 -177
  46. package/dist/ci.d.ts +0 -1
  47. package/dist/ci.js +0 -328
  48. package/dist/cli.d.ts +0 -11
  49. package/dist/cli.js +0 -1094
  50. package/dist/commands.d.ts +0 -261
  51. package/dist/commands.js +0 -1318
  52. package/dist/completions.d.ts +0 -4
  53. package/dist/completions.js +0 -110
  54. package/dist/cron/commands.d.ts +0 -47
  55. package/dist/cron/commands.js +0 -372
  56. package/dist/cron/discovery.d.ts +0 -55
  57. package/dist/cron/discovery.js +0 -85
  58. package/dist/cron/schema.d.ts +0 -45
  59. package/dist/cron/schema.js +0 -35
  60. package/dist/db/config-push.d.ts +0 -8
  61. package/dist/db/config-push.js +0 -11
  62. package/dist/db/connection.d.ts +0 -79
  63. package/dist/db/connection.js +0 -114
  64. package/dist/db/exec.d.ts +0 -1
  65. package/dist/db/exec.js +0 -11
  66. package/dist/db/generate-types.d.ts +0 -1
  67. package/dist/db/generate-types.js +0 -4
  68. package/dist/db/generated-env.d.ts +0 -69
  69. package/dist/db/generated-env.js +0 -113
  70. package/dist/db/introspect.d.ts +0 -1
  71. package/dist/db/introspect.js +0 -122
  72. package/dist/db/local-env.d.ts +0 -65
  73. package/dist/db/local-env.js +0 -23
  74. package/dist/db/new-migration.d.ts +0 -8
  75. package/dist/db/new-migration.js +0 -69
  76. package/dist/db/pooler.d.ts +0 -23
  77. package/dist/db/pooler.js +0 -55
  78. package/dist/db/run.d.ts +0 -68
  79. package/dist/db/run.js +0 -156
  80. package/dist/db/seed-buckets.d.ts +0 -2
  81. package/dist/db/seed-buckets.js +0 -4
  82. package/dist/db/seed-production.d.ts +0 -8
  83. package/dist/db/seed-production.js +0 -79
  84. package/dist/db/seed-roles.d.ts +0 -7
  85. package/dist/db/seed-roles.js +0 -33
  86. package/dist/db/session-refresh.d.ts +0 -43
  87. package/dist/db/session-refresh.js +0 -40
  88. package/dist/deploy/migrations.d.ts +0 -20
  89. package/dist/deploy/migrations.js +0 -68
  90. package/dist/deploy/orphans.d.ts +0 -20
  91. package/dist/deploy/orphans.js +0 -177
  92. package/dist/deploy/preflight.d.ts +0 -53
  93. package/dist/deploy/preflight.js +0 -189
  94. package/dist/deploy/report.d.ts +0 -26
  95. package/dist/deploy/report.js +0 -70
  96. package/dist/deploy/require-planner.d.ts +0 -2
  97. package/dist/deploy/require-planner.js +0 -60
  98. package/dist/deploy/require-token.d.ts +0 -15
  99. package/dist/deploy/require-token.js +0 -78
  100. package/dist/deploy/secrets-file.d.ts +0 -17
  101. package/dist/deploy/secrets-file.js +0 -166
  102. package/dist/deploy/write-env.d.ts +0 -40
  103. package/dist/deploy/write-env.js +0 -395
  104. package/dist/docs/index-pages.d.ts +0 -38
  105. package/dist/docs/index-pages.js +0 -186
  106. package/dist/emails/commands.d.ts +0 -15
  107. package/dist/emails/commands.js +0 -130
  108. package/dist/emails/email-types.d.ts +0 -13
  109. package/dist/emails/email-types.js +0 -1
  110. package/dist/emails/fixtures.d.ts +0 -20
  111. package/dist/emails/fixtures.js +0 -20
  112. package/dist/env/audit.d.ts +0 -206
  113. package/dist/env/audit.js +0 -436
  114. package/dist/env/cloudflare.d.ts +0 -21
  115. package/dist/env/cloudflare.js +0 -61
  116. package/dist/env/commands.d.ts +0 -99
  117. package/dist/env/commands.js +0 -613
  118. package/dist/env/discovery.d.ts +0 -15
  119. package/dist/env/discovery.js +0 -239
  120. package/dist/env/document.d.ts +0 -119
  121. package/dist/env/document.js +0 -323
  122. package/dist/env/example.d.ts +0 -68
  123. package/dist/env/example.js +0 -605
  124. package/dist/env/selection.d.ts +0 -105
  125. package/dist/env/selection.js +0 -228
  126. package/dist/env-entry.d.ts +0 -49
  127. package/dist/env-entry.js +0 -204
  128. package/dist/environment-doctor.d.ts +0 -45
  129. package/dist/environment-doctor.js +0 -429
  130. package/dist/environment.d.ts +0 -92
  131. package/dist/environment.js +0 -185
  132. package/dist/fingerprint.d.ts +0 -10
  133. package/dist/fingerprint.js +0 -18
  134. package/dist/gen/campus-map.d.ts +0 -1
  135. package/dist/gen/campus-map.js +0 -473
  136. package/dist/gen/commands.d.ts +0 -1
  137. package/dist/gen/commands.js +0 -25
  138. package/dist/gen/hypno.d.ts +0 -1
  139. package/dist/gen/hypno.js +0 -134
  140. package/dist/gh/client.d.ts +0 -80
  141. package/dist/gh/client.js +0 -259
  142. package/dist/gh/environments.d.ts +0 -83
  143. package/dist/gh/environments.js +0 -178
  144. package/dist/gh/rulesets/actors.d.ts +0 -14
  145. package/dist/gh/rulesets/actors.js +0 -69
  146. package/dist/gh/rulesets/api.d.ts +0 -15
  147. package/dist/gh/rulesets/api.js +0 -104
  148. package/dist/gh/rulesets/commands.d.ts +0 -3
  149. package/dist/gh/rulesets/commands.js +0 -203
  150. package/dist/gh/rulesets/desired.d.ts +0 -112
  151. package/dist/gh/rulesets/desired.js +0 -271
  152. package/dist/gh/rulesets/diff.d.ts +0 -65
  153. package/dist/gh/rulesets/diff.js +0 -170
  154. package/dist/gh/rulesets/types.d.ts +0 -76
  155. package/dist/gh/rulesets/types.js +0 -13
  156. package/dist/gh/settings/api.d.ts +0 -40
  157. package/dist/gh/settings/api.js +0 -180
  158. package/dist/gh/settings/commands.d.ts +0 -1
  159. package/dist/gh/settings/commands.js +0 -254
  160. package/dist/gh/settings/desired.d.ts +0 -53
  161. package/dist/gh/settings/desired.js +0 -43
  162. package/dist/gh/settings/diff.d.ts +0 -57
  163. package/dist/gh/settings/diff.js +0 -161
  164. package/dist/gh/settings/types.d.ts +0 -92
  165. package/dist/gh/settings/types.js +0 -11
  166. package/dist/gh/settings/workflows.d.ts +0 -41
  167. package/dist/gh/settings/workflows.js +0 -128
  168. package/dist/grantRoot.d.ts +0 -42
  169. package/dist/grantRoot.js +0 -89
  170. package/dist/help.d.ts +0 -18
  171. package/dist/help.js +0 -169
  172. package/dist/images/commands.d.ts +0 -32
  173. package/dist/images/commands.js +0 -231
  174. package/dist/images/events.d.ts +0 -47
  175. package/dist/images/events.js +0 -116
  176. package/dist/images/graphics.d.ts +0 -70
  177. package/dist/images/graphics.js +0 -234
  178. package/dist/images/open-graph-types.d.ts +0 -75
  179. package/dist/images/open-graph-types.js +0 -1
  180. package/dist/images/prompts.d.ts +0 -34
  181. package/dist/images/prompts.js +0 -100
  182. package/dist/images/render.d.ts +0 -21
  183. package/dist/images/render.js +0 -61
  184. package/dist/images/select.d.ts +0 -64
  185. package/dist/images/select.js +0 -96
  186. package/dist/instance.d.ts +0 -69
  187. package/dist/instance.js +0 -102
  188. package/dist/invocation.d.ts +0 -49
  189. package/dist/invocation.js +0 -78
  190. package/dist/launch-ci.d.ts +0 -1
  191. package/dist/launch-ci.js +0 -90
  192. package/dist/launch.d.ts +0 -18
  193. package/dist/menu.d.ts +0 -43
  194. package/dist/menu.js +0 -300
  195. package/dist/moderation.d.ts +0 -70
  196. package/dist/moderation.js +0 -128
  197. package/dist/oauth/browser.d.ts +0 -1
  198. package/dist/oauth/browser.js +0 -13
  199. package/dist/oauth/config.d.ts +0 -24
  200. package/dist/oauth/config.js +0 -24
  201. package/dist/oauth/connect-url.d.ts +0 -17
  202. package/dist/oauth/connect-url.js +0 -23
  203. package/dist/oauth/db.d.ts +0 -37
  204. package/dist/oauth/db.js +0 -108
  205. package/dist/oauth/device.d.ts +0 -93
  206. package/dist/oauth/device.js +0 -198
  207. package/dist/oauth/discovery.d.ts +0 -28
  208. package/dist/oauth/discovery.js +0 -54
  209. package/dist/oauth/env-file.d.ts +0 -6
  210. package/dist/oauth/env-file.js +0 -35
  211. package/dist/oauth/exchange.d.ts +0 -43
  212. package/dist/oauth/exchange.js +0 -93
  213. package/dist/oauth/label.d.ts +0 -1
  214. package/dist/oauth/label.js +0 -25
  215. package/dist/oauth/loopback.d.ts +0 -52
  216. package/dist/oauth/loopback.js +0 -168
  217. package/dist/oauth/pkce.d.ts +0 -6
  218. package/dist/oauth/pkce.js +0 -34
  219. package/dist/oauth/target.d.ts +0 -54
  220. package/dist/oauth/target.js +0 -102
  221. package/dist/oauth/transport.d.ts +0 -41
  222. package/dist/oauth/transport.js +0 -32
  223. package/dist/oauth/wizard.d.ts +0 -40
  224. package/dist/oauth/wizard.js +0 -578
  225. package/dist/persona.d.ts +0 -18
  226. package/dist/persona.js +0 -221
  227. package/dist/pick.d.ts +0 -6
  228. package/dist/pick.js +0 -64
  229. package/dist/pipes.d.ts +0 -1
  230. package/dist/pipes.js +0 -25
  231. package/dist/planner/checks.d.ts +0 -26
  232. package/dist/planner/checks.js +0 -104
  233. package/dist/planner/commands.d.ts +0 -10
  234. package/dist/planner/commands.js +0 -367
  235. package/dist/planner/db.d.ts +0 -15
  236. package/dist/planner/db.js +0 -33
  237. package/dist/planner/role.d.ts +0 -33
  238. package/dist/planner/role.js +0 -68
  239. package/dist/repo/peer-redirect-hooks.d.ts +0 -16
  240. package/dist/repo/peer-redirect-hooks.js +0 -10
  241. package/dist/repo/peer-redirect.d.ts +0 -4
  242. package/dist/repo/peer-redirect.js +0 -26
  243. package/dist/repo/peers.d.ts +0 -39
  244. package/dist/repo/peers.js +0 -139
  245. package/dist/repo/resolve.d.ts +0 -41
  246. package/dist/repo/resolve.js +0 -152
  247. package/dist/repo/root.d.ts +0 -23
  248. package/dist/repo/root.js +0 -91
  249. package/dist/repo/source.d.ts +0 -14
  250. package/dist/repo/source.js +0 -54
  251. package/dist/repo/supabase-project.d.ts +0 -60
  252. package/dist/repo/supabase-project.js +0 -124
  253. package/dist/repo/tsx-loader.d.ts +0 -6
  254. package/dist/repo/tsx-loader.js +0 -41
  255. package/dist/run/pick.d.ts +0 -90
  256. package/dist/run/pick.js +0 -664
  257. package/dist/setup.d.ts +0 -1
  258. package/dist/setup.js +0 -280
  259. package/dist/stack.d.ts +0 -48
  260. package/dist/stack.js +0 -403
  261. package/dist/telemetry.d.ts +0 -59
  262. package/dist/tier.d.ts +0 -40
  263. package/dist/tier.js +0 -96
  264. package/dist/ui.d.ts +0 -40
  265. package/dist/ui.js +0 -71
  266. package/dist/version.d.ts +0 -7
  267. package/dist/version.js +0 -17
  268. package/dist/workers.d.ts +0 -5
  269. package/dist/workers.js +0 -33
  270. package/dist/workflows/commands.d.ts +0 -54
  271. package/dist/workflows/commands.js +0 -763
@@ -1,96 +0,0 @@
1
- import { loadOpenGraph } from "../repo/source.js";
2
- /**
3
- * Resolves graphic patterns.
4
- *
5
- * Every graphic is `group/name`, and three shapes of pattern read against
6
- * that: a lone star (or a star over a star) is everything, `group/` plus a star
7
- * is a whole group, and anything else is an exact name. Deliberately not a
8
- * general glob — `event/2026-` plus a star looks like it should work and would
9
- * be one more thing to specify, and the picker covers the case where somebody
10
- * does not know the exact name.
11
- *
12
- * A bare group is accepted as shorthand for `group/*`, because `images icons`
13
- * is what people type and refusing it teaches nothing.
14
- */
15
- export function matchGraphics(patterns, graphics) {
16
- const matched = new Map();
17
- const unmatched = [];
18
- const groups = new Set(graphics.map((graphic) => graphic.group));
19
- for (const pattern of patterns) {
20
- const hits = graphics.filter((graphic) => {
21
- if (pattern === "*" || pattern === "*/*")
22
- return true;
23
- if (pattern.endsWith("/*"))
24
- return graphic.group === pattern.slice(0, -2);
25
- if (groups.has(pattern))
26
- return graphic.group === pattern;
27
- return graphic.name === pattern;
28
- });
29
- if (hits.length === 0) {
30
- unmatched.push(pattern);
31
- continue;
32
- }
33
- for (const hit of hits)
34
- matched.set(hit.name, hit);
35
- }
36
- return { matched: [...matched.values()], unmatched };
37
- }
38
- /**
39
- * Pairs each graphic with each requested format it actually supports.
40
- *
41
- * The matrix is sparse, and silently dropping a pair is the wrong answer in one
42
- * direction only: asking for `*` at every format should quietly skip the
43
- * combinations that do not exist, while asking for one graphic at one format it
44
- * cannot do should say so. The caller decides which case it is; this reports
45
- * both halves.
46
- */
47
- export async function pair(graphics, formats) {
48
- const { FORMATS } = await loadOpenGraph();
49
- const selections = [];
50
- const unsupported = [];
51
- for (const graphic of graphics) {
52
- for (const name of formats) {
53
- const format = FORMATS[name];
54
- if (!format)
55
- continue;
56
- if (graphic.formats.includes(name)) {
57
- selections.push({ graphic, format });
58
- }
59
- else {
60
- unsupported.push({ graphic: graphic.name, format: name });
61
- }
62
- }
63
- }
64
- return { selections, unsupported };
65
- }
66
- /** Every format any of these graphics can be drawn at, in registry order. */
67
- export async function formatsFor(graphics) {
68
- const { FORMATS } = await loadOpenGraph();
69
- const names = new Set(graphics.flatMap((graphic) => graphic.formats));
70
- return Object.values(FORMATS).filter((format) => names.has(format.name));
71
- }
72
- /**
73
- * Splits `--flag=value` into two tokens.
74
- *
75
- * The rest of this CLI reads flags as `--flag value`, and `positionals()`
76
- * depends on that to tell a flag's value from a subcommand. `--format=a,b`
77
- * arrives as one token, so it would be read as a positional — that is, as a
78
- * graphic name — and `images --format=og` would try to render a graphic called
79
- * `--format=og` and report nothing matched. Normalising here lets both spellings
80
- * work without teaching the shared parser about either.
81
- */
82
- export function normalizeArgv(argv) {
83
- return argv.flatMap((token) => {
84
- if (!token.startsWith("--"))
85
- return [token];
86
- const eq = token.indexOf("=");
87
- return eq === -1 ? [token] : [token.slice(0, eq), token.slice(eq + 1)];
88
- });
89
- }
90
- /** A comma-separated flag value, trimmed and emptied of blanks. */
91
- export function commaList(value) {
92
- return (value ?? "")
93
- .split(",")
94
- .map((part) => part.trim())
95
- .filter(Boolean);
96
- }
@@ -1,69 +0,0 @@
1
- import { type DbConnection } from "./db/connection.js";
2
- import { findRepoRoot } from "./repo/root.js";
3
- /**
4
- * The repo root, which is where `supabase/config.toml` lives.
5
- *
6
- * The Supabase CLI walks up from its working directory looking for that file,
7
- * and falls back to `basename(cwd)` as the project name when it finds none, so
8
- * running it from the wrong place fails with "No such container:
9
- * supabase_db_<whatever directory you were in>". Resolved via `findRepoRoot()`
10
- * (walking up from `process.cwd()`, not this source file — see `repo/root.ts`)
11
- * so it does not matter where the contributor invoked the tool from.
12
- */
13
- export { findRepoRoot };
14
- /**
15
- * Every client here goes through this one factory so they all share a type.
16
- *
17
- * supabase-js encodes the default schema in the client's type, so a `schema`
18
- * parameter of type `string` produces a client that will not unify with a
19
- * hand-written `SupabaseClient` annotation. Deriving `DevtoolsClient` from the
20
- * factory sidesteps that.
21
- */
22
- declare function makeClient(url: string, key: string, schema: string): import("@supabase/supabase-js").SupabaseClient<any, "public", string, any, any>;
23
- export type DevtoolsClient = ReturnType<typeof makeClient>;
24
- export interface Instance {
25
- apiUrl: string;
26
- publishableKey: string;
27
- secretKey: string;
28
- }
29
- /** The built-in Root role, from `supabase/seed/production/01_roles.sql`. */
30
- export declare const ROOT_ROLE_ID = "00000000-0000-0000-0000-000000000002";
31
- export interface ResolvedInstance {
32
- connection: DbConnection;
33
- instance: Instance;
34
- }
35
- export interface ResolveInstanceOptions {
36
- /** Stderr prefix, e.g. "devtools grant-root". */
37
- label?: string;
38
- /** Injectable for tests; defaults to `process.env`. */
39
- env?: NodeJS.ProcessEnv;
40
- }
41
- /**
42
- * Resolves the session's database AND the Supabase client credentials for it.
43
- *
44
- * Goes through `resolveDbConnection()` first — the exact check `db
45
- * migrate`/`db reset` run, including the local-stack-offline and
46
- * inherited-development-values guards — so a caller here refuses in exactly
47
- * the same situations and with the same messages those commands already do.
48
- * What this adds is reading `API_URL`/`PUBLISHABLE_KEY`/`SECRET_KEY` out of
49
- * the same already-entered session env `DB_URL` came from (see this file's
50
- * header), rather than shelling out to `supabase status` — which is what
51
- * makes hosted tiers reachable here at all.
52
- *
53
- * Returns `null` after reporting the reason on stderr, same contract as
54
- * `resolveDbConnection` — never throws for an expected failure.
55
- */
56
- export declare function resolveInstance(opts?: ResolveInstanceOptions): Promise<ResolvedInstance | null>;
57
- /** A service-role client. Bypasses RLS, so setup and teardown only. */
58
- export declare function adminClient(instance: Instance, schema?: string): DevtoolsClient;
59
- /**
60
- * A client signed in with a real email/password, subject to RLS.
61
- *
62
- * Signs in for real rather than hand-signing a JWT, so the token path exercised
63
- * is the one production uses, with whatever claims Supabase Auth actually puts
64
- * in a token rather than the ones we assume. Takes the password explicitly —
65
- * there is no fixed persona password any more (see `persona.ts` and
66
- * `moderation.ts`'s `withTemporaryModerator`, both of which generate a fresh
67
- * random one per account).
68
- */
69
- export declare function signedInClient(instance: Instance, email: string, password: string, schema?: string): Promise<DevtoolsClient>;
package/dist/instance.js DELETED
@@ -1,102 +0,0 @@
1
- /**
2
- * Finding the instance to work against, and signing in to it.
3
- *
4
- * `resolveInstance()` is the one entry point every command that needs a
5
- * Supabase client — `db`'s own commands excepted, which only ever need a
6
- * Postgres URL — should call. It goes through the SAME session
7
- * (`resolveDbConnection()`, `db/connection.ts`) `db migrate`/`db reset` do,
8
- * rather than a local-only `supabase status` probe: every session's env
9
- * carries `API_URL`/`PUBLISHABLE_KEY`/`SECRET_KEY` alongside `DB_URL` (see
10
- * `.env.example`), so whichever tier `--tier` named is exactly the instance
11
- * this resolves to, local Docker included.
12
- *
13
- * This replaces `detectLocalInstance()`+`assertMigrated()`, which read
14
- * `supabase status -o env` directly and therefore only ever found the Docker
15
- * stack on this machine — the reason `moderation check` and `grant-root`
16
- * used to be local-only long after `db reset`/`db migrate` moved onto the
17
- * session system.
18
- */
19
- import { createClient } from "@supabase/supabase-js";
20
- import { resolveDbConnection } from "./db/connection.js";
21
- import { findRepoRoot } from "./repo/root.js";
22
- /**
23
- * The repo root, which is where `supabase/config.toml` lives.
24
- *
25
- * The Supabase CLI walks up from its working directory looking for that file,
26
- * and falls back to `basename(cwd)` as the project name when it finds none, so
27
- * running it from the wrong place fails with "No such container:
28
- * supabase_db_<whatever directory you were in>". Resolved via `findRepoRoot()`
29
- * (walking up from `process.cwd()`, not this source file — see `repo/root.ts`)
30
- * so it does not matter where the contributor invoked the tool from.
31
- */
32
- export { findRepoRoot };
33
- /**
34
- * Every client here goes through this one factory so they all share a type.
35
- *
36
- * supabase-js encodes the default schema in the client's type, so a `schema`
37
- * parameter of type `string` produces a client that will not unify with a
38
- * hand-written `SupabaseClient` annotation. Deriving `DevtoolsClient` from the
39
- * factory sidesteps that.
40
- */
41
- function makeClient(url, key, schema) {
42
- return createClient(url, key, {
43
- db: { schema },
44
- auth: { autoRefreshToken: false, persistSession: false },
45
- });
46
- }
47
- /** The built-in Root role, from `supabase/seed/production/01_roles.sql`. */
48
- export const ROOT_ROLE_ID = "00000000-0000-0000-0000-000000000002";
49
- /**
50
- * Resolves the session's database AND the Supabase client credentials for it.
51
- *
52
- * Goes through `resolveDbConnection()` first — the exact check `db
53
- * migrate`/`db reset` run, including the local-stack-offline and
54
- * inherited-development-values guards — so a caller here refuses in exactly
55
- * the same situations and with the same messages those commands already do.
56
- * What this adds is reading `API_URL`/`PUBLISHABLE_KEY`/`SECRET_KEY` out of
57
- * the same already-entered session env `DB_URL` came from (see this file's
58
- * header), rather than shelling out to `supabase status` — which is what
59
- * makes hosted tiers reachable here at all.
60
- *
61
- * Returns `null` after reporting the reason on stderr, same contract as
62
- * `resolveDbConnection` — never throws for an expected failure.
63
- */
64
- export async function resolveInstance(opts = {}) {
65
- const label = opts.label ?? "devtools";
66
- const connection = await resolveDbConnection({ label: opts.label });
67
- if (!connection)
68
- return null;
69
- const env = opts.env ?? process.env;
70
- const apiUrl = env.API_URL;
71
- const publishableKey = env.PUBLISHABLE_KEY;
72
- const secretKey = env.SECRET_KEY;
73
- if (!apiUrl || !publishableKey || !secretKey) {
74
- process.stderr.write(`${label}: this session has a DB_URL but no API_URL/PUBLISHABLE_KEY/` +
75
- "SECRET_KEY — run `pnpm devtools env pull` for this tier, or " +
76
- "`pnpm devtools db start` for the local stack.\n");
77
- return null;
78
- }
79
- return { connection, instance: { apiUrl, publishableKey, secretKey } };
80
- }
81
- /** A service-role client. Bypasses RLS, so setup and teardown only. */
82
- export function adminClient(instance, schema = "platform") {
83
- return makeClient(instance.apiUrl, instance.secretKey, schema);
84
- }
85
- /**
86
- * A client signed in with a real email/password, subject to RLS.
87
- *
88
- * Signs in for real rather than hand-signing a JWT, so the token path exercised
89
- * is the one production uses, with whatever claims Supabase Auth actually puts
90
- * in a token rather than the ones we assume. Takes the password explicitly —
91
- * there is no fixed persona password any more (see `persona.ts` and
92
- * `moderation.ts`'s `withTemporaryModerator`, both of which generate a fresh
93
- * random one per account).
94
- */
95
- export async function signedInClient(instance, email, password, schema = "platform") {
96
- const client = makeClient(instance.apiUrl, instance.publishableKey, schema);
97
- const { error } = await client.auth.signInWithPassword({ email, password });
98
- if (error) {
99
- throw new Error(`Could not sign in as ${email}: ${error.message}.`);
100
- }
101
- return client;
102
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * Records the fully-resolved argv of the command being run, so the CLI can
3
- * close by printing a copy-pasteable line — the same command with every prompt
4
- * already answered — for anyone who reached it through the wizard or let a
5
- * missing flag fall to a prompt.
6
- *
7
- * ## Why a module-level recorder rather than a return value
8
- *
9
- * A command's inputs arrive from two places that never meet: the wizard walks
10
- * `commands.ts` and gathers the *declared* options into the argv it dispatches
11
- * (see `menu.ts`), while a runner resolves anything it prompts for *itself* —
12
- * `workflows run` picking a tier, `env init` picking projects — deep inside its
13
- * own call stack, where the dispatched argv is long out of reach. Threading a
14
- * return value back up through every runner would touch each one's signature;
15
- * a recorder every layer can reach touches only the layers that actually
16
- * prompt.
17
- *
18
- * The rule for a runner: whenever a prompt (not a flag the caller already
19
- * passed) decides a value, `recordResolved` the flag form of that decision. A
20
- * value that came in as a flag is already in the base argv, so recording it
21
- * again would double it — only the prompt branch records.
22
- */
23
- /**
24
- * Start recording for one invocation.
25
- *
26
- * `base` is what the dispatcher received: the wizard's built argv, or the argv
27
- * the user typed. `fromMenu` marks the wizard path, where every step was a
28
- * prompt, so the rerun line is worth printing even if no runner records a
29
- * thing. A typed command starts non-interactive and only earns the line if a
30
- * runner resolves a missing flag from a prompt.
31
- */
32
- export declare function beginInvocation(base: readonly string[], fromMenu: boolean): void;
33
- /**
34
- * Record the deploy tier the wizard entered up front, so the rerun line carries
35
- * it. development is the ambient default, so a prefix for it would be noise and
36
- * is dropped.
37
- */
38
- export declare function recordEnteredTier(tier: string): void;
39
- /**
40
- * Append the flag form of a value a prompt just resolved, e.g.
41
- * `recordResolved("--tier", "development")`.
42
- */
43
- export declare function recordResolved(...fragment: string[]): void;
44
- /**
45
- * The command to print, or `null` when there is nothing worth printing —
46
- * either no invocation ran, or the user typed a complete command and answered
47
- * no prompts, so echoing it back would be noise.
48
- */
49
- export declare function reproducibleCommand(): string | null;
@@ -1,78 +0,0 @@
1
- /**
2
- * Records the fully-resolved argv of the command being run, so the CLI can
3
- * close by printing a copy-pasteable line — the same command with every prompt
4
- * already answered — for anyone who reached it through the wizard or let a
5
- * missing flag fall to a prompt.
6
- *
7
- * ## Why a module-level recorder rather than a return value
8
- *
9
- * A command's inputs arrive from two places that never meet: the wizard walks
10
- * `commands.ts` and gathers the *declared* options into the argv it dispatches
11
- * (see `menu.ts`), while a runner resolves anything it prompts for *itself* —
12
- * `workflows run` picking a tier, `env init` picking projects — deep inside its
13
- * own call stack, where the dispatched argv is long out of reach. Threading a
14
- * return value back up through every runner would touch each one's signature;
15
- * a recorder every layer can reach touches only the layers that actually
16
- * prompt.
17
- *
18
- * The rule for a runner: whenever a prompt (not a flag the caller already
19
- * passed) decides a value, `recordResolved` the flag form of that decision. A
20
- * value that came in as a flag is already in the base argv, so recording it
21
- * again would double it — only the prompt branch records.
22
- */
23
- /** The base argv plus whatever prompts resolved; `null` until an invocation begins. */
24
- let argv = null;
25
- /** Did the wizard, or an in-command prompt, actually decide anything here? */
26
- let interactive = false;
27
- /**
28
- * The deploy tier `src/launch.ts` resolved and entered for this session, or
29
- * `null` for the development default. Reproduced as a leading `--tier <tier>`
30
- * flag, the same global flag `launch.ts` strips off ANY invocation before
31
- * `cli.ts` ever runs — see its header — so this reproduces the tier for
32
- * EVERY command, `db` and `env` included, exactly as typing `--tier <tier>`
33
- * up front would.
34
- */
35
- let enteredTier = null;
36
- /**
37
- * Start recording for one invocation.
38
- *
39
- * `base` is what the dispatcher received: the wizard's built argv, or the argv
40
- * the user typed. `fromMenu` marks the wizard path, where every step was a
41
- * prompt, so the rerun line is worth printing even if no runner records a
42
- * thing. A typed command starts non-interactive and only earns the line if a
43
- * runner resolves a missing flag from a prompt.
44
- */
45
- export function beginInvocation(base, fromMenu) {
46
- argv = [...base];
47
- interactive = fromMenu;
48
- enteredTier = null;
49
- }
50
- /**
51
- * Record the deploy tier the wizard entered up front, so the rerun line carries
52
- * it. development is the ambient default, so a prefix for it would be noise and
53
- * is dropped.
54
- */
55
- export function recordEnteredTier(tier) {
56
- enteredTier = tier === "development" ? null : tier;
57
- }
58
- /**
59
- * Append the flag form of a value a prompt just resolved, e.g.
60
- * `recordResolved("--tier", "development")`.
61
- */
62
- export function recordResolved(...fragment) {
63
- if (argv === null || fragment.length === 0)
64
- return;
65
- argv.push(...fragment);
66
- interactive = true;
67
- }
68
- /**
69
- * The command to print, or `null` when there is nothing worth printing —
70
- * either no invocation ran, or the user typed a complete command and answered
71
- * no prompts, so echoing it back would be noise.
72
- */
73
- export function reproducibleCommand() {
74
- if (argv === null || !interactive || argv.length === 0)
75
- return null;
76
- const tierFlag = enteredTier ? ["--tier", enteredTier] : [];
77
- return `pnpm devtools ${[...tierFlag, ...argv].join(" ")}`;
78
- }
@@ -1 +0,0 @@
1
- export declare function launchCi(argv: readonly string[]): Promise<void>;
package/dist/launch-ci.js DELETED
@@ -1,90 +0,0 @@
1
- /**
2
- * `devtools-ci`'s entry point, in the same shape as `src/launch.ts` (read
3
- * that file's header first) — resolve the session's deploy tier and enter its
4
- * environment BEFORE `ci.ts` is imported — but with one deliberate
5
- * difference: this NEVER prompts.
6
- *
7
- * CI is never interactive — `process.stdin.isTTY` is `undefined` in every job
8
- * this runs in — so `resolveSessionTier` would already refuse to prompt on
9
- * its own `isTTY` check. No `prompt` function is injected anyway, making that
10
- * doubly true rather than relying on the ambient TTY guess: a CI job that
11
- * somehow got attached to a terminal must still refuse ambiguity outright
12
- * instead of hanging on a question nobody in a workflow can answer.
13
- *
14
- * ## Which `devtools-ci` invocations reach this file at all
15
- *
16
- * Only `run ci:env` does. The bare `run ci` package script — used for
17
- * `deploy write-env`, which CREATES the env file this module would otherwise
18
- * insist on reading, and for the handful of steps that hold one narrow
19
- * credential and compose no env file at all — still runs `ci.ts` directly
20
- * through `tsx`, deliberately bypassing tier resolution entirely. See
21
- * `.github/workflows/deploy.yaml`'s own header for the two entry points and
22
- * why each step picked the one it did.
23
- *
24
- * A `deploy <app> --tier <t>` invocation's `--tier` is a command flag `ci.ts`
25
- * parses for itself (see its `runDeployCommand`), not this module's global
26
- * `--tier` — but they resolve to the same tier here: `stripTierFlag` pulls it
27
- * off before `ci.ts` sees argv, `resolveSessionTier` resolves the identical
28
- * value as `explicit`, and `ci.ts`'s own parse then falls back to
29
- * `process.env.DEPLOY_ENV`, which `enterEnvironment` just set to it.
30
- */
31
- import { findRepoRoot } from "./repo/root.js";
32
- import { loadEnvLoad, loadEnvSession } from "./repo/peers.js";
33
- import { stripTierFlag } from "./launch.js";
34
- import { captureDevtoolsError, initDevtoolsTelemetry } from "./telemetry.js";
35
- import { ignoreClosedPipes } from "./pipes.js";
36
- export async function launchCi(argv) {
37
- const { explicit, rest } = stripTierFlag(argv);
38
- // See `launch.ts`'s matching call: early, so tier resolution and env entry
39
- // are covered too. Same tag `ci.ts`'s `main()` would compute.
40
- ignoreClosedPipes();
41
- initDevtoolsTelemetry(rest.slice(0, 2).join(" ") || "help");
42
- const envLoad = await loadEnvLoad();
43
- const envSession = await loadEnvSession();
44
- const resolution = await envSession.resolveSessionTier({
45
- explicit,
46
- deployEnv: process.env.DEPLOY_ENV,
47
- available: await envSession.availableTiers(findRepoRoot()),
48
- isTTY: false,
49
- // No `prompt` — see this file's header. Ambiguity is always a refusal.
50
- });
51
- if (!resolution.ok) {
52
- process.stderr.write(`devtools-ci: ${resolution.reason}\n`);
53
- process.exit(1);
54
- }
55
- const tier = resolution.tier;
56
- try {
57
- const entered = await envSession.enterEnvironment(tier, {
58
- override: false,
59
- });
60
- for (const warning of entered.warnings) {
61
- process.stderr.write(`devtools-ci: ${warning}\n`);
62
- }
63
- process.stderr.write(`devtools-ci: loaded ${entered.files.length > 0 ? entered.files.join(", ") : "no env files"} (${tier})\n`);
64
- }
65
- catch (err) {
66
- if (!(err instanceof envLoad.MissingEnvFileError))
67
- throw err;
68
- // A CI job that reaches `run ci:env` at all has already run `deploy
69
- // write-env` (see this file's header), so a missing file here — for
70
- // ANY tier, `development` included — is never a first-run story the way
71
- // it is for a contributor's own machine. Always fatal.
72
- process.stderr.write(`devtools-ci: ${err.message}\n`);
73
- process.exit(1);
74
- }
75
- const { main } = await import("./ci.js");
76
- try {
77
- await main(rest);
78
- }
79
- catch (err) {
80
- process.stderr.write(`devtools-ci: ${err instanceof Error ? err.message : String(err)}\n`);
81
- // Report BEFORE exiting — see `captureDevtoolsError`'s header.
82
- await captureDevtoolsError(err);
83
- process.exit(1);
84
- }
85
- }
86
- // See `launch.ts`'s matching guard for why this checks `process.argv[1]`
87
- // rather than self-invoking unconditionally.
88
- if (import.meta.url === `file://${process.argv[1]}`) {
89
- await launchCi(process.argv.slice(2));
90
- }
package/dist/launch.d.ts DELETED
@@ -1,18 +0,0 @@
1
- /**
2
- * Pulls a global `--tier <t>` out of `argv`, wherever it sits, leaving every
3
- * other argument untouched and in its original order. Exported for its own
4
- * unit tests; `launch()` below is the only real caller.
5
- */
6
- export declare function stripTierFlag(argv: readonly string[]): {
7
- explicit: string | undefined;
8
- rest: string[];
9
- };
10
- /**
11
- * Resolves the session's deploy tier, enters it (or defers entry to the
12
- * menu — see this file's header), and hands off to `cli.ts`.
13
- *
14
- * Exits the process directly on a refusal from `resolveSessionTier` — there
15
- * is no command dispatched yet for a caller to fall back to, so there is
16
- * nothing this function could return that would mean anything.
17
- */
18
- export declare function launch(argv: readonly string[]): Promise<void>;
package/dist/menu.d.ts DELETED
@@ -1,43 +0,0 @@
1
- import { type Environment } from "./environment.js";
2
- /**
3
- * The command path when argv names a group with subcommands but no subcommand
4
- * token — what `devtools db` and `devtools db seed` are. Returns null for a
5
- * leaf command, an unknown token, or a bare invocation (which the no-argument
6
- * wizard already covers). The caller resumes the wizard at this node when
7
- * stdin is a TTY; a non-TTY caller keeps the dispatcher's "which of …?" exit.
8
- */
9
- export declare function bareGroupStartPath(argv: readonly string[]): string[] | null;
10
- /**
11
- * Runs the wizard, returning the `outro()` line its command earned.
12
- *
13
- * `dispatch` is the CLI's own argv handler, injected rather than imported so
14
- * that `cli.ts` keeps a single definition of what each command does and the
15
- * tests can watch what a walk produces without running it. Its return value
16
- * passes straight through, the closing line or `null` for a failure already
17
- * explained, so a command reached from the menu signs off exactly as it does
18
- * from the command line.
19
- *
20
- * `options.startPath`, from `bareGroupStartPath`, skips straight to that
21
- * node's subcommand screen — see `walk`'s `startPath` branch.
22
- *
23
- * The deploy tier is NOT asked here any more. `src/launch.ts` resolves it
24
- * before `cli.ts` — and therefore this module — is even imported, and
25
- * exports `DEPLOY_ENV`/`DEV_DB` right away, so by the time the wizard opens
26
- * `process.env` already names the session exactly as if `--tier` had been
27
- * typed. Recording it for the "run it directly next time" line only needs to
28
- * read `process.env.DEPLOY_ENV` back.
29
- *
30
- * Entering that tier — loading its `.env.<tier>` file onto `process.env` —
31
- * is what's deferred: `launch.ts` registers a hook (`env-entry.ts`'s
32
- * `setMenuEnvHook`) instead of entering up front, so whatever changed while
33
- * the reader was still walking the menu (the local stack coming up in
34
- * another terminal, `.env.generated` being rewritten) is picked up rather
35
- * than missed. `takeMenuEnvHook()` below runs it right before the chosen
36
- * command dispatches — the ONE place in a menu walk an env value is ever
37
- * actually read. `undefined` (no hook registered — a typed command entered
38
- * already, or a test drives `runMenu` directly) just dispatches straight
39
- * through, unchanged from before this existed.
40
- */
41
- export declare function runMenu(dispatch: (argv: string[]) => Promise<string | null>, env?: Environment, options?: {
42
- startPath?: string[];
43
- }): Promise<string | null>;