@cedarjs/pg 0.2.0-beta.0 → 0.3.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 (87) hide show
  1. package/README.md +112 -63
  2. package/dist/cli.cjs +15 -9
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.mjs +15 -9
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/index.cjs +3 -3
  7. package/dist/index.d.cts +54 -11
  8. package/dist/index.d.mts +54 -11
  9. package/dist/index.mjs +3 -3
  10. package/dist/jest-teardown.cjs +1 -1
  11. package/dist/jest-teardown.mjs +1 -1
  12. package/dist/jest-template.cjs +5 -3
  13. package/dist/jest-template.cjs.map +1 -1
  14. package/dist/jest-template.d.cts +5 -3
  15. package/dist/jest-template.d.mts +5 -3
  16. package/dist/jest-template.mjs +5 -3
  17. package/dist/jest-template.mjs.map +1 -1
  18. package/dist/jest.cjs +1 -1
  19. package/dist/jest.mjs +1 -1
  20. package/dist/{lifecycle-BvIx0xqq.mjs → lifecycle-2BZgSVz2.mjs} +423 -132
  21. package/dist/lifecycle-2BZgSVz2.mjs.map +1 -0
  22. package/dist/{lifecycle-BbrvFQvg.cjs → lifecycle-BCeM96tI.cjs} +438 -135
  23. package/dist/lifecycle-BCeM96tI.cjs.map +1 -0
  24. package/dist/{naming-C2nGVxPk.d.cts → naming-Df4fz_Fb.d.cts} +3 -2
  25. package/dist/{naming-C2nGVxPk.d.mts → naming-Df4fz_Fb.d.mts} +3 -2
  26. package/dist/{status-Dcnpgnlz.mjs → status-B68SGSKx.mjs} +2 -2
  27. package/dist/{status-Dcnpgnlz.mjs.map → status-B68SGSKx.mjs.map} +1 -1
  28. package/dist/{status-4Uz6A3LB.cjs → status-Z_BYdxzI.cjs} +2 -2
  29. package/dist/{status-4Uz6A3LB.cjs.map → status-Z_BYdxzI.cjs.map} +1 -1
  30. package/dist/{studio-DIFw1qWC.mjs → studio-Bi6SU9jE.mjs} +54 -6
  31. package/dist/studio-Bi6SU9jE.mjs.map +1 -0
  32. package/dist/{studio-oJE30_PO.cjs → studio-CdWIdnxr.cjs} +78 -6
  33. package/dist/studio-CdWIdnxr.cjs.map +1 -0
  34. package/dist/{template-CXMpODzK.cjs → template-Cd77H7Cr.cjs} +21 -18
  35. package/dist/template-Cd77H7Cr.cjs.map +1 -0
  36. package/dist/{template-BiJ-0TIF.mjs → template-DlqHL8Go.mjs} +21 -18
  37. package/dist/template-DlqHL8Go.mjs.map +1 -0
  38. package/dist/template-mode-BqV3GjXI.d.cts +48 -0
  39. package/dist/template-mode-BqV3GjXI.d.mts +48 -0
  40. package/dist/template-mode-DK5cAlv9.mjs +81 -0
  41. package/dist/template-mode-DK5cAlv9.mjs.map +1 -0
  42. package/dist/template-mode-DMO5-z7O.cjs +92 -0
  43. package/dist/template-mode-DMO5-z7O.cjs.map +1 -0
  44. package/dist/vite-plus.cjs +9 -9
  45. package/dist/vite-plus.cjs.map +1 -1
  46. package/dist/vite-plus.d.cts +17 -2
  47. package/dist/vite-plus.d.mts +17 -2
  48. package/dist/vite-plus.mjs +5 -5
  49. package/dist/vite-plus.mjs.map +1 -1
  50. package/dist/vitest-template.cjs +6 -3
  51. package/dist/vitest-template.cjs.map +1 -1
  52. package/dist/vitest-template.d.cts +6 -3
  53. package/dist/vitest-template.d.mts +6 -3
  54. package/dist/vitest-template.mjs +6 -3
  55. package/dist/vitest-template.mjs.map +1 -1
  56. package/dist/vitest.cjs +1 -1
  57. package/dist/vitest.mjs +1 -1
  58. package/package.json +2 -7
  59. package/scripts/autopg-version +1 -1
  60. package/scripts/ci-install-autopg.sh +7 -2
  61. package/scripts/postinstall.js +41 -13
  62. package/dist/lease-B3TuX92y.d.mts +0 -24
  63. package/dist/lease-t4I9JahV.d.cts +0 -24
  64. package/dist/lifecycle-BbrvFQvg.cjs.map +0 -1
  65. package/dist/lifecycle-BvIx0xqq.mjs.map +0 -1
  66. package/dist/nx.cjs +0 -42
  67. package/dist/nx.cjs.map +0 -1
  68. package/dist/nx.d.cts +0 -15
  69. package/dist/nx.d.mts +0 -15
  70. package/dist/nx.mjs +0 -34
  71. package/dist/nx.mjs.map +0 -1
  72. package/dist/studio-DIFw1qWC.mjs.map +0 -1
  73. package/dist/studio-oJE30_PO.cjs.map +0 -1
  74. package/dist/tasks-CNHvvlsN.cjs +0 -67
  75. package/dist/tasks-CNHvvlsN.cjs.map +0 -1
  76. package/dist/tasks-CjaZRi_G.d.mts +0 -19
  77. package/dist/tasks-D5iWIdlo.mjs +0 -38
  78. package/dist/tasks-D5iWIdlo.mjs.map +0 -1
  79. package/dist/tasks-DdQoP9We.d.cts +0 -19
  80. package/dist/template-BiJ-0TIF.mjs.map +0 -1
  81. package/dist/template-CXMpODzK.cjs.map +0 -1
  82. package/dist/template-mode-BTUsdBtA.mjs +0 -94
  83. package/dist/template-mode-BTUsdBtA.mjs.map +0 -1
  84. package/dist/template-mode-CzyVwHsi.d.cts +0 -31
  85. package/dist/template-mode-CzyVwHsi.d.mts +0 -31
  86. package/dist/template-mode-JTOxrEgE.cjs +0 -105
  87. package/dist/template-mode-JTOxrEgE.cjs.map +0 -1
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 { 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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"}
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, attach, 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>] [--json] [--print-env]\n ${CLI_NAME} run --mode=dev|test [--root <path>] [--force] [--attach] -- <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 --attach reads the existing lease instead: no acquire, no role/DB DDL, fails\n when there is no lease or the host is not listening. Use it for children that\n run after one db:ready (safe to run concurrently).\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 attach?: 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 === \"--attach\") out.attach = 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 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 { databaseUrl } = args.attach\n ? await attach({ root: args.root, mode })\n : await acquire({ root: args.root, mode, setEnv: true });\n const childEnv: NodeJS.ProcessEnv = {\n ...process.env,\n DATABASE_URL: databaseUrl,\n };\n if (mode === \"test\") childEnv.TEST_DATABASE_URL = 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/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
2
+ const require_lifecycle = require("./lifecycle-BCeM96tI.cjs");
3
3
  const require_lease = require("./lease-WlmOnNDi.cjs");
