prisma-next 0.6.0-dev.1 → 0.6.0-dev.11

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 (48) hide show
  1. package/dist/cli.mjs +5 -5
  2. package/dist/{client-qVH-rEgd.mjs → client-BCnP7cHo.mjs} +9 -119
  3. package/dist/client-BCnP7cHo.mjs.map +1 -0
  4. package/dist/commands/contract-infer.mjs +1 -1
  5. package/dist/commands/db-init.mjs +3 -3
  6. package/dist/commands/db-schema.mjs +1 -1
  7. package/dist/commands/db-sign.mjs +1 -1
  8. package/dist/commands/db-update.mjs +3 -3
  9. package/dist/commands/db-verify.mjs +1 -1
  10. package/dist/commands/migration-apply.d.mts +1 -1
  11. package/dist/commands/migration-apply.mjs +2 -2
  12. package/dist/commands/migration-plan.d.mts.map +1 -1
  13. package/dist/commands/migration-plan.mjs +1 -1
  14. package/dist/commands/migration-show.d.mts +55 -7
  15. package/dist/commands/migration-show.d.mts.map +1 -1
  16. package/dist/commands/migration-show.mjs +153 -46
  17. package/dist/commands/migration-show.mjs.map +1 -1
  18. package/dist/commands/migration-status.d.mts.map +1 -1
  19. package/dist/commands/migration-status.mjs +1 -1
  20. package/dist/{contract-infer-BK9YFGEG.mjs → contract-infer-ByxhPjpW.mjs} +2 -2
  21. package/dist/{contract-infer-BK9YFGEG.mjs.map → contract-infer-ByxhPjpW.mjs.map} +1 -1
  22. package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs +160 -0
  23. package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs.map +1 -0
  24. package/dist/{db-verify-C0y1PCO2.mjs → db-verify-Czm5T-J4.mjs} +2 -2
  25. package/dist/{db-verify-C0y1PCO2.mjs.map → db-verify-Czm5T-J4.mjs.map} +1 -1
  26. package/dist/exports/control-api.d.mts +1 -1
  27. package/dist/exports/control-api.mjs +1 -1
  28. package/dist/{init-DETSgw3h.mjs → init-BRKnARU6.mjs} +125 -25
  29. package/dist/init-BRKnARU6.mjs.map +1 -0
  30. package/dist/{inspect-live-schema-CWYxGKlb.mjs → inspect-live-schema-DxdBd4Er.mjs} +2 -2
  31. package/dist/{inspect-live-schema-CWYxGKlb.mjs.map → inspect-live-schema-DxdBd4Er.mjs.map} +1 -1
  32. package/dist/{migration-command-scaffold-B5dORFEv.mjs → migration-command-scaffold-BdV8JYXV.mjs} +2 -2
  33. package/dist/{migration-command-scaffold-B5dORFEv.mjs.map → migration-command-scaffold-BdV8JYXV.mjs.map} +1 -1
  34. package/dist/{migration-plan-C6lVaHsO.mjs → migration-plan-mRu5K81L.mjs} +89 -149
  35. package/dist/migration-plan-mRu5K81L.mjs.map +1 -0
  36. package/dist/{migration-status-CZ-D5k7k.mjs → migration-status-By9G5p2H.mjs} +6 -8
  37. package/dist/{migration-status-CZ-D5k7k.mjs.map → migration-status-By9G5p2H.mjs.map} +1 -1
  38. package/dist/{migrations-D_UJnpuW.mjs → migrations-CTsyBXCA.mjs} +42 -29
  39. package/dist/migrations-CTsyBXCA.mjs.map +1 -0
  40. package/dist/{types-D7x-IFLO.d.mts → types-LItU7E4l.d.mts} +7 -9
  41. package/dist/{types-D7x-IFLO.d.mts.map → types-LItU7E4l.d.mts.map} +1 -1
  42. package/package.json +10 -10
  43. package/dist/client-qVH-rEgd.mjs.map +0 -1
  44. package/dist/extension-pack-inputs-C7xgE-vv.mjs +0 -74
  45. package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +0 -1
  46. package/dist/init-DETSgw3h.mjs.map +0 -1
  47. package/dist/migration-plan-C6lVaHsO.mjs.map +0 -1
  48. package/dist/migrations-D_UJnpuW.mjs.map +0 -1
