@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,65 +0,0 @@
1
- /**
2
- * The environment `db introspect` hands to the `drizzle-kit` child process
3
- * it spawns.
4
- *
5
- * ## How this relates to `db/connection.ts`
6
- *
7
- * `db/connection.ts` resolves the session's one database CONNECTION (its
8
- * `DB_URL`, with sanity guards) for commands that open one themselves. This
9
- * is the other need: a whole ENVIRONMENT to hand a child process. Both read
10
- * the same source — whatever THIS PROCESS already entered — `launch.ts`
11
- * runs before
12
- * `cli.ts`'s command dispatch even imports, and enters a tier (development,
13
- * by default) into `process.env` via `@devdogsuga/env/session`'s
14
- * `enterEnvironment`, applying `selectEnvFiles`'s overlay-plus-liveness-probe
15
- * logic (`.env.generated`, the running local stack's connection block,
16
- * ahead of `.env` — see `load.ts`'s probe table) along the way.
17
- *
18
- * These two commands used to bypass all of that: each parsed `.env` directly
19
- * with raw `dotenv`, and merged it OVER `process.env`
20
- * (`{...process.env, ...tierEnv}`). Two bugs followed from that shortcut:
21
- *
22
- * a. `.env.generated` — where the running local stack's `DB_URL` actually
23
- * lives — was never read, so with the stack up these commands reported
24
- * "DB_URL is not set in .env. Run `supabase start` first" (wrong
25
- * command AND wrong file) or silently connected to a stale/hosted URL,
26
- * while every other command in this CLI, going through `selectEnvFiles`,
27
- * worked fine.
28
- * b. The precedence was inverted: a raw `.env` parse merged OVER
29
- * `process.env` clobbers whatever tier this process actually entered —
30
- * backwards from the documented expectation (now `db/connection.ts`'s)
31
- * that a command reads the tier the process is already running
32
- * under rather than reimposing development on top of it.
33
- *
34
- * `resolveLocalToolingEnv` fixes both by returning `process.env` itself
35
- * (fresh values, `.env.generated` included, whatever tier was entered)
36
- * instead of re-deriving anything. The only case it still loads a tier
37
- * itself is a caller that reaches these commands WITHOUT going through
38
- * `launch.ts` first — `process.env.DEPLOY_ENV` unset is the tell, since
39
- * `enterEnvironment` always sets it, even for `development` — and even then
40
- * it falls back to `loadEnvironment("development")`, never a raw dotenv
41
- * parse, so the overlay-plus-probe logic still applies.
42
- */
43
- import type { LoadedEnvironment } from "@devdogsuga/env/load";
44
- export interface ResolveLocalToolingEnvOptions {
45
- /** Injectable for tests; defaults to `process.env`. */
46
- processEnv?: NodeJS.ProcessEnv;
47
- /** Injectable for tests; defaults to the real `loadEnvironment`. */
48
- loadEnvironment?: (deployEnv?: string, options?: {
49
- override?: boolean;
50
- }) => Promise<LoadedEnvironment>;
51
- }
52
- /**
53
- * Returns the environment a local-tooling child process (`drizzle-kit`,
54
- * spawned by `db introspect`) should inherit.
55
- *
56
- * Normal path (the process went through `launch.ts`, as `pnpm devtools`
57
- * always does): returns `process.env` unchanged — it already carries
58
- * whatever tier was entered, `.env.generated` overlay included.
59
- *
60
- * Fallback path (no tier was ever entered — a direct import, e.g. from a
61
- * test, or a future caller that skips `launch.ts`): loads development
62
- * through the shared `loadEnvironment`, which applies the same overlay and
63
- * liveness probe `selectEnvFiles` always has, then returns that snapshot.
64
- */
65
- export declare function resolveLocalToolingEnv(opts?: ResolveLocalToolingEnvOptions): Promise<NodeJS.ProcessEnv>;
@@ -1,23 +0,0 @@
1
- import { loadEnvLoad } from "../repo/peers.js";
2
- /**
3
- * Returns the environment a local-tooling child process (`drizzle-kit`,
4
- * spawned by `db introspect`) should inherit.
5
- *
6
- * Normal path (the process went through `launch.ts`, as `pnpm devtools`
7
- * always does): returns `process.env` unchanged — it already carries
8
- * whatever tier was entered, `.env.generated` overlay included.
9
- *
10
- * Fallback path (no tier was ever entered — a direct import, e.g. from a
11
- * test, or a future caller that skips `launch.ts`): loads development
12
- * through the shared `loadEnvironment`, which applies the same overlay and
13
- * liveness probe `selectEnvFiles` always has, then returns that snapshot.
14
- */
15
- export async function resolveLocalToolingEnv(opts = {}) {
16
- const processEnv = opts.processEnv ?? process.env;
17
- if (processEnv.DEPLOY_ENV !== undefined && processEnv.DEPLOY_ENV !== "") {
18
- return processEnv;
19
- }
20
- const load = opts.loadEnvironment ?? (await loadEnvLoad()).loadEnvironment;
21
- const loaded = await load("development");
22
- return loaded.env;
23
- }
@@ -1,8 +0,0 @@
1
- /** App slug -> Postgres schema name. Schedule Builder and Study Group
2
- * Finder use underscores; their slugs use hyphens. */
3
- export declare const APP_SCHEMAS: Record<string, string>;
4
- /** Builds the `supabase migration new` name argument — `<schema>_<desc>` —
5
- * given an app slug and a free-text description. Pure, so the naming rule
6
- * is testable without spawning the CLI. */
7
- export declare function migrationName(appSlug: string, description: string): string | null;
8
- export declare function runNewMigration(appArg: string | undefined, descriptionArg: string | undefined): Promise<number>;
@@ -1,69 +0,0 @@
1
- /**
2
- * `db migration new --app <slug> <description>`
3
- *
4
- * One flat `supabase/migrations/` directory, shared by every app, so the
5
- * filename is the only thing that says whose schema a migration belongs to.
6
- * Contract: `<timestamp>_<schema>_<description>.sql`, where `schema` is
7
- * `platform`, `schedule_builder`, or `study_group_finder` — never the
8
- * app slug verbatim (schedule-builder's schema is `schedule_builder`, with
9
- * an underscore, because it is a Postgres identifier).
10
- *
11
- * The supabase CLI already produces `<timestamp>_<name>.sql` from `migration
12
- * new <name>` — its own clock, not ours, which is the part CI's
13
- * newer-than-main check actually cares about — so this only has to build
14
- * `name` as `<schema>_<description>` and hand it off unchanged.
15
- */
16
- import { select, text } from "@clack/prompts";
17
- import { unwrap } from "../ui.js";
18
- import { supabase } from "./run.js";
19
- /** App slug -> Postgres schema name. Schedule Builder and Study Group
20
- * Finder use underscores; their slugs use hyphens. */
21
- export const APP_SCHEMAS = {
22
- platform: "platform",
23
- "schedule-builder": "schedule_builder",
24
- "study-group-finder": "study_group_finder",
25
- };
26
- /** Builds the `supabase migration new` name argument — `<schema>_<desc>` —
27
- * given an app slug and a free-text description. Pure, so the naming rule
28
- * is testable without spawning the CLI. */
29
- export function migrationName(appSlug, description) {
30
- const schema = APP_SCHEMAS[appSlug];
31
- if (!schema)
32
- return null;
33
- const slug = description
34
- .trim()
35
- .toLowerCase()
36
- .replace(/[^a-z0-9]+/g, "_")
37
- .replace(/^_+|_+$/g, "");
38
- if (!slug)
39
- return null;
40
- return `${schema}_${slug}`;
41
- }
42
- async function pickApp() {
43
- return unwrap(await select({
44
- message: "Whose schema is this migration for?",
45
- options: Object.keys(APP_SCHEMAS).map((value) => ({
46
- value,
47
- label: value,
48
- })),
49
- }));
50
- }
51
- export async function runNewMigration(appArg, descriptionArg) {
52
- const app = appArg ?? (await pickApp());
53
- if (!APP_SCHEMAS[app]) {
54
- process.stderr.write(`devtools db migration new: unknown app "${app}". Expected one of: ${Object.keys(APP_SCHEMAS).join(", ")}.\n`);
55
- return 1;
56
- }
57
- const description = descriptionArg ??
58
- unwrap(await text({
59
- message: "Short description (used as the migration's filename)",
60
- placeholder: "add_widgets_table",
61
- validate: (v) => (v?.trim() ? undefined : "Required"),
62
- }));
63
- const name = migrationName(app, description);
64
- if (!name) {
65
- process.stderr.write("devtools db migration new: the description left nothing usable in the filename.\n");
66
- return 1;
67
- }
68
- return supabase("migration", "new", name);
69
- }
@@ -1,23 +0,0 @@
1
- /**
2
- * Validates a hosted `DB_URL` against the one shape it must have: the
3
- * Session pooler string, not the direct connection and not the Transaction
4
- * pooler.
5
- *
6
- * Pure and synchronous on purpose — `setup.ts`'s hosted wizard calls this
7
- * before writing anything to `.env`, and `doctor.ts`'s environment checker
8
- * calls the same function against whatever is already there, so the two
9
- * never drift into disagreeing about what a good `DB_URL` looks like.
10
- *
11
- * See the writing guide's collapsed note on poolers (docs/_shared or
12
- * toolkit/guides) for the wording this explains to a contributor; this
13
- * module only classifies, it does not print.
14
- */
15
- export type DbUrlProblem = "invalid" | "direct-connection" | "transaction-pooler";
16
- export interface DbUrlValidation {
17
- ok: boolean;
18
- problem?: DbUrlProblem;
19
- /** The FAQ anchor id for this problem, for a caller that wants to link. */
20
- faqId?: "db-url-direct-connection" | "db-url-transaction-pooler";
21
- message?: string;
22
- }
23
- export declare function validateSessionPoolerUrl(dbUrl: string): DbUrlValidation;
package/dist/db/pooler.js DELETED
@@ -1,55 +0,0 @@
1
- /**
2
- * Validates a hosted `DB_URL` against the one shape it must have: the
3
- * Session pooler string, not the direct connection and not the Transaction
4
- * pooler.
5
- *
6
- * Pure and synchronous on purpose — `setup.ts`'s hosted wizard calls this
7
- * before writing anything to `.env`, and `doctor.ts`'s environment checker
8
- * calls the same function against whatever is already there, so the two
9
- * never drift into disagreeing about what a good `DB_URL` looks like.
10
- *
11
- * See the writing guide's collapsed note on poolers (docs/_shared or
12
- * toolkit/guides) for the wording this explains to a contributor; this
13
- * module only classifies, it does not print.
14
- */
15
- /** `db.<ref>.supabase.co` — the direct connection host, IPv6-only on the
16
- * free tier. */
17
- const DIRECT_CONNECTION_HOST = /^db\.[a-z0-9]+\.supabase\.co$/i;
18
- /** The Transaction pooler's port. Session pooler is 5432, same as plain
19
- * Postgres. */
20
- const TRANSACTION_POOLER_PORT = "6543";
21
- export function validateSessionPoolerUrl(dbUrl) {
22
- let url;
23
- try {
24
- url = new URL(dbUrl);
25
- }
26
- catch {
27
- return {
28
- ok: false,
29
- problem: "invalid",
30
- message: "That does not look like a connection string (expected postgresql://...).",
31
- };
32
- }
33
- if (DIRECT_CONNECTION_HOST.test(url.hostname)) {
34
- return {
35
- ok: false,
36
- problem: "direct-connection",
37
- faqId: "db-url-direct-connection",
38
- message: `${url.hostname} is the direct connection host. It only answers on ` +
39
- "IPv6, and most campus/home networks are IPv4. Copy the Session " +
40
- "pooler string instead — Database settings → Connection string → " +
41
- "Session pooler.",
42
- };
43
- }
44
- if (url.port === TRANSACTION_POOLER_PORT) {
45
- return {
46
- ok: false,
47
- problem: "transaction-pooler",
48
- faqId: "db-url-transaction-pooler",
49
- message: "Port 6543 is the Transaction pooler, meant for serverless — it " +
50
- "breaks prepared statements (drizzle-kit hangs). Use the Session " +
51
- "pooler on port 5432 instead.",
52
- };
53
- }
54
- return { ok: true };
55
- }
package/dist/db/run.d.ts DELETED
@@ -1,68 +0,0 @@
1
- export declare function typesFile(): string;
2
- /** Spawn a pnpm command with inherited stdio; resolves to the exit code. Pass
3
- * `env` to run the child against a loaded tier rather than process.env. */
4
- export declare function run(args: string[], env?: NodeJS.ProcessEnv): Promise<number>;
5
- export interface RunWithStderrResult {
6
- code: number;
7
- stderr: string;
8
- }
9
- /** Spawn a pnpm command while echoing and retaining stderr for diagnostics.
10
- * Pass `env` to run the child against a loaded tier rather than process.env. */
11
- export declare function runWithStderr(args: string[], env?: NodeJS.ProcessEnv): Promise<RunWithStderrResult>;
12
- /** Spawn a pnpm command, capture stdout, throw on non-zero exit. */
13
- export declare function capture(args: string[]): Promise<string>;
14
- /** `pnpm exec supabase …` with inherited stdio. */
15
- export declare const supabase: (...args: string[]) => Promise<number>;
16
- /** `pnpm exec supabase …` with captured stdout. */
17
- export declare const supabaseCapture: (...args: string[]) => Promise<string>;
18
- /**
19
- * Generate and write Database types from the session's database.
20
- *
21
- * Delegates to `@devdogsuga/db/typegen`'s `generateDatabaseTypes`, which runs
22
- * `pnpm exec supabase gen types --db-url <dbUrl>` (always `--db-url` — the
23
- * session's own connection string, never the supabase CLI's
24
- * `--local`/`--linked` modes, whose defaults can disagree with what this
25
- * process entered; see `db/connection.ts`'s header) and formats the result
26
- * with `pnpm exec prettier --write`, both run against `findRepoRoot()` so the
27
- * workspace-pinned CLI versions are what actually run.
28
- */
29
- export declare function generateTypes(dbUrl: string): Promise<number>;
30
- /**
31
- * `supabase db push` over `dbUrl`, inherited stdio, resolving to the exit code.
32
- *
33
- * The one spelling of the migration push, shared by the contributor `db
34
- * migrate` path (`stack.ts`'s `pushMigrations`) and CI's `deploy migrate`.
35
- * `--yes` is the unattended apply CI wants; the contributor path omits it so a
36
- * human still confirms. Neither variant regenerates types — that is
37
- * `pushMigrations`' own second step, layered on top only where a checkout is
38
- * meant to be rewritten. A CI apply must NOT write back into the repo, which is
39
- * exactly why the bare push is factored out here rather than reused whole.
40
- */
41
- export declare function dbPush(dbUrl: string, opts?: {
42
- yes?: boolean;
43
- }): Promise<number>;
44
- /**
45
- * `supabase db push --dry-run` over `dbUrl`, returning the plan text (stdout
46
- * and stderr combined, as the workflow's old `2>&1` did).
47
- *
48
- * Throws on a non-zero exit — which for a dry run means the CONNECTION failed,
49
- * not that the plan came back empty. That throw is the invariant `deploy plan`
50
- * leans on, and the thing the old shell needed `set -o pipefail` to preserve: a
51
- * dead connection must fail the step rather than read as "no migrations to
52
- * apply". The child's own output is surfaced in the thrown message, because for
53
- * a dry run that output is precisely the reason the operator needs.
54
- */
55
- export declare function dbPushDryRun(dbUrl: string): Promise<string>;
56
- /**
57
- * `seed buckets` takes no `--db-url` (verified against the supabase 2.115.0
58
- * CLI) — it drives the Storage API, not Postgres — so it is the one data
59
- * command still keyed on local-vs-hosted rather than on the session's URL.
60
- */
61
- export type BucketsConnection = {
62
- kind: "local";
63
- } | {
64
- kind: "remote";
65
- projectRef: string | undefined;
66
- };
67
- /** Seed storage buckets on the local stack or a resolved tier's project. */
68
- export declare function seedBuckets(conn: BucketsConnection): Promise<number>;
package/dist/db/run.js DELETED
@@ -1,156 +0,0 @@
1
- /**
2
- * Shared helpers for running supabase CLI and pnpm commands from the repo root.
3
- *
4
- * The supabase CLI is a workspace devDependency (not a global install), so
5
- * every invocation goes through `pnpm exec supabase`. The cwd is always
6
- * findRepoRoot(), where `supabase/config.toml` lives.
7
- */
8
- import { execFile, spawn as nodeSpawn } from "node:child_process";
9
- import { join } from "node:path";
10
- import { promisify } from "node:util";
11
- import { findRepoRoot } from "../repo/root.js";
12
- import { loadDbTypegen } from "../repo/peers.js";
13
- const runFile = promisify(execFile);
14
- export function typesFile() {
15
- return join(findRepoRoot(), "packages", "supabase", "src", "database.types.ts");
16
- }
17
- /** Spawn a pnpm command with inherited stdio; resolves to the exit code. Pass
18
- * `env` to run the child against a loaded tier rather than process.env. */
19
- export function run(args, env) {
20
- return new Promise((resolve) => {
21
- const child = nodeSpawn("pnpm", args, {
22
- stdio: "inherit",
23
- cwd: findRepoRoot(),
24
- ...(env ? { env } : {}),
25
- });
26
- child.on("error", (error) => {
27
- process.stderr.write(`${error.message}\n`);
28
- resolve(1);
29
- });
30
- child.on("exit", (code) => resolve(code ?? 1));
31
- });
32
- }
33
- /** Spawn a pnpm command while echoing and retaining stderr for diagnostics.
34
- * Pass `env` to run the child against a loaded tier rather than process.env. */
35
- export function runWithStderr(args, env) {
36
- return new Promise((resolve) => {
37
- const child = nodeSpawn("pnpm", args, {
38
- stdio: ["inherit", "inherit", "pipe"],
39
- cwd: findRepoRoot(),
40
- ...(env ? { env } : {}),
41
- });
42
- let stderr = "";
43
- child.stderr.setEncoding("utf8");
44
- child.stderr.on("data", (chunk) => {
45
- stderr += chunk;
46
- process.stderr.write(chunk);
47
- });
48
- child.on("error", (error) => {
49
- const message = `${error.message}\n`;
50
- stderr += message;
51
- process.stderr.write(message);
52
- resolve({ code: 1, stderr });
53
- });
54
- child.on("exit", (code) => resolve({ code: code ?? 1, stderr }));
55
- });
56
- }
57
- /** Spawn a pnpm command, capture stdout, throw on non-zero exit. */
58
- export async function capture(args) {
59
- const { stdout } = await runFile("pnpm", args, {
60
- cwd: findRepoRoot(),
61
- encoding: "utf8",
62
- });
63
- return stdout;
64
- }
65
- /** `pnpm exec supabase …` with inherited stdio. */
66
- export const supabase = (...args) => run(["exec", "supabase", ...args]);
67
- /** `pnpm exec supabase …` with captured stdout. */
68
- export const supabaseCapture = (...args) => capture(["exec", "supabase", ...args]);
69
- /**
70
- * Generate and write Database types from the session's database.
71
- *
72
- * Delegates to `@devdogsuga/db/typegen`'s `generateDatabaseTypes`, which runs
73
- * `pnpm exec supabase gen types --db-url <dbUrl>` (always `--db-url` — the
74
- * session's own connection string, never the supabase CLI's
75
- * `--local`/`--linked` modes, whose defaults can disagree with what this
76
- * process entered; see `db/connection.ts`'s header) and formats the result
77
- * with `pnpm exec prettier --write`, both run against `findRepoRoot()` so the
78
- * workspace-pinned CLI versions are what actually run.
79
- */
80
- export async function generateTypes(dbUrl) {
81
- try {
82
- const { generateDatabaseTypes } = await loadDbTypegen();
83
- await generateDatabaseTypes({
84
- dbUrl,
85
- outFile: typesFile(),
86
- cwd: findRepoRoot(),
87
- });
88
- }
89
- catch {
90
- return 1;
91
- }
92
- return 0;
93
- }
94
- /**
95
- * `supabase db push` over `dbUrl`, inherited stdio, resolving to the exit code.
96
- *
97
- * The one spelling of the migration push, shared by the contributor `db
98
- * migrate` path (`stack.ts`'s `pushMigrations`) and CI's `deploy migrate`.
99
- * `--yes` is the unattended apply CI wants; the contributor path omits it so a
100
- * human still confirms. Neither variant regenerates types — that is
101
- * `pushMigrations`' own second step, layered on top only where a checkout is
102
- * meant to be rewritten. A CI apply must NOT write back into the repo, which is
103
- * exactly why the bare push is factored out here rather than reused whole.
104
- */
105
- export function dbPush(dbUrl, opts = {}) {
106
- const args = ["db", "push", "--db-url", dbUrl];
107
- if (opts.yes)
108
- args.push("--yes");
109
- return supabase(...args);
110
- }
111
- /**
112
- * `supabase db push --dry-run` over `dbUrl`, returning the plan text (stdout
113
- * and stderr combined, as the workflow's old `2>&1` did).
114
- *
115
- * Throws on a non-zero exit — which for a dry run means the CONNECTION failed,
116
- * not that the plan came back empty. That throw is the invariant `deploy plan`
117
- * leans on, and the thing the old shell needed `set -o pipefail` to preserve: a
118
- * dead connection must fail the step rather than read as "no migrations to
119
- * apply". The child's own output is surfaced in the thrown message, because for
120
- * a dry run that output is precisely the reason the operator needs.
121
- */
122
- export async function dbPushDryRun(dbUrl) {
123
- try {
124
- const { stdout, stderr } = await runFile("pnpm", ["exec", "supabase", "db", "push", "--db-url", dbUrl, "--dry-run"], { cwd: findRepoRoot(), encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
125
- return `${stdout}${stderr}`;
126
- }
127
- catch (err) {
128
- const e = err;
129
- const detail = `${e.stdout ?? ""}${e.stderr ?? ""}`.trim();
130
- throw new Error(detail
131
- ? `supabase db push --dry-run failed:\n${detail}`
132
- : (e.message ?? "supabase db push --dry-run failed"));
133
- }
134
- }
135
- /** Seed storage buckets on the local stack or a resolved tier's project. */
136
- export async function seedBuckets(conn) {
137
- if (conn.kind === "local") {
138
- return supabase("seed", "buckets", "--local", "--yes");
139
- }
140
- // Surfaced here, before the supabase CLI ever runs, rather than left for it
141
- // to reject: an empty `--project-ref ""` is exactly the kind of ambiguous
142
- // failure this whole module exists to avoid.
143
- if (!conn.projectRef) {
144
- process.stderr.write("devtools db: seed buckets against a hosted project needs PROJECT_REF in the session's env file.\n");
145
- return 1;
146
- }
147
- // `seed buckets` (unlike `config push`) rejects a bare `--project-ref` as
148
- // ambiguous with `--local` and demands `--linked` alongside it. That does
149
- // NOT mean it needs an ambient `supabase link` state on disk — verified
150
- // empirically in an unlinked checkout, `--project-ref` names the target
151
- // directly and `--linked` is just the mode selector for "use that ref",
152
- // not "use whatever `supabase link` last remembered". So this stays
153
- // consistent with `db/connection.ts`'s rule of never depending on
154
- // `--linked`'s persisted state.
155
- return supabase("seed", "buckets", "--project-ref", conn.projectRef, "--linked");
156
- }
@@ -1,2 +0,0 @@
1
- import { type BucketsConnection } from "./run.js";
2
- export declare function runSeedBuckets(conn: BucketsConnection): Promise<number>;
@@ -1,4 +0,0 @@
1
- import { seedBuckets } from "./run.js";
2
- export async function runSeedBuckets(conn) {
3
- return seedBuckets(conn);
4
- }
@@ -1,8 +0,0 @@
1
- /** Injectable so a test can fake the connection without a real Postgres. */
2
- export interface SeedProductionDb {
3
- unsafe(query: string): Promise<unknown>;
4
- end(): Promise<void>;
5
- }
6
- export declare function runSeedProduction(dbUrl: string, deps?: {
7
- connect: (url: string) => SeedProductionDb;
8
- }): Promise<number>;
@@ -1,79 +0,0 @@
1
- /**
2
- * `db seed production` — apply `supabase/seed/production/*.sql` to a target.
3
- *
4
- * The DevDogsUGA repo splits its seeds into `supabase/seed/production/`
5
- * (the role catalogue and the officer board — content every tier needs)
6
- * and `supabase/seed/development/` (password-login personas and a worked
7
- * moderation report — local-dev-only, never meant to reach a hosted
8
- * target). `db reset` used to run both, but only ever against a LOCAL
9
- * stack, back when `detectLocalInstance()` was the only way this CLI found
10
- * a database at all. The session system changed that: `db reset` now runs
11
- * against any tier, including staging and production, so a reset there
12
- * explicitly passes `--no-seed` to the Supabase CLI and calls this function
13
- * itself afterward (see `stack.ts`'s `reset()`) — the config-derived
14
- * `[db.seed]` list is no longer trusted to keep development's seeds off a
15
- * hosted target on its own. `production/` is also what a staging or
16
- * production target needs applied WITHOUT a reset — an already-migrated
17
- * database that only needs this content refreshed — which is this command's
18
- * other, still-current use: run it directly, instead of hand-picking files
19
- * with `db query --file`.
20
- *
21
- * That is a deliberate departure from `runSeedRoles` (`seed-roles.ts`),
22
- * which pipes its one file through `supabase db query --file --db-url`.
23
- * `03_officers.sql` is many separate `insert into` statements in one file,
24
- * and the supabase CLI's `db query` runs its `--file` argument as a single
25
- * PREPARED statement — confirmed against the local stack, where it fails
26
- * every multi-statement seed file with "cannot insert multiple commands
27
- * into a prepared statement". `01_roles.sql` only ever worked through that
28
- * path because it happens to be one big `with … insert … select`
29
- * statement. So this connects directly with `postgres` (`prepare: false`,
30
- * the same setting `planner/db.ts` uses and for the same reason: the
31
- * simple query protocol, not the extended one, is what allows more than
32
- * one statement per round trip) and runs each file's raw text, rather than
33
- * shelling out per file.
34
- */
35
- import { readdirSync, readFileSync } from "node:fs";
36
- import { join } from "node:path";
37
- import postgres from "postgres";
38
- import { findRepoRoot } from "../repo/root.js";
39
- const SEED_DIR = "production";
40
- // Lazy, like seed-roles.ts's `seedFiles()` — computed inside
41
- // `runSeedProduction`, not at module load, so importing this file never
42
- // calls `findRepoRoot()` (or touches the filesystem) on its own.
43
- function seedFiles() {
44
- const dir = join(findRepoRoot(), "supabase", "seed", SEED_DIR);
45
- return readdirSync(dir)
46
- .filter((name) => name.endsWith(".sql"))
47
- .sort()
48
- .map((name) => join(dir, name));
49
- }
50
- /** Real connection: `prepare: false` so multi-statement files run over the
51
- * simple query protocol instead of gotrue's `db query --file` prepared-
52
- * statement path, which refuses them. `max: 1` — this is a short-lived,
53
- * sequential CLI invocation, never a pool. */
54
- function connect(dbUrl) {
55
- const sql = postgres(dbUrl, { max: 1, prepare: false, connect_timeout: 15 });
56
- return {
57
- unsafe: (query) => sql.unsafe(query),
58
- end: () => sql.end({ timeout: 5 }),
59
- };
60
- }
61
- export async function runSeedProduction(dbUrl, deps = { connect }) {
62
- const db = deps.connect(dbUrl);
63
- try {
64
- for (const file of seedFiles()) {
65
- try {
66
- await db.unsafe(readFileSync(file, "utf8"));
67
- }
68
- catch (err) {
69
- process.stderr.write(`devtools db seed production: ${file} failed: ` +
70
- `${err instanceof Error ? err.message : String(err)}\n`);
71
- return 1;
72
- }
73
- }
74
- return 0;
75
- }
76
- finally {
77
- await db.end();
78
- }
79
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Always `--db-url` — the session's own connection string, never the
3
- * supabase CLI's `--local`/`--linked` modes. `db query`, which this runs
4
- * through, supports it the same way `db reset`/`db push` do. See
5
- * `db/connection.ts`'s header.
6
- */
7
- export declare function runSeedRoles(dbUrl: string): Promise<number>;
@@ -1,33 +0,0 @@
1
- /**
2
- * `db seed roles` — reconcile platform's role catalogue against a target.
3
- *
4
- * Runs 01_roles.sql, the complete built-in and organizational role catalogue,
5
- * against the chosen target. It never assigns Root: bootstrapping that
6
- * break-glass role requires the explicit, service-key-backed grant-root command.
7
- */
8
- import { join } from "node:path";
9
- import { findRepoRoot } from "../repo/root.js";
10
- import { supabase } from "./run.js";
11
- // Lazy — computed inside `runSeedRoles`, not at module load, so importing
12
- // this file never calls `findRepoRoot()` on its own (it used to, as a
13
- // top-level `const`, which broke `--help`/`setup` outside a repo — see
14
- // `workers.ts`'s header for the general pattern this follows).
15
- function seedFiles() {
16
- return [
17
- join(findRepoRoot(), "supabase", "seed", "production", "01_roles.sql"),
18
- ];
19
- }
20
- /**
21
- * Always `--db-url` — the session's own connection string, never the
22
- * supabase CLI's `--local`/`--linked` modes. `db query`, which this runs
23
- * through, supports it the same way `db reset`/`db push` do. See
24
- * `db/connection.ts`'s header.
25
- */
26
- export async function runSeedRoles(dbUrl) {
27
- for (const file of seedFiles()) {
28
- const code = await supabase("db", "query", "--file", file, "--db-url", dbUrl);
29
- if (code !== 0)
30
- return code;
31
- }
32
- return 0;
33
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * BUG 2 fix: keeping this process's environment in sync with the local
3
- * stack's lifecycle.
4
- *
5
- * `launch.ts` enters a deploy tier into `process.env` exactly ONCE, before
6
- * `cli.ts` ever dispatches a command. `db start` (`startLocalStack`, in
7
- * `../stack.ts`) then writes a NEW `.env.generated` — the running stack's
8
- * fresh connection block — and `db stop` (`stopLocalStack`) deletes it. Left
9
- * alone, `process.env` keeps whatever it held at launch for the rest of a
10
- * wizard session: `db start` followed by `db introspect` in the SAME
11
- * session would still hand `drizzle-kit` the stale (or absent)
12
- * `.env.generated` values `resolveLocalToolingEnv` reads straight off
13
- * `process.env` (see `local-env.ts`) — the exact staleness BUG 1 fixed
14
- * `db introspect` from reading off disk, reappearing one layer up.
15
- *
16
- * `refreshSessionEnv` closes that gap by re-running the SAME
17
- * `enterEnvironment("development", …)` `launch.ts` used at startup —
18
- * overlay-plus-liveness-probe included — after a stack command that could
19
- * have changed `.env.generated` succeeds.
20
- *
21
- * ⚠️ Guarded to development only. `DEPLOY_ENV` naming a deployed tier means
22
- * this session targets staging or production (see `../db/connection.ts`);
23
- * blindly re-entering development here would silently overwrite that tier's
24
- * connection with local values mid-session, for a stack command
25
- * (`start`/`stop`/`restart`) that only ever touches the LOCAL Docker stack
26
- * in the first place.
27
- */
28
- import type { EnteredEnvironment } from "@devdogsuga/env/session";
29
- export interface RefreshSessionEnvOptions {
30
- /** Injectable for tests; defaults to `process.env.DEPLOY_ENV`. */
31
- deployEnv?: string;
32
- /** Injectable for tests; defaults to the real `enterEnvironment`. */
33
- enterEnvironment?: (tier: "development", opts: {
34
- override: boolean;
35
- }) => Promise<EnteredEnvironment>;
36
- }
37
- /**
38
- * Re-enters development — refreshing `process.env` from `.env.generated`'s
39
- * latest state — when (and only when) this process is already running under
40
- * development. Returns the one-line note callers report on success, or an
41
- * empty array when the guard held and nothing needed refreshing.
42
- */
43
- export declare function refreshSessionEnv(opts?: RefreshSessionEnvOptions): Promise<string[]>;