@cedarjs/pg 0.2.0-alpha.0 → 0.2.0-beta.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 (92) hide show
  1. package/README.md +250 -229
  2. package/dist/cli.cjs +89 -39
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.mjs +73 -23
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/dev-env.cjs +1 -1
  7. package/dist/dev-env.mjs +1 -1
  8. package/dist/index.cjs +9 -8
  9. package/dist/index.d.cts +31 -3
  10. package/dist/index.d.mts +31 -3
  11. package/dist/index.mjs +7 -7
  12. package/dist/jest-teardown.cjs +1 -1
  13. package/dist/jest-teardown.mjs +1 -1
  14. package/dist/jest-template.cjs +4 -1
  15. package/dist/jest-template.cjs.map +1 -1
  16. package/dist/jest-template.d.cts +4 -1
  17. package/dist/jest-template.d.mts +4 -1
  18. package/dist/jest-template.mjs +4 -1
  19. package/dist/jest-template.mjs.map +1 -1
  20. package/dist/jest.cjs +1 -1
  21. package/dist/jest.mjs +1 -1
  22. package/dist/{lease-BSBBpaR4.mjs → lease-DS1SX8U_.mjs} +23 -3
  23. package/dist/lease-DS1SX8U_.mjs.map +1 -0
  24. package/dist/{lease-Bq9wKwQa.cjs → lease-WlmOnNDi.cjs} +41 -3
  25. package/dist/lease-WlmOnNDi.cjs.map +1 -0
  26. package/dist/{lifecycle-DEJ4GgWV.cjs → lifecycle-BbrvFQvg.cjs} +175 -78
  27. package/dist/lifecycle-BbrvFQvg.cjs.map +1 -0
  28. package/dist/{lifecycle-BOo6xBjD.mjs → lifecycle-BvIx0xqq.mjs} +175 -78
  29. package/dist/lifecycle-BvIx0xqq.mjs.map +1 -0
  30. package/dist/{load-dev-env-7UjMHhw7.mjs → load-dev-env-BULkXyen.mjs} +2 -2
  31. package/dist/{load-dev-env-7UjMHhw7.mjs.map → load-dev-env-BULkXyen.mjs.map} +1 -1
  32. package/dist/{load-dev-env-cII6N4ZP.cjs → load-dev-env-Bl6Ddv1U.cjs} +2 -2
  33. package/dist/{load-dev-env-cII6N4ZP.cjs.map → load-dev-env-Bl6Ddv1U.cjs.map} +1 -1
  34. package/dist/{load-mode-env-B0qO9DZx.cjs → load-mode-env-CX9vd56X.cjs} +2 -2
  35. package/dist/{load-mode-env-B0qO9DZx.cjs.map → load-mode-env-CX9vd56X.cjs.map} +1 -1
  36. package/dist/{load-mode-env-C8gy4v9V.mjs → load-mode-env-Ce9ujisN.mjs} +2 -2
  37. package/dist/{load-mode-env-C8gy4v9V.mjs.map → load-mode-env-Ce9ujisN.mjs.map} +1 -1
  38. package/dist/{load-test-env-C34wpkIX.mjs → load-test-env-BqtA6V-d.mjs} +2 -2
  39. package/dist/{load-test-env-C34wpkIX.mjs.map → load-test-env-BqtA6V-d.mjs.map} +1 -1
  40. package/dist/{load-test-env-CkdUjTpV.cjs → load-test-env-Dcgh6YHV.cjs} +2 -2
  41. package/dist/{load-test-env-CkdUjTpV.cjs.map → load-test-env-Dcgh6YHV.cjs.map} +1 -1
  42. package/dist/nx.cjs +12 -14
  43. package/dist/nx.cjs.map +1 -1
  44. package/dist/nx.mjs +10 -12
  45. package/dist/nx.mjs.map +1 -1
  46. package/dist/status-4Uz6A3LB.cjs +31 -0
  47. package/dist/status-4Uz6A3LB.cjs.map +1 -0
  48. package/dist/status-Dcnpgnlz.mjs +26 -0
  49. package/dist/status-Dcnpgnlz.mjs.map +1 -0
  50. package/dist/studio-DIFw1qWC.mjs +173 -0
  51. package/dist/studio-DIFw1qWC.mjs.map +1 -0
  52. package/dist/studio-oJE30_PO.cjs +208 -0
  53. package/dist/studio-oJE30_PO.cjs.map +1 -0
  54. package/dist/{tasks-Caud9yHr.cjs → tasks-CNHvvlsN.cjs} +4 -4
  55. package/dist/{tasks-Caud9yHr.cjs.map → tasks-CNHvvlsN.cjs.map} +1 -1
  56. package/dist/{tasks-KherHLac.mjs → tasks-D5iWIdlo.mjs} +2 -2
  57. package/dist/{tasks-KherHLac.mjs.map → tasks-D5iWIdlo.mjs.map} +1 -1
  58. package/dist/{template-CGw3C1Ob.mjs → template-BiJ-0TIF.mjs} +3 -3
  59. package/dist/{template-CGw3C1Ob.mjs.map → template-BiJ-0TIF.mjs.map} +1 -1
  60. package/dist/{template-D0gJ_MS2.cjs → template-CXMpODzK.cjs} +3 -3
  61. package/dist/{template-D0gJ_MS2.cjs.map → template-CXMpODzK.cjs.map} +1 -1
  62. package/dist/{template-mode-IjlFOG4O.mjs → template-mode-BTUsdBtA.mjs} +27 -13
  63. package/dist/template-mode-BTUsdBtA.mjs.map +1 -0
  64. package/dist/{template-mode-CcxV_Iju.d.cts → template-mode-CzyVwHsi.d.cts} +4 -1
  65. package/dist/{template-mode-CcxV_Iju.d.mts → template-mode-CzyVwHsi.d.mts} +4 -1
  66. package/dist/{template-mode-BkEs9LnY.cjs → template-mode-JTOxrEgE.cjs} +27 -13
  67. package/dist/template-mode-JTOxrEgE.cjs.map +1 -0
  68. package/dist/test-env.cjs +1 -1
  69. package/dist/test-env.mjs +1 -1
  70. package/dist/vite-plus.cjs +107 -4
  71. package/dist/vite-plus.cjs.map +1 -1
  72. package/dist/vite-plus.d.cts +25 -1
  73. package/dist/vite-plus.d.mts +25 -1
  74. package/dist/vite-plus.mjs +108 -5
  75. package/dist/vite-plus.mjs.map +1 -1
  76. package/dist/vitest-template.cjs +1 -1
  77. package/dist/vitest-template.d.cts +1 -1
  78. package/dist/vitest-template.d.mts +1 -1
  79. package/dist/vitest-template.mjs +1 -1
  80. package/dist/vitest.cjs +1 -1
  81. package/dist/vitest.mjs +1 -1
  82. package/package.json +11 -2
  83. package/dist/constants-Ct8myrEn.cjs +0 -41
  84. package/dist/constants-Ct8myrEn.cjs.map +0 -1
  85. package/dist/constants-NLR0U4NR.mjs +0 -24
  86. package/dist/constants-NLR0U4NR.mjs.map +0 -1
  87. package/dist/lease-BSBBpaR4.mjs.map +0 -1
  88. package/dist/lease-Bq9wKwQa.cjs.map +0 -1
  89. package/dist/lifecycle-BOo6xBjD.mjs.map +0 -1
  90. package/dist/lifecycle-DEJ4GgWV.cjs.map +0 -1
  91. package/dist/template-mode-BkEs9LnY.cjs.map +0 -1
  92. package/dist/template-mode-IjlFOG4O.mjs.map +0 -1
package/dist/cli.cjs CHANGED
@@ -1,19 +1,21 @@
1
1
  #!/usr/bin/env node
2
- const require_lifecycle = require("./lifecycle-DEJ4GgWV.cjs");
3
- const require_constants = require("./constants-Ct8myrEn.cjs");
4
- const require_lease = require("./lease-Bq9wKwQa.cjs");
5
- let node_child_process = require("node:child_process");
2
+ const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
3
+ const require_lease = require("./lease-WlmOnNDi.cjs");
4
+ const require_status = require("./status-4Uz6A3LB.cjs");
5
+ const require_studio = require("./studio-oJE30_PO.cjs");
6
6
  //#region src/cli.ts