@@ -0,0 +1,160 @@
1
+ import { t as CliStructuredError } from "./cli-errors-D3_sMh2K.mjs";
2
+ import { notOk, ok } from "@prisma-next/utils/result";
3
+ import { loadContractSpaceAggregate } from "@prisma-next/migration-tools/aggregate";
4
+ //#region src/utils/extension-pack-inputs.ts
5
+ /**
6
+ * Project the CLI's `Config.extensionPacks` array into the canonical
7
+ * {@link ExtensionPackInput} shape. The single `as ExtensionPackLike`
8
+ * structural cast in the CLI lives inside this function.
9
+ */
10
+ function toExtensionInputs(extensionPacks) {
11
+ return extensionPacks.map((raw) => {
12
+ const pack = raw;
13
+ if (pack.contractSpace === void 0) return {
14
+ id: pack.id,
15
+ targetId: pack.targetId
16
+ };
17
+ return {
18
+ id: pack.id,
19
+ targetId: pack.targetId,
20
+ contractSpace: {
21
+ contractJson: pack.contractSpace.contractJson,
22
+ headRef: pack.contractSpace.headRef,
23
+ migrations: pack.contractSpace.migrations ?? []
24
+ }
25
+ };
26
+ });
27
+ }
28
+ /**
29
+ * Minimal aggregate-loader projection that extracts `id` + `targetId`
30
+ * from raw extension pack descriptors **without invoking any
31
+ * `contractSpace` accessor**. Inspects the own-property descriptor so
32
+ * that getter-backed `contractSpace` declarations are detected but
33
+ * never called.
34
+ *
35
+ * Inclusion semantics match {@link toDeclaredExtensions}: a data
36
+ * property whose value is explicitly `undefined` is treated as "no
37
+ * contract-space declaration" and skipped, mirroring the
38
+ * `pack.contractSpace === undefined` check used on canonicalised
39
+ * inputs. Prototype-chain `contractSpace` properties (no own
40
+ * descriptor) are also skipped.
41
+ *
42
+ * This variant must be used by `buildContractSpaceAggregate` so that
43
+ * the aggregate path (including `db verify`) never reads
44
+ * `contractSpace.contractJson` from extension descriptors — the loader
45
+ * always reads the contract from on-disk artefacts instead.
46
+ */
47
+ function toDeclaredExtensionsFromRaw(extensionPacks) {
48
+ const entries = [];
49
+ for (const raw of extensionPacks) {
50
+ if (typeof raw !== "object" || raw === null) continue;
51
+ const descriptor = Object.getOwnPropertyDescriptor(raw, "contractSpace");
52
+ if (descriptor === void 0) continue;
53
+ if ("value" in descriptor && descriptor.value === void 0) continue;
54
+ const pack = raw;
55
+ entries.push({
56
+ id: pack.id,
57
+ targetId: pack.targetId
58
+ });
59
+ }
60
+ return entries;
61
+ }
62
+ //#endregion
63
+ //#region src/utils/contract-space-aggregate-loader.ts
64
+ /**
65
+ * Render a {@link LoadAggregateError} into a CLI structured-error
66
+ * envelope. Preserves error codes `5001` (layout) and `5002` (marker /
67
+ * disjointness / etc.) so existing integration tests and downstream
68
+ * tooling continue to assert on the same `meta.violations[]` shape
69
+ * they did under the old precheck/marker-check helpers.
70
+ */
71
+ function mapLoadAggregateError(error) {
72
+ if (error.kind === "layoutViolation") {
73
+ const lines = error.violations.map((v) => `- [${v.kind}] ${v.spaceId}`);
74
+ return new CliStructuredError("5001", error.violations.length === 1 ? "Contract-space layout violation detected" : `Contract-space layout violations detected (${error.violations.length})`, {
75
+ domain: "MIG",
76
+ why: `The on-disk \`migrations/\` directory and your \`extensionPacks\` declaration are not in agreement.\n${lines.join("\n")}`,
77
+ fix: "Run `prisma-next migrate` to materialise on-disk artefacts for declared extensions, or remove the orphan directory.",
78
+ docsUrl: "https://pris.ly/contract-spaces",
79
+ meta: { violations: error.violations.map((v) => ({
80
+ kind: v.kind,
81
+ spaceId: v.spaceId
82
+ })) }
83
+ });
84
+ }
85
+ if (error.kind === "disjointnessViolation") return new CliStructuredError("5002", `Contract-space disjointness violation: storage element "${error.element}" claimed by multiple spaces`, {
86
+ domain: "MIG",
87
+ why: `Spaces ${error.claimedBy.map((s) => `"${s}"`).join(", ")} all claim the storage element "${error.element}". Each storage element must be owned by exactly one contract space.`,
88
+ fix: "Update the conflicting contracts so each storage element is claimed by exactly one space.",
89
+ docsUrl: "https://pris.ly/contract-spaces",
90
+ meta: { violations: [{
91
+ kind: "disjointness",
92
+ spaceId: error.claimedBy.join(","),
93
+ element: error.element,
94
+ claimedBy: error.claimedBy
95
+ }] }
96
+ });
97
+ if (error.kind === "integrityFailure") return new CliStructuredError("5002", `Contract-space integrity failure for "${error.spaceId}"`, {
98
+ domain: "MIG",
99
+ why: error.detail,
100
+ fix: "Run `prisma-next migrate` to refresh on-disk artefacts, or restore the on-disk `migrations/` directory from version control.",
101
+ docsUrl: "https://pris.ly/contract-spaces",
102
+ meta: { violations: [{
103
+ kind: "integrity",
104
+ spaceId: error.spaceId,
105
+ detail: error.detail
106
+ }] }
107
+ });
108
+ if (error.kind === "validationFailure") return new CliStructuredError("5002", `Contract-space contract validation failed for "${error.spaceId}"`, {
109
+ domain: "MIG",
110
+ why: error.detail,
111
+ fix: "Run `prisma-next migrate` to refresh on-disk artefacts, or fix the extension descriptor producing the invalid contract.",
112
+ meta: { violations: [{
113
+ kind: "validation",
114
+ spaceId: error.spaceId,
115
+ detail: error.detail
116
+ }] }
117
+ });
118
+ return new CliStructuredError("5002", `Contract-space target mismatch for "${error.spaceId}"`, {
119
+ domain: "MIG",
120
+ why: `Space "${error.spaceId}" targets "${error.actual}" but the project's adapter targets "${error.expected}".`,
121
+ fix: "Update the extension descriptor to target the configured database, or change the project adapter.",
122
+ meta: { violations: [{
123
+ kind: "targetMismatch",
124
+ spaceId: error.spaceId,
125
+ expected: error.expected,
126
+ actual: error.actual
127
+ }] }
128
+ });
129
+ }
130
+ /**
131
+ * Run the aggregate loader at the CLI surface, mapping any
132
+ * {@link LoadAggregateError} into a {@link CliStructuredError} envelope.
133
+ *
134
+ * App-side migration packages flow through `inputs.appMigrationPackages`
135
+ * (defaulting to `[]`). `db init` / `db update` leave it empty: the
136
+ * planner's `synth` strategy is used for the app member (driven by
137
+ * `callerPolicy.ignoreGraphFor`), so the app's authored `migrations/`
138
+ * graph does not need to be walked. `migration apply` threads the
139
+ * already-loaded app-space packages through so the graph-walk strategy
140
+ * can plot a path through them — replay forbids synth.
141
+ *
142
+ * @see specs/contract-space-aggregate-spec.md § Loader.
143
+ */
144
+ async function buildContractSpaceAggregate(inputs) {
145
+ const declaredExtensions = toDeclaredExtensionsFromRaw(inputs.extensionPacks);
146
+ const result = await loadContractSpaceAggregate({
147
+ targetId: inputs.targetId,
148
+ migrationsDir: inputs.migrationsDir,
149
+ appContract: inputs.appContract,
150
+ declaredExtensions,
151
+ validateContract: inputs.validateContract,
152
+ appMigrationPackages: inputs.appMigrationPackages ?? []
153
+ });
154
+ if (!result.ok) return notOk(mapLoadAggregateError(result.failure));
155
+ return ok(result.value.aggregate);
156
+ }
157
+ //#endregion
158
+ export { toExtensionInputs as n, buildContractSpaceAggregate as t };
159
+
160
+ //# sourceMappingURL=contract-space-aggregate-loader-BrwKK6Q6.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-space-aggregate-loader-BrwKK6Q6.mjs","names":[],"sources":["../src/utils/extension-pack-inputs.ts","../src/utils/contract-space-aggregate-loader.ts"],"sourcesContent":["/**\n * Single descriptor-import boundary for CLI consumers of `Config.extensionPacks`.\n *\n * Every CLI command / utility that reads an extension descriptor's\n * `contractSpace` projection (loader, migrate-pass, extension-migrations\n * pass, migration commands) goes through {@link toExtensionInputs}. The\n * structural cast `pack as { contractSpace?: ... }` lives **only** here —\n * downstream code consumes the canonical shape and maps it to its own\n * narrower shape via the per-consumer adapters below.\n *\n * The CLI receives extension descriptors typed against the SQL family\n * (or any other family in the future); this helper only depends on the\n * structural shape of `contractSpace`. SQL-family callers pass the same\n * `contractJson` / `headRef.hash` value through unchanged.\n */\nimport type { DeclaredExtensionEntry } from '@prisma-next/migration-tools/aggregate';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport type { MigrationOps } from '@prisma-next/migration-tools/package';\n\n/**\n * In-memory authored migration package shipped by an extension descriptor.\n * Mirrors the `MigrationPackage` shape from\n * `@prisma-next/framework-components/control` minus `dirPath`; redeclared\n * structurally here so the helper does not couple to the SQL family's\n * `ExtensionMigrationPackage` type.\n */\nexport interface DescriptorMigrationPackage {\n readonly dirName: string;\n readonly metadata: MigrationMetadata;\n readonly ops: MigrationOps;\n}\n\n/**\n * The most-general projection of a single declared extension pack\n * needed by the CLI's descriptor-import boundary.\n *\n * - `id` / `targetId` are always present.\n * - `contractSpace` is present only when the extension declares one.\n * When present, it carries the canonical inputs every downstream\n * consumer needs — `contractJson`, `headRef`, and the descriptor's\n * pre-built migration packages.\n */\nexport interface ExtensionPackInput {\n readonly id: string;\n readonly targetId: string;\n readonly contractSpace?: {\n readonly contractJson: unknown;\n readonly headRef: {\n readonly hash: string;\n readonly invariants: readonly string[];\n };\n readonly migrations: readonly DescriptorMigrationPackage[];\n };\n}\n\n/**\n * Structural shape we read off each `Config.extensionPacks` entry.\n *\n * The CLI is the descriptor-import boundary; `extensionPacks` is the only\n * surface where the SQL-family-typed `ControlExtensionDescriptor` flows\n * into framework-neutral helpers. The structural cast lives here, and\n * here alone — every other CLI consumer reads the canonical\n * {@link ExtensionPackInput} shape produced by {@link toExtensionInputs}.\n */\ntype ExtensionPackLike = {\n readonly id: string;\n readonly targetId: string;\n readonly contractSpace?: {\n readonly contractJson: unknown;\n readonly headRef: {\n readonly hash: string;\n readonly invariants: readonly string[];\n };\n readonly migrations?: readonly DescriptorMigrationPackage[];\n };\n};\n\n/**\n * Project the CLI's `Config.extensionPacks` array into the canonical\n * {@link ExtensionPackInput} shape. The single `as ExtensionPackLike`\n * structural cast in the CLI lives inside this function.\n */\nexport function toExtensionInputs(\n extensionPacks: ReadonlyArray<unknown>,\n): readonly ExtensionPackInput[] {\n return extensionPacks.map((raw) => {\n const pack = raw as ExtensionPackLike;\n if (pack.contractSpace === undefined) {\n return { id: pack.id, targetId: pack.targetId };\n }\n return {\n id: pack.id,\n targetId: pack.targetId,\n contractSpace: {\n contractJson: pack.contractSpace.contractJson,\n headRef: pack.contractSpace.headRef,\n migrations: pack.contractSpace.migrations ?? [],\n },\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Per-consumer adapters: take the canonical `ExtensionPackInput[]` and\n// project to whatever narrower shape the downstream primitive needs.\n// ---------------------------------------------------------------------------\n\n/**\n * Aggregate-loader projection. Surfaces `id` + `targetId` per\n * contract-space-bearing extension to\n * {@link import('./contract-space-aggregate-loader').buildContractSpaceAggregate}.\n *\n * Codec-only extensions (no `contractSpace` declaration) are filtered\n * out: they are not contract-space members, so the aggregate loader\n * has nothing to do with them. Filtering happens at this descriptor-\n * import boundary so the loader stays oblivious to that distinction —\n * every entry it sees expects an on-disk `migrations/<id>/` directory.\n */\nexport function toDeclaredExtensions(\n inputs: ReadonlyArray<ExtensionPackInput>,\n): readonly DeclaredExtensionEntry[] {\n const entries: DeclaredExtensionEntry[] = [];\n for (const pack of inputs) {\n if (pack.contractSpace === undefined) continue;\n entries.push({ id: pack.id, targetId: pack.targetId });\n }\n return entries;\n}\n\n/**\n * Minimal aggregate-loader projection that extracts `id` + `targetId`\n * from raw extension pack descriptors **without invoking any\n * `contractSpace` accessor**. Inspects the own-property descriptor so\n * that getter-backed `contractSpace` declarations are detected but\n * never called.\n *\n * Inclusion semantics match {@link toDeclaredExtensions}: a data\n * property whose value is explicitly `undefined` is treated as \"no\n * contract-space declaration\" and skipped, mirroring the\n * `pack.contractSpace === undefined` check used on canonicalised\n * inputs. Prototype-chain `contractSpace` properties (no own\n * descriptor) are also skipped.\n *\n * This variant must be used by `buildContractSpaceAggregate` so that\n * the aggregate path (including `db verify`) never reads\n * `contractSpace.contractJson` from extension descriptors — the loader\n * always reads the contract from on-disk artefacts instead.\n */\nexport function toDeclaredExtensionsFromRaw(\n extensionPacks: ReadonlyArray<unknown>,\n): readonly DeclaredExtensionEntry[] {\n const entries: DeclaredExtensionEntry[] = [];\n for (const raw of extensionPacks) {\n if (typeof raw !== 'object' || raw === null) continue;\n const descriptor = Object.getOwnPropertyDescriptor(raw, 'contractSpace');\n if (descriptor === undefined) continue;\n if ('value' in descriptor && descriptor.value === undefined) continue;\n const pack = raw as { readonly id: string; readonly targetId: string };\n entries.push({ id: pack.id, targetId: pack.targetId });\n }\n return entries;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { ControlExtensionDescriptor } from '@prisma-next/framework-components/control';\nimport type {\n ContractSpaceAggregate,\n LoadAggregateError,\n LoadAggregateInput,\n LoadAggregateOutput,\n} from '@prisma-next/migration-tools/aggregate';\nimport { loadContractSpaceAggregate } from '@prisma-next/migration-tools/aggregate';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { CliStructuredError } from './cli-errors';\nimport { toDeclaredExtensionsFromRaw } from './extension-pack-inputs';\n\n/**\n * Render a {@link LoadAggregateError} into a CLI structured-error\n * envelope. Preserves error codes `5001` (layout) and `5002` (marker /\n * disjointness / etc.) so existing integration tests and downstream\n * tooling continue to assert on the same `meta.violations[]` shape\n * they did under the old precheck/marker-check helpers.\n */\nexport function mapLoadAggregateError(error: LoadAggregateError): CliStructuredError {\n if (error.kind === 'layoutViolation') {\n const lines = error.violations.map((v) => `- [${v.kind}] ${v.spaceId}`);\n const summary =\n error.violations.length === 1\n ? 'Contract-space layout violation detected'\n : `Contract-space layout violations detected (${error.violations.length})`;\n return new CliStructuredError('5001', summary, {\n domain: 'MIG',\n why: `The on-disk \\`migrations/\\` directory and your \\`extensionPacks\\` declaration are not in agreement.\\n${lines.join('\\n')}`,\n fix: 'Run `prisma-next migrate` to materialise on-disk artefacts for declared extensions, or remove the orphan directory.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: error.violations.map((v) => ({\n kind: v.kind,\n spaceId: v.spaceId,\n })),\n },\n });\n }\n if (error.kind === 'disjointnessViolation') {\n return new CliStructuredError(\n '5002',\n `Contract-space disjointness violation: storage element \"${error.element}\" claimed by multiple spaces`,\n {\n domain: 'MIG',\n why: `Spaces ${error.claimedBy.map((s) => `\"${s}\"`).join(', ')} all claim the storage element \"${error.element}\". Each storage element must be owned by exactly one contract space.`,\n fix: 'Update the conflicting contracts so each storage element is claimed by exactly one space.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: [\n {\n kind: 'disjointness',\n spaceId: error.claimedBy.join(','),\n element: error.element,\n claimedBy: error.claimedBy,\n },\n ],\n },\n },\n );\n }\n if (error.kind === 'integrityFailure') {\n return new CliStructuredError(\n '5002',\n `Contract-space integrity failure for \"${error.spaceId}\"`,\n {\n domain: 'MIG',\n why: error.detail,\n fix: 'Run `prisma-next migrate` to refresh on-disk artefacts, or restore the on-disk `migrations/` directory from version control.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: [{ kind: 'integrity', spaceId: error.spaceId, detail: error.detail }],\n },\n },\n );\n }\n if (error.kind === 'validationFailure') {\n return new CliStructuredError(\n '5002',\n `Contract-space contract validation failed for \"${error.spaceId}\"`,\n {\n domain: 'MIG',\n why: error.detail,\n fix: 'Run `prisma-next migrate` to refresh on-disk artefacts, or fix the extension descriptor producing the invalid contract.',\n meta: {\n violations: [{ kind: 'validation', spaceId: error.spaceId, detail: error.detail }],\n },\n },\n );\n }\n // targetMismatch\n return new CliStructuredError('5002', `Contract-space target mismatch for \"${error.spaceId}\"`, {\n domain: 'MIG',\n why: `Space \"${error.spaceId}\" targets \"${error.actual}\" but the project's adapter targets \"${error.expected}\".`,\n fix: 'Update the extension descriptor to target the configured database, or change the project adapter.',\n meta: {\n violations: [\n {\n kind: 'targetMismatch',\n spaceId: error.spaceId,\n expected: error.expected,\n actual: error.actual,\n },\n ],\n },\n });\n}\n\n/**\n * Inputs needed to compose the aggregate loader at the CLI surface.\n *\n * Keeps the loader framework-neutral (no `Config` import) by accepting\n * already-resolved structural inputs: validated app contract, target\n * id, migrations root directory, and the set of extension descriptors.\n */\nexport interface BuildAggregateInputs<TFamilyId extends string, TTargetId extends string> {\n readonly targetId: TTargetId;\n readonly migrationsDir: string;\n readonly appContract: Contract;\n readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n readonly validateContract: (contractJson: unknown) => Contract;\n /**\n * App-space migration packages to hydrate the app member's\n * migration graph with. Defaults to `[]` (matches the `db init` /\n * `db update` daily-driver behaviour, where the app's authored\n * `migrations/` graph is not walked — the planner uses the synth\n * strategy for the app member instead).\n *\n * `migration apply` callers thread the user's authored app-space\n * packages (loaded via `loadMigrationPackages(appMigrationsDir)`)\n * through here so the graph-walk strategy can plot a path through\n * them — the prod-time replay path explicitly forbids synth.\n */\n readonly appMigrationPackages?: ReadonlyArray<OnDiskMigrationPackage>;\n}\n\n/**\n * Run the aggregate loader at the CLI surface, mapping any\n * {@link LoadAggregateError} into a {@link CliStructuredError} envelope.\n *\n * App-side migration packages flow through `inputs.appMigrationPackages`\n * (defaulting to `[]`). `db init` / `db update` leave it empty: the\n * planner's `synth` strategy is used for the app member (driven by\n * `callerPolicy.ignoreGraphFor`), so the app's authored `migrations/`\n * graph does not need to be walked. `migration apply` threads the\n * already-loaded app-space packages through so the graph-walk strategy\n * can plot a path through them — replay forbids synth.\n *\n * @see specs/contract-space-aggregate-spec.md § Loader.\n */\nexport async function buildContractSpaceAggregate<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n inputs: BuildAggregateInputs<TFamilyId, TTargetId>,\n): Promise<Result<ContractSpaceAggregate, CliStructuredError>> {\n const declaredExtensions = toDeclaredExtensionsFromRaw(\n inputs.extensionPacks as ReadonlyArray<unknown>,\n );\n\n const loadInput: LoadAggregateInput = {\n targetId: inputs.targetId,\n migrationsDir: inputs.migrationsDir,\n appContract: inputs.appContract,\n declaredExtensions,\n validateContract: inputs.validateContract,\n appMigrationPackages: inputs.appMigrationPackages ?? [],\n };\n\n const result: LoadAggregateOutput = await loadContractSpaceAggregate(loadInput);\n if (!result.ok) {\n return notOk(mapLoadAggregateError(result.failure));\n }\n return ok(result.value.aggregate);\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { c as resolveContractPath, d as setCommandDescriptions, f as setCommandE
4
4
  import { t as createProgressAdapter } from "./progress-adapter-DFfvZcYL.mjs";