4
- const require_template = require("./template-CXMpODzK.cjs");
4
+ const require_template = require("./template-Cd77H7Cr.cjs");
5
5
  const require_load_test_env = require("./load-test-env-Dcgh6YHV.cjs");
6
6
  const require_load_dev_env = require("./load-dev-env-Bl6Ddv1U.cjs");
7
- const require_status = require("./status-4Uz6A3LB.cjs");
7
+ const require_status = require("./status-Z_BYdxzI.cjs");
8
8
  //#region src/adapters/acquire-task.ts
9
9
  /** Run acquireIfNeeded, then optional afterAcquire (migrate / db:ready). */
10
10
  function createAcquireTask(options) {
package/dist/index.d.cts CHANGED
@@ -1,5 +1,25 @@
1
- import { a as WorktreeIdentity, i as buildRoleName, n as buildCloneDatabaseName, o as resolveRoot, r as buildDatabaseName, s as resolveWorktreeIdentity, t as DbMode } from "./naming-C2nGVxPk.cjs";
2
- import { a as readLease, i as parseLease, n as envFilePath, r as isOrphanLease, t as Lease } from "./lease-t4I9JahV.cjs";
1
+ import { a as WorktreeIdentity, i as buildRoleName, n as buildCloneDatabaseName, o as resolveRoot, r as buildDatabaseName, s as resolveWorktreeIdentity, t as DbMode } from "./naming-Df4fz_Fb.cjs";
2
+ //#region src/core/lease.d.ts
3
+ type Lease = {
4
+ schemaVersion: 1;
5
+ mode: DbMode;
6
+ root: string;
7
+ repoSlug: string;
8
+ worktreeSlug: string;
9
+ pathHash: string;
10
+ databaseName: string;
11
+ roleName: string;
12
+ port: number;
13
+ pid: number;
14
+ createdAt: string;
15
+ };
16
+ /** Narrow-parse a lease; reject incomplete or wrong-version records. */
17
+ declare function parseLease(raw: unknown): Lease | null;
18
+ /** Absolute `.cedarpg/<mode>.env` path (resolves root when omitted). */
19
+ declare function envFilePath(root: string | undefined, mode: DbMode): string;
20
+ declare function readLease(root: string, mode: DbMode): Lease | null;
21
+ declare function isOrphanLease(lease: Lease): boolean;
22
+ //#endregion
3
23
  //#region src/core/policy.d.ts
4
24
  /**
5
25
  * Shared acquire skip policy for test-runner adapters and Cedar CLI bridges.
@@ -58,6 +78,14 @@ type AcquireOptions = {
58
78
  mode: DbMode;
59
79
  /** Inject DATABASE_URL / TEST_DATABASE_URL into process.env (default true). */
60
80
  setEnv?: boolean;
81
+ /**
82
+ * Start from an empty database (default false): first DROP every database
83
+ * owned by this worktree's role for `mode` — the leased DB, TEMPLATE clones,
84
+ * crashed-run leftovers — then create it again. Scoped by the role (the
85
+ * lease's when it is for this database, else the derived name), so it works
86
+ * without a lease file and never touches other worktrees.
87
+ */
88
+ fresh?: boolean;
61
89
  };