7
7
  function printHelp() {
8
- process.stdout.write(`${require_constants.CLI_NAME}: worktree-isolated local Postgres (via autopg)
8
+ process.stdout.write(`${require_lease.CLI_NAME}: worktree-isolated local Postgres (via autopg)
9
9
 
10
10
  Usage:
11
- ${require_constants.CLI_NAME} acquire --mode=dev|test [--root <path>] [--force] [--json] [--print-env]
12
- ${require_constants.CLI_NAME} run --mode=dev|test [--root <path>] [--force] -- <cmd…>
13
- ${require_constants.CLI_NAME} dispose [--mode=dev|test] [--root <path>]
14
- ${require_constants.CLI_NAME} gc [--json]
15
- ${require_constants.CLI_NAME} print-url [--mode=dev|test] [--root <path>]
16
- ${require_constants.CLI_NAME} --help
11
+ ${require_lease.CLI_NAME} acquire --mode=dev|test [--root <path>] [--force] [--json] [--print-env]
12
+ ${require_lease.CLI_NAME} run --mode=dev|test [--root <path>] [--force] -- <cmd…>
13
+ ${require_lease.CLI_NAME} dispose [--mode=dev|test] [--root <path>]
14
+ ${require_lease.CLI_NAME} gc [--json]
15
+ ${require_lease.CLI_NAME} print-url [--mode=dev|test] [--root <path>]
16
+ ${require_lease.CLI_NAME} status [--mode=dev|test] [--root <path>] [--json]
17
+ ${require_lease.CLI_NAME} studio [--mode=dev|test] [--root <path>] [--prisma|--drizzle]
18
+ ${require_lease.CLI_NAME} --help
17
19
 
18
20
  Modes:
19
21
  dev Keep DB across restarts (default when --mode omitted)
@@ -23,6 +25,11 @@ run:
23
25
  Acquire, set DATABASE_URL (+ TEST_DATABASE_URL in test) on the child, exec <cmd…>.
24
26
  --force sets CEDAR_PG_FORCE (escape hatch); child env overwrite is always on.
25
27
 
28
+ status / studio:
29
+ Read-only lease inspection (no acquire). studio runs Prisma or Drizzle Kit Studio
30
+ attached (stdio + exit code) with DATABASE_URL from the lease. Detects from cwd
31
+ up to the worktree (auto; --prisma / --drizzle to force).
32
+
26
33
  Env:
27
34
  AUTOPG_BIN Path to autopg binary
28
35
  CEDAR_PG=0 Disable adapters that auto-acquire
@@ -49,6 +56,8 @@ function parseArgs(argv) {
49
56
  else if (a === "--json") out.json = true;
50
57
  else if (a === "--print-env") out.printEnv = true;
51
58
  else if (a === "--force") out.force = true;
59
+ else if (a === "--prisma") out.prisma = true;
60
+ else if (a === "--drizzle") out.drizzle = true;
52
61
  else if (a.startsWith("--mode=")) out.mode = parseMode(a.slice(7));
53
62
  else if (a === "--mode") out.mode = parseMode(flagArgs[++i]);
54
63
  else if (a.startsWith("--root=")) out.root = a.slice(7);
@@ -57,18 +66,66 @@ function parseArgs(argv) {
57
66
  }
58
67
  return out;
59
68
  }
69
+ function studioPrefer(args) {
70
+ if (args.prisma && args.drizzle) throw new Error("pass only one of --prisma or --drizzle");
71
+ if (args.prisma) return "prisma";
72
+ if (args.drizzle) return "drizzle";
73
+ }
74
+ function writeLines(stream, lines) {
75
+ for (const line of lines) stream.write(`${line}\n`);
76
+ }
60
77
  function runChild(command, env) {
61
78
  const [file, ...args] = command;
62
- if (!file) throw new Error(`run requires a command after -- (e.g. ${require_constants.CLI_NAME} run --mode=dev -- yarn dev)`);
63
- return new Promise((resolve, reject) => {
64
- const child = (0, node_child_process.spawn)(file, args, {
65
- stdio: "inherit",
66
- env
67
- });
68
- child.on("error", reject);
69
- child.on("exit", (code, signal) => {
70
- resolve(signal ? 1 : code ?? 1);
71
- });
79
+ if (!file) throw new Error(`run requires a command after -- (e.g. ${require_lease.CLI_NAME} run --mode=dev -- yarn dev)`);
80
+ return require_studio.runAttached(file, args, { env });
81
+ }
82
+ function cmdPrintUrl(args) {
83
+ const status = require_status.resolveDevStatus({
84
+ root: args.root,
85
+ mode: args.mode
86
+ });
87
+ if (!status.ok) {
88
+ writeLines(process.stderr, require_studio.formatDevStatus(status));
89
+ return 2;
90
+ }
91
+ process.stdout.write(`${status.databaseUrl}\n`);
92
+ return 0;
93
+ }
94
+ function cmdStatus(args) {
95
+ const status = require_status.resolveDevStatus({
96
+ root: args.root,
97
+ mode: args.mode
98
+ });
99
+ if (args.json) {
100
+ process.stdout.write(`${JSON.stringify(status, null, 2)}\n`);
101
+ return status.ok ? 0 : 2;
102
+ }
103
+ writeLines(process.stdout, require_studio.formatDevStatus(status));
104
+ return status.ok ? 0 : 2;
105
+ }
106
+ async function cmdStudio(args) {
107
+ const prefer = studioPrefer(args);
108
+ const status = require_status.resolveDevStatus({
109
+ root: args.root,
110
+ mode: args.mode
111
+ });
112
+ if (!status.ok) {
113
+ writeLines(process.stderr, require_studio.formatDevStatus(status));
114
+ return 2;
115
+ }
116
+ const studio = require_studio.detectStudio({
117
+ root: status.root,
118
+ cwd: process.cwd(),
119
+ prefer
120
+ });
121
+ if (!studio) {
122
+ process.stderr.write(`${require_lease.CLI_NAME}: no Prisma or Drizzle Studio found (install prisma or drizzle-kit)\n`);
123
+ return 1;
124
+ }
125
+ process.stdout.write(`${require_lease.CLI_NAME}: opening ${studio.kind} studio (${studio.command} ${studio.args.join(" ")})\n`);
126
+ return require_studio.runStudio({
127
+ databaseUrl: status.databaseUrl,
128
+ studio
72
129
  });
73
130
  }
74
131
  async function main() {
@@ -108,7 +165,7 @@ async function main() {
108
165
  root: result.root
109
166
  }, null, 2)}\n`);
110
167
  else if (!args.printEnv) {
111
- process.stdout.write(`${require_constants.CLI_NAME}: ${result.databaseName} (${result.repoSlug}/${result.worktreeSlug} ${result.mode})\n`);
168
+ process.stdout.write(`${require_lease.CLI_NAME}: ${result.databaseName} (${result.repoSlug}/${result.worktreeSlug} ${result.mode})\n`);
112
169
  process.stdout.write(`${result.databaseUrl}\n`);
113
170
  }
114
171
  return 0;
@@ -135,41 +192,34 @@ async function main() {
135
192
  mode
136
193
  });
137
194
  if (result.dropped) {
138
- process.stdout.write(`${require_constants.CLI_NAME}: disposed ${mode} (${result.databaseName})\n`);
195
+ process.stdout.write(`${require_lease.CLI_NAME}: disposed ${mode} (${result.databaseName})\n`);
139
196
  return 0;
140
197
  }
141
198
  if (result.reason === "no-lease") {
142
- process.stdout.write(`${require_constants.CLI_NAME}: nothing to dispose for ${mode} (no lease)\n`);
199
+ process.stdout.write(`${require_lease.CLI_NAME}: nothing to dispose for ${mode} (no lease)\n`);
143
200
  return 0;
144
201
  }
145
- process.stderr.write(`${require_constants.CLI_NAME}: could not dispose ${mode}: autopg host unavailable (lease kept for retry)\n`);
202
+ process.stderr.write(`${require_lease.CLI_NAME}: could not dispose ${mode}: autopg host unavailable (lease kept for retry)\n`);
146
203
  return 1;
147
204
  }
148
205
  if (args.cmd === "gc") {
149
206
  const result = await require_lifecycle.gc();
150
207
  if (args.json) process.stdout.write(`${JSON.stringify(result)}\n`);
151
208
  else {
152
- process.stdout.write(`${require_constants.CLI_NAME} gc: dropped ${result.dropped.length} database(s)\n`);
209
+ process.stdout.write(`${require_lease.CLI_NAME} gc: dropped ${result.dropped.length} database(s)\n`);
153
210
  for (const name of result.dropped) process.stdout.write(` ${name}\n`);
154
211
  }
155
212
  return 0;
156
213
  }
157
- if (args.cmd === "print-url") {
158
- const mode = args.mode ?? "dev";
159
- const lease = require_lease.readLease(require_lease.resolveWorktreeIdentity(args.root).root, mode);
160
- if (!lease) {
161
- process.stderr.write(`${require_constants.CLI_NAME}: no ${mode} lease; run \`${require_constants.CLI_NAME} acquire --mode=${mode}\` first\n`);
162
- return 2;
163
- }
164
- process.stdout.write(`${require_lifecycle.urlFromLease(lease)}\n`);
165
- return 0;
166
- }
167
- process.stderr.write(`${require_constants.CLI_NAME}: unknown command ${args.cmd}\n`);
214
+ if (args.cmd === "print-url") return cmdPrintUrl(args);
215
+ if (args.cmd === "status") return cmdStatus(args);
216
+ if (args.cmd === "studio") return await cmdStudio(args);
217
+ process.stderr.write(`${require_lease.CLI_NAME}: unknown command ${args.cmd}\n`);
168
218
  printHelp();
169
219
  return 64;