5
5
  import { t as TerminalUI } from "./terminal-ui-C_hFNbAn.mjs";
6
6
  import { t as handleResult } from "./result-handler-rmPVKIP2.mjs";
7
- import { o as ContractValidationError, t as createControlClient } from "./client-qVH-rEgd.mjs";
7
+ import { a as ContractValidationError, t as createControlClient } from "./client-BCnP7cHo.mjs";
8
8
  import { c as formatVerifyOutput, i as formatSchemaVerifyOutput, r as formatSchemaVerifyJson, s as formatVerifyJson } from "./verify-CiwNWM9N.mjs";
9
9
  import { Command } from "commander";
10
10
  import { ifDefined } from "@prisma-next/utils/defined";
@@ -401,4 +401,4 @@ function createDbVerifyCommand() {
401
401
  //#endregion
402
402
  export { createDbVerifyCommand as t };
403
403
 
404
- //# sourceMappingURL=db-verify-C0y1PCO2.mjs.map
404
+ //# sourceMappingURL=db-verify-Czm5T-J4.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"db-verify-C0y1PCO2.mjs","names":[],"sources":["../src/utils/combine-schema-results.ts","../src/commands/db-verify.ts"],"sourcesContent":["import type { VerifyDatabaseSchemaResult } from '@prisma-next/framework-components/control';\n\n/**\n * Collapse the aggregate verifier's per-space schema results into a\n * single {@link VerifyDatabaseSchemaResult} for the existing CLI\n * display surface. Concatenates issues across members; sums counts;\n * uses the app member's result as the structural envelope (storage\n * hash, target).\n *\n * **Summary policy.** Preserve the per-family phrasing whenever the\n * combined `ok` flag agrees with the app member's `ok` flag — this is\n * the common case (single-family deployments, single-app deployments)\n * and the family's \"satisfies / does not satisfy contract\" phrasing\n * stays user-visible. When the app passes but an extension fails (or\n * vice versa) the app's summary contradicts the envelope, so fall back\n * to the first failing member's summary. This keeps family phrasing\n * intact and the envelope internally consistent (`ok: false` ↔ failure\n * summary).\n */\nexport function combineSchemaResults(\n perSpace: ReadonlyMap<string, VerifyDatabaseSchemaResult>,\n appSpaceId: string,\n strict: boolean,\n): VerifyDatabaseSchemaResult {\n const appResult = perSpace.get(appSpaceId) ?? perSpace.values().next().value;\n if (appResult === undefined) {\n throw new Error('Aggregate verifier returned no schema results — this is a wiring bug.');\n }\n\n let okAll = true;\n let firstFailure: VerifyDatabaseSchemaResult | undefined;\n let issues: VerifyDatabaseSchemaResult['schema']['issues'] = [];\n const counts = { pass: 0, warn: 0, fail: 0, totalNodes: 0 };\n const childRoots: Array<VerifyDatabaseSchemaResult['schema']['root']> = [];\n for (const [, result] of perSpace) {\n if (!result.ok) {\n okAll = false;\n if (firstFailure === undefined) firstFailure = result;\n }\n issues = [...issues, ...result.schema.issues];\n counts.pass += result.schema.counts.pass;\n counts.warn += result.schema.counts.warn;\n counts.fail += result.schema.counts.fail;\n counts.totalNodes += result.schema.counts.totalNodes;\n childRoots.push(result.schema.root);\n }\n\n // When `okAll !== appResult.ok`, exactly one shape is reachable: app passes\n // (`appResult.ok === true`) and at least one other member failed\n // (`okAll === false`). In that shape the failure was assigned to\n // `firstFailure` during iteration, so non-null assertion is safe. The mirror\n // shape (app fails while every member passes) is impossible because\n // `appResult` either *is* a member of `perSpace` or is the first iterator\n // value; either way its `ok` flag participates in `okAll`.\n const summary =\n okAll === appResult.ok\n ? appResult.summary\n : (firstFailure as VerifyDatabaseSchemaResult).summary;\n\n return {\n ok: okAll,\n ...(okAll ? {} : { code: appResult.code ?? 'PN-RUN-3010' }),\n summary,\n contract: appResult.contract,\n target: appResult.target,\n schema: {\n issues,\n root: {\n status: okAll ? 'pass' : 'fail',\n kind: 'aggregate',\n name: 'aggregate',\n contractPath: '',\n code: 'AGGREGATE',\n message: okAll ? 'Aggregate schema matches' : 'Aggregate schema mismatch',\n expected: undefined,\n actual: undefined,\n children: childRoots,\n },\n counts,\n },\n meta: { strict },\n timings: { total: 0 },\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type {\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport { ContractValidationError } from '../control-api/errors';\nimport {\n CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorHashMismatch,\n errorMarkerMissing,\n errorRuntime,\n errorTargetMismatch,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { combineSchemaResults } from '../utils/combine-schema-results';\nimport {\n addGlobalOptions,\n maskConnectionUrl,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport {\n type DbVerifyCommandSuccessResult,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatVerifyJson,\n formatVerifyOutput,\n} from '../utils/formatters/verify';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface DbVerifyOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly markerOnly?: boolean;\n readonly schemaOnly?: boolean;\n readonly strict?: boolean;\n}\n\ntype DbVerifyMode = 'full' | 'marker-only' | 'schema-only';\n\n/**\n * Maps a VerifyDatabaseResult failure to a CliStructuredError.\n */\nfunction mapVerifyFailure(verifyResult: VerifyDatabaseResult): CliStructuredError {\n if (!verifyResult.ok && verifyResult.code) {\n if (verifyResult.code === VERIFY_CODE_MARKER_MISSING) {\n return errorMarkerMissing();\n }\n if (verifyResult.code === VERIFY_CODE_HASH_MISMATCH) {\n const storageMatch = verifyResult.marker?.storageHash === verifyResult.contract.storageHash;\n const profileMatch =\n !verifyResult.contract.profileHash ||\n verifyResult.marker?.profileHash === verifyResult.contract.profileHash;\n\n if (!storageMatch) {\n return errorHashMismatch({\n why: 'Contract storageHash does not match database marker',\n expected: verifyResult.contract.storageHash,\n ...ifDefined('actual', verifyResult.marker?.storageHash),\n });\n }\n\n return errorHashMismatch({\n why: profileMatch\n ? 'Contract hash does not match database marker'\n : 'Contract profileHash does not match database marker',\n ...ifDefined('expected', verifyResult.contract.profileHash),\n ...ifDefined('actual', verifyResult.marker?.profileHash),\n });\n }\n if (verifyResult.code === VERIFY_CODE_TARGET_MISMATCH) {\n return errorTargetMismatch(\n verifyResult.target.expected,\n verifyResult.target.actual ?? 'unknown',\n );\n }\n // Unknown code - fall through to runtime error\n }\n return errorRuntime(verifyResult.summary);\n}\n\ntype DbVerifyFailure = CliStructuredError | VerifyDatabaseSchemaResult;\n\nfunction errorInvalidVerifyMode(options: {\n readonly why: string;\n readonly fix: string;\n}): CliStructuredError {\n return new CliStructuredError('4012', 'Invalid verify mode', {\n domain: 'CLI',\n why: options.why,\n fix: options.fix,\n docsUrl: 'https://pris.ly/db-verify',\n });\n}\n\nfunction resolveDbVerifyMode(options: DbVerifyOptions): Result<DbVerifyMode, CliStructuredError> {\n if (options.markerOnly && options.schemaOnly) {\n return notOk(\n errorInvalidVerifyMode({\n why: '`--marker-only` and `--schema-only` cannot be used together',\n fix: 'Choose one mode: omit both to check the marker and schema, use `--marker-only` to check only the marker, or use `--schema-only` to check only the live schema.',\n }),\n );\n }\n\n if (options.markerOnly && options.strict) {\n return notOk(\n errorInvalidVerifyMode({\n why: '`--strict` requires schema verification, but `--marker-only` skips it',\n fix: 'Remove `--strict`, or use `db verify` / `db verify --schema-only` when you want to check the live schema in strict mode.',\n }),\n );\n }\n\n if (options.schemaOnly) {\n return ok('schema-only');\n }\n\n if (options.markerOnly) {\n return ok('marker-only');\n }\n\n return ok('full');\n}\n\nfunction formatDbVerifyModeLabel(mode: DbVerifyMode, strict: boolean): string {\n if (mode === 'marker-only') {\n return 'marker only';\n }\n\n if (mode === 'schema-only') {\n return `schema only (${strict ? 'strict' : 'tolerant'})`;\n }\n\n return `full (marker + schema, ${strict ? 'strict' : 'tolerant'})`;\n}\n\nfunction formatDbVerifyInvocation(mode: DbVerifyMode, strict: boolean): string {\n const args = ['db verify'];\n\n if (mode === 'marker-only') {\n args.push('--marker-only');\n }\n\n if (mode === 'schema-only') {\n args.push('--schema-only');\n }\n\n if (strict) {\n args.push('--strict');\n }\n\n return args.join(' ');\n}\n\nfunction createDbVerifyConnectionRequiredError(options: {\n readonly configPath: string;\n readonly mode: DbVerifyMode;\n readonly strict: boolean;\n}): CliStructuredError {\n const invocation = formatDbVerifyInvocation(options.mode, options.strict);\n return errorDatabaseConnectionRequired({\n why: `Database connection is required for ${invocation} (set db.connection in ${options.configPath}, or pass --db <url>)`,\n retryCommand: `prisma-next ${invocation} --db <url>`,\n });\n}\n\nfunction renderVerifyHeader(\n paths: { configPath: string; contractPath: string },\n options: DbVerifyOptions,\n mode: DbVerifyMode,\n flags: GlobalFlags,\n ui: TerminalUI,\n): void {\n if (flags.json || flags.quiet) return;\n\n const description =\n mode === 'schema-only'\n ? 'Check whether the live database schema matches your contract'\n : mode === 'marker-only'\n ? 'Check whether the database marker matches your contract'\n : 'Check whether the database marker and live schema match your contract';\n\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: paths.configPath },\n { label: 'contract', value: paths.contractPath },\n { label: 'mode', value: formatDbVerifyModeLabel(mode, options.strict ?? false) },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n\n ui.stderr(\n formatStyledHeader({\n command: 'db verify',\n description,\n url: 'https://pris.ly/db-verify',\n details,\n flags,\n }),\n );\n}\n\nasync function resolveVerifyPaths(options: DbVerifyOptions) {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n return { config, configPath, contractPathAbsolute, contractPath };\n}\n\ntype VerifyPaths = Awaited<ReturnType<typeof resolveVerifyPaths>>;\n\ninterface VerifySetup extends VerifyPaths {\n readonly contractJson: Record<string, unknown>;\n readonly dbConnection: string;\n}\n\nasync function resolveVerifySetup(\n paths: VerifyPaths,\n options: DbVerifyOptions,\n mode: DbVerifyMode,\n): Promise<Result<VerifySetup, CliStructuredError>> {\n const { config, configPath, contractPathAbsolute, contractPath } = paths;\n\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n const dbConnection = options.db ?? config.db?.connection;\n if (typeof dbConnection !== 'string' || dbConnection.length === 0) {\n return notOk(\n createDbVerifyConnectionRequiredError({\n configPath,\n mode,\n strict: options.strict ?? false,\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: `Config.driver is required for ${formatDbVerifyInvocation(mode, options.strict ?? false)}`,\n }),\n );\n }\n\n return ok({ ...paths, contractJson, dbConnection });\n}\n\nfunction createVerifyClient(setup: VerifySetup) {\n return createControlClient({\n family: setup.config.family,\n target: setup.config.target,\n adapter: setup.config.adapter,\n driver: setup.config.driver!,\n extensionPacks: setup.config.extensionPacks ?? [],\n });\n}\n\nfunction wrapVerifyError(\n error: unknown,\n contractPathAbsolute: string,\n modeLabel: string,\n): Result<never, CliStructuredError> {\n if (error instanceof CliStructuredError) {\n return notOk(error);\n }\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during ${modeLabel}: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n}\n\n/**\n * Executes the db verify command and returns a structured Result.\n */\nasync function executeDbVerifyCommand(\n options: DbVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n mode: Extract<DbVerifyMode, 'full' | 'marker-only'>,\n): Promise<Result<DbVerifyCommandSuccessResult, DbVerifyFailure>> {\n const startTime = Date.now();\n const paths = await resolveVerifyPaths(options);\n renderVerifyHeader(paths, options, mode, flags, ui);\n\n const setupResult = await resolveVerifySetup(paths, options, mode);\n if (!setupResult.ok) return setupResult;\n const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);\n\n const client = createVerifyClient(setupResult.value);\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n // Single-contract marker verification preserved for the existing\n // marker / target / hash failure surface (`PN-RUN-3001/3002/3003`).\n // The aggregate verifier (run below for the per-space marker /\n // schema checks) does not duplicate this: it concerns itself with\n // marker-vs-on-disk and orphan-marker drift, not the\n // hash-mismatch-against-the-app-contract lane that today's\n // `client.verify` covers.\n const verifyResult = await client.verify({\n contract: contractJson,\n connection: dbConnection,\n onProgress,\n });\n\n if (!verifyResult.ok) {\n return notOk(mapVerifyFailure(verifyResult));\n }\n\n // Aggregate verifier (loader → verifier pipeline). Runs the layout\n // precheck, marker-aware per-space verifier, and (full mode only)\n // per-space pre-projected schema verification (closes F23).\n const aggregateResult = await client.dbVerify({\n contract: contractJson,\n migrationsDir,\n strict: options.strict ?? false,\n skipSchema: mode === 'marker-only',\n skipMarker: false,\n onProgress,\n });\n if (!aggregateResult.ok) return notOk(aggregateResult.failure);\n\n if (mode === 'marker-only') {\n return ok({\n ok: true,\n mode: 'marker-only',\n summary: 'Database marker matches contract',\n contract: verifyResult.contract,\n marker: verifyResult.marker,\n target: verifyResult.target,\n ...ifDefined('missingCodecs', verifyResult.missingCodecs),\n ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),\n warning: 'Schema verification skipped because --marker-only was provided',\n meta: {\n ...(verifyResult.meta ?? {}),\n schemaVerification: 'skipped',\n },\n timings: { total: Date.now() - startTime },\n });\n }\n\n const combined = combineSchemaResults(\n aggregateResult.value.schemaResults,\n aggregateResult.value.appSpaceId,\n options.strict ?? false,\n );\n if (!combined.ok) {\n return notOk(combined);\n }\n\n return ok({\n ok: true,\n mode: 'full',\n summary: 'Database marker and schema match contract',\n contract: verifyResult.contract,\n marker: verifyResult.marker,\n target: verifyResult.target,\n ...ifDefined('missingCodecs', verifyResult.missingCodecs),\n ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),\n schema: {\n summary: combined.summary,\n counts: combined.schema.counts,\n strict: combined.meta?.strict ?? false,\n },\n meta: {\n ...(verifyResult.meta ?? {}),\n schemaVerification: 'performed',\n },\n timings: { total: Date.now() - startTime },\n });\n } catch (error) {\n return wrapVerifyError(error, contractPathAbsolute, 'db verify');\n } finally {\n await client.close();\n }\n}\n\nasync function executeDbSchemaOnlyVerifyCommand(\n options: DbVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<VerifyDatabaseSchemaResult, CliStructuredError>> {\n const paths = await resolveVerifyPaths(options);\n renderVerifyHeader(paths, options, 'schema-only', flags, ui);\n\n const setupResult = await resolveVerifySetup(paths, options, 'schema-only');\n if (!setupResult.ok) return setupResult;\n const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);\n\n const client = createVerifyClient(setupResult.value);\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n await client.connect(dbConnection);\n const aggregateResult = await client.dbVerify({\n contract: contractJson,\n migrationsDir,\n strict: options.strict ?? false,\n skipSchema: false,\n skipMarker: true,\n onProgress,\n });\n if (!aggregateResult.ok) return notOk(aggregateResult.failure);\n\n return ok(\n combineSchemaResults(\n aggregateResult.value.schemaResults,\n aggregateResult.value.appSpaceId,\n options.strict ?? false,\n ),\n );\n } catch (error) {\n return wrapVerifyError(error, contractPathAbsolute, 'db verify --schema-only');\n } finally {\n await client.close();\n }\n}\n\nexport function createDbVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Check whether the database marker and live schema match your contract',\n 'Verifies the database marker first, then checks the database schema matches your contract.\\n' +\n 'Use `--marker-only` for marker-only verification, `--schema-only` to skip marker checks and\\n' +\n 'inspect only the live schema, and `--strict` to fail if the database includes elements\\n' +\n 'not present in the contract.',\n );\n setCommandExamples(command, [\n 'prisma-next db verify --db $DATABASE_URL',\n 'prisma-next db verify --db $DATABASE_URL --strict',\n 'prisma-next db verify --db $DATABASE_URL --schema-only',\n 'prisma-next db verify --db $DATABASE_URL --schema-only --strict',\n 'prisma-next db verify --db $DATABASE_URL --marker-only',\n 'prisma-next db verify --db $DATABASE_URL --json',\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--marker-only', 'Skip schema verification and only check the database marker')\n .option(\n '--schema-only',\n 'Skip marker verification and only check whether the live schema satisfies the contract',\n )\n .option(\n '--strict',\n 'Strict mode: schema elements not present in the contract are considered an error',\n false,\n )\n .action(async (options: DbVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const modeResult = resolveDbVerifyMode(options);\n if (!modeResult.ok) {\n const exitCode = handleResult(modeResult as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n const mode = modeResult.value;\n\n if (mode === 'schema-only') {\n const result = await executeDbSchemaOnlyVerifyCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (schemaVerifyResult) => {\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n\n if (result.ok && !result.value.ok) {\n process.exit(1);\n }\n\n process.exit(exitCode);\n }\n\n const result = await executeDbVerifyCommand(options, flags, ui, mode);\n\n if (result.ok) {\n if (flags.json) {\n ui.output(formatVerifyJson(result.value));\n } else {\n const output = formatVerifyOutput(result.value, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(0);\n }\n\n if (CliStructuredError.is(result.failure)) {\n const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(result.failure));\n } else {\n // Always show schema-drift failures, even in quiet mode — exiting 1 without\n // diagnostics is unhelpful.\n const output = formatSchemaVerifyOutput(result.failure, { ...flags, quiet: false });\n if (output) {\n ui.log(output);\n }\n }\n process.exit(1);\n });\n\n return command;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"db-verify-Czm5T-J4.mjs","names":[],"sources":["../src/utils/combine-schema-results.ts","../src/commands/db-verify.ts"],"sourcesContent":["import type { VerifyDatabaseSchemaResult } from '@prisma-next/framework-components/control';\n\n/**\n * Collapse the aggregate verifier's per-space schema results into a\n * single {@link VerifyDatabaseSchemaResult} for the existing CLI\n * display surface. Concatenates issues across members; sums counts;\n * uses the app member's result as the structural envelope (storage\n * hash, target).\n *\n * **Summary policy.** Preserve the per-family phrasing whenever the\n * combined `ok` flag agrees with the app member's `ok` flag — this is\n * the common case (single-family deployments, single-app deployments)\n * and the family's \"satisfies / does not satisfy contract\" phrasing\n * stays user-visible. When the app passes but an extension fails (or\n * vice versa) the app's summary contradicts the envelope, so fall back\n * to the first failing member's summary. This keeps family phrasing\n * intact and the envelope internally consistent (`ok: false` ↔ failure\n * summary).\n */\nexport function combineSchemaResults(\n perSpace: ReadonlyMap<string, VerifyDatabaseSchemaResult>,\n appSpaceId: string,\n strict: boolean,\n): VerifyDatabaseSchemaResult {\n const appResult = perSpace.get(appSpaceId) ?? perSpace.values().next().value;\n if (appResult === undefined) {\n throw new Error('Aggregate verifier returned no schema results — this is a wiring bug.');\n }\n\n let okAll = true;\n let firstFailure: VerifyDatabaseSchemaResult | undefined;\n let issues: VerifyDatabaseSchemaResult['schema']['issues'] = [];\n const counts = { pass: 0, warn: 0, fail: 0, totalNodes: 0 };\n const childRoots: Array<VerifyDatabaseSchemaResult['schema']['root']> = [];\n for (const [, result] of perSpace) {\n if (!result.ok) {\n okAll = false;\n if (firstFailure === undefined) firstFailure = result;\n }\n issues = [...issues, ...result.schema.issues];\n counts.pass += result.schema.counts.pass;\n counts.warn += result.schema.counts.warn;\n counts.fail += result.schema.counts.fail;\n counts.totalNodes += result.schema.counts.totalNodes;\n childRoots.push(result.schema.root);\n }\n\n // When `okAll !== appResult.ok`, exactly one shape is reachable: app passes\n // (`appResult.ok === true`) and at least one other member failed\n // (`okAll === false`). In that shape the failure was assigned to\n // `firstFailure` during iteration, so non-null assertion is safe. The mirror\n // shape (app fails while every member passes) is impossible because\n // `appResult` either *is* a member of `perSpace` or is the first iterator\n // value; either way its `ok` flag participates in `okAll`.\n const summary =\n okAll === appResult.ok\n ? appResult.summary\n : (firstFailure as VerifyDatabaseSchemaResult).summary;\n\n return {\n ok: okAll,\n ...(okAll ? {} : { code: appResult.code ?? 'PN-RUN-3010' }),\n summary,\n contract: appResult.contract,\n target: appResult.target,\n schema: {\n issues,\n root: {\n status: okAll ? 'pass' : 'fail',\n kind: 'aggregate',\n name: 'aggregate',\n contractPath: '',\n code: 'AGGREGATE',\n message: okAll ? 'Aggregate schema matches' : 'Aggregate schema mismatch',\n expected: undefined,\n actual: undefined,\n children: childRoots,\n },\n counts,\n },\n meta: { strict },\n timings: { total: 0 },\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport type {\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport { ContractValidationError } from '../control-api/errors';\nimport {\n CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorHashMismatch,\n errorMarkerMissing,\n errorRuntime,\n errorTargetMismatch,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { combineSchemaResults } from '../utils/combine-schema-results';\nimport {\n addGlobalOptions,\n maskConnectionUrl,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport {\n type DbVerifyCommandSuccessResult,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatVerifyJson,\n formatVerifyOutput,\n} from '../utils/formatters/verify';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface DbVerifyOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly markerOnly?: boolean;\n readonly schemaOnly?: boolean;\n readonly strict?: boolean;\n}\n\ntype DbVerifyMode = 'full' | 'marker-only' | 'schema-only';\n\n/**\n * Maps a VerifyDatabaseResult failure to a CliStructuredError.\n */\nfunction mapVerifyFailure(verifyResult: VerifyDatabaseResult): CliStructuredError {\n if (!verifyResult.ok && verifyResult.code) {\n if (verifyResult.code === VERIFY_CODE_MARKER_MISSING) {\n return errorMarkerMissing();\n }\n if (verifyResult.code === VERIFY_CODE_HASH_MISMATCH) {\n const storageMatch = verifyResult.marker?.storageHash === verifyResult.contract.storageHash;\n const profileMatch =\n !verifyResult.contract.profileHash ||\n verifyResult.marker?.profileHash === verifyResult.contract.profileHash;\n\n if (!storageMatch) {\n return errorHashMismatch({\n why: 'Contract storageHash does not match database marker',\n expected: verifyResult.contract.storageHash,\n ...ifDefined('actual', verifyResult.marker?.storageHash),\n });\n }\n\n return errorHashMismatch({\n why: profileMatch\n ? 'Contract hash does not match database marker'\n : 'Contract profileHash does not match database marker',\n ...ifDefined('expected', verifyResult.contract.profileHash),\n ...ifDefined('actual', verifyResult.marker?.profileHash),\n });\n }\n if (verifyResult.code === VERIFY_CODE_TARGET_MISMATCH) {\n return errorTargetMismatch(\n verifyResult.target.expected,\n verifyResult.target.actual ?? 'unknown',\n );\n }\n // Unknown code - fall through to runtime error\n }\n return errorRuntime(verifyResult.summary);\n}\n\ntype DbVerifyFailure = CliStructuredError | VerifyDatabaseSchemaResult;\n\nfunction errorInvalidVerifyMode(options: {\n readonly why: string;\n readonly fix: string;\n}): CliStructuredError {\n return new CliStructuredError('4012', 'Invalid verify mode', {\n domain: 'CLI',\n why: options.why,\n fix: options.fix,\n docsUrl: 'https://pris.ly/db-verify',\n });\n}\n\nfunction resolveDbVerifyMode(options: DbVerifyOptions): Result<DbVerifyMode, CliStructuredError> {\n if (options.markerOnly && options.schemaOnly) {\n return notOk(\n errorInvalidVerifyMode({\n why: '`--marker-only` and `--schema-only` cannot be used together',\n fix: 'Choose one mode: omit both to check the marker and schema, use `--marker-only` to check only the marker, or use `--schema-only` to check only the live schema.',\n }),\n );\n }\n\n if (options.markerOnly && options.strict) {\n return notOk(\n errorInvalidVerifyMode({\n why: '`--strict` requires schema verification, but `--marker-only` skips it',\n fix: 'Remove `--strict`, or use `db verify` / `db verify --schema-only` when you want to check the live schema in strict mode.',\n }),\n );\n }\n\n if (options.schemaOnly) {\n return ok('schema-only');\n }\n\n if (options.markerOnly) {\n return ok('marker-only');\n }\n\n return ok('full');\n}\n\nfunction formatDbVerifyModeLabel(mode: DbVerifyMode, strict: boolean): string {\n if (mode === 'marker-only') {\n return 'marker only';\n }\n\n if (mode === 'schema-only') {\n return `schema only (${strict ? 'strict' : 'tolerant'})`;\n }\n\n return `full (marker + schema, ${strict ? 'strict' : 'tolerant'})`;\n}\n\nfunction formatDbVerifyInvocation(mode: DbVerifyMode, strict: boolean): string {\n const args = ['db verify'];\n\n if (mode === 'marker-only') {\n args.push('--marker-only');\n }\n\n if (mode === 'schema-only') {\n args.push('--schema-only');\n }\n\n if (strict) {\n args.push('--strict');\n }\n\n return args.join(' ');\n}\n\nfunction createDbVerifyConnectionRequiredError(options: {\n readonly configPath: string;\n readonly mode: DbVerifyMode;\n readonly strict: boolean;\n}): CliStructuredError {\n const invocation = formatDbVerifyInvocation(options.mode, options.strict);\n return errorDatabaseConnectionRequired({\n why: `Database connection is required for ${invocation} (set db.connection in ${options.configPath}, or pass --db <url>)`,\n retryCommand: `prisma-next ${invocation} --db <url>`,\n });\n}\n\nfunction renderVerifyHeader(\n paths: { configPath: string; contractPath: string },\n options: DbVerifyOptions,\n mode: DbVerifyMode,\n flags: GlobalFlags,\n ui: TerminalUI,\n): void {\n if (flags.json || flags.quiet) return;\n\n const description =\n mode === 'schema-only'\n ? 'Check whether the live database schema matches your contract'\n : mode === 'marker-only'\n ? 'Check whether the database marker matches your contract'\n : 'Check whether the database marker and live schema match your contract';\n\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: paths.configPath },\n { label: 'contract', value: paths.contractPath },\n { label: 'mode', value: formatDbVerifyModeLabel(mode, options.strict ?? false) },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n\n ui.stderr(\n formatStyledHeader({\n command: 'db verify',\n description,\n url: 'https://pris.ly/db-verify',\n details,\n flags,\n }),\n );\n}\n\nasync function resolveVerifyPaths(options: DbVerifyOptions) {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n return { config, configPath, contractPathAbsolute, contractPath };\n}\n\ntype VerifyPaths = Awaited<ReturnType<typeof resolveVerifyPaths>>;\n\ninterface VerifySetup extends VerifyPaths {\n readonly contractJson: Record<string, unknown>;\n readonly dbConnection: string;\n}\n\nasync function resolveVerifySetup(\n paths: VerifyPaths,\n options: DbVerifyOptions,\n mode: DbVerifyMode,\n): Promise<Result<VerifySetup, CliStructuredError>> {\n const { config, configPath, contractPathAbsolute, contractPath } = paths;\n\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n const dbConnection = options.db ?? config.db?.connection;\n if (typeof dbConnection !== 'string' || dbConnection.length === 0) {\n return notOk(\n createDbVerifyConnectionRequiredError({\n configPath,\n mode,\n strict: options.strict ?? false,\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: `Config.driver is required for ${formatDbVerifyInvocation(mode, options.strict ?? false)}`,\n }),\n );\n }\n\n return ok({ ...paths, contractJson, dbConnection });\n}\n\nfunction createVerifyClient(setup: VerifySetup) {\n return createControlClient({\n family: setup.config.family,\n target: setup.config.target,\n adapter: setup.config.adapter,\n driver: setup.config.driver!,\n extensionPacks: setup.config.extensionPacks ?? [],\n });\n}\n\nfunction wrapVerifyError(\n error: unknown,\n contractPathAbsolute: string,\n modeLabel: string,\n): Result<never, CliStructuredError> {\n if (error instanceof CliStructuredError) {\n return notOk(error);\n }\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during ${modeLabel}: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n}\n\n/**\n * Executes the db verify command and returns a structured Result.\n */\nasync function executeDbVerifyCommand(\n options: DbVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n mode: Extract<DbVerifyMode, 'full' | 'marker-only'>,\n): Promise<Result<DbVerifyCommandSuccessResult, DbVerifyFailure>> {\n const startTime = Date.now();\n const paths = await resolveVerifyPaths(options);\n renderVerifyHeader(paths, options, mode, flags, ui);\n\n const setupResult = await resolveVerifySetup(paths, options, mode);\n if (!setupResult.ok) return setupResult;\n const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);\n\n const client = createVerifyClient(setupResult.value);\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n // Single-contract marker verification preserved for the existing\n // marker / target / hash failure surface (`PN-RUN-3001/3002/3003`).\n // The aggregate verifier (run below for the per-space marker /\n // schema checks) does not duplicate this: it concerns itself with\n // marker-vs-on-disk and orphan-marker drift, not the\n // hash-mismatch-against-the-app-contract lane that today's\n // `client.verify` covers.\n const verifyResult = await client.verify({\n contract: contractJson,\n connection: dbConnection,\n onProgress,\n });\n\n if (!verifyResult.ok) {\n return notOk(mapVerifyFailure(verifyResult));\n }\n\n // Aggregate verifier (loader → verifier pipeline). Runs the layout\n // precheck, marker-aware per-space verifier, and (full mode only)\n // per-space pre-projected schema verification (closes F23).\n const aggregateResult = await client.dbVerify({\n contract: contractJson,\n migrationsDir,\n strict: options.strict ?? false,\n skipSchema: mode === 'marker-only',\n skipMarker: false,\n onProgress,\n });\n if (!aggregateResult.ok) return notOk(aggregateResult.failure);\n\n if (mode === 'marker-only') {\n return ok({\n ok: true,\n mode: 'marker-only',\n summary: 'Database marker matches contract',\n contract: verifyResult.contract,\n marker: verifyResult.marker,\n target: verifyResult.target,\n ...ifDefined('missingCodecs', verifyResult.missingCodecs),\n ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),\n warning: 'Schema verification skipped because --marker-only was provided',\n meta: {\n ...(verifyResult.meta ?? {}),\n schemaVerification: 'skipped',\n },\n timings: { total: Date.now() - startTime },\n });\n }\n\n const combined = combineSchemaResults(\n aggregateResult.value.schemaResults,\n aggregateResult.value.appSpaceId,\n options.strict ?? false,\n );\n if (!combined.ok) {\n return notOk(combined);\n }\n\n return ok({\n ok: true,\n mode: 'full',\n summary: 'Database marker and schema match contract',\n contract: verifyResult.contract,\n marker: verifyResult.marker,\n target: verifyResult.target,\n ...ifDefined('missingCodecs', verifyResult.missingCodecs),\n ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),\n schema: {\n summary: combined.summary,\n counts: combined.schema.counts,\n strict: combined.meta?.strict ?? false,\n },\n meta: {\n ...(verifyResult.meta ?? {}),\n schemaVerification: 'performed',\n },\n timings: { total: Date.now() - startTime },\n });\n } catch (error) {\n return wrapVerifyError(error, contractPathAbsolute, 'db verify');\n } finally {\n await client.close();\n }\n}\n\nasync function executeDbSchemaOnlyVerifyCommand(\n options: DbVerifyOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<VerifyDatabaseSchemaResult, CliStructuredError>> {\n const paths = await resolveVerifyPaths(options);\n renderVerifyHeader(paths, options, 'schema-only', flags, ui);\n\n const setupResult = await resolveVerifySetup(paths, options, 'schema-only');\n if (!setupResult.ok) return setupResult;\n const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);\n\n const client = createVerifyClient(setupResult.value);\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n await client.connect(dbConnection);\n const aggregateResult = await client.dbVerify({\n contract: contractJson,\n migrationsDir,\n strict: options.strict ?? false,\n skipSchema: false,\n skipMarker: true,\n onProgress,\n });\n if (!aggregateResult.ok) return notOk(aggregateResult.failure);\n\n return ok(\n combineSchemaResults(\n aggregateResult.value.schemaResults,\n aggregateResult.value.appSpaceId,\n options.strict ?? false,\n ),\n );\n } catch (error) {\n return wrapVerifyError(error, contractPathAbsolute, 'db verify --schema-only');\n } finally {\n await client.close();\n }\n}\n\nexport function createDbVerifyCommand(): Command {\n const command = new Command('verify');\n setCommandDescriptions(\n command,\n 'Check whether the database marker and live schema match your contract',\n 'Verifies the database marker first, then checks the database schema matches your contract.\\n' +\n 'Use `--marker-only` for marker-only verification, `--schema-only` to skip marker checks and\\n' +\n 'inspect only the live schema, and `--strict` to fail if the database includes elements\\n' +\n 'not present in the contract.',\n );\n setCommandExamples(command, [\n 'prisma-next db verify --db $DATABASE_URL',\n 'prisma-next db verify --db $DATABASE_URL --strict',\n 'prisma-next db verify --db $DATABASE_URL --schema-only',\n 'prisma-next db verify --db $DATABASE_URL --schema-only --strict',\n 'prisma-next db verify --db $DATABASE_URL --marker-only',\n 'prisma-next db verify --db $DATABASE_URL --json',\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--marker-only', 'Skip schema verification and only check the database marker')\n .option(\n '--schema-only',\n 'Skip marker verification and only check whether the live schema satisfies the contract',\n )\n .option(\n '--strict',\n 'Strict mode: schema elements not present in the contract are considered an error',\n false,\n )\n .action(async (options: DbVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const modeResult = resolveDbVerifyMode(options);\n if (!modeResult.ok) {\n const exitCode = handleResult(modeResult as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n const mode = modeResult.value;\n\n if (mode === 'schema-only') {\n const result = await executeDbSchemaOnlyVerifyCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (schemaVerifyResult) => {\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n\n if (result.ok && !result.value.ok) {\n process.exit(1);\n }\n\n process.exit(exitCode);\n }\n\n const result = await executeDbVerifyCommand(options, flags, ui, mode);\n\n if (result.ok) {\n if (flags.json) {\n ui.output(formatVerifyJson(result.value));\n } else {\n const output = formatVerifyOutput(result.value, flags);\n if (output) {\n ui.log(output);\n }\n }\n process.exit(0);\n }\n\n if (CliStructuredError.is(result.failure)) {\n const exitCode = handleResult(result as Result<never, CliStructuredError>, flags, ui);\n process.exit(exitCode);\n }\n\n if (flags.json) {\n ui.output(formatSchemaVerifyJson(result.failure));\n } else {\n // Always show schema-drift failures, even in quiet mode — exiting 1 without\n // diagnostics is unhelpful.\n const output = formatSchemaVerifyOutput(result.failure, { ...flags, quiet: false });\n if (output) {\n ui.log(output);\n }\n }\n process.exit(1);\n });\n\n return command;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { A as ExecuteDbVerifyOptions, C as EmitSuccess, D as SchemaVerifyOptions, E as OnControlProgress, M as executeDbVerify, O as SignOptions, S as EmitResult, _ as DbUpdateSuccess, a as ControlClient, b as EmitFailureCode, c as DbInitFailure, d as DbInitResult, f as DbInitSuccess, g as DbUpdateResult, h as DbUpdateOptions, i as ControlActionName, j as ExecuteDbVerifyResult, k as VerifyOptions, l as DbInitFailureCode, m as DbUpdateFailureCode, n as ContractEmitOptions, o as ControlClientOptions, p as DbUpdateFailure, r as ContractEmitResult, s as ControlProgressEvent, u as DbInitOptions, v as EmitContractConfig, w as IntrospectOptions, x as EmitOptions, y as EmitFailure } from "../types-D7x-IFLO.mjs";
1
+ import { A as ExecuteDbVerifyOptions, C as EmitSuccess, D as SchemaVerifyOptions, E as OnControlProgress, M as executeDbVerify, O as SignOptions, S as EmitResult, _ as DbUpdateSuccess, a as ControlClient, b as EmitFailureCode, c as DbInitFailure, d as DbInitResult, f as DbInitSuccess, g as DbUpdateResult, h as DbUpdateOptions, i as ControlActionName, j as ExecuteDbVerifyResult, k as VerifyOptions, l as DbInitFailureCode, m as DbUpdateFailureCode, n as ContractEmitOptions, o as ControlClientOptions, p as DbUpdateFailure, r as ContractEmitResult, s as ControlProgressEvent, u as DbInitOptions, v as EmitContractConfig, w as IntrospectOptions, x as EmitOptions, y as EmitFailure } from "../types-LItU7E4l.mjs";
2
2
  import { ControlDriverInstance, ControlExtensionDescriptor, ControlFamilyInstance, ControlStack, SignDatabaseResult, TargetMigrationsCapability, VerifyDatabaseResult, VerifyDatabaseSchemaResult } from "@prisma-next/framework-components/control";
3
3
  import { TargetBoundComponentDescriptor } from "@prisma-next/framework-components/components";
4
4
  import { Contract } from "@prisma-next/contract/types";
@@ -1,4 +1,4 @@
1
1
  import { n as executeContractEmit, r as disposeEmitQueue } from "../contract-emit-B77TsJqf.mjs";
2
2
  import { t as enrichContract } from "../contract-enrichment-Dani0mMW.mjs";
3
- import { i as executeDbInit, n as executeDbVerify, r as executeDbUpdate, t as createControlClient } from "../client-qVH-rEgd.mjs";
3
+ import { i as executeDbInit, n as executeDbVerify, r as executeDbUpdate, t as createControlClient } from "../client-BCnP7cHo.mjs";
4
4
  export { createControlClient, disposeEmitQueue, enrichContract, executeContractEmit, executeDbInit, executeDbUpdate, executeDbVerify };
@@ -2,12 +2,12 @@ import { t as CliStructuredError } from "./cli-errors-D3_sMh2K.mjs";
2
2
  import { i as formatErrorOutput, r as formatErrorJson, t as TerminalUI } from "./terminal-ui-C_hFNbAn.mjs";
3
3
  import { i as renderInitOutro, n as buildNextSteps, r as formatInitJson, t as InitOutputSchema } from "./output-B16Kefzx.mjs";
4
4
  import { createRequire } from "node:module";
5
- import { dirname, extname, isAbsolute, join, normalize } from "pathe";
5
+ import { basename, dirname, extname, isAbsolute, join, normalize } from "pathe";
6
6
  import * as clack from "@clack/prompts";
7
7
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
8
8
  import { execFile } from "node:child_process";
9
9
  import { promisify } from "node:util";
10
- import { detect } from "package-manager-detector/detect";
10
+ import { detect, getUserAgent } from "package-manager-detector/detect";
11
11
  import { applyEdits, modify, parse, printParseErrorCode } from "jsonc-parser";
12
12
  //#region src/commands/init/detect-package-manager.ts
13
13
  const KNOWN = new Set([
@@ -17,9 +17,31 @@ const KNOWN = new Set([
17
17
  "bun",
18
18
  "deno"
19
19
  ]);
20
+ /**
21
+ * Resolves the package manager `init` should drive for `add` / `install`
22
+ * commands. Tries, in order:
23
+ *
24
+ * 1. **`detect()`** — walks up from `cwd` looking for a lockfile, the
25
+ * `packageManager` field, the `devEngines.packageManager` field, or
26
+ * install metadata. This is the right answer whenever the user is
27
+ * anywhere inside an existing project, including a deep workspace
28
+ * subdirectory.
29
+ *
30
+ * 2. **`getUserAgent()`** — parses `npm_config_user_agent`, the env var
31
+ * every PM sets when it spawns a script. This catches the
32
+ * bare-directory case where there's no project to walk up to but the
33
+ * user invoked us via `pnpm dlx prisma-next init` / `bunx
34
+ * prisma-next init` / `yarn dlx …`. Same signal used by every
35
+ * `create-*` tool in the ecosystem (`create-vite`, `create-next-app`,
36
+ * `create-astro`, `@antfu/ni`, …).
37
+ *
38
+ * 3. **`npm`** — final fallback. Always present alongside Node.
39
+ */
20
40
  async function detectPackageManager(cwd) {
21
- const result = await detect({ cwd });
22
- if (result && KNOWN.has(result.name)) return result.name;
41
+ const detected = await detect({ cwd });
42
+ if (detected && KNOWN.has(detected.name)) return detected.name;
43
+ const userAgent = getUserAgent();
44
+ if (userAgent !== null && KNOWN.has(userAgent)) return userAgent;
23
45
  return "npm";
24
46
  }
25
47
  function hasProjectManifest(cwd) {
@@ -142,21 +164,6 @@ function stripQuotes(value) {
142
164
  //#endregion
143
165
  //#region src/commands/init/errors.ts
144
166
  /**
145
- * No `package.json` / `deno.json` / `deno.jsonc` in the target directory.
146
- *
147
- * `init` cannot bootstrap a fresh project from a bare directory (NG1) — that
148
- * gap is tracked separately. The fix is for the user to run `npm init` (or
149
- * the equivalent for their package manager) first.
150
- */
151
- function errorInitMissingManifest() {
152
- return new CliStructuredError("5001", "No project manifest found", {
153
- domain: "CLI",
154
- why: "No package.json or deno.json found in the target directory. `prisma-next init` requires an existing project to attach to.",
155
- fix: "Initialize your project first (e.g. `npm init -y` or `deno init`), then re-run `prisma-next init`.",
156
- docsUrl: "https://prisma-next.dev/docs/cli/init"
157
- });
158
- }
159
- /**
160
167
  * Re-init in non-interactive mode without `--force`. Distinct from the
161
168
  * decline-the-prompt path (which is `errorInitUserAborted`) because here
162
169
  * the user was never given the choice — `--force` is the contract.
@@ -519,6 +526,58 @@ function mergePackageScripts(existing, required = REQUIRED_SCRIPTS) {
519
526
  warnings
520
527
  };
521
528
  }
529
+ /**
530
+ * Idempotently sets `"type": "module"` on a `package.json` so the
531
+ * scaffolded `prisma/db.ts` — which uses the ESM-only `with { type: 'json' }`
532
+ * import attribute — loads as ES module under Node's loader (TML-2494).
533
+ *
534
+ * Without this field Node either:
535
+ *
536
+ * - emits `MODULE_TYPELESS_PACKAGE_JSON` and reparses the file as ESM
537
+ * with a perf penalty (Node 22+ with `--experimental-strip-types`), or
538
+ * - hard-fails with `ERR_*` because the CJS loader cannot parse the
539
+ * import-attribute syntax (older Node, or any tool that doesn't
540
+ * reparse).
541
+ *
542
+ * Behaviour:
543
+ *
544
+ * - **Field missing** → set to `"module"`. New entry is inserted right
545
+ * after `"name"` (when present) so the diff lands in a conventional
546
+ * spot for human review; falls through to the natural append position
547
+ * otherwise.
548
+ * - **Field already `"module"`** → no-op (idempotent).
549
+ * - **Field set to anything else** (e.g. `"commonjs"`) → leave it alone
550
+ * and surface a structured warning. The user explicitly opted out of
551
+ * ESM and we don't silently overwrite that.
552
+ */
553
+ function ensureEsmModuleType(existing) {
554
+ const parsed = JSON.parse(existing);
555
+ const currentType = parsed["type"];
556
+ if (currentType === "module") return {
557
+ content: null,
558
+ warning: null
559
+ };
560
+ if (typeof currentType === "string" && currentType !== "module") return {
561
+ content: null,
562
+ warning: `package.json declares "type": "${currentType}" — keeping yours, but the scaffolded prisma/db.ts uses an ESM-only import attribute (\`with { type: 'json' }\`) and will not load under that module type.\nIf you want the default, set "type": "module" in package.json.`
563
+ };
564
+ const next = {};
565
+ let inserted = false;
566
+ for (const [key, value] of Object.entries(parsed)) {
567
+ if (key === "type") continue;
568
+ next[key] = value;
569
+ if (!inserted && key === "name") {
570
+ next["type"] = "module";
571
+ inserted = true;
572
+ }
573
+ }
574
+ if (!inserted) next["type"] = "module";
575
+ const trailingNewline = existing.endsWith("\n") ? "\n" : "";
576
+ return {
577
+ content: `${JSON.stringify(next, null, 2)}${trailingNewline}`,
578
+ warning: null
579
+ };
580
+ }
522
581
  //#endregion
523
582
  //#region src/commands/init/templates/code-templates.ts
524
583
  function targetPackageName(target) {
@@ -1561,7 +1620,6 @@ async function runInit(baseDir, runOptions) {
1561
1620
  const filesWritten = [];
1562
1621
  const filesDeleted = [];
1563
1622
  if (!flags.json && !flags.quiet) clack.intro("prisma-next init", { output: process.stderr });
1564
- if (!hasProjectManifest(baseDir)) return emitError(ui, flags, errorInitMissingManifest());
1565
1623
  let inputs;
1566
1624
  try {
1567
1625
  inputs = await resolveInitInputs({
@@ -1645,9 +1703,11 @@ async function runInit(baseDir, runOptions) {
1645
1703
  content: newGitattributes
1646
1704
  });
1647
1705
  const packageJsonPath = join(baseDir, "package.json");
1706
+ const packageJsonExisted = existsSync(packageJsonPath);
1707
+ const synthesisePackageJson = !packageJsonExisted && !hasProjectManifest(baseDir);
1648
1708
  let parsedPackageJson = null;
1649
- if (existsSync(packageJsonPath)) {
1650
- const pkgRaw = readFileSync(packageJsonPath, "utf-8");
1709
+ if (packageJsonExisted || synthesisePackageJson) {
1710
+ const pkgRaw = packageJsonExisted ? readFileSync(packageJsonPath, "utf-8") : defaultPackageJsonContent(basename(baseDir));
1651
1711
  try {
1652
1712
  parsedPackageJson = JSON.parse(pkgRaw);
1653
1713
  } catch (err) {
@@ -1658,7 +1718,7 @@ async function runInit(baseDir, runOptions) {
1658
1718
  throw err;
1659
1719
  }
1660
1720
  let workingPkg = pkgRaw;
1661
- let pkgChanged = false;
1721
+ let pkgChanged = synthesisePackageJson;
1662
1722
  if (inputs.removePreviousFacade !== null) {
1663
1723
  const next = removeDependency(workingPkg, inputs.removePreviousFacade);
1664
1724
  if (next !== null) {
@@ -1671,11 +1731,18 @@ async function runInit(baseDir, runOptions) {
1671
1731
  workingPkg = nextPkg;
1672
1732
  pkgChanged = true;
1673
1733
  }
1734
+ const { content: typedPkg, warning: typeWarning } = ensureEsmModuleType(workingPkg);
1735
+ if (typedPkg !== null) {
1736
+ workingPkg = typedPkg;
1737
+ pkgChanged = true;
1738
+ }
1674
1739
  if (pkgChanged) filesToWrite.push({
1675
1740
  path: "package.json",
1676
1741
  content: workingPkg
1677
1742
  });
1678
1743
  warnings.push(...scriptWarnings);
1744
+ if (typeWarning !== null) warnings.push(typeWarning);
1745
+ if (synthesisePackageJson) warnings.push("No package.json found in the target directory; created a minimal one. Edit `name` / `version` to taste.");
1679
1746
  }
1680
1747
  for (const file of filesToWrite) {
1681
1748
  const fullPath = join(baseDir, file.path);
@@ -1806,7 +1873,6 @@ function emitError(ui, flags, error) {
1806
1873
  */
1807
1874
  function exitCodeForError(error) {
1808
1875
  switch (error.code) {
1809
- case "5001":
1810
1876
  case "5002":
1811
1877
  case "5003":
1812
1878
  case "5004":
@@ -2047,7 +2113,41 @@ function causeMessage(err) {
2047
2113
  if (err instanceof Error) return err.message;
2048
2114
  return String(err);
2049
2115
  }
2116
+ /**
2117
+ * Minimal `package.json` content used when init runs in a directory
2118
+ * that has no project manifest (TML-2496). Mirrors the npm 11 `init -y`
2119
+ * defaults, with two deliberate deviations:
2120
+ *
2121
+ * - `"private": true` so a stray `npm publish` cannot leak the
2122
+ * placeholder. Users who want to publish have to opt in by removing
2123
+ * the field.
2124
+ * - `"type": "module"` so the scaffolded ESM imports in
2125
+ * `prisma-next.config.ts` and `db.ts` typecheck and run without
2126
+ * additional tsconfig coercion.
2127
+ *
2128
+ * Exported for unit tests so the canonical shape is asserted in one
2129
+ * place rather than re-derived at every call site.
2130
+ */
2131
+ function defaultPackageJsonContent(rawName) {
2132
+ return `${JSON.stringify({
2133
+ name: sanitisePackageName(rawName),
2134
+ version: "0.0.0",
2135
+ private: true,
2136
+ type: "module"
2137
+ }, null, 2)}\n`;
2138
+ }
2139
+ /**
2140
+ * npm package names are restricted to lowercase, no leading dot/underscore,
2141
+ * and a small URL-safe character set. `basename(cwd)` happily returns
2142
+ * "My Project" or ".hidden" — both rejected by `npm install` validation.
2143
+ * Coerce to a safe fallback rather than emit a manifest npm refuses to
2144
+ * read.
2145
+ */
2146
+ function sanitisePackageName(raw) {
2147
+ const trimmed = raw.toLowerCase().replace(/[^a-z0-9._~-]/g, "-").replace(/^[._-]+/, "").replace(/-+/g, "-");
2148
+ return trimmed.length > 0 ? trimmed : "my-app";
2149
+ }
2050
2150
  //#endregion
2051
2151
  export { runInit };
2052
2152
 
2053
- //# sourceMappingURL=init-DETSgw3h.mjs.map
2153
+ //# sourceMappingURL=init-BRKnARU6.mjs.map