@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.
- package/README.md +250 -229
- package/dist/cli.cjs +89 -39
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +73 -23
- package/dist/cli.mjs.map +1 -1
- package/dist/dev-env.cjs +1 -1
- package/dist/dev-env.mjs +1 -1
- package/dist/index.cjs +9 -8
- package/dist/index.d.cts +31 -3
- package/dist/index.d.mts +31 -3
- package/dist/index.mjs +7 -7
- package/dist/jest-teardown.cjs +1 -1
- package/dist/jest-teardown.mjs +1 -1
- package/dist/jest-template.cjs +4 -1
- package/dist/jest-template.cjs.map +1 -1
- package/dist/jest-template.d.cts +4 -1
- package/dist/jest-template.d.mts +4 -1
- package/dist/jest-template.mjs +4 -1
- package/dist/jest-template.mjs.map +1 -1
- package/dist/jest.cjs +1 -1
- package/dist/jest.mjs +1 -1
- package/dist/{lease-BSBBpaR4.mjs → lease-DS1SX8U_.mjs} +23 -3
- package/dist/lease-DS1SX8U_.mjs.map +1 -0
- package/dist/{lease-Bq9wKwQa.cjs → lease-WlmOnNDi.cjs} +41 -3
- package/dist/lease-WlmOnNDi.cjs.map +1 -0
- package/dist/{lifecycle-DEJ4GgWV.cjs → lifecycle-BbrvFQvg.cjs} +175 -78
- package/dist/lifecycle-BbrvFQvg.cjs.map +1 -0
- package/dist/{lifecycle-BOo6xBjD.mjs → lifecycle-BvIx0xqq.mjs} +175 -78
- package/dist/lifecycle-BvIx0xqq.mjs.map +1 -0
- package/dist/{load-dev-env-7UjMHhw7.mjs → load-dev-env-BULkXyen.mjs} +2 -2
- package/dist/{load-dev-env-7UjMHhw7.mjs.map → load-dev-env-BULkXyen.mjs.map} +1 -1
- package/dist/{load-dev-env-cII6N4ZP.cjs → load-dev-env-Bl6Ddv1U.cjs} +2 -2
- package/dist/{load-dev-env-cII6N4ZP.cjs.map → load-dev-env-Bl6Ddv1U.cjs.map} +1 -1
- package/dist/{load-mode-env-B0qO9DZx.cjs → load-mode-env-CX9vd56X.cjs} +2 -2
- package/dist/{load-mode-env-B0qO9DZx.cjs.map → load-mode-env-CX9vd56X.cjs.map} +1 -1
- package/dist/{load-mode-env-C8gy4v9V.mjs → load-mode-env-Ce9ujisN.mjs} +2 -2
- package/dist/{load-mode-env-C8gy4v9V.mjs.map → load-mode-env-Ce9ujisN.mjs.map} +1 -1
- package/dist/{load-test-env-C34wpkIX.mjs → load-test-env-BqtA6V-d.mjs} +2 -2
- package/dist/{load-test-env-C34wpkIX.mjs.map → load-test-env-BqtA6V-d.mjs.map} +1 -1
- package/dist/{load-test-env-CkdUjTpV.cjs → load-test-env-Dcgh6YHV.cjs} +2 -2
- package/dist/{load-test-env-CkdUjTpV.cjs.map → load-test-env-Dcgh6YHV.cjs.map} +1 -1
- package/dist/nx.cjs +12 -14
- package/dist/nx.cjs.map +1 -1
- package/dist/nx.mjs +10 -12
- package/dist/nx.mjs.map +1 -1
- package/dist/status-4Uz6A3LB.cjs +31 -0
- package/dist/status-4Uz6A3LB.cjs.map +1 -0
- package/dist/status-Dcnpgnlz.mjs +26 -0
- package/dist/status-Dcnpgnlz.mjs.map +1 -0
- package/dist/studio-DIFw1qWC.mjs +173 -0
- package/dist/studio-DIFw1qWC.mjs.map +1 -0
- package/dist/studio-oJE30_PO.cjs +208 -0
- package/dist/studio-oJE30_PO.cjs.map +1 -0
- package/dist/{tasks-Caud9yHr.cjs → tasks-CNHvvlsN.cjs} +4 -4
- package/dist/{tasks-Caud9yHr.cjs.map → tasks-CNHvvlsN.cjs.map} +1 -1
- package/dist/{tasks-KherHLac.mjs → tasks-D5iWIdlo.mjs} +2 -2
- package/dist/{tasks-KherHLac.mjs.map → tasks-D5iWIdlo.mjs.map} +1 -1
- package/dist/{template-CGw3C1Ob.mjs → template-BiJ-0TIF.mjs} +3 -3
- package/dist/{template-CGw3C1Ob.mjs.map → template-BiJ-0TIF.mjs.map} +1 -1
- package/dist/{template-D0gJ_MS2.cjs → template-CXMpODzK.cjs} +3 -3
- package/dist/{template-D0gJ_MS2.cjs.map → template-CXMpODzK.cjs.map} +1 -1
- package/dist/{template-mode-IjlFOG4O.mjs → template-mode-BTUsdBtA.mjs} +27 -13
- package/dist/template-mode-BTUsdBtA.mjs.map +1 -0
- package/dist/{template-mode-CcxV_Iju.d.cts → template-mode-CzyVwHsi.d.cts} +4 -1
- package/dist/{template-mode-CcxV_Iju.d.mts → template-mode-CzyVwHsi.d.mts} +4 -1
- package/dist/{template-mode-BkEs9LnY.cjs → template-mode-JTOxrEgE.cjs} +27 -13
- package/dist/template-mode-JTOxrEgE.cjs.map +1 -0
- package/dist/test-env.cjs +1 -1
- package/dist/test-env.mjs +1 -1
- package/dist/vite-plus.cjs +107 -4
- package/dist/vite-plus.cjs.map +1 -1
- package/dist/vite-plus.d.cts +25 -1
- package/dist/vite-plus.d.mts +25 -1
- package/dist/vite-plus.mjs +108 -5
- package/dist/vite-plus.mjs.map +1 -1
- package/dist/vitest-template.cjs +1 -1
- package/dist/vitest-template.d.cts +1 -1
- package/dist/vitest-template.d.mts +1 -1
- package/dist/vitest-template.mjs +1 -1
- package/dist/vitest.cjs +1 -1
- package/dist/vitest.mjs +1 -1
- package/package.json +11 -2
- package/dist/constants-Ct8myrEn.cjs +0 -41
- package/dist/constants-Ct8myrEn.cjs.map +0 -1
- package/dist/constants-NLR0U4NR.mjs +0 -24
- package/dist/constants-NLR0U4NR.mjs.map +0 -1
- package/dist/lease-BSBBpaR4.mjs.map +0 -1
- package/dist/lease-Bq9wKwQa.cjs.map +0 -1
- package/dist/lifecycle-BOo6xBjD.mjs.map +0 -1
- package/dist/lifecycle-DEJ4GgWV.cjs.map +0 -1
- package/dist/template-mode-BkEs9LnY.cjs.map +0 -1
- package/dist/template-mode-IjlFOG4O.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-
|
|
1
|
+
{"version":3,"file":"tasks-CNHvvlsN.cjs","names":["CLI_NAME"],"sources":["../src/adapters/tasks.ts"],"sourcesContent":["/** Shared CLI command strings and lifecycle target defs for Vite+ / Nx. */\n\nimport { CLI_NAME } from \"../core/constants.ts\";\nimport type { DbMode } from \"../core/naming.ts\";\n\nexport const CEDAR_PG_TASK_ACQUIRE_DEV = \"db:acquire\";\nexport const CEDAR_PG_TASK_ACQUIRE_TEST = \"db:acquire-test\";\nexport const CEDAR_PG_TASK_DISPOSE_TEST = \"db:dispose-test\";\n\nexport type CedarPgCommands = {\n acquireDev: string;\n acquireTest: string;\n disposeTest: string;\n};\n\nexport type CedarPgLifecycleTarget = {\n command: string;\n cache?: boolean;\n};\n\nexport type CedarPgLifecycleTargetsOptions = {\n bin?: string;\n /** Include dispose-test target (default: true). */\n includeDisposeTest?: boolean;\n};\n\nexport function cedarPgCommands(bin = CLI_NAME): CedarPgCommands {\n return {\n acquireDev: `${bin} acquire --mode=dev`,\n acquireTest: `${bin} acquire --mode=test --print-env`,\n disposeTest: `${bin} dispose --mode=test`,\n };\n}\n\nexport function cedarPgLifecycleTargets(\n options: CedarPgLifecycleTargetsOptions = {},\n): Record<string, CedarPgLifecycleTarget> {\n const cmds = cedarPgCommands(options.bin ?? CLI_NAME);\n const targets: Record<string, CedarPgLifecycleTarget> = {\n [CEDAR_PG_TASK_ACQUIRE_DEV]: { command: cmds.acquireDev, cache: false },\n [CEDAR_PG_TASK_ACQUIRE_TEST]: { command: cmds.acquireTest, cache: false },\n };\n if (options.includeDisposeTest !== false) {\n targets[CEDAR_PG_TASK_DISPOSE_TEST] = { command: cmds.disposeTest, cache: false };\n }\n return targets;\n}\n\nexport function cedarPgRunCommand(mode: DbMode, command: string, bin = CLI_NAME): string {\n return `${bin} run --mode=${mode} -- ${command}`;\n}\n"],"mappings":";;;AAKA,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;AAC1C,MAAa,6BAA6B;AAmB1C,SAAgB,gBAAgB,MAAMA,cAAAA,UAA2B;CAC/D,OAAO;EACL,YAAY,GAAG,IAAI;EACnB,aAAa,GAAG,IAAI;EACpB,aAAa,GAAG,IAAI;CACtB;AACF;AAEA,SAAgB,wBACd,UAA0C,CAAC,GACH;CACxC,MAAM,OAAO,gBAAgB,QAAQ,OAAA,SAAe;CACpD,MAAM,UAAkD;GACrD,4BAA4B;GAAE,SAAS,KAAK;GAAY,OAAO;EAAM;GACrE,6BAA6B;GAAE,SAAS,KAAK;GAAa,OAAO;EAAM;CAC1E;CACA,IAAI,QAAQ,uBAAuB,OACjC,QAAQ,8BAA8B;EAAE,SAAS,KAAK;EAAa,OAAO;CAAM;CAElF,OAAO;AACT;AAEA,SAAgB,kBAAkB,MAAc,SAAiB,MAAMA,cAAAA,UAAkB;CACvF,OAAO,GAAG,IAAI,cAAc,KAAK,MAAM;AACzC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { p as CLI_NAME } from "./lease-DS1SX8U_.mjs";
|
|
2
2
|
//#region src/adapters/tasks.ts
|
|
3
3
|
/** Shared CLI command strings and lifecycle target defs for Vite+ / Nx. */
|
|
4
4
|
const CEDAR_PG_TASK_ACQUIRE_DEV = "db:acquire";
|
|
@@ -35,4 +35,4 @@ function cedarPgRunCommand(mode, command, bin = CLI_NAME) {
|
|
|
35
35
|
//#endregion
|
|
36
36
|
export { cedarPgRunCommand as a, cedarPgLifecycleTargets as i, CEDAR_PG_TASK_ACQUIRE_TEST as n, CEDAR_PG_TASK_DISPOSE_TEST as r, CEDAR_PG_TASK_ACQUIRE_DEV as t };
|
|
37
37
|
|
|
38
|
-
//# sourceMappingURL=tasks-
|
|
38
|
+
//# sourceMappingURL=tasks-D5iWIdlo.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks-
|
|
1
|
+
{"version":3,"file":"tasks-D5iWIdlo.mjs","names":[],"sources":["../src/adapters/tasks.ts"],"sourcesContent":["/** Shared CLI command strings and lifecycle target defs for Vite+ / Nx. */\n\nimport { CLI_NAME } from \"../core/constants.ts\";\nimport type { DbMode } from \"../core/naming.ts\";\n\nexport const CEDAR_PG_TASK_ACQUIRE_DEV = \"db:acquire\";\nexport const CEDAR_PG_TASK_ACQUIRE_TEST = \"db:acquire-test\";\nexport const CEDAR_PG_TASK_DISPOSE_TEST = \"db:dispose-test\";\n\nexport type CedarPgCommands = {\n acquireDev: string;\n acquireTest: string;\n disposeTest: string;\n};\n\nexport type CedarPgLifecycleTarget = {\n command: string;\n cache?: boolean;\n};\n\nexport type CedarPgLifecycleTargetsOptions = {\n bin?: string;\n /** Include dispose-test target (default: true). */\n includeDisposeTest?: boolean;\n};\n\nexport function cedarPgCommands(bin = CLI_NAME): CedarPgCommands {\n return {\n acquireDev: `${bin} acquire --mode=dev`,\n acquireTest: `${bin} acquire --mode=test --print-env`,\n disposeTest: `${bin} dispose --mode=test`,\n };\n}\n\nexport function cedarPgLifecycleTargets(\n options: CedarPgLifecycleTargetsOptions = {},\n): Record<string, CedarPgLifecycleTarget> {\n const cmds = cedarPgCommands(options.bin ?? CLI_NAME);\n const targets: Record<string, CedarPgLifecycleTarget> = {\n [CEDAR_PG_TASK_ACQUIRE_DEV]: { command: cmds.acquireDev, cache: false },\n [CEDAR_PG_TASK_ACQUIRE_TEST]: { command: cmds.acquireTest, cache: false },\n };\n if (options.includeDisposeTest !== false) {\n targets[CEDAR_PG_TASK_DISPOSE_TEST] = { command: cmds.disposeTest, cache: false };\n }\n return targets;\n}\n\nexport function cedarPgRunCommand(mode: DbMode, command: string, bin = CLI_NAME): string {\n return `${bin} run --mode=${mode} -- ${command}`;\n}\n"],"mappings":";;;AAKA,MAAa,4BAA4B;AACzC,MAAa,6BAA6B;AAC1C,MAAa,6BAA6B;AAmB1C,SAAgB,gBAAgB,MAAM,UAA2B;CAC/D,OAAO;EACL,YAAY,GAAG,IAAI;EACnB,aAAa,GAAG,IAAI;EACpB,aAAa,GAAG,IAAI;CACtB;AACF;AAEA,SAAgB,wBACd,UAA0C,CAAC,GACH;CACxC,MAAM,OAAO,gBAAgB,QAAQ,OAAA,SAAe;CACpD,MAAM,UAAkD;GACrD,4BAA4B;GAAE,SAAS,KAAK;GAAY,OAAO;EAAM;GACrE,6BAA6B;GAAE,SAAS,KAAK;GAAa,OAAO;EAAM;CAC1E;CACA,IAAI,QAAQ,uBAAuB,OACjC,QAAQ,8BAA8B;EAAE,SAAS,KAAK;EAAa,OAAO;CAAM;CAElF,OAAO;AACT;AAEA,SAAgB,kBAAkB,MAAc,SAAiB,MAAM,UAAkB;CACvF,OAAO,GAAG,IAAI,cAAc,KAAK,MAAM;AACzC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as buildCloneDatabaseName, S as runIfNeeded, _ as setDatabaseIsTemplate, f as dropDatabase, l as buildDatabaseUrl, o as ensureHostRunning, u as cloneDatabaseFromTemplate, v as applyDatabaseUrlEnv } from "./lifecycle-
|
|
2
|
-
import { f as resolveWorktreeIdentity, l as readLease } from "./lease-
|
|
1
|
+
import { C as buildCloneDatabaseName, S as runIfNeeded, _ as setDatabaseIsTemplate, f as dropDatabase, l as buildDatabaseUrl, o as ensureHostRunning, u as cloneDatabaseFromTemplate, v as applyDatabaseUrlEnv } from "./lifecycle-BvIx0xqq.mjs";
|
|
2
|
+
import { f as resolveWorktreeIdentity, l as readLease } from "./lease-DS1SX8U_.mjs";
|
|
3
3
|
//#region src/core/template.ts
|
|
4
4
|
async function resolveAdminUrl(adminUrl) {
|
|
5
5
|
return adminUrl ?? (await ensureHostRunning()).adminUrl;
|
|
@@ -85,4 +85,4 @@ async function cloneFromTemplateIfNeeded(options) {
|
|
|
85
85
|
//#endregion
|
|
86
86
|
export { cloneFromTemplateIfNeeded as n, markTemplate as r, cloneFromTemplate as t };
|
|
87
87
|
|
|
88
|
-
//# sourceMappingURL=template-
|
|
88
|
+
//# sourceMappingURL=template-BiJ-0TIF.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-
|
|
1
|
+
{"version":3,"file":"template-BiJ-0TIF.mjs","names":[],"sources":["../src/core/template.ts"],"sourcesContent":["import { buildCloneDatabaseName, type DbMode } from \"./naming.ts\";\nimport { readLease } from \"./lease.ts\";\nimport { applyDatabaseUrlEnv, runIfNeeded, type ResolveAcquireSkipInput } from \"./policy.ts\";\nimport { resolveWorktreeIdentity } from \"./worktree.ts\";\nimport {\n buildDatabaseUrl,\n cloneDatabaseFromTemplate,\n dropDatabase,\n setDatabaseIsTemplate,\n} from \"../providers/autopg.ts\";\nimport { ensureHostRunning } from \"../providers/host.ts\";\n\nasync function resolveAdminUrl(adminUrl?: string): Promise<string> {\n return adminUrl ?? (await ensureHostRunning()).adminUrl;\n}\n\nexport type MarkTemplateOptions = {\n root?: string;\n mode: DbMode;\n /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */\n adminUrl?: string;\n};\n\n/**\n * After migrations, mark the leased DB as a PostgreSQL TEMPLATE so workers can clone it.\n * Requires a lease from `acquire` (no datname override).\n */\nexport async function markTemplate(\n options: MarkTemplateOptions,\n): Promise<{ databaseName: string; adminUrl: string }> {\n const identity = resolveWorktreeIdentity(options.root);\n const mode = options.mode;\n const lease = readLease(identity.root, mode);\n if (!lease) {\n throw new Error(`no ${mode} lease; run acquire before markTemplate`);\n }\n const adminUrl = await resolveAdminUrl(options.adminUrl);\n await setDatabaseIsTemplate({\n adminUrl,\n databaseName: lease.databaseName,\n isTemplate: true,\n });\n return { databaseName: lease.databaseName, adminUrl };\n}\n\nexport type CloneFromTemplateOptions = {\n root?: string;\n mode: DbMode;\n /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */\n adminUrl?: string;\n /**\n * Suffix for the clone datname (e.g. Jest worker id).\n * Defaults to `<pid>_<base36 time>`.\n */\n name?: string;\n /**\n * Inject DATABASE_URL / TEST_DATABASE_URL for this clone (default false).\n * Host `cloneFromTemplateIfNeeded` defaults true; worker adapters pass true explicitly.\n */\n setEnv?: boolean;\n};\n\nexport type CloneResult = {\n databaseUrl: string;\n adminUrl: string;\n databaseName: string;\n roleName: string;\n templateName: string;\n port: number;\n /**\n * DROP this clone only (leaves TEMPLATE + role if still owned elsewhere).\n * Not suite teardown — use role-scoped `dispose` for that.\n */\n dropClone: () => Promise<void>;\n};\n\n/**\n * Clone the leased TEMPLATE database via admin (`CREATE DATABASE … TEMPLATE`).\n * Reuses the template role so `databaseUrl` passwords stay valid (scheme v2).\n * Provider rejects when the leased DB is not marked TEMPLATE.\n * Port comes from the lease; admin URL is passed through or rediscovered.\n */\nexport async function cloneFromTemplate(options: CloneFromTemplateOptions): Promise<CloneResult> {\n const identity = resolveWorktreeIdentity(options.root);\n const mode = options.mode;\n const lease = readLease(identity.root, mode);\n if (!lease) {\n throw new Error(`no ${mode} lease; run acquire + markTemplate before cloneFromTemplate`);\n }\n\n const adminUrl = await resolveAdminUrl(options.adminUrl);\n const suffix = options.name ?? `${process.pid}_${Date.now().toString(36)}`;\n const databaseName = buildCloneDatabaseName(lease.databaseName, suffix);\n\n await cloneDatabaseFromTemplate({\n adminUrl,\n templateName: lease.databaseName,\n databaseName,\n roleName: lease.roleName,\n });\n\n const databaseUrl = buildDatabaseUrl({\n port: lease.port,\n databaseName,\n roleName: lease.roleName,\n });\n\n if (options.setEnv) {\n applyDatabaseUrlEnv(databaseUrl, { mode });\n }\n\n const roleName = lease.roleName;\n\n return {\n databaseUrl,\n adminUrl,\n databaseName,\n roleName,\n templateName: lease.databaseName,\n port: lease.port,\n dropClone: async () => {\n await dropDatabase({ adminUrl, databaseName, roleName });\n },\n };\n}\n\nexport type CloneFromTemplateIfNeededOptions = CloneFromTemplateOptions & ResolveAcquireSkipInput;\n\nexport type CloneFromTemplateIfNeededResult =\n | { status: \"skipped\"; reason: \"disabled\" }\n | { status: \"skipped\"; reason: \"external-url\"; databaseUrl: string }\n | ({ status: \"cloned\" } & CloneResult);\n\n/**\n * Resolve skip policy then clone. Host entry for worker adapters (same skip\n * semantics as `acquireIfNeeded`). Defaults `setEnv` on for skip and clone paths.\n */\nexport async function cloneFromTemplateIfNeeded(\n options: CloneFromTemplateIfNeededOptions,\n): Promise<CloneFromTemplateIfNeededResult> {\n const outcome = await runIfNeeded(options, () =>\n cloneFromTemplate({\n ...options,\n setEnv: options.setEnv !== false,\n }),\n );\n if (outcome.status === \"skipped\") return outcome;\n return { status: \"cloned\", ...outcome.value };\n}\n"],"mappings":";;;AAYA,eAAe,gBAAgB,UAAoC;CACjE,OAAO,aAAa,MAAM,kBAAkB,EAAA,CAAG;AACjD;;;;;AAaA,eAAsB,aACpB,SACqD;CACrD,MAAM,WAAW,wBAAwB,QAAQ,IAAI;CACrD,MAAM,OAAO,QAAQ;CACrB,MAAM,QAAQ,UAAU,SAAS,MAAM,IAAI;CAC3C,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,MAAM,KAAK,wCAAwC;CAErE,MAAM,WAAW,MAAM,gBAAgB,QAAQ,QAAQ;CACvD,MAAM,sBAAsB;EAC1B;EACA,cAAc,MAAM;EACpB,YAAY;CACd,CAAC;CACD,OAAO;EAAE,cAAc,MAAM;EAAc;CAAS;AACtD;;;;;;;AAuCA,eAAsB,kBAAkB,SAAyD;CAC/F,MAAM,WAAW,wBAAwB,QAAQ,IAAI;CACrD,MAAM,OAAO,QAAQ;CACrB,MAAM,QAAQ,UAAU,SAAS,MAAM,IAAI;CAC3C,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,MAAM,KAAK,4DAA4D;CAGzF,MAAM,WAAW,MAAM,gBAAgB,QAAQ,QAAQ;CACvD,MAAM,SAAS,QAAQ,QAAQ,GAAG,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE;CACvE,MAAM,eAAe,uBAAuB,MAAM,cAAc,MAAM;CAEtE,MAAM,0BAA0B;EAC9B;EACA,cAAc,MAAM;EACpB;EACA,UAAU,MAAM;CAClB,CAAC;CAED,MAAM,cAAc,iBAAiB;EACnC,MAAM,MAAM;EACZ;EACA,UAAU,MAAM;CAClB,CAAC;CAED,IAAI,QAAQ,QACV,oBAAoB,aAAa,EAAE,KAAK,CAAC;CAG3C,MAAM,WAAW,MAAM;CAEvB,OAAO;EACL;EACA;EACA;EACA;EACA,cAAc,MAAM;EACpB,MAAM,MAAM;EACZ,WAAW,YAAY;GACrB,MAAM,aAAa;IAAE;IAAU;IAAc;GAAS,CAAC;EACzD;CACF;AACF;;;;;AAaA,eAAsB,0BACpB,SAC0C;CAC1C,MAAM,UAAU,MAAM,YAAY,eAChC,kBAAkB;EAChB,GAAG;EACH,QAAQ,QAAQ,WAAW;CAC7B,CAAC,CACH;CACA,IAAI,QAAQ,WAAW,WAAW,OAAO;CACzC,OAAO;EAAE,QAAQ;EAAU,GAAG,QAAQ;CAAM;AAC9C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_lifecycle = require("./lifecycle-
|
|
2
|
-
const require_lease = require("./lease-
|
|
1
|
+
const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
|
|
2
|
+
const require_lease = require("./lease-WlmOnNDi.cjs");
|
|
3
3
|
//#region src/core/template.ts
|
|
4
4
|
async function resolveAdminUrl(adminUrl) {
|
|
5
5
|
return adminUrl ?? (await require_lifecycle.ensureHostRunning()).adminUrl;
|
|
@@ -102,4 +102,4 @@ Object.defineProperty(exports, "markTemplate", {
|
|
|
102
102
|
}
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
//# sourceMappingURL=template-
|
|
105
|
+
//# sourceMappingURL=template-CXMpODzK.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template-
|
|
1
|
+
{"version":3,"file":"template-CXMpODzK.cjs","names":["ensureHostRunning","resolveWorktreeIdentity","readLease","setDatabaseIsTemplate","buildCloneDatabaseName","cloneDatabaseFromTemplate","buildDatabaseUrl","dropDatabase","runIfNeeded"],"sources":["../src/core/template.ts"],"sourcesContent":["import { buildCloneDatabaseName, type DbMode } from \"./naming.ts\";\nimport { readLease } from \"./lease.ts\";\nimport { applyDatabaseUrlEnv, runIfNeeded, type ResolveAcquireSkipInput } from \"./policy.ts\";\nimport { resolveWorktreeIdentity } from \"./worktree.ts\";\nimport {\n buildDatabaseUrl,\n cloneDatabaseFromTemplate,\n dropDatabase,\n setDatabaseIsTemplate,\n} from \"../providers/autopg.ts\";\nimport { ensureHostRunning } from \"../providers/host.ts\";\n\nasync function resolveAdminUrl(adminUrl?: string): Promise<string> {\n return adminUrl ?? (await ensureHostRunning()).adminUrl;\n}\n\nexport type MarkTemplateOptions = {\n root?: string;\n mode: DbMode;\n /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */\n adminUrl?: string;\n};\n\n/**\n * After migrations, mark the leased DB as a PostgreSQL TEMPLATE so workers can clone it.\n * Requires a lease from `acquire` (no datname override).\n */\nexport async function markTemplate(\n options: MarkTemplateOptions,\n): Promise<{ databaseName: string; adminUrl: string }> {\n const identity = resolveWorktreeIdentity(options.root);\n const mode = options.mode;\n const lease = readLease(identity.root, mode);\n if (!lease) {\n throw new Error(`no ${mode} lease; run acquire before markTemplate`);\n }\n const adminUrl = await resolveAdminUrl(options.adminUrl);\n await setDatabaseIsTemplate({\n adminUrl,\n databaseName: lease.databaseName,\n isTemplate: true,\n });\n return { databaseName: lease.databaseName, adminUrl };\n}\n\nexport type CloneFromTemplateOptions = {\n root?: string;\n mode: DbMode;\n /** Superuser URL from `acquire`; when omitted, discovers/starts the host. */\n adminUrl?: string;\n /**\n * Suffix for the clone datname (e.g. Jest worker id).\n * Defaults to `<pid>_<base36 time>`.\n */\n name?: string;\n /**\n * Inject DATABASE_URL / TEST_DATABASE_URL for this clone (default false).\n * Host `cloneFromTemplateIfNeeded` defaults true; worker adapters pass true explicitly.\n */\n setEnv?: boolean;\n};\n\nexport type CloneResult = {\n databaseUrl: string;\n adminUrl: string;\n databaseName: string;\n roleName: string;\n templateName: string;\n port: number;\n /**\n * DROP this clone only (leaves TEMPLATE + role if still owned elsewhere).\n * Not suite teardown — use role-scoped `dispose` for that.\n */\n dropClone: () => Promise<void>;\n};\n\n/**\n * Clone the leased TEMPLATE database via admin (`CREATE DATABASE … TEMPLATE`).\n * Reuses the template role so `databaseUrl` passwords stay valid (scheme v2).\n * Provider rejects when the leased DB is not marked TEMPLATE.\n * Port comes from the lease; admin URL is passed through or rediscovered.\n */\nexport async function cloneFromTemplate(options: CloneFromTemplateOptions): Promise<CloneResult> {\n const identity = resolveWorktreeIdentity(options.root);\n const mode = options.mode;\n const lease = readLease(identity.root, mode);\n if (!lease) {\n throw new Error(`no ${mode} lease; run acquire + markTemplate before cloneFromTemplate`);\n }\n\n const adminUrl = await resolveAdminUrl(options.adminUrl);\n const suffix = options.name ?? `${process.pid}_${Date.now().toString(36)}`;\n const databaseName = buildCloneDatabaseName(lease.databaseName, suffix);\n\n await cloneDatabaseFromTemplate({\n adminUrl,\n templateName: lease.databaseName,\n databaseName,\n roleName: lease.roleName,\n });\n\n const databaseUrl = buildDatabaseUrl({\n port: lease.port,\n databaseName,\n roleName: lease.roleName,\n });\n\n if (options.setEnv) {\n applyDatabaseUrlEnv(databaseUrl, { mode });\n }\n\n const roleName = lease.roleName;\n\n return {\n databaseUrl,\n adminUrl,\n databaseName,\n roleName,\n templateName: lease.databaseName,\n port: lease.port,\n dropClone: async () => {\n await dropDatabase({ adminUrl, databaseName, roleName });\n },\n };\n}\n\nexport type CloneFromTemplateIfNeededOptions = CloneFromTemplateOptions & ResolveAcquireSkipInput;\n\nexport type CloneFromTemplateIfNeededResult =\n | { status: \"skipped\"; reason: \"disabled\" }\n | { status: \"skipped\"; reason: \"external-url\"; databaseUrl: string }\n | ({ status: \"cloned\" } & CloneResult);\n\n/**\n * Resolve skip policy then clone. Host entry for worker adapters (same skip\n * semantics as `acquireIfNeeded`). Defaults `setEnv` on for skip and clone paths.\n */\nexport async function cloneFromTemplateIfNeeded(\n options: CloneFromTemplateIfNeededOptions,\n): Promise<CloneFromTemplateIfNeededResult> {\n const outcome = await runIfNeeded(options, () =>\n cloneFromTemplate({\n ...options,\n setEnv: options.setEnv !== false,\n }),\n );\n if (outcome.status === \"skipped\") return outcome;\n return { status: \"cloned\", ...outcome.value };\n}\n"],"mappings":";;;AAYA,eAAe,gBAAgB,UAAoC;CACjE,OAAO,aAAa,MAAMA,kBAAAA,kBAAkB,EAAA,CAAG;AACjD;;;;;AAaA,eAAsB,aACpB,SACqD;CACrD,MAAM,WAAWC,cAAAA,wBAAwB,QAAQ,IAAI;CACrD,MAAM,OAAO,QAAQ;CACrB,MAAM,QAAQC,cAAAA,UAAU,SAAS,MAAM,IAAI;CAC3C,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,MAAM,KAAK,wCAAwC;CAErE,MAAM,WAAW,MAAM,gBAAgB,QAAQ,QAAQ;CACvD,MAAMC,kBAAAA,sBAAsB;EAC1B;EACA,cAAc,MAAM;EACpB,YAAY;CACd,CAAC;CACD,OAAO;EAAE,cAAc,MAAM;EAAc;CAAS;AACtD;;;;;;;AAuCA,eAAsB,kBAAkB,SAAyD;CAC/F,MAAM,WAAWF,cAAAA,wBAAwB,QAAQ,IAAI;CACrD,MAAM,OAAO,QAAQ;CACrB,MAAM,QAAQC,cAAAA,UAAU,SAAS,MAAM,IAAI;CAC3C,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,MAAM,KAAK,4DAA4D;CAGzF,MAAM,WAAW,MAAM,gBAAgB,QAAQ,QAAQ;CACvD,MAAM,SAAS,QAAQ,QAAQ,GAAG,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,SAAS,EAAE;CACvE,MAAM,eAAeE,kBAAAA,uBAAuB,MAAM,cAAc,MAAM;CAEtE,MAAMC,kBAAAA,0BAA0B;EAC9B;EACA,cAAc,MAAM;EACpB;EACA,UAAU,MAAM;CAClB,CAAC;CAED,MAAM,cAAcC,kBAAAA,iBAAiB;EACnC,MAAM,MAAM;EACZ;EACA,UAAU,MAAM;CAClB,CAAC;CAED,IAAI,QAAQ,QACV,kBAAA,oBAAoB,aAAa,EAAE,KAAK,CAAC;CAG3C,MAAM,WAAW,MAAM;CAEvB,OAAO;EACL;EACA;EACA;EACA;EACA,cAAc,MAAM;EACpB,MAAM,MAAM;EACZ,WAAW,YAAY;GACrB,MAAMC,kBAAAA,aAAa;IAAE;IAAU;IAAc;GAAS,CAAC;EACzD;CACF;AACF;;;;;AAaA,eAAsB,0BACpB,SAC0C;CAC1C,MAAM,UAAU,MAAMC,kBAAAA,YAAY,eAChC,kBAAkB;EAChB,GAAG;EACH,QAAQ,QAAQ,WAAW;CAC7B,CAAC,CACH;CACA,IAAI,QAAQ,WAAW,WAAW,OAAO;CACzC,OAAO;EAAE,QAAQ;EAAU,GAAG,QAAQ;CAAM;AAC9C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as acquireIfNeeded, r as dispose } from "./lifecycle-
|
|
2
|
-
import { n as cloneFromTemplateIfNeeded, r as markTemplate } from "./template-
|
|
1
|
+
import { n as acquireIfNeeded, r as dispose } from "./lifecycle-BvIx0xqq.mjs";
|
|
2
|
+
import { n as cloneFromTemplateIfNeeded, r as markTemplate } from "./template-BiJ-0TIF.mjs";
|
|
3
3
|
//#region src/adapters/template-mode.ts
|
|
4
4
|
/**
|
|
5
5
|
* Runner orchestration: acquire → migrate → markTemplate.
|
|
@@ -39,8 +39,16 @@ async function setupTemplateMode(options) {
|
|
|
39
39
|
}
|
|
40
40
|
return result;
|
|
41
41
|
}
|
|
42
|
-
let
|
|
43
|
-
|
|
42
|
+
/** Survives Jest `setupFiles` module reloads (module-scoped `let` does not). */
|
|
43
|
+
const CLONE_WORKER_MEMO = Symbol.for("@cedarjs/pg/cloneWorkerDatabase");
|
|
44
|
+
function readCloneWorkerMemo() {
|
|
45
|
+
return globalThis[CLONE_WORKER_MEMO];
|
|
46
|
+
}
|
|
47
|
+
function writeCloneWorkerMemo(memo) {
|
|
48
|
+
const g = globalThis;
|
|
49
|
+
if (memo === void 0) delete g[CLONE_WORKER_MEMO];
|
|
50
|
+
else g[CLONE_WORKER_MEMO] = memo;
|
|
51
|
+
}
|
|
44
52
|
function resolveWorkerName(options) {
|
|
45
53
|
return options.name ?? process.env.JEST_WORKER_ID ?? process.env.VITEST_POOL_ID ?? String(process.pid);
|
|
46
54
|
}
|
|
@@ -51,16 +59,19 @@ function workerOptionsKey(root, name) {
|
|
|
51
59
|
* Process-once per-worker clone (JEST_WORKER_ID / VITEST_POOL_ID / pid by default).
|
|
52
60
|
* Uses `cloneFromTemplateIfNeeded` (same skip policy as `acquireIfNeeded`) with `setEnv: true`.
|
|
53
61
|
* First call wins for `root`/`name`; conflicting later calls throw.
|
|
62
|
+
*
|
|
63
|
+
* Memo lives on `globalThis` so Jest `setupFiles` (module reload per file) still
|
|
64
|
+
* shares one clone per worker. `setupFilesAfterEnv` + `beforeAll` also works.
|
|
54
65
|
*/
|
|
55
66
|
function cloneWorkerDatabase(options = {}) {
|
|
56
67
|
const name = resolveWorkerName(options);
|
|
57
68
|
const key = workerOptionsKey(options.root, name);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
const existing = readCloneWorkerMemo();
|
|
70
|
+
if (existing) {
|
|
71
|
+
if (existing.key !== key) throw new Error(`cloneWorkerDatabase already started with different root/name (first: ${JSON.stringify(existing.key)}, now: ${JSON.stringify(key)})`);
|
|
72
|
+
return existing.promise;
|
|
61
73
|
}
|
|
62
|
-
|
|
63
|
-
workerOnce = (async () => {
|
|
74
|
+
const promise = (async () => {
|
|
64
75
|
await cloneFromTemplateIfNeeded({
|
|
65
76
|
root: options.root,
|
|
66
77
|
mode: "test",
|
|
@@ -68,13 +79,16 @@ function cloneWorkerDatabase(options = {}) {
|
|
|
68
79
|
setEnv: true
|
|
69
80
|
});
|
|
70
81
|
})().catch((err) => {
|
|
71
|
-
|
|
72
|
-
workerOnceKey = void 0;
|
|
82
|
+
writeCloneWorkerMemo(void 0);
|
|
73
83
|
throw err;
|
|
74
84
|
});
|
|
75
|
-
|
|
85
|
+
writeCloneWorkerMemo({
|
|
86
|
+
promise,
|
|
87
|
+
key
|
|
88
|
+
});
|
|
89
|
+
return promise;
|
|
76
90
|
}
|
|
77
91
|
//#endregion
|
|
78
92
|
export { setupTemplateMode as n, cloneWorkerDatabase as t };
|
|
79
93
|
|
|
80
|
-
//# sourceMappingURL=template-mode-
|
|
94
|
+
//# sourceMappingURL=template-mode-BTUsdBtA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-mode-BTUsdBtA.mjs","names":[],"sources":["../src/adapters/template-mode.ts"],"sourcesContent":["import { dispose, acquireIfNeeded, type AcquireIfNeededResult } from \"../core/lifecycle.ts\";\nimport { cloneFromTemplateIfNeeded, markTemplate } from \"../core/template.ts\";\n\nexport type TemplateMigrateContext = {\n databaseUrl: string;\n adminUrl: string;\n databaseName: string;\n roleName: string;\n};\n\nexport type TemplateMigrateFn = (ctx: TemplateMigrateContext) => void | Promise<void>;\n\nexport type SetupTemplateModeOptions = {\n root?: string;\n /** App-owned migrate; runs once, then `markTemplate`. Required. */\n migrate: TemplateMigrateFn;\n setEnv?: boolean;\n};\n\n/**\n * Runner orchestration: acquire → migrate → markTemplate.\n * After acquire succeeds, migrate + markTemplate are all-or-nothing: any failure\n * best-effort disposes the lease so Vitest (no separate teardown) does not leak.\n * Programmatic apps that do not need a migrate hook should call core\n * `acquire` + `markTemplate` + `cloneFromTemplate` + `dispose` instead.\n */\nexport async function setupTemplateMode(\n options: SetupTemplateModeOptions,\n): Promise<AcquireIfNeededResult> {\n const result = await acquireIfNeeded({\n root: options.root,\n mode: \"test\",\n setEnv: options.setEnv !== false,\n });\n if (result.status !== \"acquired\") return result;\n\n try {\n await options.migrate({\n databaseUrl: result.databaseUrl,\n adminUrl: result.adminUrl,\n databaseName: result.databaseName,\n roleName: result.roleName,\n });\n await markTemplate({\n root: result.root,\n mode: \"test\",\n adminUrl: result.adminUrl,\n });\n } catch (err) {\n try {\n await dispose({ root: result.root, mode: \"test\" });\n } catch {\n // best-effort: leave lease for dispose/gc retry\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(\n `template setup failed after acquire; cleaned up lease DB (${result.databaseName}). ` +\n `Fix the error and re-run: ${detail}`,\n { cause: err },\n );\n }\n\n return result;\n}\n\nexport type CloneWorkerDatabaseOptions = {\n root?: string;\n /** Clone suffix; defaults to JEST_WORKER_ID / VITEST_POOL_ID / pid. */\n name?: string;\n};\n\n/** Survives Jest `setupFiles` module reloads (module-scoped `let` does not). */\nconst CLONE_WORKER_MEMO = Symbol.for(\"@cedarjs/pg/cloneWorkerDatabase\");\n\ntype CloneWorkerMemo = {\n promise: Promise<void>;\n key: string;\n};\n\ntype GlobalWithCloneWorkerMemo = typeof globalThis & {\n [CLONE_WORKER_MEMO]?: CloneWorkerMemo;\n};\n\nfunction readCloneWorkerMemo(): CloneWorkerMemo | undefined {\n return (globalThis as GlobalWithCloneWorkerMemo)[CLONE_WORKER_MEMO];\n}\n\nfunction writeCloneWorkerMemo(memo: CloneWorkerMemo | undefined): void {\n const g = globalThis as GlobalWithCloneWorkerMemo;\n if (memo === undefined) delete g[CLONE_WORKER_MEMO];\n else g[CLONE_WORKER_MEMO] = memo;\n}\n\nfunction resolveWorkerName(options: CloneWorkerDatabaseOptions): string {\n return (\n options.name ?? process.env.JEST_WORKER_ID ?? process.env.VITEST_POOL_ID ?? String(process.pid)\n );\n}\n\nfunction workerOptionsKey(root: string | undefined, name: string): string {\n return `${root ?? \"\"}\\0${name}`;\n}\n\n/**\n * Process-once per-worker clone (JEST_WORKER_ID / VITEST_POOL_ID / pid by default).\n * Uses `cloneFromTemplateIfNeeded` (same skip policy as `acquireIfNeeded`) with `setEnv: true`.\n * First call wins for `root`/`name`; conflicting later calls throw.\n *\n * Memo lives on `globalThis` so Jest `setupFiles` (module reload per file) still\n * shares one clone per worker. `setupFilesAfterEnv` + `beforeAll` also works.\n */\nexport function cloneWorkerDatabase(options: CloneWorkerDatabaseOptions = {}): Promise<void> {\n const name = resolveWorkerName(options);\n const key = workerOptionsKey(options.root, name);\n const existing = readCloneWorkerMemo();\n if (existing) {\n if (existing.key !== key) {\n throw new Error(\n `cloneWorkerDatabase already started with different root/name ` +\n `(first: ${JSON.stringify(existing.key)}, now: ${JSON.stringify(key)})`,\n );\n }\n return existing.promise;\n }\n const promise = (async () => {\n await cloneFromTemplateIfNeeded({\n root: options.root,\n mode: \"test\",\n name,\n setEnv: true,\n });\n })().catch((err) => {\n writeCloneWorkerMemo(undefined);\n throw err;\n });\n writeCloneWorkerMemo({ promise, key });\n return promise;\n}\n"],"mappings":";;;;;;;;;;AA0BA,eAAsB,kBACpB,SACgC;CAChC,MAAM,SAAS,MAAM,gBAAgB;EACnC,MAAM,QAAQ;EACd,MAAM;EACN,QAAQ,QAAQ,WAAW;CAC7B,CAAC;CACD,IAAI,OAAO,WAAW,YAAY,OAAO;CAEzC,IAAI;EACF,MAAM,QAAQ,QAAQ;GACpB,aAAa,OAAO;GACpB,UAAU,OAAO;GACjB,cAAc,OAAO;GACrB,UAAU,OAAO;EACnB,CAAC;EACD,MAAM,aAAa;GACjB,MAAM,OAAO;GACb,MAAM;GACN,UAAU,OAAO;EACnB,CAAC;CACH,SAAS,KAAK;EACZ,IAAI;GACF,MAAM,QAAQ;IAAE,MAAM,OAAO;IAAM,MAAM;GAAO,CAAC;EACnD,QAAQ,CAER;EACA,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EAC9D,MAAM,IAAI,MACR,6DAA6D,OAAO,aAAa,+BAClD,UAC/B,EAAE,OAAO,IAAI,CACf;CACF;CAEA,OAAO;AACT;;AASA,MAAM,oBAAoB,OAAO,IAAI,iCAAiC;AAWtE,SAAS,sBAAmD;CAC1D,OAAQ,WAAyC;AACnD;AAEA,SAAS,qBAAqB,MAAyC;CACrE,MAAM,IAAI;CACV,IAAI,SAAS,KAAA,GAAW,OAAO,EAAE;MAC5B,EAAE,qBAAqB;AAC9B;AAEA,SAAS,kBAAkB,SAA6C;CACtE,OACE,QAAQ,QAAQ,QAAQ,IAAI,kBAAkB,QAAQ,IAAI,kBAAkB,OAAO,QAAQ,GAAG;AAElG;AAEA,SAAS,iBAAiB,MAA0B,MAAsB;CACxE,OAAO,GAAG,QAAQ,GAAG,IAAI;AAC3B;;;;;;;;;AAUA,SAAgB,oBAAoB,UAAsC,CAAC,GAAkB;CAC3F,MAAM,OAAO,kBAAkB,OAAO;CACtC,MAAM,MAAM,iBAAiB,QAAQ,MAAM,IAAI;CAC/C,MAAM,WAAW,oBAAoB;CACrC,IAAI,UAAU;EACZ,IAAI,SAAS,QAAQ,KACnB,MAAM,IAAI,MACR,wEACa,KAAK,UAAU,SAAS,GAAG,EAAE,SAAS,KAAK,UAAU,GAAG,EAAE,EACzE;EAEF,OAAO,SAAS;CAClB;CACA,MAAM,WAAW,YAAY;EAC3B,MAAM,0BAA0B;GAC9B,MAAM,QAAQ;GACd,MAAM;GACN;GACA,QAAQ;EACV,CAAC;CACH,EAAA,CAAG,CAAC,CAAC,OAAO,QAAQ;EAClB,qBAAqB,KAAA,CAAS;EAC9B,MAAM;CACR,CAAC;CACD,qBAAqB;EAAE;EAAS;CAAI,CAAC;CACrC,OAAO;AACT"}
|
|
@@ -21,8 +21,11 @@ type CloneWorkerDatabaseOptions = {
|
|
|
21
21
|
* Process-once per-worker clone (JEST_WORKER_ID / VITEST_POOL_ID / pid by default).
|
|
22
22
|
* Uses `cloneFromTemplateIfNeeded` (same skip policy as `acquireIfNeeded`) with `setEnv: true`.
|
|
23
23
|
* First call wins for `root`/`name`; conflicting later calls throw.
|
|
24
|
+
*
|
|
25
|
+
* Memo lives on `globalThis` so Jest `setupFiles` (module reload per file) still
|
|
26
|
+
* shares one clone per worker. `setupFilesAfterEnv` + `beforeAll` also works.
|
|
24
27
|
*/
|
|
25
28
|
declare function cloneWorkerDatabase(options?: CloneWorkerDatabaseOptions): Promise<void>;
|
|
26
29
|
//#endregion
|
|
27
30
|
export { cloneWorkerDatabase as i, TemplateMigrateContext as n, TemplateMigrateFn as r, SetupTemplateModeOptions as t };
|
|
28
|
-
//# sourceMappingURL=template-mode-
|
|
31
|
+
//# sourceMappingURL=template-mode-CzyVwHsi.d.cts.map
|
|
@@ -21,8 +21,11 @@ type CloneWorkerDatabaseOptions = {
|
|
|
21
21
|
* Process-once per-worker clone (JEST_WORKER_ID / VITEST_POOL_ID / pid by default).
|
|
22
22
|
* Uses `cloneFromTemplateIfNeeded` (same skip policy as `acquireIfNeeded`) with `setEnv: true`.
|
|
23
23
|
* First call wins for `root`/`name`; conflicting later calls throw.
|
|
24
|
+
*
|
|
25
|
+
* Memo lives on `globalThis` so Jest `setupFiles` (module reload per file) still
|
|
26
|
+
* shares one clone per worker. `setupFilesAfterEnv` + `beforeAll` also works.
|
|
24
27
|
*/
|
|
25
28
|
declare function cloneWorkerDatabase(options?: CloneWorkerDatabaseOptions): Promise<void>;
|
|
26
29
|
//#endregion
|
|
27
30
|
export { cloneWorkerDatabase as i, TemplateMigrateContext as n, TemplateMigrateFn as r, SetupTemplateModeOptions as t };
|
|
28
|
-
//# sourceMappingURL=template-mode-
|
|
31
|
+
//# sourceMappingURL=template-mode-CzyVwHsi.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_lifecycle = require("./lifecycle-
|
|
2
|
-
const require_template = require("./template-
|
|
1
|
+
const require_lifecycle = require("./lifecycle-BbrvFQvg.cjs");
|
|
2
|
+
const require_template = require("./template-CXMpODzK.cjs");
|
|
3
3
|
//#region src/adapters/template-mode.ts
|
|
4
4
|
/**
|
|
5
5
|
* Runner orchestration: acquire → migrate → markTemplate.
|
|
@@ -39,8 +39,16 @@ async function setupTemplateMode(options) {
|
|
|
39
39
|
}
|
|
40
40
|
return result;
|
|
41
41
|
}
|
|
42
|
-
let
|
|
43
|
-
|
|
42
|
+
/** Survives Jest `setupFiles` module reloads (module-scoped `let` does not). */
|
|
43
|
+
const CLONE_WORKER_MEMO = Symbol.for("@cedarjs/pg/cloneWorkerDatabase");
|
|
44
|
+
function readCloneWorkerMemo() {
|
|
45
|
+
return globalThis[CLONE_WORKER_MEMO];
|
|
46
|
+
}
|
|
47
|
+
function writeCloneWorkerMemo(memo) {
|
|
48
|
+
const g = globalThis;
|
|
49
|
+
if (memo === void 0) delete g[CLONE_WORKER_MEMO];
|
|
50
|
+
else g[CLONE_WORKER_MEMO] = memo;
|
|
51
|
+
}
|
|
44
52
|
function resolveWorkerName(options) {
|
|
45
53
|
return options.name ?? process.env.JEST_WORKER_ID ?? process.env.VITEST_POOL_ID ?? String(process.pid);
|
|
46
54
|
}
|
|
@@ -51,16 +59,19 @@ function workerOptionsKey(root, name) {
|
|
|
51
59
|
* Process-once per-worker clone (JEST_WORKER_ID / VITEST_POOL_ID / pid by default).
|
|
52
60
|
* Uses `cloneFromTemplateIfNeeded` (same skip policy as `acquireIfNeeded`) with `setEnv: true`.
|
|
53
61
|
* First call wins for `root`/`name`; conflicting later calls throw.
|
|
62
|
+
*
|
|
63
|
+
* Memo lives on `globalThis` so Jest `setupFiles` (module reload per file) still
|
|
64
|
+
* shares one clone per worker. `setupFilesAfterEnv` + `beforeAll` also works.
|
|
54
65
|
*/
|
|
55
66
|
function cloneWorkerDatabase(options = {}) {
|
|
56
67
|
const name = resolveWorkerName(options);
|
|
57
68
|
const key = workerOptionsKey(options.root, name);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
const existing = readCloneWorkerMemo();
|
|
70
|
+
if (existing) {
|
|
71
|
+
if (existing.key !== key) throw new Error(`cloneWorkerDatabase already started with different root/name (first: ${JSON.stringify(existing.key)}, now: ${JSON.stringify(key)})`);
|
|
72
|
+
return existing.promise;
|
|
61
73
|
}
|
|
62
|
-
|
|
63
|
-
workerOnce = (async () => {
|
|
74
|
+
const promise = (async () => {
|
|
64
75
|
await require_template.cloneFromTemplateIfNeeded({
|
|
65
76
|
root: options.root,
|
|
66
77
|
mode: "test",
|
|
@@ -68,11 +79,14 @@ function cloneWorkerDatabase(options = {}) {
|
|
|
68
79
|
setEnv: true
|
|
69
80
|
});
|
|
70
81
|
})().catch((err) => {
|
|
71
|
-
|
|
72
|
-
workerOnceKey = void 0;
|
|
82
|
+
writeCloneWorkerMemo(void 0);
|
|
73
83
|
throw err;
|
|
74
84
|
});
|
|
75
|
-
|
|
85
|
+
writeCloneWorkerMemo({
|
|
86
|
+
promise,
|
|
87
|
+
key
|
|
88
|
+
});
|
|
89
|
+
return promise;
|
|
76
90
|
}
|
|
77
91
|
//#endregion
|
|
78
92
|
Object.defineProperty(exports, "cloneWorkerDatabase", {
|
|
@@ -88,4 +102,4 @@ Object.defineProperty(exports, "setupTemplateMode", {
|
|
|
88
102
|
}
|
|
89
103
|
});
|
|
90
104
|
|
|
91
|
-
//# sourceMappingURL=template-mode-
|
|
105
|
+
//# sourceMappingURL=template-mode-JTOxrEgE.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-mode-JTOxrEgE.cjs","names":["acquireIfNeeded","markTemplate","dispose","cloneFromTemplateIfNeeded"],"sources":["../src/adapters/template-mode.ts"],"sourcesContent":["import { dispose, acquireIfNeeded, type AcquireIfNeededResult } from \"../core/lifecycle.ts\";\nimport { cloneFromTemplateIfNeeded, markTemplate } from \"../core/template.ts\";\n\nexport type TemplateMigrateContext = {\n databaseUrl: string;\n adminUrl: string;\n databaseName: string;\n roleName: string;\n};\n\nexport type TemplateMigrateFn = (ctx: TemplateMigrateContext) => void | Promise<void>;\n\nexport type SetupTemplateModeOptions = {\n root?: string;\n /** App-owned migrate; runs once, then `markTemplate`. Required. */\n migrate: TemplateMigrateFn;\n setEnv?: boolean;\n};\n\n/**\n * Runner orchestration: acquire → migrate → markTemplate.\n * After acquire succeeds, migrate + markTemplate are all-or-nothing: any failure\n * best-effort disposes the lease so Vitest (no separate teardown) does not leak.\n * Programmatic apps that do not need a migrate hook should call core\n * `acquire` + `markTemplate` + `cloneFromTemplate` + `dispose` instead.\n */\nexport async function setupTemplateMode(\n options: SetupTemplateModeOptions,\n): Promise<AcquireIfNeededResult> {\n const result = await acquireIfNeeded({\n root: options.root,\n mode: \"test\",\n setEnv: options.setEnv !== false,\n });\n if (result.status !== \"acquired\") return result;\n\n try {\n await options.migrate({\n databaseUrl: result.databaseUrl,\n adminUrl: result.adminUrl,\n databaseName: result.databaseName,\n roleName: result.roleName,\n });\n await markTemplate({\n root: result.root,\n mode: \"test\",\n adminUrl: result.adminUrl,\n });\n } catch (err) {\n try {\n await dispose({ root: result.root, mode: \"test\" });\n } catch {\n // best-effort: leave lease for dispose/gc retry\n }\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(\n `template setup failed after acquire; cleaned up lease DB (${result.databaseName}). ` +\n `Fix the error and re-run: ${detail}`,\n { cause: err },\n );\n }\n\n return result;\n}\n\nexport type CloneWorkerDatabaseOptions = {\n root?: string;\n /** Clone suffix; defaults to JEST_WORKER_ID / VITEST_POOL_ID / pid. */\n name?: string;\n};\n\n/** Survives Jest `setupFiles` module reloads (module-scoped `let` does not). */\nconst CLONE_WORKER_MEMO = Symbol.for(\"@cedarjs/pg/cloneWorkerDatabase\");\n\ntype CloneWorkerMemo = {\n promise: Promise<void>;\n key: string;\n};\n\ntype GlobalWithCloneWorkerMemo = typeof globalThis & {\n [CLONE_WORKER_MEMO]?: CloneWorkerMemo;\n};\n\nfunction readCloneWorkerMemo(): CloneWorkerMemo | undefined {\n return (globalThis as GlobalWithCloneWorkerMemo)[CLONE_WORKER_MEMO];\n}\n\nfunction writeCloneWorkerMemo(memo: CloneWorkerMemo | undefined): void {\n const g = globalThis as GlobalWithCloneWorkerMemo;\n if (memo === undefined) delete g[CLONE_WORKER_MEMO];\n else g[CLONE_WORKER_MEMO] = memo;\n}\n\nfunction resolveWorkerName(options: CloneWorkerDatabaseOptions): string {\n return (\n options.name ?? process.env.JEST_WORKER_ID ?? process.env.VITEST_POOL_ID ?? String(process.pid)\n );\n}\n\nfunction workerOptionsKey(root: string | undefined, name: string): string {\n return `${root ?? \"\"}\\0${name}`;\n}\n\n/**\n * Process-once per-worker clone (JEST_WORKER_ID / VITEST_POOL_ID / pid by default).\n * Uses `cloneFromTemplateIfNeeded` (same skip policy as `acquireIfNeeded`) with `setEnv: true`.\n * First call wins for `root`/`name`; conflicting later calls throw.\n *\n * Memo lives on `globalThis` so Jest `setupFiles` (module reload per file) still\n * shares one clone per worker. `setupFilesAfterEnv` + `beforeAll` also works.\n */\nexport function cloneWorkerDatabase(options: CloneWorkerDatabaseOptions = {}): Promise<void> {\n const name = resolveWorkerName(options);\n const key = workerOptionsKey(options.root, name);\n const existing = readCloneWorkerMemo();\n if (existing) {\n if (existing.key !== key) {\n throw new Error(\n `cloneWorkerDatabase already started with different root/name ` +\n `(first: ${JSON.stringify(existing.key)}, now: ${JSON.stringify(key)})`,\n );\n }\n return existing.promise;\n }\n const promise = (async () => {\n await cloneFromTemplateIfNeeded({\n root: options.root,\n mode: \"test\",\n name,\n setEnv: true,\n });\n })().catch((err) => {\n writeCloneWorkerMemo(undefined);\n throw err;\n });\n writeCloneWorkerMemo({ promise, key });\n return promise;\n}\n"],"mappings":";;;;;;;;;;AA0BA,eAAsB,kBACpB,SACgC;CAChC,MAAM,SAAS,MAAMA,kBAAAA,gBAAgB;EACnC,MAAM,QAAQ;EACd,MAAM;EACN,QAAQ,QAAQ,WAAW;CAC7B,CAAC;CACD,IAAI,OAAO,WAAW,YAAY,OAAO;CAEzC,IAAI;EACF,MAAM,QAAQ,QAAQ;GACpB,aAAa,OAAO;GACpB,UAAU,OAAO;GACjB,cAAc,OAAO;GACrB,UAAU,OAAO;EACnB,CAAC;EACD,MAAMC,iBAAAA,aAAa;GACjB,MAAM,OAAO;GACb,MAAM;GACN,UAAU,OAAO;EACnB,CAAC;CACH,SAAS,KAAK;EACZ,IAAI;GACF,MAAMC,kBAAAA,QAAQ;IAAE,MAAM,OAAO;IAAM,MAAM;GAAO,CAAC;EACnD,QAAQ,CAER;EACA,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EAC9D,MAAM,IAAI,MACR,6DAA6D,OAAO,aAAa,+BAClD,UAC/B,EAAE,OAAO,IAAI,CACf;CACF;CAEA,OAAO;AACT;;AASA,MAAM,oBAAoB,OAAO,IAAI,iCAAiC;AAWtE,SAAS,sBAAmD;CAC1D,OAAQ,WAAyC;AACnD;AAEA,SAAS,qBAAqB,MAAyC;CACrE,MAAM,IAAI;CACV,IAAI,SAAS,KAAA,GAAW,OAAO,EAAE;MAC5B,EAAE,qBAAqB;AAC9B;AAEA,SAAS,kBAAkB,SAA6C;CACtE,OACE,QAAQ,QAAQ,QAAQ,IAAI,kBAAkB,QAAQ,IAAI,kBAAkB,OAAO,QAAQ,GAAG;AAElG;AAEA,SAAS,iBAAiB,MAA0B,MAAsB;CACxE,OAAO,GAAG,QAAQ,GAAG,IAAI;AAC3B;;;;;;;;;AAUA,SAAgB,oBAAoB,UAAsC,CAAC,GAAkB;CAC3F,MAAM,OAAO,kBAAkB,OAAO;CACtC,MAAM,MAAM,iBAAiB,QAAQ,MAAM,IAAI;CAC/C,MAAM,WAAW,oBAAoB;CACrC,IAAI,UAAU;EACZ,IAAI,SAAS,QAAQ,KACnB,MAAM,IAAI,MACR,wEACa,KAAK,UAAU,SAAS,GAAG,EAAE,SAAS,KAAK,UAAU,GAAG,EAAE,EACzE;EAEF,OAAO,SAAS;CAClB;CACA,MAAM,WAAW,YAAY;EAC3B,MAAMC,iBAAAA,0BAA0B;GAC9B,MAAM,QAAQ;GACd,MAAM;GACN;GACA,QAAQ;EACV,CAAC;CACH,EAAA,CAAG,CAAC,CAAC,OAAO,QAAQ;EAClB,qBAAqB,KAAA,CAAS;EAC9B,MAAM;CACR,CAAC;CACD,qBAAqB;EAAE;EAAS;CAAI,CAAC;CACrC,OAAO;AACT"}
|
package/dist/test-env.cjs
CHANGED
package/dist/test-env.mjs
CHANGED
package/dist/vite-plus.cjs
CHANGED
|
@@ -1,18 +1,120 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
2
|
+
const require_lease = require("./lease-WlmOnNDi.cjs");
|
|
3
|
+
const require_status = require("./status-4Uz6A3LB.cjs");
|
|
4
|
+
const require_studio = require("./studio-oJE30_PO.cjs");
|
|
5
|
+
const require_tasks = require("./tasks-CNHvvlsN.cjs");
|
|
6
|
+
//#region src/adapters/vite-dev-plugin.ts
|
|
7
|
+
const requireVite = (0, require("node:module").createRequire)(require("url").pathToFileURL(__filename).href);
|
|
8
|
+
function installedViteVersion() {
|
|
9
|
+
try {
|
|
10
|
+
return requireVite("vite/package.json").version;
|
|
11
|
+
} catch {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function viteBindsPluginShortcuts(version) {
|
|
16
|
+
const resolved = version ?? installedViteVersion();
|
|
17
|
+
if (resolved === void 0) return false;
|
|
18
|
+
return Number.parseInt(resolved, 10) >= 8;
|
|
19
|
+
}
|
|
20
|
+
function shouldShowPanel() {
|
|
21
|
+
return Boolean(process.stdin.isTTY) && !process.env.CI;
|
|
22
|
+
}
|
|
23
|
+
function logStatus(server, options) {
|
|
24
|
+
const status = require_status.resolveDevStatus({
|
|
25
|
+
root: options.root,
|
|
26
|
+
mode: options.mode
|
|
27
|
+
});
|
|
28
|
+
for (const line of require_studio.formatDevStatus(status)) if (status.ok) server.config.logger.info(line);
|
|
29
|
+
else server.config.logger.warn(line);
|
|
30
|
+
return status;
|
|
31
|
+
}
|
|
32
|
+
function createStudioLauncher(options) {
|
|
33
|
+
let studioChild;
|
|
34
|
+
const prefer = options.studio === false ? void 0 : options.studio;
|
|
35
|
+
return (s) => {
|
|
36
|
+
const status = logStatus(s, options);
|
|
37
|
+
if (!status.ok) return;
|
|
38
|
+
const studio = require_studio.detectStudio({
|
|
39
|
+
root: status.root,
|
|
40
|
+
cwd: options.cwd ?? s.config.root,
|
|
41
|
+
prefer
|
|
42
|
+
});
|
|
43
|
+
if (!studio) {
|
|
44
|
+
s.config.logger.warn(`${require_lease.CLI_NAME}: no Prisma or Drizzle Studio found (install prisma or drizzle-kit)`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (require_studio.studioChildRunning(studioChild)) {
|
|
48
|
+
s.config.logger.info(`${require_lease.CLI_NAME}: studio already running`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const child = require_studio.openStudio({
|
|
52
|
+
databaseUrl: status.databaseUrl,
|
|
53
|
+
studio
|
|
54
|
+
});
|
|
55
|
+
child.once("error", (err) => {
|
|
56
|
+
studioChild = void 0;
|
|
57
|
+
s.config.logger.error(`${require_lease.CLI_NAME}: studio failed: ${err.message}`);
|
|
58
|
+
});
|
|
59
|
+
child.once("exit", (code, signal) => {
|
|
60
|
+
studioChild = void 0;
|
|
61
|
+
if (code && code !== 0) s.config.logger.warn(`${require_lease.CLI_NAME}: studio exited ${code}`);
|
|
62
|
+
else if (signal) s.config.logger.warn(`${require_lease.CLI_NAME}: studio killed (${signal})`);
|
|
63
|
+
});
|
|
64
|
+
studioChild = child;
|
|
65
|
+
s.config.logger.info(`${require_lease.CLI_NAME}: opening ${studio.kind} studio (${studio.command} ${studio.args.join(" ")})`);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Vite / Vite+ plugin: print a cedar-pg status panel on listen and register
|
|
70
|
+
* CLI shortcuts (`d` status, `s` studio) on Vite 8+. Does **not** acquire —
|
|
71
|
+
* pair with `cedarPgTasks()` / `dependsOn: ['db:acquire']`.
|
|
72
|
+
*
|
|
73
|
+
* @param viteVersion Test-only override for the shortcut gate. Omit in production.
|
|
74
|
+
*/
|
|
75
|
+
function cedarPgDev(options = {}, viteVersion) {
|
|
76
|
+
return {
|
|
77
|
+
name: "cedar-pg-dev",
|
|
78
|
+
configureServer(server) {
|
|
79
|
+
if (shouldShowPanel() && server.httpServer) server.httpServer.once("listening", () => {
|
|
80
|
+
logStatus(server, options);
|
|
81
|
+
});
|
|
82
|
+
if (!viteBindsPluginShortcuts(viteVersion)) return;
|
|
83
|
+
const dShortcut = {
|
|
84
|
+
key: "d",
|
|
85
|
+
description: "show cedar-pg database status",
|
|
86
|
+
action(s) {
|
|
87
|
+
logStatus(s, options);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const shortcuts = options.studio === false ? [dShortcut] : [dShortcut, {
|
|
91
|
+
key: "s",
|
|
92
|
+
description: "open Prisma/Drizzle studio (cedar-pg DATABASE_URL)",
|
|
93
|
+
action: createStudioLauncher(options)
|
|
94
|
+
}];
|
|
95
|
+
server.bindCLIShortcuts({
|
|
96
|
+
print: false,
|
|
97
|
+
customShortcuts: shortcuts
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
3
103
|
//#region src/adapters/vite-plus.ts
|
|
4
104
|
/**
|
|
5
105
|
* Consumer adapter for external Vite+ projects.
|
|
6
106
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
107
|
+
* - `cedarPgTasks()` — merge into `run.tasks` so `vp run test` / `vp run dev`
|
|
108
|
+
* depend on cedarpg acquire.
|
|
109
|
+
* - `cedarPgDev()` — Vite plugin: status panel + `d` / `s` shortcuts on Vite 8 (no acquire).
|
|
9
110
|
*
|
|
10
111
|
* @example
|
|
11
112
|
* ```ts
|
|
12
113
|
* import { defineConfig } from 'vite-plus'
|
|
13
|
-
* import { cedarPgTasks } from '@cedarjs/pg/vite-plus'
|
|
114
|
+
* import { cedarPgTasks, cedarPgDev } from '@cedarjs/pg/vite-plus'
|
|
14
115
|
*
|
|
15
116
|
* export default defineConfig({
|
|
117
|
+
* plugins: [cedarPgDev()],
|
|
16
118
|
* run: {
|
|
17
119
|
* tasks: {
|
|
18
120
|
* ...cedarPgTasks(),
|
|
@@ -35,6 +137,7 @@ const require_tasks = require("./tasks-Caud9yHr.cjs");
|
|
|
35
137
|
exports.CEDAR_PG_TASK_ACQUIRE_DEV = require_tasks.CEDAR_PG_TASK_ACQUIRE_DEV;
|
|
36
138
|
exports.CEDAR_PG_TASK_ACQUIRE_TEST = require_tasks.CEDAR_PG_TASK_ACQUIRE_TEST;
|
|
37
139
|
exports.CEDAR_PG_TASK_DISPOSE_TEST = require_tasks.CEDAR_PG_TASK_DISPOSE_TEST;
|
|
140
|
+
exports.cedarPgDev = cedarPgDev;
|
|
38
141
|
exports.cedarPgTasks = require_tasks.cedarPgLifecycleTargets;
|
|
39
142
|
|
|
40
143
|
//# sourceMappingURL=vite-plus.cjs.map
|
package/dist/vite-plus.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-plus.cjs","names":[],"sources":["../src/adapters/vite-plus.ts"],"sourcesContent":["/**\n * Consumer adapter for external Vite+ projects.\n *\n *
|
|
1
|
+
{"version":3,"file":"vite-plus.cjs","names":["resolveDevStatus","formatDevStatus","detectStudio","CLI_NAME","studioChildRunning","openStudio"],"sources":["../src/adapters/vite-dev-plugin.ts","../src/adapters/vite-plus.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport type { ChildProcess } from \"node:child_process\";\nimport type { Plugin, ViteDevServer } from \"vite\";\nimport { CLI_NAME } from \"../core/constants.ts\";\nimport { resolveDevStatus, type DevStatus } from \"../core/status.ts\";\nimport type { DbMode } from \"../core/naming.ts\";\nimport { formatDevStatus } from \"./status-format.ts\";\nimport { detectStudio, openStudio, studioChildRunning, type StudioKind } from \"./studio.ts\";\n\nconst requireVite = createRequire(import.meta.url);\n\nfunction installedViteVersion(): string | undefined {\n try {\n return (requireVite(\"vite/package.json\") as { version: string }).version;\n } catch {\n return undefined;\n }\n}\n\nexport function viteBindsPluginShortcuts(version?: string): boolean {\n const resolved = version ?? installedViteVersion();\n if (resolved === undefined) return false;\n return Number.parseInt(resolved, 10) >= 8;\n}\n\nexport type CedarPgDevOptions = {\n mode?: DbMode;\n /** Worktree / lease root. Omit to resolve from cwd (git toplevel). */\n root?: string;\n /** App package to search for Prisma/Drizzle. Defaults to Vite `config.root`. */\n cwd?: string;\n /** Force Prisma/Drizzle Studio; `false` disables the `s` shortcut. Omit to auto-detect. */\n studio?: StudioKind | false;\n};\n\nfunction shouldShowPanel(): boolean {\n return Boolean(process.stdin.isTTY) && !process.env.CI;\n}\n\nfunction logStatus(server: ViteDevServer, options: CedarPgDevOptions): DevStatus {\n const status = resolveDevStatus({ root: options.root, mode: options.mode });\n for (const line of formatDevStatus(status)) {\n if (status.ok) server.config.logger.info(line);\n else server.config.logger.warn(line);\n }\n return status;\n}\n\nfunction createStudioLauncher(options: CedarPgDevOptions): (s: ViteDevServer) => void {\n let studioChild: ChildProcess | undefined;\n const prefer = options.studio === false ? undefined : options.studio;\n return (s) => {\n const status = logStatus(s, options);\n if (!status.ok) return;\n\n const studio = detectStudio({\n root: status.root,\n cwd: options.cwd ?? s.config.root,\n prefer,\n });\n if (!studio) {\n s.config.logger.warn(\n `${CLI_NAME}: no Prisma or Drizzle Studio found (install prisma or drizzle-kit)`,\n );\n return;\n }\n\n if (studioChildRunning(studioChild)) {\n s.config.logger.info(`${CLI_NAME}: studio already running`);\n return;\n }\n\n const child = openStudio({ databaseUrl: status.databaseUrl, studio });\n child.once(\"error\", (err) => {\n studioChild = undefined;\n s.config.logger.error(`${CLI_NAME}: studio failed: ${err.message}`);\n });\n child.once(\"exit\", (code, signal) => {\n studioChild = undefined;\n if (code && code !== 0) {\n s.config.logger.warn(`${CLI_NAME}: studio exited ${code}`);\n } else if (signal) {\n s.config.logger.warn(`${CLI_NAME}: studio killed (${signal})`);\n }\n });\n studioChild = child;\n s.config.logger.info(\n `${CLI_NAME}: opening ${studio.kind} studio (${studio.command} ${studio.args.join(\" \")})`,\n );\n };\n}\n\n/**\n * Vite / Vite+ plugin: print a cedar-pg status panel on listen and register\n * CLI shortcuts (`d` status, `s` studio) on Vite 8+. Does **not** acquire —\n * pair with `cedarPgTasks()` / `dependsOn: ['db:acquire']`.\n *\n * @param viteVersion Test-only override for the shortcut gate. Omit in production.\n */\nexport function cedarPgDev(options: CedarPgDevOptions = {}, viteVersion?: string): Plugin {\n return {\n name: \"cedar-pg-dev\",\n configureServer(server) {\n if (shouldShowPanel() && server.httpServer) {\n server.httpServer.once(\"listening\", () => {\n logStatus(server, options);\n });\n }\n\n if (!viteBindsPluginShortcuts(viteVersion)) {\n return;\n }\n\n const dShortcut = {\n key: \"d\",\n description: \"show cedar-pg database status\",\n action(s: ViteDevServer) {\n logStatus(s, options);\n },\n };\n const shortcuts =\n options.studio === false\n ? [dShortcut]\n : [\n dShortcut,\n {\n key: \"s\",\n description: \"open Prisma/Drizzle studio (cedar-pg DATABASE_URL)\",\n action: createStudioLauncher(options),\n },\n ];\n\n server.bindCLIShortcuts({\n print: false,\n customShortcuts: shortcuts,\n });\n },\n };\n}\n","/**\n * Consumer adapter for external Vite+ projects.\n *\n * - `cedarPgTasks()` — merge into `run.tasks` so `vp run test` / `vp run dev`\n * depend on cedarpg acquire.\n * - `cedarPgDev()` — Vite plugin: status panel + `d` / `s` shortcuts on Vite 8 (no acquire).\n *\n * @example\n * ```ts\n * import { defineConfig } from 'vite-plus'\n * import { cedarPgTasks, cedarPgDev } from '@cedarjs/pg/vite-plus'\n *\n * export default defineConfig({\n * plugins: [cedarPgDev()],\n * run: {\n * tasks: {\n * ...cedarPgTasks(),\n * test: {\n * command: 'vp test',\n * dependsOn: ['db:acquire-test'],\n * env: ['DATABASE_URL', 'TEST_DATABASE_URL'],\n * },\n * dev: {\n * command: 'vp dev',\n * dependsOn: ['db:acquire'],\n * env: ['DATABASE_URL'],\n * },\n * },\n * },\n * })\n * ```\n */\n\nimport {\n cedarPgLifecycleTargets,\n type CedarPgLifecycleTarget,\n type CedarPgLifecycleTargetsOptions,\n CEDAR_PG_TASK_DISPOSE_TEST,\n CEDAR_PG_TASK_ACQUIRE_DEV,\n CEDAR_PG_TASK_ACQUIRE_TEST,\n} from \"./tasks.ts\";\n\nexport {\n CEDAR_PG_TASK_ACQUIRE_DEV,\n CEDAR_PG_TASK_ACQUIRE_TEST,\n CEDAR_PG_TASK_DISPOSE_TEST,\n cedarPgLifecycleTargets as cedarPgTasks,\n};\n\nexport type CedarPgTaskDef = CedarPgLifecycleTarget;\nexport type CedarPgTasksOptions = CedarPgLifecycleTargetsOptions;\n\nexport { cedarPgDev } from \"./vite-dev-plugin.ts\";\nexport type { CedarPgDevOptions } from \"./vite-dev-plugin.ts\";\n"],"mappings":";;;;;;AASA,MAAM,eAAA,wBAAA,CAAA,CAAA,cAAA,CAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,IAA2C;AAEjD,SAAS,uBAA2C;CAClD,IAAI;EACF,OAAQ,YAAY,mBAAmB,CAAC,CAAyB;CACnE,QAAQ;EACN;CACF;AACF;AAEA,SAAgB,yBAAyB,SAA2B;CAClE,MAAM,WAAW,WAAW,qBAAqB;CACjD,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,OAAO,OAAO,SAAS,UAAU,EAAE,KAAK;AAC1C;AAYA,SAAS,kBAA2B;CAClC,OAAO,QAAQ,QAAQ,MAAM,KAAK,KAAK,CAAC,QAAQ,IAAI;AACtD;AAEA,SAAS,UAAU,QAAuB,SAAuC;CAC/E,MAAM,SAASA,eAAAA,iBAAiB;EAAE,MAAM,QAAQ;EAAM,MAAM,QAAQ;CAAK,CAAC;CAC1E,KAAK,MAAM,QAAQC,eAAAA,gBAAgB,MAAM,GACvC,IAAI,OAAO,IAAI,OAAO,OAAO,OAAO,KAAK,IAAI;MACxC,OAAO,OAAO,OAAO,KAAK,IAAI;CAErC,OAAO;AACT;AAEA,SAAS,qBAAqB,SAAwD;CACpF,IAAI;CACJ,MAAM,SAAS,QAAQ,WAAW,QAAQ,KAAA,IAAY,QAAQ;CAC9D,QAAQ,MAAM;EACZ,MAAM,SAAS,UAAU,GAAG,OAAO;EACnC,IAAI,CAAC,OAAO,IAAI;EAEhB,MAAM,SAASC,eAAAA,aAAa;GAC1B,MAAM,OAAO;GACb,KAAK,QAAQ,OAAO,EAAE,OAAO;GAC7B;EACF,CAAC;EACD,IAAI,CAAC,QAAQ;GACX,EAAE,OAAO,OAAO,KACd,GAAGC,cAAAA,SAAS,oEACd;GACA;EACF;EAEA,IAAIC,eAAAA,mBAAmB,WAAW,GAAG;GACnC,EAAE,OAAO,OAAO,KAAK,GAAGD,cAAAA,SAAS,yBAAyB;GAC1D;EACF;EAEA,MAAM,QAAQE,eAAAA,WAAW;GAAE,aAAa,OAAO;GAAa;EAAO,CAAC;EACpE,MAAM,KAAK,UAAU,QAAQ;GAC3B,cAAc,KAAA;GACd,EAAE,OAAO,OAAO,MAAM,GAAGF,cAAAA,SAAS,mBAAmB,IAAI,SAAS;EACpE,CAAC;EACD,MAAM,KAAK,SAAS,MAAM,WAAW;GACnC,cAAc,KAAA;GACd,IAAI,QAAQ,SAAS,GACnB,EAAE,OAAO,OAAO,KAAK,GAAGA,cAAAA,SAAS,kBAAkB,MAAM;QACpD,IAAI,QACT,EAAE,OAAO,OAAO,KAAK,GAAGA,cAAAA,SAAS,mBAAmB,OAAO,EAAE;EAEjE,CAAC;EACD,cAAc;EACd,EAAE,OAAO,OAAO,KACd,GAAGA,cAAAA,SAAS,YAAY,OAAO,KAAK,WAAW,OAAO,QAAQ,GAAG,OAAO,KAAK,KAAK,GAAG,EAAE,EACzF;CACF;AACF;;;;;;;;AASA,SAAgB,WAAW,UAA6B,CAAC,GAAG,aAA8B;CACxF,OAAO;EACL,MAAM;EACN,gBAAgB,QAAQ;GACtB,IAAI,gBAAgB,KAAK,OAAO,YAC9B,OAAO,WAAW,KAAK,mBAAmB;IACxC,UAAU,QAAQ,OAAO;GAC3B,CAAC;GAGH,IAAI,CAAC,yBAAyB,WAAW,GACvC;GAGF,MAAM,YAAY;IAChB,KAAK;IACL,aAAa;IACb,OAAO,GAAkB;KACvB,UAAU,GAAG,OAAO;IACtB;GACF;GACA,MAAM,YACJ,QAAQ,WAAW,QACf,CAAC,SAAS,IACV,CACE,WACA;IACE,KAAK;IACL,aAAa;IACb,QAAQ,qBAAqB,OAAO;GACtC,CACF;GAEN,OAAO,iBAAiB;IACtB,OAAO;IACP,iBAAiB;GACnB,CAAC;EACH;CACF;AACF"}
|
package/dist/vite-plus.d.cts
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
|
+
import { t as DbMode } from "./naming-C2nGVxPk.cjs";
|
|
1
2
|
import { a as CedarPgLifecycleTargetsOptions, i as CedarPgLifecycleTarget, n as CEDAR_PG_TASK_ACQUIRE_TEST, o as cedarPgLifecycleTargets, r as CEDAR_PG_TASK_DISPOSE_TEST, t as CEDAR_PG_TASK_ACQUIRE_DEV } from "./tasks-DdQoP9We.cjs";
|
|
3
|
+
import { Plugin } from "vite";
|
|
4
|
+
//#region src/adapters/studio.d.ts
|
|
5
|
+
type StudioKind = "prisma" | "drizzle";
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/adapters/vite-dev-plugin.d.ts
|
|
8
|
+
type CedarPgDevOptions = {
|
|
9
|
+
mode?: DbMode;
|
|
10
|
+
/** Worktree / lease root. Omit to resolve from cwd (git toplevel). */
|
|
11
|
+
root?: string;
|
|
12
|
+
/** App package to search for Prisma/Drizzle. Defaults to Vite `config.root`. */
|
|
13
|
+
cwd?: string;
|
|
14
|
+
/** Force Prisma/Drizzle Studio; `false` disables the `s` shortcut. Omit to auto-detect. */
|
|
15
|
+
studio?: StudioKind | false;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Vite / Vite+ plugin: print a cedar-pg status panel on listen and register
|
|
19
|
+
* CLI shortcuts (`d` status, `s` studio) on Vite 8+. Does **not** acquire —
|
|
20
|
+
* pair with `cedarPgTasks()` / `dependsOn: ['db:acquire']`.
|
|
21
|
+
*
|
|
22
|
+
* @param viteVersion Test-only override for the shortcut gate. Omit in production.
|
|
23
|
+
*/
|
|
24
|
+
declare function cedarPgDev(options?: CedarPgDevOptions, viteVersion?: string): Plugin;
|
|
25
|
+
//#endregion
|
|
2
26
|
//#region src/adapters/vite-plus.d.ts
|
|
3
27
|
type CedarPgTaskDef = CedarPgLifecycleTarget;
|
|
4
28
|
type CedarPgTasksOptions = CedarPgLifecycleTargetsOptions;
|
|
5
29
|
//#endregion
|
|
6
|
-
export { CEDAR_PG_TASK_ACQUIRE_DEV, CEDAR_PG_TASK_ACQUIRE_TEST, CEDAR_PG_TASK_DISPOSE_TEST, CedarPgTaskDef, CedarPgTasksOptions, cedarPgLifecycleTargets as cedarPgTasks };
|
|
30
|
+
export { CEDAR_PG_TASK_ACQUIRE_DEV, CEDAR_PG_TASK_ACQUIRE_TEST, CEDAR_PG_TASK_DISPOSE_TEST, type CedarPgDevOptions, CedarPgTaskDef, CedarPgTasksOptions, cedarPgDev, cedarPgLifecycleTargets as cedarPgTasks };
|
|
7
31
|
//# sourceMappingURL=vite-plus.d.cts.map
|
package/dist/vite-plus.d.mts
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
|
+
import { t as DbMode } from "./naming-C2nGVxPk.mjs";
|
|
1
2
|
import { a as CedarPgLifecycleTargetsOptions, i as CedarPgLifecycleTarget, n as CEDAR_PG_TASK_ACQUIRE_TEST, o as cedarPgLifecycleTargets, r as CEDAR_PG_TASK_DISPOSE_TEST, t as CEDAR_PG_TASK_ACQUIRE_DEV } from "./tasks-CjaZRi_G.mjs";
|
|
3
|
+
import { Plugin } from "vite";
|
|
4
|
+
//#region src/adapters/studio.d.ts
|
|
5
|
+
type StudioKind = "prisma" | "drizzle";
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/adapters/vite-dev-plugin.d.ts
|
|
8
|
+
type CedarPgDevOptions = {
|
|
9
|
+
mode?: DbMode;
|
|
10
|
+
/** Worktree / lease root. Omit to resolve from cwd (git toplevel). */
|
|
11
|
+
root?: string;
|
|
12
|
+
/** App package to search for Prisma/Drizzle. Defaults to Vite `config.root`. */
|
|
13
|
+
cwd?: string;
|
|
14
|
+
/** Force Prisma/Drizzle Studio; `false` disables the `s` shortcut. Omit to auto-detect. */
|
|
15
|
+
studio?: StudioKind | false;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Vite / Vite+ plugin: print a cedar-pg status panel on listen and register
|
|
19
|
+
* CLI shortcuts (`d` status, `s` studio) on Vite 8+. Does **not** acquire —
|
|
20
|
+
* pair with `cedarPgTasks()` / `dependsOn: ['db:acquire']`.
|
|
21
|
+
*
|
|
22
|
+
* @param viteVersion Test-only override for the shortcut gate. Omit in production.
|
|
23
|
+
*/
|
|
24
|
+
declare function cedarPgDev(options?: CedarPgDevOptions, viteVersion?: string): Plugin;
|
|
25
|
+
//#endregion
|
|
2
26
|
//#region src/adapters/vite-plus.d.ts
|
|
3
27
|
type CedarPgTaskDef = CedarPgLifecycleTarget;
|
|
4
28
|
type CedarPgTasksOptions = CedarPgLifecycleTargetsOptions;
|
|
5
29
|
//#endregion
|
|
6
|
-
export { CEDAR_PG_TASK_ACQUIRE_DEV, CEDAR_PG_TASK_ACQUIRE_TEST, CEDAR_PG_TASK_DISPOSE_TEST, CedarPgTaskDef, CedarPgTasksOptions, cedarPgLifecycleTargets as cedarPgTasks };
|
|
30
|
+
export { CEDAR_PG_TASK_ACQUIRE_DEV, CEDAR_PG_TASK_ACQUIRE_TEST, CEDAR_PG_TASK_DISPOSE_TEST, type CedarPgDevOptions, CedarPgTaskDef, CedarPgTasksOptions, cedarPgDev, cedarPgLifecycleTargets as cedarPgTasks };
|
|
7
31
|
//# sourceMappingURL=vite-plus.d.mts.map
|