170
220
  } catch (err) {
171
221
  const message = err instanceof Error ? err.message : String(err);
172
- process.stderr.write(`${require_constants.CLI_NAME}: ${message}\n`);
222
+ process.stderr.write(`${require_lease.CLI_NAME}: ${message}\n`);
173
223
  return 1;
174
224
  }
175
225
  }
@@ -177,7 +227,7 @@ main().then((code) => {
177
227
  process.exit(code);
178
228
  }).catch((err) => {
179
229
  const message = err instanceof Error ? err.message : String(err);
180
- process.stderr.write(`${require_constants.CLI_NAME}: ${message}\n`);
230
+ process.stderr.write(`${require_lease.CLI_NAME}: ${message}\n`);
181
231
  process.exit(1);
182
232
  });
183
233
  //#endregion
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.cjs","names":["CLI_NAME","acquire","dispose","gc","readLease","resolveWorktreeIdentity","urlFromLease"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { CLI_NAME } from \"./core/constants.ts\";\nimport { acquire, dispose, gc, urlFromLease } from \"./core/lifecycle.ts\";\nimport { resolveWorktreeIdentity } from \"./core/worktree.ts\";\nimport { readLease } from \"./core/lease.ts\";\nimport type { DbMode } from \"./core/naming.ts\";\n\nfunction printHelp(): void {\n process.stdout.write(`${CLI_NAME}: worktree-isolated local Postgres (via autopg)\n\nUsage:\n ${CLI_NAME} acquire --mode=dev|test [--root <path>] [--force] [--json] [--print-env]\n ${CLI_NAME} run --mode=dev|test [--root <path>] [--force] -- <cmd…>\n ${CLI_NAME} dispose [--mode=dev|test] [--root <path>]\n ${CLI_NAME} gc [--json]\n ${CLI_NAME} print-url [--mode=dev|test] [--root <path>]\n ${CLI_NAME} --help\n\nModes:\n dev Keep DB across restarts (default when --mode omitted)\n test Drop DB on dispose / test teardown\n\nrun:\n Acquire, set DATABASE_URL (+ TEST_DATABASE_URL in test) on the child, exec <cmd…>.\n --force sets CEDAR_PG_FORCE (escape hatch); child env overwrite is always on.\n\nEnv:\n AUTOPG_BIN Path to autopg binary\n CEDAR_PG=0 Disable adapters that auto-acquire\n CEDAR_PG_FORCE=1 Ignore external-URL escape hatch (same as --force)\n`);\n}\n\nfunction parseMode(value: string | undefined): DbMode {\n if (value === \"dev\" || value === \"test\") return value;\n throw new Error(\"--mode must be dev or test\");\n}\n\ntype ParsedArgs = {\n cmd?: string;\n mode?: DbMode;\n root?: string;\n json?: boolean;\n printEnv?: boolean;\n force?: boolean;\n help?: boolean;\n child?: string[];\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {};\n const rest = [...argv];\n out.cmd = rest.shift();\n\n const dash = rest.indexOf(\"--\");\n let flagArgs = rest;\n if (dash >= 0) {\n flagArgs = rest.slice(0, dash);\n out.child = rest.slice(dash + 1);\n }\n\n for (let i = 0; i < flagArgs.length; i++) {\n const a = flagArgs[i]!;\n if (a === \"--help\" || a === \"-h\") out.help = true;\n else if (a === \"--json\") out.json = true;\n else if (a === \"--print-env\") out.printEnv = true;\n else if (a === \"--force\") out.force = true;\n else if (a.startsWith(\"--mode=\")) out.mode = parseMode(a.slice(7));\n else if (a === \"--mode\") out.mode = parseMode(flagArgs[++i]);\n else if (a.startsWith(\"--root=\")) out.root = a.slice(7);\n else if (a === \"--root\") out.root = flagArgs[++i];\n else throw new Error(`unknown argument: ${a}`);\n }\n return out;\n}\n\nfunction runChild(command: string[], env: NodeJS.ProcessEnv): Promise<number> {\n const [file, ...args] = command;\n if (!file) {\n throw new Error(\n `run requires a command after -- (e.g. ${CLI_NAME} run --mode=dev -- yarn dev)`,\n );\n }\n return new Promise((resolve, reject) => {\n const child = spawn(file, args, { stdio: \"inherit\", env });\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n resolve(signal ? 1 : (code ?? 1));\n });\n });\n}\n\nasync function main(): Promise<number> {\n const argv = process.argv.slice(2);\n if (argv.length === 0 || argv[0] === \"help\" || argv[0] === \"--help\" || argv[0] === \"-h\") {\n printHelp();\n return 0;\n }\n const args = parseArgs(argv);\n if (args.help) {\n printHelp();\n return 0;\n }\n\n try {\n if (args.cmd === \"acquire\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n if (args.printEnv) {\n process.stdout.write(`DATABASE_URL=${result.databaseUrl}\\n`);\n if (mode === \"test\") {\n process.stdout.write(`TEST_DATABASE_URL=${result.databaseUrl}\\n`);\n }\n }\n if (args.json) {\n process.stdout.write(\n `${JSON.stringify(\n {\n databaseUrl: result.databaseUrl,\n adminUrl: result.adminUrl,\n databaseName: result.databaseName,\n roleName: result.roleName,\n repoSlug: result.repoSlug,\n worktreeSlug: result.worktreeSlug,\n pathHash: result.pathHash,\n mode: result.mode,\n port: result.port,\n root: result.root,\n },\n null,\n 2,\n )}\\n`,\n );\n } else if (!args.printEnv) {\n process.stdout.write(\n `${CLI_NAME}: ${result.databaseName} (${result.repoSlug}/${result.worktreeSlug} ${result.mode})\\n`,\n );\n process.stdout.write(`${result.databaseUrl}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"run\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n const childEnv: NodeJS.ProcessEnv = {\n ...process.env,\n DATABASE_URL: result.databaseUrl,\n };\n if (mode === \"test\") childEnv.TEST_DATABASE_URL = result.databaseUrl;\n return await runChild(args.child ?? [], childEnv);\n }\n\n if (args.cmd === \"dispose\") {\n const mode = args.mode ?? \"test\";\n const result = await dispose({ root: args.root, mode });\n if (result.dropped) {\n process.stdout.write(`${CLI_NAME}: disposed ${mode} (${result.databaseName})\\n`);\n return 0;\n }\n if (result.reason === \"no-lease\") {\n process.stdout.write(`${CLI_NAME}: nothing to dispose for ${mode} (no lease)\\n`);\n return 0;\n }\n process.stderr.write(\n `${CLI_NAME}: could not dispose ${mode}: autopg host unavailable (lease kept for retry)\\n`,\n );\n return 1;\n }\n\n if (args.cmd === \"gc\") {\n const result = await gc();\n if (args.json) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n } else {\n process.stdout.write(`${CLI_NAME} gc: dropped ${result.dropped.length} database(s)\\n`);\n for (const name of result.dropped) process.stdout.write(` ${name}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"print-url\") {\n const mode = args.mode ?? \"dev\";\n const identity = resolveWorktreeIdentity(args.root);\n const lease = readLease(identity.root, mode);\n if (!lease) {\n process.stderr.write(\n `${CLI_NAME}: no ${mode} lease; run \\`${CLI_NAME} acquire --mode=${mode}\\` first\\n`,\n );\n return 2;\n }\n process.stdout.write(`${urlFromLease(lease)}\\n`);\n return 0;\n }\n\n process.stderr.write(`${CLI_NAME}: unknown command ${args.cmd}\\n`);\n printHelp();\n return 64;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n return 1;\n }\n}\n\nmain()\n .then((code) => {\n process.exit(code);\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n process.exit(1);\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.cjs","names":["CLI_NAME","runAttached","resolveDevStatus","formatDevStatus","detectStudio","runStudio","acquire","dispose","gc"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI_NAME } from \"./core/constants.ts\";\nimport { acquire, dispose, gc } from \"./core/lifecycle.ts\";\nimport { resolveDevStatus } from \"./core/status.ts\";\nimport type { DbMode } from \"./core/naming.ts\";\nimport { runAttached } from \"./adapters/child.ts\";\nimport { formatDevStatus } from \"./adapters/status-format.ts\";\nimport { detectStudio, runStudio, type StudioKind } from \"./adapters/studio.ts\";\n\nfunction printHelp(): void {\n process.stdout.write(`${CLI_NAME}: worktree-isolated local Postgres (via autopg)\n\nUsage:\n ${CLI_NAME} acquire --mode=dev|test [--root <path>] [--force] [--json] [--print-env]\n ${CLI_NAME} run --mode=dev|test [--root <path>] [--force] -- <cmd…>\n ${CLI_NAME} dispose [--mode=dev|test] [--root <path>]\n ${CLI_NAME} gc [--json]\n ${CLI_NAME} print-url [--mode=dev|test] [--root <path>]\n ${CLI_NAME} status [--mode=dev|test] [--root <path>] [--json]\n ${CLI_NAME} studio [--mode=dev|test] [--root <path>] [--prisma|--drizzle]\n ${CLI_NAME} --help\n\nModes:\n dev Keep DB across restarts (default when --mode omitted)\n test Drop DB on dispose / test teardown\n\nrun:\n Acquire, set DATABASE_URL (+ TEST_DATABASE_URL in test) on the child, exec <cmd…>.\n --force sets CEDAR_PG_FORCE (escape hatch); child env overwrite is always on.\n\nstatus / studio:\n Read-only lease inspection (no acquire). studio runs Prisma or Drizzle Kit Studio\n attached (stdio + exit code) with DATABASE_URL from the lease. Detects from cwd\n up to the worktree (auto; --prisma / --drizzle to force).\n\nEnv:\n AUTOPG_BIN Path to autopg binary\n CEDAR_PG=0 Disable adapters that auto-acquire\n CEDAR_PG_FORCE=1 Ignore external-URL escape hatch (same as --force)\n`);\n}\n\nfunction parseMode(value: string | undefined): DbMode {\n if (value === \"dev\" || value === \"test\") return value;\n throw new Error(\"--mode must be dev or test\");\n}\n\ntype ParsedArgs = {\n cmd?: string;\n mode?: DbMode;\n root?: string;\n json?: boolean;\n printEnv?: boolean;\n force?: boolean;\n help?: boolean;\n prisma?: boolean;\n drizzle?: boolean;\n child?: string[];\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {};\n const rest = [...argv];\n out.cmd = rest.shift();\n\n const dash = rest.indexOf(\"--\");\n let flagArgs = rest;\n if (dash >= 0) {\n flagArgs = rest.slice(0, dash);\n out.child = rest.slice(dash + 1);\n }\n\n for (let i = 0; i < flagArgs.length; i++) {\n const a = flagArgs[i]!;\n if (a === \"--help\" || a === \"-h\") out.help = true;\n else if (a === \"--json\") out.json = true;\n else if (a === \"--print-env\") out.printEnv = true;\n else if (a === \"--force\") out.force = true;\n else if (a === \"--prisma\") out.prisma = true;\n else if (a === \"--drizzle\") out.drizzle = true;\n else if (a.startsWith(\"--mode=\")) out.mode = parseMode(a.slice(7));\n else if (a === \"--mode\") out.mode = parseMode(flagArgs[++i]);\n else if (a.startsWith(\"--root=\")) out.root = a.slice(7);\n else if (a === \"--root\") out.root = flagArgs[++i];\n else throw new Error(`unknown argument: ${a}`);\n }\n return out;\n}\n\nfunction studioPrefer(args: ParsedArgs): StudioKind | undefined {\n if (args.prisma && args.drizzle) {\n throw new Error(\"pass only one of --prisma or --drizzle\");\n }\n if (args.prisma) return \"prisma\";\n if (args.drizzle) return \"drizzle\";\n return undefined;\n}\n\nfunction writeLines(stream: NodeJS.WriteStream, lines: string[]): void {\n for (const line of lines) stream.write(`${line}\\n`);\n}\n\nfunction runChild(command: string[], env: NodeJS.ProcessEnv): Promise<number> {\n const [file, ...args] = command;\n if (!file) {\n throw new Error(\n `run requires a command after -- (e.g. ${CLI_NAME} run --mode=dev -- yarn dev)`,\n );\n }\n return runAttached(file, args, { env });\n}\n\nfunction cmdPrintUrl(args: ParsedArgs): number {\n const status = resolveDevStatus({ root: args.root, mode: args.mode });\n if (!status.ok) {\n writeLines(process.stderr, formatDevStatus(status));\n return 2;\n }\n process.stdout.write(`${status.databaseUrl}\\n`);\n return 0;\n}\n\nfunction cmdStatus(args: ParsedArgs): number {\n const status = resolveDevStatus({ root: args.root, mode: args.mode });\n if (args.json) {\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`);\n return status.ok ? 0 : 2;\n }\n writeLines(process.stdout, formatDevStatus(status));\n return status.ok ? 0 : 2;\n}\n\nasync function cmdStudio(args: ParsedArgs): Promise<number> {\n const prefer = studioPrefer(args);\n const status = resolveDevStatus({ root: args.root, mode: args.mode });\n if (!status.ok) {\n writeLines(process.stderr, formatDevStatus(status));\n return 2;\n }\n const studio = detectStudio({ root: status.root, cwd: process.cwd(), prefer });\n if (!studio) {\n process.stderr.write(\n `${CLI_NAME}: no Prisma or Drizzle Studio found (install prisma or drizzle-kit)\\n`,\n );\n return 1;\n }\n process.stdout.write(\n `${CLI_NAME}: opening ${studio.kind} studio (${studio.command} ${studio.args.join(\" \")})\\n`,\n );\n return runStudio({ databaseUrl: status.databaseUrl, studio });\n}\n\nasync function main(): Promise<number> {\n const argv = process.argv.slice(2);\n if (argv.length === 0 || argv[0] === \"help\" || argv[0] === \"--help\" || argv[0] === \"-h\") {\n printHelp();\n return 0;\n }\n const args = parseArgs(argv);\n if (args.help) {\n printHelp();\n return 0;\n }\n\n try {\n if (args.cmd === \"acquire\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n if (args.printEnv) {\n process.stdout.write(`DATABASE_URL=${result.databaseUrl}\\n`);\n if (mode === \"test\") {\n process.stdout.write(`TEST_DATABASE_URL=${result.databaseUrl}\\n`);\n }\n }\n if (args.json) {\n process.stdout.write(\n `${JSON.stringify(\n {\n databaseUrl: result.databaseUrl,\n adminUrl: result.adminUrl,\n databaseName: result.databaseName,\n roleName: result.roleName,\n repoSlug: result.repoSlug,\n worktreeSlug: result.worktreeSlug,\n pathHash: result.pathHash,\n mode: result.mode,\n port: result.port,\n root: result.root,\n },\n null,\n 2,\n )}\\n`,\n );\n } else if (!args.printEnv) {\n process.stdout.write(\n `${CLI_NAME}: ${result.databaseName} (${result.repoSlug}/${result.worktreeSlug} ${result.mode})\\n`,\n );\n process.stdout.write(`${result.databaseUrl}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"run\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n const childEnv: NodeJS.ProcessEnv = {\n ...process.env,\n DATABASE_URL: result.databaseUrl,\n };\n if (mode === \"test\") childEnv.TEST_DATABASE_URL = result.databaseUrl;\n return await runChild(args.child ?? [], childEnv);\n }\n\n if (args.cmd === \"dispose\") {\n const mode = args.mode ?? \"test\";\n const result = await dispose({ root: args.root, mode });\n if (result.dropped) {\n process.stdout.write(`${CLI_NAME}: disposed ${mode} (${result.databaseName})\\n`);\n return 0;\n }\n if (result.reason === \"no-lease\") {\n process.stdout.write(`${CLI_NAME}: nothing to dispose for ${mode} (no lease)\\n`);\n return 0;\n }\n process.stderr.write(\n `${CLI_NAME}: could not dispose ${mode}: autopg host unavailable (lease kept for retry)\\n`,\n );\n return 1;\n }\n\n if (args.cmd === \"gc\") {\n const result = await gc();\n if (args.json) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n } else {\n process.stdout.write(`${CLI_NAME} gc: dropped ${result.dropped.length} database(s)\\n`);\n for (const name of result.dropped) process.stdout.write(` ${name}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"print-url\") {\n return cmdPrintUrl(args);\n }\n\n if (args.cmd === \"status\") {\n return cmdStatus(args);\n }\n\n if (args.cmd === \"studio\") {\n return await cmdStudio(args);\n }\n\n process.stderr.write(`${CLI_NAME}: unknown command ${args.cmd}\\n`);\n printHelp();\n return 64;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n return 1;\n }\n}\n\nmain()\n .then((code) => {\n process.exit(code);\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n process.exit(1);\n });\n"],"mappings":"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"}
package/dist/cli.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { a as urlFromLease, i as gc, r as dispose, t as acquire } from "./lifecycle-BOo6xBjD.mjs";
3
- import { t as CLI_NAME } from "./constants-NLR0U4NR.mjs";
4
- import { f as resolveWorktreeIdentity, l as readLease } from "./lease-BSBBpaR4.mjs";
5
- import { spawn } from "node:child_process";
2
+ import { i as gc, r as dispose, t as acquire } from "./lifecycle-BvIx0xqq.mjs";
3
+ import { p as CLI_NAME } from "./lease-DS1SX8U_.mjs";
4
+ import { t as resolveDevStatus } from "./status-Dcnpgnlz.mjs";
5
+ import { a as formatDevStatus, o as runAttached, r as runStudio, t as detectStudio } from "./studio-DIFw1qWC.mjs";
6
6
  //#region src/cli.ts