62
90
  type AcquireResult = {
63
91
  databaseUrl: string;
@@ -128,7 +156,7 @@ declare function gc(): Promise<{
128
156
  type MarkTemplateOptions = {
129
157
  root?: string;
130
158
  mode: DbMode;
131
- /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */
159
+ /** Superuser URL from `acquire`; when omitted, built from the lease port (never starts the host). */
132
160
  adminUrl?: string;
133
161
  };
134
162
  /**
@@ -142,13 +170,19 @@ declare function markTemplate(options: MarkTemplateOptions): Promise<{
142
170
  type CloneFromTemplateOptions = {
143
171
  root?: string;
144
172
  mode: DbMode;
145
- /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */
173
+ /** Superuser URL from `acquire`; when omitted, built from the lease port (never starts the host). */
146
174
  adminUrl?: string;
147
175
  /**
148
176
  * Suffix for the clone datname (e.g. Jest worker id).
149
177
  * Defaults to `<pid>_<base36 time>`.
150
178
  */
151
179
  name?: string;
180
+ /**
181
+ * Keep an existing `<template>_c_<name>` owned by the lease role instead of
182
+ * failing with `database already exists` (default false). Worker adapters pass
183
+ * true so every test file in one worker attaches to the same clone.
184
+ */
185
+ reuse?: boolean;
152
186
  /**
153
187
  * Inject DATABASE_URL / TEST_DATABASE_URL for this clone (default false).
154
188
  * Host `cloneFromTemplateIfNeeded` defaults true; worker adapters pass true explicitly.
@@ -172,7 +206,9 @@ type CloneResult = {
172
206
  * Clone the leased TEMPLATE database via admin (`CREATE DATABASE … TEMPLATE`).
173
207
  * Reuses the template role so `databaseUrl` passwords stay valid (scheme v2).
174
208
  * Provider rejects when the leased DB is not marked TEMPLATE.
175
- * Port comes from the lease; admin URL is passed through or rediscovered.
209
+ * Port comes from the lease; admin URL is passed through or built from the lease
210
+ * port. Fails when nothing listens there (setup should have acquired).
211
+ * An existing clone datname fails unless `reuse` is set and the lease role owns it.
176
212
  */
177
213
  declare function cloneFromTemplate(options: CloneFromTemplateOptions): Promise<CloneResult>;
178
214
  type CloneFromTemplateIfNeededOptions = CloneFromTemplateOptions & ResolveAcquireSkipInput;
@@ -273,21 +309,28 @@ type AutopgDiscovery = {
273
309
  adminUrl: string;
274
310
  bin: string;
275
311
  };
312
+ type HostStatusPaths = {
313
+ dataDir?: string;
314
+ socketDir?: string;
315
+ logsDir?: string;
316
+ };
276
317
  declare const INSTALL_HINT: string;
277
318
  /** Password scheme v2: sha256(PASSWORD_SALT_PREFIX + "\\0" + roleName) hex[:32]. Frozen for URL rebuild. */
278
319
  declare const ROLE_PASSWORD_SCHEME: "v2";
279
320
  declare function resolveAutopgBin(): string | null;
280
321
  declare function requireAutopgBin(): string;
281
322
  /**
282
- * Parse `autopg status --json` → the **registered** port. Throws only when the
283
- * output is not autopg status JSON.
323
+ * Parse `autopg status --json` → the **registered** port (and data/socket/logs
324
+ * dirs when present). Throws only when the output is not autopg status JSON.
284
325
  *
285
326
  * 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.
327
+ * and its `status` / `ready` describe the supervisor (autopg ≥ v3.2: `ready` needs
328
+ * pm2 `online`; pm2's raw state is `supervisorStatus`). Neither, nor `runtime.live`,
329
+ * is the attach gate — a bare postmaster (e.g. one cedar-pg revived) is
330
+ * query-ready while status stays `stopped` / `ready: false`.
331
+ * Liveness is a TCP accept on the port, proven by the caller (`acquire`).
289
332
  */
290
- declare function parseHostStatus(json: string): {
333
+ declare function parseHostStatus(json: string): HostStatusPaths & {
291
334
  port: number;
292
335
  };
293
336
  /**
package/dist/index.d.mts CHANGED
@@ -1,5 +1,25 @@
1
- import { a as WorktreeIdentity, i as buildRoleName, n as buildCloneDatabaseName, o as resolveRoot, r as buildDatabaseName, s as resolveWorktreeIdentity, t as DbMode } from "./naming-C2nGVxPk.mjs";
2
- import { a as readLease, i as parseLease, n as envFilePath, r as isOrphanLease, t as Lease } from "./lease-B3TuX92y.mjs";
1
+ import { a as WorktreeIdentity, i as buildRoleName, n as buildCloneDatabaseName, o as resolveRoot, r as buildDatabaseName, s as resolveWorktreeIdentity, t as DbMode } from "./naming-Df4fz_Fb.mjs";
2
+ //#region src/core/lease.d.ts
3
+ type Lease = {
4
+ schemaVersion: 1;
5
+ mode: DbMode;
6
+ root: string;
7
+ repoSlug: string;
8
+ worktreeSlug: string;
9
+ pathHash: string;
10
+ databaseName: string;
11
+ roleName: string;
12
+ port: number;
13
+ pid: number;
14
+ createdAt: string;
15
+ };
16
+ /** Narrow-parse a lease; reject incomplete or wrong-version records. */
17
+ declare function parseLease(raw: unknown): Lease | null;
18
+ /** Absolute `.cedarpg/<mode>.env` path (resolves root when omitted). */
19
+ declare function envFilePath(root: string | undefined, mode: DbMode): string;
20
+ declare function readLease(root: string, mode: DbMode): Lease | null;
21
+ declare function isOrphanLease(lease: Lease): boolean;
22
+ //#endregion
3
23
  //#region src/core/policy.d.ts
4
24
  /**
5
25
  * Shared acquire skip policy for test-runner adapters and Cedar CLI bridges.
@@ -58,6 +78,14 @@ type AcquireOptions = {
58
78
  mode: DbMode;
59
79
  /** Inject DATABASE_URL / TEST_DATABASE_URL into process.env (default true). */
60
80
  setEnv?: boolean;
81
+ /**
82
+ * Start from an empty database (default false): first DROP every database
83
+ * owned by this worktree's role for `mode` — the leased DB, TEMPLATE clones,
84
+ * crashed-run leftovers — then create it again. Scoped by the role (the
85
+ * lease's when it is for this database, else the derived name), so it works
86
+ * without a lease file and never touches other worktrees.
87
+ */
88
+ fresh?: boolean;
61
89
  };
62
90
  type AcquireResult = {
63
91
  databaseUrl: string;
@@ -128,7 +156,7 @@ declare function gc(): Promise<{
128
156
  type MarkTemplateOptions = {
129
157
  root?: string;
130
158
  mode: DbMode;
131
- /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */
159
+ /** Superuser URL from `acquire`; when omitted, built from the lease port (never starts the host). */
132
160
  adminUrl?: string;
133
161
  };
134
162
  /**
@@ -142,13 +170,19 @@ declare function markTemplate(options: MarkTemplateOptions): Promise<{
142
170
  type CloneFromTemplateOptions = {
143
171
  root?: string;
144
172
  mode: DbMode;
145
- /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */
173
+ /** Superuser URL from `acquire`; when omitted, built from the lease port (never starts the host). */
146
174
  adminUrl?: string;
147
175
  /**
148
176
  * Suffix for the clone datname (e.g. Jest worker id).
149
177
  * Defaults to `<pid>_<base36 time>`.
150
178
  */
151
179
  name?: string;
180
+ /**
181
+ * Keep an existing `<template>_c_<name>` owned by the lease role instead of
182
+ * failing with `database already exists` (default false). Worker adapters pass
183
+ * true so every test file in one worker attaches to the same clone.
184
+ */
185
+ reuse?: boolean;
152
186
  /**
153
187
  * Inject DATABASE_URL / TEST_DATABASE_URL for this clone (default false).
154
188
  * Host `cloneFromTemplateIfNeeded` defaults true; worker adapters pass true explicitly.
@@ -172,7 +206,9 @@ type CloneResult = {
172
206
  * Clone the leased TEMPLATE database via admin (`CREATE DATABASE … TEMPLATE`).
173
207
  * Reuses the template role so `databaseUrl` passwords stay valid (scheme v2).
174
208
  * Provider rejects when the leased DB is not marked TEMPLATE.
175
- * Port comes from the lease; admin URL is passed through or rediscovered.
209
+ * Port comes from the lease; admin URL is passed through or built from the lease
210
+ * port. Fails when nothing listens there (setup should have acquired).
211
+ * An existing clone datname fails unless `reuse` is set and the lease role owns it.
176
212
  */
177
213
  declare function cloneFromTemplate(options: CloneFromTemplateOptions): Promise<CloneResult>;
178
214
  type CloneFromTemplateIfNeededOptions = CloneFromTemplateOptions & ResolveAcquireSkipInput;
@@ -273,21 +309,28 @@ type AutopgDiscovery = {
273
309
  adminUrl: string;
274
310
  bin: string;
275
311
  };
312
+ type HostStatusPaths = {
313
+ dataDir?: string;
314
+ socketDir?: string;
315
+ logsDir?: string;
316
+ };
276
317
  declare const INSTALL_HINT: string;
277
318
  /** Password scheme v2: sha256(PASSWORD_SALT_PREFIX + "\\0" + roleName) hex[:32]. Frozen for URL rebuild. */
278
319
  declare const ROLE_PASSWORD_SCHEME: "v2";
279
320
  declare function resolveAutopgBin(): string | null;
280
321
  declare function requireAutopgBin(): string;
281
322
  /**
282
- * Parse `autopg status --json` → the **registered** port. Throws only when the
283
- * output is not autopg status JSON.
323
+ * Parse `autopg status --json` → the **registered** port (and data/socket/logs
324
+ * dirs when present). Throws only when the output is not autopg status JSON.
284
325
  *
285
326
  * 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.
327
+ * and its `status` / `ready` describe the supervisor (autopg ≥ v3.2: `ready` needs
328
+ * pm2 `online`; pm2's raw state is `supervisorStatus`). Neither, nor `runtime.live`,
329
+ * is the attach gate — a bare postmaster (e.g. one cedar-pg revived) is
330
+ * query-ready while status stays `stopped` / `ready: false`.
331
+ * Liveness is a TCP accept on the port, proven by the caller (`acquire`).
289
332
  */
290
- declare function parseHostStatus(json: string): {
333
+ declare function parseHostStatus(json: string): HostStatusPaths & {
291
334
  port: number;
292
335
  };
293
336
  /**
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { C as buildCloneDatabaseName, T as buildRoleName, a as urlFromLease, b as isExternalDatabaseEscapeHatch, c as ROLE_PASSWORD_SCHEME, d as discoverHost, g as rolePasswordFor, h as resolveAutopgBin, i as gc, l as buildDatabaseUrl, m as requireAutopgBin, n as acquireIfNeeded, p as parseHostStatus, r as dispose, s as INSTALL_HINT, t as acquire, v as applyDatabaseUrlEnv, w as buildDatabaseName, x as resolveAcquireSkip, y as isCedarPgManagedUrl } from "./lifecycle-BvIx0xqq.mjs";
2
1
  import { c as parseLease, d as resolveRoot, f as resolveWorktreeIdentity, h as STATE_DIRNAME, i as isOrphanLease, l as readLease, p as CLI_NAME, t as envFilePath } from "./lease-DS1SX8U_.mjs";
3
- import { n as cloneFromTemplateIfNeeded, r as markTemplate, t as cloneFromTemplate } from "./template-BiJ-0TIF.mjs";
2
+ import { C as resolveAcquireSkip, D as buildRoleName, E as buildDatabaseName, S as isExternalDatabaseEscapeHatch, T as buildCloneDatabaseName, _ as rolePasswordFor, a as gc, b as applyDatabaseUrlEnv, c as ROLE_PASSWORD_SCHEME, f as discoverHost, g as resolveAutopgBin, h as requireAutopgBin, i as dispose, m as parseHostStatus, n as acquireIfNeeded, o as urlFromLease, s as INSTALL_HINT, t as acquire, u as buildDatabaseUrl, x as isCedarPgManagedUrl } from "./lifecycle-2BZgSVz2.mjs";
3
+ import { n as cloneFromTemplateIfNeeded, r as markTemplate, t as cloneFromTemplate } from "./template-DlqHL8Go.mjs";
4
4
  import { t as loadTestEnv } from "./load-test-env-BqtA6V-d.mjs";
5
5
  import { t as loadDevEnv } from "./load-dev-env-BULkXyen.mjs";
6
- import { t as resolveDevStatus } from "./status-Dcnpgnlz.mjs";
6
+ import { t as resolveDevStatus } from "./status-B68SGSKx.mjs";
7
7
  //#region src/adapters/acquire-task.ts
8
8
  /** Run acquireIfNeeded, then optional afterAcquire (migrate / db:ready). */
9
9
  function createAcquireTask(options) {
@@ -1,4 +1,4 @@
1
- const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
1
+ const require_lifecycle = require("./lifecycle-BCeM96tI.cjs");
2
2
  //#region src/adapters/jest-teardown.ts
3
3
  /**
4
4
  * Jest `globalTeardown` entry (default export).
@@ -1,4 +1,4 @@
1
- import { r as dispose } from "./lifecycle-BvIx0xqq.mjs";
1
+ import { i as dispose } from "./lifecycle-2BZgSVz2.mjs";
2
2
  //#region src/adapters/jest-teardown.ts
3
3
  /**
4
4
  * Jest `globalTeardown` entry (default export).
@@ -2,10 +2,11 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_template_mode = require("./template-mode-JTOxrEgE.cjs");
5
+ const require_template_mode = require("./template-mode-DMO5-z7O.cjs");
6
6
  //#region src/adapters/jest-template.ts
7
7
  /**
8
- * Jest globalSetup (template mode).
8
+ * Jest globalSetup (template mode). Drops crashed-run leftovers under this
9
+ * worktree's test role, then acquire → migrate → markTemplate.
9
10
  *
10
11
  * ```js
11
12
  * // jest.cedar-global.cjs
@@ -17,7 +18,8 @@ const require_template_mode = require("./template-mode-JTOxrEgE.cjs");
17
18
  * // process.env.CEDAR_PG_FORCE = "1";
18
19
  * globalSetup: "<rootDir>/jest.cedar-global.cjs",
19
20
  * globalTeardown: require.resolve("@cedarjs/pg/jest-teardown"),
20
- * // Prefer setupFilesAfterEnv + beforeAll; setupFiles also works (memo is process-scoped).
21
+ * // Runs per test file; every file in a worker reuses that worker's clone,
22
+ * // truncated with RESTART IDENTITY first (`cloneWorkerDatabase({ reset: "none" })` opts out).
21
23
  * setupFilesAfterEnv: ["<rootDir>/jest.cedar-worker.cjs"],
22
24
  *
23
25
  * // jest.cedar-worker.cjs
@@ -1 +1 @@
1
- {"version":3,"file":"jest-template.cjs","names":["setupTemplateMode"],"sources":["../src/adapters/jest-template.ts"],"sourcesContent":["import {\n cloneWorkerDatabase,\n setupTemplateMode,\n type SetupTemplateModeOptions,\n} from \"./template-mode.ts\";\n\nexport { cloneWorkerDatabase };\nexport type {\n SetupTemplateModeOptions,\n TemplateMigrateFn,\n TemplateMigrateContext,\n} from \"./template-mode.ts\";\n\n/**\n * Jest globalSetup (template mode).\n *\n * ```js\n * // jest.cedar-global.cjs\n * const { createGlobalSetup } = require(\"@cedarjs/pg/jest/template\");\n * module.exports = createGlobalSetup({ migrate: async ({ databaseUrl }) => {} });\n *\n * // jest.config.cjs\n * // When .env has a real TEST_DATABASE_URL, set once here (inherits to workers):\n * // process.env.CEDAR_PG_FORCE = \"1\";\n * globalSetup: \"<rootDir>/jest.cedar-global.cjs\",\n * globalTeardown: require.resolve(\"@cedarjs/pg/jest-teardown\"),\n * // Prefer setupFilesAfterEnv + beforeAll; setupFiles also works (memo is process-scoped).\n * setupFilesAfterEnv: [\"<rootDir>/jest.cedar-worker.cjs\"],\n *\n * // jest.cedar-worker.cjs\n * const { cloneWorkerDatabase } = require(\"@cedarjs/pg/jest/template\");\n * beforeAll(() => cloneWorkerDatabase());\n * ```\n *\n * Stock `@cedarjs/pg/jest` is one shared test DB only.\n */\nexport function createGlobalSetup(options: SetupTemplateModeOptions) {\n return async () => {\n await setupTemplateMode(options);\n };\n}\n\n/** String `require.resolve` without a migrate hook is unsupported — use `createGlobalSetup`. */\nexport default async function globalSetup(): Promise<void> {\n throw new Error(\n \"@cedarjs/pg/jest/template requires createGlobalSetup({ migrate }). \" +\n \"Point globalSetup at a local module that exports createGlobalSetup({ migrate }).\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,kBAAkB,SAAmC;CACnE,OAAO,YAAY;EACjB,MAAMA,sBAAAA,kBAAkB,OAAO;CACjC;AACF;;AAGA,eAA8B,cAA6B;CACzD,MAAM,IAAI,MACR,qJAEF;AACF"}
1
+ {"version":3,"file":"jest-template.cjs","names":["setupTemplateMode"],"sources":["../src/adapters/jest-template.ts"],"sourcesContent":["import {\n cloneWorkerDatabase,\n setupTemplateMode,\n type SetupTemplateModeOptions,\n} from \"./template-mode.ts\";\n\nexport { cloneWorkerDatabase };\nexport type {\n SetupTemplateModeOptions,\n TemplateMigrateFn,\n TemplateMigrateContext,\n} from \"./template-mode.ts\";\n\n/**\n * Jest globalSetup (template mode). Drops crashed-run leftovers under this\n * worktree's test role, then acquire → migrate → markTemplate.\n *\n * ```js\n * // jest.cedar-global.cjs\n * const { createGlobalSetup } = require(\"@cedarjs/pg/jest/template\");\n * module.exports = createGlobalSetup({ migrate: async ({ databaseUrl }) => {} });\n *\n * // jest.config.cjs\n * // When .env has a real TEST_DATABASE_URL, set once here (inherits to workers):\n * // process.env.CEDAR_PG_FORCE = \"1\";\n * globalSetup: \"<rootDir>/jest.cedar-global.cjs\",\n * globalTeardown: require.resolve(\"@cedarjs/pg/jest-teardown\"),\n * // Runs per test file; every file in a worker reuses that worker's clone,\n * // truncated with RESTART IDENTITY first (`cloneWorkerDatabase({ reset: \"none\" })` opts out).\n * setupFilesAfterEnv: [\"<rootDir>/jest.cedar-worker.cjs\"],\n *\n * // jest.cedar-worker.cjs\n * const { cloneWorkerDatabase } = require(\"@cedarjs/pg/jest/template\");\n * beforeAll(() => cloneWorkerDatabase());\n * ```\n *\n * Stock `@cedarjs/pg/jest` is one shared test DB only.\n */\nexport function createGlobalSetup(options: SetupTemplateModeOptions) {\n return async () => {\n await setupTemplateMode(options);\n };\n}\n\n/** String `require.resolve` without a migrate hook is unsupported — use `createGlobalSetup`. */\nexport default async function globalSetup(): Promise<void> {\n throw new Error(\n \"@cedarjs/pg/jest/template requires createGlobalSetup({ migrate }). \" +\n \"Point globalSetup at a local module that exports createGlobalSetup({ migrate }).\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,kBAAkB,SAAmC;CACnE,OAAO,YAAY;EACjB,MAAMA,sBAAAA,kBAAkB,OAAO;CACjC;AACF;;AAGA,eAA8B,cAA6B;CACzD,MAAM,IAAI,MACR,qJAEF;AACF"}
@@ -1,7 +1,8 @@
1
- import { i as cloneWorkerDatabase, n as TemplateMigrateContext, r as TemplateMigrateFn, t as SetupTemplateModeOptions } from "./template-mode-CzyVwHsi.cjs";
1
+ import { i as cloneWorkerDatabase, n as TemplateMigrateContext, r as TemplateMigrateFn, t as SetupTemplateModeOptions } from "./template-mode-BqV3GjXI.cjs";
2
2
  //#region src/adapters/jest-template.d.ts
3
3
  /**
4
- * Jest globalSetup (template mode).
4
+ * Jest globalSetup (template mode). Drops crashed-run leftovers under this
5
+ * worktree's test role, then acquire → migrate → markTemplate.
5
6
  *
6
7
  * ```js
7
8
  * // jest.cedar-global.cjs
@@ -13,7 +14,8 @@ import { i as cloneWorkerDatabase, n as TemplateMigrateContext, r as TemplateMig
13
14
  * // process.env.CEDAR_PG_FORCE = "1";
14
15
  * globalSetup: "<rootDir>/jest.cedar-global.cjs",
15
16
  * globalTeardown: require.resolve("@cedarjs/pg/jest-teardown"),
16
- * // Prefer setupFilesAfterEnv + beforeAll; setupFiles also works (memo is process-scoped).
17
+ * // Runs per test file; every file in a worker reuses that worker's clone,
18
+ * // truncated with RESTART IDENTITY first (`cloneWorkerDatabase({ reset: "none" })` opts out).
17
19
  * setupFilesAfterEnv: ["<rootDir>/jest.cedar-worker.cjs"],
18
20
  *
19
21
  * // jest.cedar-worker.cjs
@@ -1,7 +1,8 @@
1
- import { i as cloneWorkerDatabase, n as TemplateMigrateContext, r as TemplateMigrateFn, t as SetupTemplateModeOptions } from "./template-mode-CzyVwHsi.mjs";
1
+ import { i as cloneWorkerDatabase, n as TemplateMigrateContext, r as TemplateMigrateFn, t as SetupTemplateModeOptions } from "./template-mode-BqV3GjXI.mjs";
2
2
  //#region src/adapters/jest-template.d.ts
3
3
  /**
4
- * Jest globalSetup (template mode).
4
+ * Jest globalSetup (template mode). Drops crashed-run leftovers under this
5
+ * worktree's test role, then acquire → migrate → markTemplate.
5
6
  *
6
7
  * ```js
7
8
  * // jest.cedar-global.cjs
@@ -13,7 +14,8 @@ import { i as cloneWorkerDatabase, n as TemplateMigrateContext, r as TemplateMig
13
14
  * // process.env.CEDAR_PG_FORCE = "1";
14
15
  * globalSetup: "<rootDir>/jest.cedar-global.cjs",
15
16
  * globalTeardown: require.resolve("@cedarjs/pg/jest-teardown"),
16
- * // Prefer setupFilesAfterEnv + beforeAll; setupFiles also works (memo is process-scoped).
17
+ * // Runs per test file; every file in a worker reuses that worker's clone,
18
+ * // truncated with RESTART IDENTITY first (`cloneWorkerDatabase({ reset: "none" })` opts out).
17
19
  * setupFilesAfterEnv: ["<rootDir>/jest.cedar-worker.cjs"],
18
20
  *
19
21
  * // jest.cedar-worker.cjs
@@ -1,7 +1,8 @@
1
- import { n as setupTemplateMode, t as cloneWorkerDatabase } from "./template-mode-BTUsdBtA.mjs";
1
+ import { n as setupTemplateMode, t as cloneWorkerDatabase } from "./template-mode-DK5cAlv9.mjs";
2
2
  //#region src/adapters/jest-template.ts
3
3
  /**
4
- * Jest globalSetup (template mode).
4
+ * Jest globalSetup (template mode). Drops crashed-run leftovers under this
5
+ * worktree's test role, then acquire → migrate → markTemplate.
5
6
  *
6
7
  * ```js
7
8
  * // jest.cedar-global.cjs
@@ -13,7 +14,8 @@ import { n as setupTemplateMode, t as cloneWorkerDatabase } from "./template-mod
13
14
  * // process.env.CEDAR_PG_FORCE = "1";
14
15
  * globalSetup: "<rootDir>/jest.cedar-global.cjs",
15
16
  * globalTeardown: require.resolve("@cedarjs/pg/jest-teardown"),
16
- * // Prefer setupFilesAfterEnv + beforeAll; setupFiles also works (memo is process-scoped).
17
+ * // Runs per test file; every file in a worker reuses that worker's clone,
18
+ * // truncated with RESTART IDENTITY first (`cloneWorkerDatabase({ reset: "none" })` opts out).
17
19
  * setupFilesAfterEnv: ["<rootDir>/jest.cedar-worker.cjs"],
18
20
  *
19
21
  * // jest.cedar-worker.cjs
@@ -1 +1 @@
1
- {"version":3,"file":"jest-template.mjs","names":[],"sources":["../src/adapters/jest-template.ts"],"sourcesContent":["import {\n cloneWorkerDatabase,\n setupTemplateMode,\n type SetupTemplateModeOptions,\n} from \"./template-mode.ts\";\n\nexport { cloneWorkerDatabase };\nexport type {\n SetupTemplateModeOptions,\n TemplateMigrateFn,\n TemplateMigrateContext,\n} from \"./template-mode.ts\";\n\n/**\n * Jest globalSetup (template mode).\n *\n * ```js\n * // jest.cedar-global.cjs\n * const { createGlobalSetup } = require(\"@cedarjs/pg/jest/template\");\n * module.exports = createGlobalSetup({ migrate: async ({ databaseUrl }) => {} });\n *\n * // jest.config.cjs\n * // When .env has a real TEST_DATABASE_URL, set once here (inherits to workers):\n * // process.env.CEDAR_PG_FORCE = \"1\";\n * globalSetup: \"<rootDir>/jest.cedar-global.cjs\",\n * globalTeardown: require.resolve(\"@cedarjs/pg/jest-teardown\"),\n * // Prefer setupFilesAfterEnv + beforeAll; setupFiles also works (memo is process-scoped).\n * setupFilesAfterEnv: [\"<rootDir>/jest.cedar-worker.cjs\"],\n *\n * // jest.cedar-worker.cjs\n * const { cloneWorkerDatabase } = require(\"@cedarjs/pg/jest/template\");\n * beforeAll(() => cloneWorkerDatabase());\n * ```\n *\n * Stock `@cedarjs/pg/jest` is one shared test DB only.\n */\nexport function createGlobalSetup(options: SetupTemplateModeOptions) {\n return async () => {\n await setupTemplateMode(options);\n };\n}\n\n/** String `require.resolve` without a migrate hook is unsupported — use `createGlobalSetup`. */\nexport default async function globalSetup(): Promise<void> {\n throw new Error(\n \"@cedarjs/pg/jest/template requires createGlobalSetup({ migrate }). \" +\n \"Point globalSetup at a local module that exports createGlobalSetup({ migrate }).\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,kBAAkB,SAAmC;CACnE,OAAO,YAAY;EACjB,MAAM,kBAAkB,OAAO;CACjC;AACF;;AAGA,eAA8B,cAA6B;CACzD,MAAM,IAAI,MACR,qJAEF;AACF"}
1
+ {"version":3,"file":"jest-template.mjs","names":[],"sources":["../src/adapters/jest-template.ts"],"sourcesContent":["import {\n cloneWorkerDatabase,\n setupTemplateMode,\n type SetupTemplateModeOptions,\n} from \"./template-mode.ts\";\n\nexport { cloneWorkerDatabase };\nexport type {\n SetupTemplateModeOptions,\n TemplateMigrateFn,\n TemplateMigrateContext,\n} from \"./template-mode.ts\";\n\n/**\n * Jest globalSetup (template mode). Drops crashed-run leftovers under this\n * worktree's test role, then acquire → migrate → markTemplate.\n *\n * ```js\n * // jest.cedar-global.cjs\n * const { createGlobalSetup } = require(\"@cedarjs/pg/jest/template\");\n * module.exports = createGlobalSetup({ migrate: async ({ databaseUrl }) => {} });\n *\n * // jest.config.cjs\n * // When .env has a real TEST_DATABASE_URL, set once here (inherits to workers):\n * // process.env.CEDAR_PG_FORCE = \"1\";\n * globalSetup: \"<rootDir>/jest.cedar-global.cjs\",\n * globalTeardown: require.resolve(\"@cedarjs/pg/jest-teardown\"),\n * // Runs per test file; every file in a worker reuses that worker's clone,\n * // truncated with RESTART IDENTITY first (`cloneWorkerDatabase({ reset: \"none\" })` opts out).\n * setupFilesAfterEnv: [\"<rootDir>/jest.cedar-worker.cjs\"],\n *\n * // jest.cedar-worker.cjs\n * const { cloneWorkerDatabase } = require(\"@cedarjs/pg/jest/template\");\n * beforeAll(() => cloneWorkerDatabase());\n * ```\n *\n * Stock `@cedarjs/pg/jest` is one shared test DB only.\n */\nexport function createGlobalSetup(options: SetupTemplateModeOptions) {\n return async () => {\n await setupTemplateMode(options);\n };\n}\n\n/** String `require.resolve` without a migrate hook is unsupported — use `createGlobalSetup`. */\nexport default async function globalSetup(): Promise<void> {\n throw new Error(\n \"@cedarjs/pg/jest/template requires createGlobalSetup({ migrate }). \" +\n \"Point globalSetup at a local module that exports createGlobalSetup({ migrate }).\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,kBAAkB,SAAmC;CACnE,OAAO,YAAY;EACjB,MAAM,kBAAkB,OAAO;CACjC;AACF;;AAGA,eAA8B,cAA6B;CACzD,MAAM,IAAI,MACR,qJAEF;AACF"}
package/dist/jest.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
1
+ const require_lifecycle = require("./lifecycle-BCeM96tI.cjs");
2
2
  //#region src/adapters/jest.ts
3
3
  /**
4
4
  * Jest globalSetup for a single shared test DB (`acquireIfNeeded` + dispose).
package/dist/jest.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as acquireIfNeeded } from "./lifecycle-BvIx0xqq.mjs";
1
+ import { n as acquireIfNeeded } from "./lifecycle-2BZgSVz2.mjs";
2
2
  //#region src/adapters/jest.ts
3
3
  /**
4
4
  * Jest globalSetup for a single shared test DB (`acquireIfNeeded` + dispose).