7
7
  function printHelp() {
8
8
  process.stdout.write(`${CLI_NAME}: worktree-isolated local Postgres (via autopg)
@@ -13,6 +13,8 @@ Usage:
13
13
  ${CLI_NAME} dispose [--mode=dev|test] [--root <path>]
14
14
  ${CLI_NAME} gc [--json]
15
15
  ${CLI_NAME} print-url [--mode=dev|test] [--root <path>]
16
+ ${CLI_NAME} status [--mode=dev|test] [--root <path>] [--json]
17
+ ${CLI_NAME} studio [--mode=dev|test] [--root <path>] [--prisma|--drizzle]
16
18
  ${CLI_NAME} --help
17
19
 
18
20
  Modes:
@@ -23,6 +25,11 @@ run:
23
25
  Acquire, set DATABASE_URL (+ TEST_DATABASE_URL in test) on the child, exec <cmd…>.
24
26
  --force sets CEDAR_PG_FORCE (escape hatch); child env overwrite is always on.
25
27
 
28
+ status / studio:
29
+ Read-only lease inspection (no acquire). studio runs Prisma or Drizzle Kit Studio
30
+ attached (stdio + exit code) with DATABASE_URL from the lease. Detects from cwd
31
+ up to the worktree (auto; --prisma / --drizzle to force).
32
+
26
33
  Env:
27
34
  AUTOPG_BIN Path to autopg binary
28
35
  CEDAR_PG=0 Disable adapters that auto-acquire
@@ -49,6 +56,8 @@ function parseArgs(argv) {
49
56
  else if (a === "--json") out.json = true;
50
57
  else if (a === "--print-env") out.printEnv = true;
51
58
  else if (a === "--force") out.force = true;
59
+ else if (a === "--prisma") out.prisma = true;
60
+ else if (a === "--drizzle") out.drizzle = true;
52
61
  else if (a.startsWith("--mode=")) out.mode = parseMode(a.slice(7));
53
62
  else if (a === "--mode") out.mode = parseMode(flagArgs[++i]);
54
63
  else if (a.startsWith("--root=")) out.root = a.slice(7);
@@ -57,18 +66,66 @@ function parseArgs(argv) {
57
66
  }
58
67
  return out;
59
68
  }
69
+ function studioPrefer(args) {
70
+ if (args.prisma && args.drizzle) throw new Error("pass only one of --prisma or --drizzle");
71
+ if (args.prisma) return "prisma";
72
+ if (args.drizzle) return "drizzle";
73
+ }
74
+ function writeLines(stream, lines) {
75
+ for (const line of lines) stream.write(`${line}\n`);
76
+ }
60
77
  function runChild(command, env) {
61
78
  const [file, ...args] = command;
62
79
  if (!file) throw new Error(`run requires a command after -- (e.g. ${CLI_NAME} run --mode=dev -- yarn dev)`);
63
- return new Promise((resolve, reject) => {
64
- const child = spawn(file, args, {
65
- stdio: "inherit",
66
- env
67
- });
68
- child.on("error", reject);
69
- child.on("exit", (code, signal) => {
70
- resolve(signal ? 1 : code ?? 1);
71
- });
80
+ return runAttached(file, args, { env });
81
+ }
82
+ function cmdPrintUrl(args) {
83
+ const status = resolveDevStatus({
84
+ root: args.root,
85
+ mode: args.mode
86
+ });
87
+ if (!status.ok) {
88
+ writeLines(process.stderr, formatDevStatus(status));
89
+ return 2;
90
+ }
91
+ process.stdout.write(`${status.databaseUrl}\n`);
92
+ return 0;
93
+ }
94
+ function cmdStatus(args) {
95
+ const status = resolveDevStatus({
96
+ root: args.root,
97
+ mode: args.mode
98
+ });
99
+ if (args.json) {
100
+ process.stdout.write(`${JSON.stringify(status, null, 2)}\n`);
101
+ return status.ok ? 0 : 2;
102
+ }
103
+ writeLines(process.stdout, formatDevStatus(status));
104
+ return status.ok ? 0 : 2;
105
+ }
106
+ async function cmdStudio(args) {
107
+ const prefer = studioPrefer(args);
108
+ const status = resolveDevStatus({
109
+ root: args.root,
110
+ mode: args.mode
111
+ });
112
+ if (!status.ok) {
113
+ writeLines(process.stderr, formatDevStatus(status));
114
+ return 2;
115
+ }
116
+ const studio = detectStudio({
117
+ root: status.root,
118
+ cwd: process.cwd(),
119
+ prefer
120
+ });
121
+ if (!studio) {
122
+ process.stderr.write(`${CLI_NAME}: no Prisma or Drizzle Studio found (install prisma or drizzle-kit)\n`);
123
+ return 1;
124
+ }
125
+ process.stdout.write(`${CLI_NAME}: opening ${studio.kind} studio (${studio.command} ${studio.args.join(" ")})\n`);
126
+ return runStudio({
127
+ databaseUrl: status.databaseUrl,
128
+ studio
72
129
  });
73
130
  }
74
131
  async function main() {
@@ -154,16 +211,9 @@ async function main() {
154
211
  }
155
212
  return 0;
156
213
  }
157
- if (args.cmd === "print-url") {
158
- const mode = args.mode ?? "dev";
159
- const lease = readLease(resolveWorktreeIdentity(args.root).root, mode);
160
- if (!lease) {
161
- process.stderr.write(`${CLI_NAME}: no ${mode} lease; run \`${CLI_NAME} acquire --mode=${mode}\` first\n`);
162
- return 2;
163
- }
164
- process.stdout.write(`${urlFromLease(lease)}\n`);
165
- return 0;
166
- }
214
+ if (args.cmd === "print-url") return cmdPrintUrl(args);
215
+ if (args.cmd === "status") return cmdStatus(args);
216
+ if (args.cmd === "studio") return await cmdStudio(args);
167
217
  process.stderr.write(`${CLI_NAME}: unknown command ${args.cmd}\n`);
168
218
  printHelp();
169
219
  return 64;
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { CLI_NAME } from \"./core/constants.ts\";\nimport { acquire, dispose, gc, urlFromLease } from \"./core/lifecycle.ts\";\nimport { resolveWorktreeIdentity } from \"./core/worktree.ts\";\nimport { readLease } from \"./core/lease.ts\";\nimport type { DbMode } from \"./core/naming.ts\";\n\nfunction printHelp(): void {\n process.stdout.write(`${CLI_NAME}: worktree-isolated local Postgres (via autopg)\n\nUsage:\n ${CLI_NAME} acquire --mode=dev|test [--root <path>] [--force] [--json] [--print-env]\n ${CLI_NAME} run --mode=dev|test [--root <path>] [--force] -- <cmd…>\n ${CLI_NAME} dispose [--mode=dev|test] [--root <path>]\n ${CLI_NAME} gc [--json]\n ${CLI_NAME} print-url [--mode=dev|test] [--root <path>]\n ${CLI_NAME} --help\n\nModes:\n dev Keep DB across restarts (default when --mode omitted)\n test Drop DB on dispose / test teardown\n\nrun:\n Acquire, set DATABASE_URL (+ TEST_DATABASE_URL in test) on the child, exec <cmd…>.\n --force sets CEDAR_PG_FORCE (escape hatch); child env overwrite is always on.\n\nEnv:\n AUTOPG_BIN Path to autopg binary\n CEDAR_PG=0 Disable adapters that auto-acquire\n CEDAR_PG_FORCE=1 Ignore external-URL escape hatch (same as --force)\n`);\n}\n\nfunction parseMode(value: string | undefined): DbMode {\n if (value === \"dev\" || value === \"test\") return value;\n throw new Error(\"--mode must be dev or test\");\n}\n\ntype ParsedArgs = {\n cmd?: string;\n mode?: DbMode;\n root?: string;\n json?: boolean;\n printEnv?: boolean;\n force?: boolean;\n help?: boolean;\n child?: string[];\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {};\n const rest = [...argv];\n out.cmd = rest.shift();\n\n const dash = rest.indexOf(\"--\");\n let flagArgs = rest;\n if (dash >= 0) {\n flagArgs = rest.slice(0, dash);\n out.child = rest.slice(dash + 1);\n }\n\n for (let i = 0; i < flagArgs.length; i++) {\n const a = flagArgs[i]!;\n if (a === \"--help\" || a === \"-h\") out.help = true;\n else if (a === \"--json\") out.json = true;\n else if (a === \"--print-env\") out.printEnv = true;\n else if (a === \"--force\") out.force = true;\n else if (a.startsWith(\"--mode=\")) out.mode = parseMode(a.slice(7));\n else if (a === \"--mode\") out.mode = parseMode(flagArgs[++i]);\n else if (a.startsWith(\"--root=\")) out.root = a.slice(7);\n else if (a === \"--root\") out.root = flagArgs[++i];\n else throw new Error(`unknown argument: ${a}`);\n }\n return out;\n}\n\nfunction runChild(command: string[], env: NodeJS.ProcessEnv): Promise<number> {\n const [file, ...args] = command;\n if (!file) {\n throw new Error(\n `run requires a command after -- (e.g. ${CLI_NAME} run --mode=dev -- yarn dev)`,\n );\n }\n return new Promise((resolve, reject) => {\n const child = spawn(file, args, { stdio: \"inherit\", env });\n child.on(\"error\", reject);\n child.on(\"exit\", (code, signal) => {\n resolve(signal ? 1 : (code ?? 1));\n });\n });\n}\n\nasync function main(): Promise<number> {\n const argv = process.argv.slice(2);\n if (argv.length === 0 || argv[0] === \"help\" || argv[0] === \"--help\" || argv[0] === \"-h\") {\n printHelp();\n return 0;\n }\n const args = parseArgs(argv);\n if (args.help) {\n printHelp();\n return 0;\n }\n\n try {\n if (args.cmd === \"acquire\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n if (args.printEnv) {\n process.stdout.write(`DATABASE_URL=${result.databaseUrl}\\n`);\n if (mode === \"test\") {\n process.stdout.write(`TEST_DATABASE_URL=${result.databaseUrl}\\n`);\n }\n }\n if (args.json) {\n process.stdout.write(\n `${JSON.stringify(\n {\n databaseUrl: result.databaseUrl,\n adminUrl: result.adminUrl,\n databaseName: result.databaseName,\n roleName: result.roleName,\n repoSlug: result.repoSlug,\n worktreeSlug: result.worktreeSlug,\n pathHash: result.pathHash,\n mode: result.mode,\n port: result.port,\n root: result.root,\n },\n null,\n 2,\n )}\\n`,\n );\n } else if (!args.printEnv) {\n process.stdout.write(\n `${CLI_NAME}: ${result.databaseName} (${result.repoSlug}/${result.worktreeSlug} ${result.mode})\\n`,\n );\n process.stdout.write(`${result.databaseUrl}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"run\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n const childEnv: NodeJS.ProcessEnv = {\n ...process.env,\n DATABASE_URL: result.databaseUrl,\n };\n if (mode === \"test\") childEnv.TEST_DATABASE_URL = result.databaseUrl;\n return await runChild(args.child ?? [], childEnv);\n }\n\n if (args.cmd === \"dispose\") {\n const mode = args.mode ?? \"test\";\n const result = await dispose({ root: args.root, mode });\n if (result.dropped) {\n process.stdout.write(`${CLI_NAME}: disposed ${mode} (${result.databaseName})\\n`);\n return 0;\n }\n if (result.reason === \"no-lease\") {\n process.stdout.write(`${CLI_NAME}: nothing to dispose for ${mode} (no lease)\\n`);\n return 0;\n }\n process.stderr.write(\n `${CLI_NAME}: could not dispose ${mode}: autopg host unavailable (lease kept for retry)\\n`,\n );\n return 1;\n }\n\n if (args.cmd === \"gc\") {\n const result = await gc();\n if (args.json) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n } else {\n process.stdout.write(`${CLI_NAME} gc: dropped ${result.dropped.length} database(s)\\n`);\n for (const name of result.dropped) process.stdout.write(` ${name}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"print-url\") {\n const mode = args.mode ?? \"dev\";\n const identity = resolveWorktreeIdentity(args.root);\n const lease = readLease(identity.root, mode);\n if (!lease) {\n process.stderr.write(\n `${CLI_NAME}: no ${mode} lease; run \\`${CLI_NAME} acquire --mode=${mode}\\` first\\n`,\n );\n return 2;\n }\n process.stdout.write(`${urlFromLease(lease)}\\n`);\n return 0;\n }\n\n process.stderr.write(`${CLI_NAME}: unknown command ${args.cmd}\\n`);\n printHelp();\n return 64;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n return 1;\n }\n}\n\nmain()\n .then((code) => {\n process.exit(code);\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n process.exit(1);\n });\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI_NAME } from \"./core/constants.ts\";\nimport { acquire, dispose, gc } from \"./core/lifecycle.ts\";\nimport { resolveDevStatus } from \"./core/status.ts\";\nimport type { DbMode } from \"./core/naming.ts\";\nimport { runAttached } from \"./adapters/child.ts\";\nimport { formatDevStatus } from \"./adapters/status-format.ts\";\nimport { detectStudio, runStudio, type StudioKind } from \"./adapters/studio.ts\";\n\nfunction printHelp(): void {\n process.stdout.write(`${CLI_NAME}: worktree-isolated local Postgres (via autopg)\n\nUsage:\n ${CLI_NAME} acquire --mode=dev|test [--root <path>] [--force] [--json] [--print-env]\n ${CLI_NAME} run --mode=dev|test [--root <path>] [--force] -- <cmd…>\n ${CLI_NAME} dispose [--mode=dev|test] [--root <path>]\n ${CLI_NAME} gc [--json]\n ${CLI_NAME} print-url [--mode=dev|test] [--root <path>]\n ${CLI_NAME} status [--mode=dev|test] [--root <path>] [--json]\n ${CLI_NAME} studio [--mode=dev|test] [--root <path>] [--prisma|--drizzle]\n ${CLI_NAME} --help\n\nModes:\n dev Keep DB across restarts (default when --mode omitted)\n test Drop DB on dispose / test teardown\n\nrun:\n Acquire, set DATABASE_URL (+ TEST_DATABASE_URL in test) on the child, exec <cmd…>.\n --force sets CEDAR_PG_FORCE (escape hatch); child env overwrite is always on.\n\nstatus / studio:\n Read-only lease inspection (no acquire). studio runs Prisma or Drizzle Kit Studio\n attached (stdio + exit code) with DATABASE_URL from the lease. Detects from cwd\n up to the worktree (auto; --prisma / --drizzle to force).\n\nEnv:\n AUTOPG_BIN Path to autopg binary\n CEDAR_PG=0 Disable adapters that auto-acquire\n CEDAR_PG_FORCE=1 Ignore external-URL escape hatch (same as --force)\n`);\n}\n\nfunction parseMode(value: string | undefined): DbMode {\n if (value === \"dev\" || value === \"test\") return value;\n throw new Error(\"--mode must be dev or test\");\n}\n\ntype ParsedArgs = {\n cmd?: string;\n mode?: DbMode;\n root?: string;\n json?: boolean;\n printEnv?: boolean;\n force?: boolean;\n help?: boolean;\n prisma?: boolean;\n drizzle?: boolean;\n child?: string[];\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = {};\n const rest = [...argv];\n out.cmd = rest.shift();\n\n const dash = rest.indexOf(\"--\");\n let flagArgs = rest;\n if (dash >= 0) {\n flagArgs = rest.slice(0, dash);\n out.child = rest.slice(dash + 1);\n }\n\n for (let i = 0; i < flagArgs.length; i++) {\n const a = flagArgs[i]!;\n if (a === \"--help\" || a === \"-h\") out.help = true;\n else if (a === \"--json\") out.json = true;\n else if (a === \"--print-env\") out.printEnv = true;\n else if (a === \"--force\") out.force = true;\n else if (a === \"--prisma\") out.prisma = true;\n else if (a === \"--drizzle\") out.drizzle = true;\n else if (a.startsWith(\"--mode=\")) out.mode = parseMode(a.slice(7));\n else if (a === \"--mode\") out.mode = parseMode(flagArgs[++i]);\n else if (a.startsWith(\"--root=\")) out.root = a.slice(7);\n else if (a === \"--root\") out.root = flagArgs[++i];\n else throw new Error(`unknown argument: ${a}`);\n }\n return out;\n}\n\nfunction studioPrefer(args: ParsedArgs): StudioKind | undefined {\n if (args.prisma && args.drizzle) {\n throw new Error(\"pass only one of --prisma or --drizzle\");\n }\n if (args.prisma) return \"prisma\";\n if (args.drizzle) return \"drizzle\";\n return undefined;\n}\n\nfunction writeLines(stream: NodeJS.WriteStream, lines: string[]): void {\n for (const line of lines) stream.write(`${line}\\n`);\n}\n\nfunction runChild(command: string[], env: NodeJS.ProcessEnv): Promise<number> {\n const [file, ...args] = command;\n if (!file) {\n throw new Error(\n `run requires a command after -- (e.g. ${CLI_NAME} run --mode=dev -- yarn dev)`,\n );\n }\n return runAttached(file, args, { env });\n}\n\nfunction cmdPrintUrl(args: ParsedArgs): number {\n const status = resolveDevStatus({ root: args.root, mode: args.mode });\n if (!status.ok) {\n writeLines(process.stderr, formatDevStatus(status));\n return 2;\n }\n process.stdout.write(`${status.databaseUrl}\\n`);\n return 0;\n}\n\nfunction cmdStatus(args: ParsedArgs): number {\n const status = resolveDevStatus({ root: args.root, mode: args.mode });\n if (args.json) {\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`);\n return status.ok ? 0 : 2;\n }\n writeLines(process.stdout, formatDevStatus(status));\n return status.ok ? 0 : 2;\n}\n\nasync function cmdStudio(args: ParsedArgs): Promise<number> {\n const prefer = studioPrefer(args);\n const status = resolveDevStatus({ root: args.root, mode: args.mode });\n if (!status.ok) {\n writeLines(process.stderr, formatDevStatus(status));\n return 2;\n }\n const studio = detectStudio({ root: status.root, cwd: process.cwd(), prefer });\n if (!studio) {\n process.stderr.write(\n `${CLI_NAME}: no Prisma or Drizzle Studio found (install prisma or drizzle-kit)\\n`,\n );\n return 1;\n }\n process.stdout.write(\n `${CLI_NAME}: opening ${studio.kind} studio (${studio.command} ${studio.args.join(\" \")})\\n`,\n );\n return runStudio({ databaseUrl: status.databaseUrl, studio });\n}\n\nasync function main(): Promise<number> {\n const argv = process.argv.slice(2);\n if (argv.length === 0 || argv[0] === \"help\" || argv[0] === \"--help\" || argv[0] === \"-h\") {\n printHelp();\n return 0;\n }\n const args = parseArgs(argv);\n if (args.help) {\n printHelp();\n return 0;\n }\n\n try {\n if (args.cmd === \"acquire\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n if (args.printEnv) {\n process.stdout.write(`DATABASE_URL=${result.databaseUrl}\\n`);\n if (mode === \"test\") {\n process.stdout.write(`TEST_DATABASE_URL=${result.databaseUrl}\\n`);\n }\n }\n if (args.json) {\n process.stdout.write(\n `${JSON.stringify(\n {\n databaseUrl: result.databaseUrl,\n adminUrl: result.adminUrl,\n databaseName: result.databaseName,\n roleName: result.roleName,\n repoSlug: result.repoSlug,\n worktreeSlug: result.worktreeSlug,\n pathHash: result.pathHash,\n mode: result.mode,\n port: result.port,\n root: result.root,\n },\n null,\n 2,\n )}\\n`,\n );\n } else if (!args.printEnv) {\n process.stdout.write(\n `${CLI_NAME}: ${result.databaseName} (${result.repoSlug}/${result.worktreeSlug} ${result.mode})\\n`,\n );\n process.stdout.write(`${result.databaseUrl}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"run\") {\n if (args.force) process.env.CEDAR_PG_FORCE = \"1\";\n const mode = args.mode ?? \"dev\";\n const result = await acquire({\n root: args.root,\n mode,\n setEnv: true,\n });\n const childEnv: NodeJS.ProcessEnv = {\n ...process.env,\n DATABASE_URL: result.databaseUrl,\n };\n if (mode === \"test\") childEnv.TEST_DATABASE_URL = result.databaseUrl;\n return await runChild(args.child ?? [], childEnv);\n }\n\n if (args.cmd === \"dispose\") {\n const mode = args.mode ?? \"test\";\n const result = await dispose({ root: args.root, mode });\n if (result.dropped) {\n process.stdout.write(`${CLI_NAME}: disposed ${mode} (${result.databaseName})\\n`);\n return 0;\n }\n if (result.reason === \"no-lease\") {\n process.stdout.write(`${CLI_NAME}: nothing to dispose for ${mode} (no lease)\\n`);\n return 0;\n }\n process.stderr.write(\n `${CLI_NAME}: could not dispose ${mode}: autopg host unavailable (lease kept for retry)\\n`,\n );\n return 1;\n }\n\n if (args.cmd === \"gc\") {\n const result = await gc();\n if (args.json) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n } else {\n process.stdout.write(`${CLI_NAME} gc: dropped ${result.dropped.length} database(s)\\n`);\n for (const name of result.dropped) process.stdout.write(` ${name}\\n`);\n }\n return 0;\n }\n\n if (args.cmd === \"print-url\") {\n return cmdPrintUrl(args);\n }\n\n if (args.cmd === \"status\") {\n return cmdStatus(args);\n }\n\n if (args.cmd === \"studio\") {\n return await cmdStudio(args);\n }\n\n process.stderr.write(`${CLI_NAME}: unknown command ${args.cmd}\\n`);\n printHelp();\n return 64;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n return 1;\n }\n}\n\nmain()\n .then((code) => {\n process.exit(code);\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`${CLI_NAME}: ${message}\\n`);\n process.exit(1);\n });\n"],"mappings":"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"}
package/dist/dev-env.cjs CHANGED
@@ -6,7 +6,7 @@
6
6
  * import "@cedarjs/pg/dev-env";
7
7
  * ```
8
8
  */
9
- require("./load-dev-env-cII6N4ZP.cjs").loadDevEnv({ overwrite: true });
9
+ require("./load-dev-env-Bl6Ddv1U.cjs").loadDevEnv({ overwrite: true });
10
10
  //#endregion
11
11
 
12
12
  //# sourceMappingURL=dev-env.cjs.map
package/dist/dev-env.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as loadDevEnv } from "./load-dev-env-7UjMHhw7.mjs";
1
+ import { t as loadDevEnv } from "./load-dev-env-BULkXyen.mjs";
2
2
  //#region src/adapters/dev-env.ts
3
3
  /**
4
4
  * `setupFiles`-style entry: load `.cedarpg/dev.env` with overwrite.
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_lifecycle = require("./lifecycle-DEJ4GgWV.cjs");
3
- const require_constants = require("./constants-Ct8myrEn.cjs");
4
- const require_lease = require("./lease-Bq9wKwQa.cjs");
5
- const require_template = require("./template-D0gJ_MS2.cjs");
6
- const require_load_test_env = require("./load-test-env-CkdUjTpV.cjs");
7
- const require_load_dev_env = require("./load-dev-env-cII6N4ZP.cjs");
2
+ const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
3
+ const require_lease = require("./lease-WlmOnNDi.cjs");
4
+ const require_template = require("./template-CXMpODzK.cjs");
5
+ const require_load_test_env = require("./load-test-env-Dcgh6YHV.cjs");
6
+ const require_load_dev_env = require("./load-dev-env-Bl6Ddv1U.cjs");
7
+ const require_status = require("./status-4Uz6A3LB.cjs");
8
8
  //#region src/adapters/acquire-task.ts
9
9
  /** Run acquireIfNeeded, then optional afterAcquire (migrate / db:ready). */
10
10
  function createAcquireTask(options) {
@@ -28,10 +28,10 @@ function createAcquireTask(options) {
28
28
  };
29
29
  }
30
30
  //#endregion
31
- exports.CLI_NAME = require_constants.CLI_NAME;
31
+ exports.CLI_NAME = require_lease.CLI_NAME;
32
32
  exports.INSTALL_HINT = require_lifecycle.INSTALL_HINT;
33
33
  exports.ROLE_PASSWORD_SCHEME = require_lifecycle.ROLE_PASSWORD_SCHEME;
34
- exports.STATE_DIRNAME = require_constants.STATE_DIRNAME;
34
+ exports.STATE_DIRNAME = require_lease.STATE_DIRNAME;
35
35
  exports.acquire = require_lifecycle.acquire;
36
36
  exports.acquireIfNeeded = require_lifecycle.acquireIfNeeded;
37
37
  exports.applyDatabaseUrlEnv = require_lifecycle.applyDatabaseUrlEnv;
@@ -58,6 +58,7 @@ exports.readLease = require_lease.readLease;
58
58
  exports.requireAutopgBin = require_lifecycle.requireAutopgBin;
59
59
  exports.resolveAcquireSkip = require_lifecycle.resolveAcquireSkip;
60
60
  exports.resolveAutopgBin = require_lifecycle.resolveAutopgBin;
61
+ exports.resolveDevStatus = require_status.resolveDevStatus;
61
62
  exports.resolveRoot = require_lease.resolveRoot;
62
63
  exports.resolveWorktreeIdentity = require_lease.resolveWorktreeIdentity;
63
64
  exports.rolePasswordFor = require_lifecycle.rolePasswordFor;
package/dist/index.d.cts CHANGED
@@ -247,6 +247,26 @@ type CreateAcquireTaskOptions = {
247
247
  /** Run acquireIfNeeded, then optional afterAcquire (migrate / db:ready). */
248
248
  declare function createAcquireTask(options: CreateAcquireTaskOptions): () => Promise<void>;
249
249
  //#endregion
250
+ //#region src/core/status.d.ts
251
+ type ResolveDevStatusOptions = {
252
+ root?: string;
253
+ mode?: DbMode;
254
+ };
255
+ type DevStatus = {
256
+ ok: true;
257
+ mode: DbMode;
258
+ root: string;
259
+ lease: Lease;
260
+ databaseUrl: string;
261
+ envPath: string;
262
+ } | {
263
+ ok: false;
264
+ mode: DbMode;
265
+ root: string;
266
+ };
267
+ /** Read-only lease snapshot for CLI / Vite panel (no acquire, no host). */
268
+ declare function resolveDevStatus(options?: ResolveDevStatusOptions): DevStatus;
269
+ //#endregion
250
270
  //#region src/providers/autopg.d.ts
251
271
  type AutopgDiscovery = {
252
272
  port: number;
@@ -259,13 +279,21 @@ declare const ROLE_PASSWORD_SCHEME: "v2";
259
279
  declare function resolveAutopgBin(): string | null;
260
280
  declare function requireAutopgBin(): string;
261
281
  /**
262
- * Parse `autopg status --json` output. Requires a numeric port and running !== false.
282
+ * Parse `autopg status --json` → the **registered** port. Throws only when the
283
+ * output is not autopg status JSON.
284
+ *
285
+ * Registration is not liveness: autopg reports a port for a stopped host too,
286
+ * and its `status` string is supervisor-specific (pm2 `online`, systemd-user /
287
+ * launchd differ). Liveness is a TCP accept on the port, proven by the caller —
288
+ * `acquire` does that before it connects.
263
289
  */
264
290
  declare function parseHostStatus(json: string): {
265
291
  port: number;
266
292
  };
267
293
  /**
268
- * Discover a live autopg host via `autopg status --json`. Throws if the host is not proven live.
294
+ * Discover the registered autopg host (port + admin URL) via `autopg status --json`.
295
+ * Throws when autopg cannot be queried; does **not** prove a listener — probe TCP
296
+ * (or use `acquire`, which does) before connecting.
269
297
  */
270
298
  declare function discoverHost(bin?: string): AutopgDiscovery;
271
299
  /**
@@ -283,5 +311,5 @@ declare function buildDatabaseUrl(opts: {
283
311
  password?: string;
284
312
  }): string;
285
313
  //#endregion
286
- export { type AcquireIfNeededOptions, type AcquireIfNeededResult, type AcquireOptions, type AcquireResult, type AcquireSkip, type AcquireTaskContext, type AutopgDiscovery, CLI_NAME, type CloneFromTemplateIfNeededOptions, type CloneFromTemplateIfNeededResult, type CloneFromTemplateOptions, type CloneResult, type CreateAcquireTaskOptions, type DbMode, type DisposeOptions, type DisposeResult, INSTALL_HINT, type Lease, type LoadDevEnvOptions, type LoadTestEnvOptions, type MarkTemplateOptions, ROLE_PASSWORD_SCHEME, type ResolveAcquireSkipInput, STATE_DIRNAME, type WorktreeIdentity, acquire, acquireIfNeeded, applyDatabaseUrlEnv, buildCloneDatabaseName, buildDatabaseName, buildDatabaseUrl, buildRoleName, cloneFromTemplate, cloneFromTemplateIfNeeded, createAcquireTask, discoverHost, dispose, envFilePath, gc, isCedarPgManagedUrl, isExternalDatabaseEscapeHatch, isOrphanLease, loadDevEnv, loadTestEnv, markTemplate, parseHostStatus, parseLease, readLease, requireAutopgBin, resolveAcquireSkip, resolveAutopgBin, resolveRoot, resolveWorktreeIdentity, rolePasswordFor, urlFromLease };
314
+ export { type AcquireIfNeededOptions, type AcquireIfNeededResult, type AcquireOptions, type AcquireResult, type AcquireSkip, type AcquireTaskContext, type AutopgDiscovery, CLI_NAME, type CloneFromTemplateIfNeededOptions, type CloneFromTemplateIfNeededResult, type CloneFromTemplateOptions, type CloneResult, type CreateAcquireTaskOptions, type DbMode, type DevStatus, type DisposeOptions, type DisposeResult, INSTALL_HINT, type Lease, type LoadDevEnvOptions, type LoadTestEnvOptions, type MarkTemplateOptions, ROLE_PASSWORD_SCHEME, type ResolveAcquireSkipInput, type ResolveDevStatusOptions, STATE_DIRNAME, type WorktreeIdentity, acquire, acquireIfNeeded, applyDatabaseUrlEnv, buildCloneDatabaseName, buildDatabaseName, buildDatabaseUrl, buildRoleName, cloneFromTemplate, cloneFromTemplateIfNeeded, createAcquireTask, discoverHost, dispose, envFilePath, gc, isCedarPgManagedUrl, isExternalDatabaseEscapeHatch, isOrphanLease, loadDevEnv, loadTestEnv, markTemplate, parseHostStatus, parseLease, readLease, requireAutopgBin, resolveAcquireSkip, resolveAutopgBin, resolveDevStatus, resolveRoot, resolveWorktreeIdentity, rolePasswordFor, urlFromLease };
287
315
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.mts CHANGED
@@ -247,6 +247,26 @@ type CreateAcquireTaskOptions = {
247
247
  /** Run acquireIfNeeded, then optional afterAcquire (migrate / db:ready). */
248
248
  declare function createAcquireTask(options: CreateAcquireTaskOptions): () => Promise<void>;
249
249
  //#endregion
250
+ //#region src/core/status.d.ts
251
+ type ResolveDevStatusOptions = {
252
+ root?: string;
253
+ mode?: DbMode;
254
+ };
255
+ type DevStatus = {
256
+ ok: true;
257
+ mode: DbMode;
258
+ root: string;
259
+ lease: Lease;
260
+ databaseUrl: string;
261
+ envPath: string;
262
+ } | {
263
+ ok: false;
264
+ mode: DbMode;
265
+ root: string;
266
+ };
267
+ /** Read-only lease snapshot for CLI / Vite panel (no acquire, no host). */
268
+ declare function resolveDevStatus(options?: ResolveDevStatusOptions): DevStatus;
269
+ //#endregion
250
270
  //#region src/providers/autopg.d.ts
251
271
  type AutopgDiscovery = {
252
272
  port: number;
@@ -259,13 +279,21 @@ declare const ROLE_PASSWORD_SCHEME: "v2";
259
279
  declare function resolveAutopgBin(): string | null;
260
280
  declare function requireAutopgBin(): string;
261
281
  /**
262
- * Parse `autopg status --json` output. Requires a numeric port and running !== false.
282
+ * Parse `autopg status --json` → the **registered** port. Throws only when the
283
+ * output is not autopg status JSON.
284
+ *
285
+ * Registration is not liveness: autopg reports a port for a stopped host too,
286
+ * and its `status` string is supervisor-specific (pm2 `online`, systemd-user /
287
+ * launchd differ). Liveness is a TCP accept on the port, proven by the caller —
288
+ * `acquire` does that before it connects.
263
289
  */
264
290
  declare function parseHostStatus(json: string): {
265
291
  port: number;
266
292
  };
267
293
  /**
268
- * Discover a live autopg host via `autopg status --json`. Throws if the host is not proven live.
294
+ * Discover the registered autopg host (port + admin URL) via `autopg status --json`.
295
+ * Throws when autopg cannot be queried; does **not** prove a listener — probe TCP
296
+ * (or use `acquire`, which does) before connecting.
269
297
  */
270
298
  declare function discoverHost(bin?: string): AutopgDiscovery;
271
299
  /**
@@ -283,5 +311,5 @@ declare function buildDatabaseUrl(opts: {
283
311
  password?: string;
284
312
  }): string;
285
313
  //#endregion
286
- export { type AcquireIfNeededOptions, type AcquireIfNeededResult, type AcquireOptions, type AcquireResult, type AcquireSkip, type AcquireTaskContext, type AutopgDiscovery, CLI_NAME, type CloneFromTemplateIfNeededOptions, type CloneFromTemplateIfNeededResult, type CloneFromTemplateOptions, type CloneResult, type CreateAcquireTaskOptions, type DbMode, type DisposeOptions, type DisposeResult, INSTALL_HINT, type Lease, type LoadDevEnvOptions, type LoadTestEnvOptions, type MarkTemplateOptions, ROLE_PASSWORD_SCHEME, type ResolveAcquireSkipInput, STATE_DIRNAME, type WorktreeIdentity, acquire, acquireIfNeeded, applyDatabaseUrlEnv, buildCloneDatabaseName, buildDatabaseName, buildDatabaseUrl, buildRoleName, cloneFromTemplate, cloneFromTemplateIfNeeded, createAcquireTask, discoverHost, dispose, envFilePath, gc, isCedarPgManagedUrl, isExternalDatabaseEscapeHatch, isOrphanLease, loadDevEnv, loadTestEnv, markTemplate, parseHostStatus, parseLease, readLease, requireAutopgBin, resolveAcquireSkip, resolveAutopgBin, resolveRoot, resolveWorktreeIdentity, rolePasswordFor, urlFromLease };
314
+ export { type AcquireIfNeededOptions, type AcquireIfNeededResult, type AcquireOptions, type AcquireResult, type AcquireSkip, type AcquireTaskContext, type AutopgDiscovery, CLI_NAME, type CloneFromTemplateIfNeededOptions, type CloneFromTemplateIfNeededResult, type CloneFromTemplateOptions, type CloneResult, type CreateAcquireTaskOptions, type DbMode, type DevStatus, type DisposeOptions, type DisposeResult, INSTALL_HINT, type Lease, type LoadDevEnvOptions, type LoadTestEnvOptions, type MarkTemplateOptions, ROLE_PASSWORD_SCHEME, type ResolveAcquireSkipInput, type ResolveDevStatusOptions, STATE_DIRNAME, type WorktreeIdentity, acquire, acquireIfNeeded, applyDatabaseUrlEnv, buildCloneDatabaseName, buildDatabaseName, buildDatabaseUrl, buildRoleName, cloneFromTemplate, cloneFromTemplateIfNeeded, createAcquireTask, discoverHost, dispose, envFilePath, gc, isCedarPgManagedUrl, isExternalDatabaseEscapeHatch, isOrphanLease, loadDevEnv, loadTestEnv, markTemplate, parseHostStatus, parseLease, readLease, requireAutopgBin, resolveAcquireSkip, resolveAutopgBin, resolveDevStatus, resolveRoot, resolveWorktreeIdentity, rolePasswordFor, urlFromLease };
287
315
  //# sourceMappingURL=index.d.mts.map