@prisma-next/cli 0.1.0-dev.2 → 0.1.0-dev.20

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createContractEmitCommand
3
- } from "../chunk-4Q3MO4TK.js";
4
- import "../chunk-3EODSNGS.js";
3
+ } from "../chunk-VWAVGWUP.js";
4
+ import "../chunk-ZKEJZ3NU.js";
5
5
  import "../chunk-HWYQOCAJ.js";
6
6
  export {
7
7
  createContractEmitCommand
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+
3
+ declare function createDbInitCommand(): Command;
4
+
5
+ export { createDbInitCommand };
@@ -0,0 +1,240 @@
1
+ import {
2
+ assertFrameworkComponentsCompatible
3
+ } from "../chunk-YDE4ILKH.js";
4
+ import {
5
+ errorDatabaseUrlRequired,
6
+ errorDriverRequired,
7
+ errorFileNotFound,
8
+ errorMigrationPlanningFailed,
9
+ errorRuntime,
10
+ errorTargetMigrationNotSupported,
11
+ errorUnexpected,
12
+ formatCommandHelp,
13
+ formatDbInitApplyOutput,
14
+ formatDbInitJson,
15
+ formatDbInitPlanOutput,
16
+ formatStyledHeader,
17
+ handleResult,
18
+ parseGlobalFlags,
19
+ performAction,
20
+ setCommandDescriptions,
21
+ withSpinner
22
+ } from "../chunk-ZKEJZ3NU.js";
23
+ import {
24
+ loadConfig
25
+ } from "../chunk-HWYQOCAJ.js";
26
+
27
+ // src/commands/db-init.ts
28
+ import { readFile } from "fs/promises";
29
+ import { relative, resolve } from "path";
30
+ import { Command } from "commander";
31
+ function createDbInitCommand() {
32
+ const command = new Command("init");
33
+ setCommandDescriptions(
34
+ command,
35
+ "Bootstrap a database to match the current contract and write the contract marker",
36
+ "Initializes a database to match your emitted contract using additive-only operations.\nCreates tables, columns, indexes, and constraints defined in your contract.\nWrites a contract marker to track the database state. This operation is idempotent.\n\nCurrently supports empty databases only. Use --plan to preview changes without applying."
37
+ );
38
+ command.configureHelp({
39
+ formatHelp: (cmd) => {
40
+ const flags = parseGlobalFlags({});
41
+ return formatCommandHelp({ command: cmd, flags });
42
+ }
43
+ }).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--plan", "Preview planned operations without applying", false).option("--json [format]", "Output as JSON (object or ndjson)", false).option("-q, --quiet", "Quiet mode: errors only").option("-v, --verbose", "Verbose output: debug info, timings").option("-vv, --trace", "Trace output: deep internals, stack traces").option("--timestamps", "Add timestamps to output").option("--color", "Force color output").option("--no-color", "Disable color output").action(async (options) => {
44
+ const flags = parseGlobalFlags(options);
45
+ const startTime = Date.now();
46
+ const result = await performAction(async () => {
47
+ const config = await loadConfig(options.config);
48
+ const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
49
+ const contractPathAbsolute = config.contract?.output ? resolve(config.contract.output) : resolve("src/prisma/contract.json");
50
+ const contractPath = relative(process.cwd(), contractPathAbsolute);
51
+ if (flags.json !== "object" && !flags.quiet) {
52
+ const details = [
53
+ { label: "config", value: configPath },
54
+ { label: "contract", value: contractPath }
55
+ ];
56
+ if (options.db) {
57
+ details.push({ label: "database", value: options.db });
58
+ }
59
+ if (options.plan) {
60
+ details.push({ label: "mode", value: "plan (dry run)" });
61
+ }
62
+ const header = formatStyledHeader({
63
+ command: "db init",
64
+ description: "Bootstrap a database to match the current contract",
65
+ url: "https://pris.ly/db-init",
66
+ details,
67
+ flags
68
+ });
69
+ console.log(header);
70
+ }
71
+ let contractJsonContent;
72
+ try {
73
+ contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
74
+ } catch (error) {
75
+ if (error instanceof Error && error.code === "ENOENT") {
76
+ throw errorFileNotFound(contractPathAbsolute, {
77
+ why: `Contract file not found at ${contractPathAbsolute}`
78
+ });
79
+ }
80
+ throw errorUnexpected(error instanceof Error ? error.message : String(error), {
81
+ why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`
82
+ });
83
+ }
84
+ let contractJson;
85
+ try {
86
+ contractJson = JSON.parse(contractJsonContent);
87
+ } catch (error) {
88
+ throw errorUnexpected(error instanceof Error ? error.message : String(error), {
89
+ why: `Failed to parse contract JSON at ${contractPathAbsolute}: ${error instanceof Error ? error.message : String(error)}`
90
+ });
91
+ }
92
+ const dbUrl = options.db ?? config.db?.url;
93
+ if (!dbUrl) {
94
+ throw errorDatabaseUrlRequired({ why: "Database URL is required for db init" });
95
+ }
96
+ if (!config.driver) {
97
+ throw errorDriverRequired({ why: "Config.driver is required for db init" });
98
+ }
99
+ const driverDescriptor = config.driver;
100
+ if (!config.target.migrations) {
101
+ throw errorTargetMigrationNotSupported({
102
+ why: `Target "${config.target.id}" does not support migrations`
103
+ });
104
+ }
105
+ const migrations = config.target.migrations;
106
+ const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {
107
+ message: "Connecting to database...",
108
+ flags
109
+ });
110
+ try {
111
+ const familyInstance = config.family.create({
112
+ target: config.target,
113
+ adapter: config.adapter,
114
+ driver: driverDescriptor,
115
+ extensions: config.extensions ?? []
116
+ });
117
+ const rawComponents = [config.target, config.adapter, ...config.extensions ?? []];
118
+ const frameworkComponents = assertFrameworkComponentsCompatible(
119
+ config.family.familyId,
120
+ config.target.targetId,
121
+ rawComponents
122
+ );
123
+ const contractIR = familyInstance.validateContractIR(contractJson);
124
+ const planner = migrations.createPlanner(familyInstance);
125
+ const runner = migrations.createRunner(familyInstance);
126
+ const schemaIR = await withSpinner(() => familyInstance.introspect({ driver }), {
127
+ message: "Introspecting database schema...",
128
+ flags
129
+ });
130
+ const policy = { allowedOperationClasses: ["additive"] };
131
+ const plannerResult = await withSpinner(
132
+ async () => planner.plan({
133
+ contract: contractIR,
134
+ schema: schemaIR,
135
+ policy,
136
+ frameworkComponents
137
+ }),
138
+ {
139
+ message: "Planning migration...",
140
+ flags
141
+ }
142
+ );
143
+ if (plannerResult.kind === "failure") {
144
+ throw errorMigrationPlanningFailed({ conflicts: plannerResult.conflicts });
145
+ }
146
+ const migrationPlan = plannerResult.plan;
147
+ if (options.plan) {
148
+ const dbInitResult2 = {
149
+ ok: true,
150
+ mode: "plan",
151
+ plan: {
152
+ targetId: migrationPlan.targetId,
153
+ destination: migrationPlan.destination,
154
+ operations: migrationPlan.operations.map((op) => ({
155
+ id: op.id,
156
+ label: op.label,
157
+ operationClass: op.operationClass
158
+ }))
159
+ },
160
+ summary: `Planned ${migrationPlan.operations.length} operation(s)`,
161
+ timings: { total: Date.now() - startTime }
162
+ };
163
+ return dbInitResult2;
164
+ }
165
+ const callbacks = {
166
+ onOperationStart: (op) => {
167
+ if (!flags.quiet && flags.json !== "object") {
168
+ console.log(` \u2192 ${op.label}...`);
169
+ }
170
+ },
171
+ onOperationComplete: (_op) => {
172
+ }
173
+ };
174
+ const runnerResult = await withSpinner(
175
+ () => runner.execute({
176
+ plan: migrationPlan,
177
+ driver,
178
+ destinationContract: contractIR,
179
+ policy,
180
+ callbacks,
181
+ frameworkComponents
182
+ }),
183
+ {
184
+ message: "Applying migration plan...",
185
+ flags
186
+ }
187
+ );
188
+ if (!runnerResult.ok) {
189
+ throw errorRuntime(runnerResult.failure.summary, {
190
+ why: runnerResult.failure.why ?? `Migration runner failed: ${runnerResult.failure.code}`,
191
+ meta: { code: runnerResult.failure.code }
192
+ });
193
+ }
194
+ const execution = runnerResult.value;
195
+ const dbInitResult = {
196
+ ok: true,
197
+ mode: "apply",
198
+ plan: {
199
+ targetId: migrationPlan.targetId,
200
+ destination: migrationPlan.destination,
201
+ operations: migrationPlan.operations.map((op) => ({
202
+ id: op.id,
203
+ label: op.label,
204
+ operationClass: op.operationClass
205
+ }))
206
+ },
207
+ execution: {
208
+ operationsPlanned: execution.operationsPlanned,
209
+ operationsExecuted: execution.operationsExecuted
210
+ },
211
+ marker: migrationPlan.destination.profileHash ? {
212
+ coreHash: migrationPlan.destination.coreHash,
213
+ profileHash: migrationPlan.destination.profileHash
214
+ } : { coreHash: migrationPlan.destination.coreHash },
215
+ summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,
216
+ timings: { total: Date.now() - startTime }
217
+ };
218
+ return dbInitResult;
219
+ } finally {
220
+ await driver.close();
221
+ }
222
+ });
223
+ const exitCode = handleResult(result, flags, (dbInitResult) => {
224
+ if (flags.json === "object") {
225
+ console.log(formatDbInitJson(dbInitResult));
226
+ } else {
227
+ const output = dbInitResult.mode === "plan" ? formatDbInitPlanOutput(dbInitResult, flags) : formatDbInitApplyOutput(dbInitResult, flags);
228
+ if (output) {
229
+ console.log(output);
230
+ }
231
+ }
232
+ });
233
+ process.exit(exitCode);
234
+ });
235
+ return command;
236
+ }
237
+ export {
238
+ createDbInitCommand
239
+ };
240
+ //# sourceMappingURL=db-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/commands/db-init.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport type {\n MigrationPlan,\n MigrationPlannerResult,\n MigrationPlanOperation,\n MigrationRunnerResult,\n} from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorMigrationPlanningFailed,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n type DbInitResult,\n formatCommandHelp,\n formatDbInitApplyOutput,\n formatDbInitJson,\n formatDbInitPlanOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { performAction } from '../utils/result';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbInitOptions {\n readonly db?: string;\n readonly config?: string;\n readonly plan?: boolean;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbInitCommand(): Command {\n const command = new Command('init');\n setCommandDescriptions(\n command,\n 'Bootstrap a database to match the current contract and write the contract marker',\n 'Initializes a database to match your emitted contract using additive-only operations.\\n' +\n 'Creates tables, columns, indexes, and constraints defined in your contract.\\n' +\n 'Writes a contract marker to track the database state. This operation is idempotent.\\n' +\n '\\n' +\n 'Currently supports empty databases only. Use --plan to preview changes without applying.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--plan', 'Preview planned operations without applying', false)\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbInitOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const result = await performAction(async () => {\n // Load config\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 = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n if (options.plan) {\n details.push({ label: 'mode', value: 'plan (dry run)' });\n }\n const header = formatStyledHeader({\n command: 'db init',\n description: 'Bootstrap a database to match the current contract',\n url: 'https://pris.ly/db-init',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file\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 throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw 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 let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n throw errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to parse contract JSON at ${contractPathAbsolute}: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired({ why: 'Database URL is required for db init' });\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired({ why: 'Config.driver is required for db init' });\n }\n const driverDescriptor = config.driver;\n\n // Check target supports migrations via the migrations capability\n if (!config.target.migrations) {\n throw errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n });\n }\n const migrations = config.target.migrations;\n\n // Create driver\n const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const familyInstance = config.family.create({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensions: config.extensions ?? [],\n });\n const rawComponents = [config.target, config.adapter, ...(config.extensions ?? [])];\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n rawComponents,\n );\n\n // Validate contract\n const contractIR = familyInstance.validateContractIR(contractJson);\n\n // Create planner and runner from target migrations capability\n const planner = migrations.createPlanner(familyInstance);\n const runner = migrations.createRunner(familyInstance);\n\n // Introspect live schema\n const schemaIR = await withSpinner(() => familyInstance.introspect({ driver }), {\n message: 'Introspecting database schema...',\n flags,\n });\n\n // Policy for init mode (additive only)\n const policy = { allowedOperationClasses: ['additive'] as const };\n\n // Plan migration\n const plannerResult: MigrationPlannerResult = await withSpinner(\n async () =>\n planner.plan({\n contract: contractIR,\n schema: schemaIR,\n policy,\n frameworkComponents,\n }),\n {\n message: 'Planning migration...',\n flags,\n },\n );\n\n if (plannerResult.kind === 'failure') {\n throw errorMigrationPlanningFailed({ conflicts: plannerResult.conflicts });\n }\n\n const migrationPlan: MigrationPlan = plannerResult.plan;\n\n // Plan mode - don't execute\n if (options.plan) {\n const dbInitResult: DbInitResult = {\n ok: true,\n mode: 'plan',\n plan: {\n targetId: migrationPlan.targetId,\n destination: migrationPlan.destination,\n operations: migrationPlan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n },\n summary: `Planned ${migrationPlan.operations.length} operation(s)`,\n timings: { total: Date.now() - startTime },\n };\n return dbInitResult;\n }\n\n // Apply mode - execute runner\n const callbacks = {\n onOperationStart: (op: MigrationPlanOperation) => {\n if (!flags.quiet && flags.json !== 'object') {\n console.log(` → ${op.label}...`);\n }\n },\n onOperationComplete: (_op: MigrationPlanOperation) => {\n // Could log completion if needed\n },\n };\n\n const runnerResult: MigrationRunnerResult = await withSpinner(\n () =>\n runner.execute({\n plan: migrationPlan,\n driver,\n destinationContract: contractIR,\n policy,\n callbacks,\n frameworkComponents,\n }),\n {\n message: 'Applying migration plan...',\n flags,\n },\n );\n\n if (!runnerResult.ok) {\n throw errorRuntime(runnerResult.failure.summary, {\n why:\n runnerResult.failure.why ?? `Migration runner failed: ${runnerResult.failure.code}`,\n meta: { code: runnerResult.failure.code },\n });\n }\n\n const execution = runnerResult.value;\n\n const dbInitResult: DbInitResult = {\n ok: true,\n mode: 'apply',\n plan: {\n targetId: migrationPlan.targetId,\n destination: migrationPlan.destination,\n operations: migrationPlan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n },\n execution: {\n operationsPlanned: execution.operationsPlanned,\n operationsExecuted: execution.operationsExecuted,\n },\n marker: migrationPlan.destination.profileHash\n ? {\n coreHash: migrationPlan.destination.coreHash,\n profileHash: migrationPlan.destination.profileHash,\n }\n : { coreHash: migrationPlan.destination.coreHash },\n summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,\n timings: { total: Date.now() - startTime },\n };\n return dbInitResult;\n } finally {\n await driver.close();\n }\n });\n\n // Handle result\n const exitCode = handleResult(result, flags, (dbInitResult) => {\n if (flags.json === 'object') {\n console.log(formatDbInitJson(dbInitResult));\n } else {\n const output =\n dbInitResult.mode === 'plan'\n ? formatDbInitPlanOutput(dbInitResult, flags)\n : formatDbInitApplyOutput(dbInitResult, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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","names":["dbInitResult"]}
@@ -8,7 +8,7 @@ import {
8
8
  performAction,
9
9
  setCommandDescriptions,
10
10
  withSpinner
11
- } from "../chunk-3EODSNGS.js";
11
+ } from "../chunk-ZKEJZ3NU.js";
12
12
  import {
13
13
  loadConfig
14
14
  } from "../chunk-HWYQOCAJ.js";
@@ -46,8 +46,7 @@ function createDbIntrospectCommand() {
46
46
  const contractPath = resolve(config.contract.output);
47
47
  try {
48
48
  const contractJsonContent = await readFile(contractPath, "utf-8");
49
- const contractJson = JSON.parse(contractJsonContent);
50
- contractIR = contractJson;
49
+ contractIR = JSON.parse(contractJsonContent);
51
50
  } catch (error) {
52
51
  if (error instanceof Error && error.code !== "ENOENT") {
53
52
  throw errorUnexpected(error.message, {
@@ -95,14 +94,13 @@ function createDbIntrospectCommand() {
95
94
  driver: driverDescriptor,
96
95
  extensions: config.extensions ?? []
97
96
  });
98
- const typedFamilyInstance = familyInstance;
99
97
  if (contractIR) {
100
- contractIR = typedFamilyInstance.validateContractIR(contractIR);
98
+ contractIR = familyInstance.validateContractIR(contractIR);
101
99
  }
102
100
  let schemaIR;
103
101
  try {
104
102
  schemaIR = await withSpinner(
105
- () => typedFamilyInstance.introspect({
103
+ () => familyInstance.introspect({
106
104
  driver,
107
105
  contractIR
108
106
  }),
@@ -117,9 +115,9 @@ function createDbIntrospectCommand() {
117
115
  });
118
116
  }
119
117
  let schemaView;
120
- if (typedFamilyInstance.toSchemaView) {
118
+ if (familyInstance.toSchemaView) {
121
119
  try {
122
- schemaView = typedFamilyInstance.toSchemaView(schemaIR);
120
+ schemaView = familyInstance.toSchemaView(schemaIR);
123
121
  } catch (error) {
124
122
  if (flags.verbose) {
125
123
  console.error(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/db-introspect.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorRuntime,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';\nimport type { FamilyInstance, IntrospectSchemaResult } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatIntrospectJson,\n formatIntrospectOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { performAction } from '../utils/result';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbIntrospectOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbIntrospectCommand(): Command {\n const command = new Command('introspect');\n setCommandDescriptions(\n command,\n 'Inspect the database schema',\n 'Reads the live database schema and displays it as a tree structure. This command\\n' +\n 'does not check the schema against your contract - it only shows what exists in\\n' +\n 'the database. Use `db verify` or `db schema-verify` to compare against your contract.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbIntrospectOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n const startTime = Date.now();\n\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n // Optionally load contract if contract config exists\n let contractIR: unknown | undefined;\n if (config.contract?.output) {\n const contractPath = resolve(config.contract.output);\n try {\n const contractJsonContent = await readFile(contractPath, 'utf-8');\n const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n // Validate contract using family instance (will be created later)\n // For now, we'll pass the raw JSON and let the family instance validate it\n contractIR = contractJson;\n } catch (error) {\n // Contract file is optional for introspection - don't fail if it doesn't exist\n if (error instanceof Error && (error as { code?: string }).code !== 'ENOENT') {\n throw errorUnexpected(error.message, {\n why: `Failed to read contract file: ${error.message}`,\n });\n }\n }\n }\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n ];\n if (options.db) {\n // Mask password in URL for security\n const maskedUrl = options.db.replace(/:([^:@]+)@/, ':****@');\n details.push({ label: 'database', value: maskedUrl });\n } else if (config.db?.url) {\n // Mask password in URL for security\n const maskedUrl = config.db.url.replace(/:([^:@]+)@/, ':****@');\n details.push({ label: 'database', value: maskedUrl });\n }\n const header = formatStyledHeader({\n command: 'db introspect',\n description: 'Inspect the database schema',\n url: 'https://pris.ly/db-introspect',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create driver\n const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const familyInstance = config.family.create({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensions: config.extensions ?? [],\n });\n const typedFamilyInstance = familyInstance as FamilyInstance<string>;\n\n // Validate contract IR if we loaded it\n if (contractIR) {\n contractIR = typedFamilyInstance.validateContractIR(contractIR);\n }\n\n // Call family instance introspect method\n let schemaIR: unknown;\n try {\n schemaIR = await withSpinner(\n () =>\n typedFamilyInstance.introspect({\n driver,\n contractIR,\n }),\n {\n message: 'Introspecting database schema...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from introspect() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to introspect database: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Optionally call toSchemaView if available\n let schemaView: CoreSchemaView | undefined;\n if (typedFamilyInstance.toSchemaView) {\n try {\n schemaView = typedFamilyInstance.toSchemaView(schemaIR);\n } catch (error) {\n // Schema view projection is optional - log but don't fail\n if (flags.verbose) {\n console.error(\n `Warning: Failed to project schema to view: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n const totalTime = Date.now() - startTime;\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n // Build result envelope\n const introspectResult: IntrospectSchemaResult<unknown> = {\n ok: true,\n summary: 'Schema introspected successfully',\n target: {\n familyId: config.family.familyId,\n id: config.target.targetId,\n },\n schema: schemaIR,\n ...(configPath || options.db || config.db?.url\n ? {\n meta: {\n ...(configPath ? { configPath } : {}),\n ...(options.db || config.db?.url\n ? {\n dbUrl: (options.db ?? config.db?.url ?? '').replace(\n /:([^:@]+)@/,\n ':****@',\n ),\n }\n : {}),\n },\n }\n : {}),\n timings: {\n total: totalTime,\n },\n };\n\n return { introspectResult, schemaView };\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (value) => {\n const { introspectResult, schemaView } = value;\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatIntrospectJson(introspectResult));\n } else {\n // Human-readable output to stdout\n const output = formatIntrospectOutput(introspectResult, schemaView, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/commands/db-introspect.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorRuntime,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type { CoreSchemaView } from '@prisma-next/core-control-plane/schema-view';\nimport type { IntrospectSchemaResult } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatIntrospectJson,\n formatIntrospectOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { performAction } from '../utils/result';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbIntrospectOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbIntrospectCommand(): Command {\n const command = new Command('introspect');\n setCommandDescriptions(\n command,\n 'Inspect the database schema',\n 'Reads the live database schema and displays it as a tree structure. This command\\n' +\n 'does not check the schema against your contract - it only shows what exists in\\n' +\n 'the database. Use `db verify` or `db schema-verify` to compare against your contract.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbIntrospectOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n const startTime = Date.now();\n\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n // Optionally load contract if contract config exists\n let contractIR: unknown | undefined;\n if (config.contract?.output) {\n const contractPath = resolve(config.contract.output);\n try {\n const contractJsonContent = await readFile(contractPath, 'utf-8');\n contractIR = JSON.parse(contractJsonContent);\n } catch (error) {\n // Contract file is optional for introspection - don't fail if it doesn't exist\n if (error instanceof Error && (error as { code?: string }).code !== 'ENOENT') {\n throw errorUnexpected(error.message, {\n why: `Failed to read contract file: ${error.message}`,\n });\n }\n }\n }\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n ];\n if (options.db) {\n // Mask password in URL for security\n const maskedUrl = options.db.replace(/:([^:@]+)@/, ':****@');\n details.push({ label: 'database', value: maskedUrl });\n } else if (config.db?.url) {\n // Mask password in URL for security\n const maskedUrl = config.db.url.replace(/:([^:@]+)@/, ':****@');\n details.push({ label: 'database', value: maskedUrl });\n }\n const header = formatStyledHeader({\n command: 'db introspect',\n description: 'Inspect the database schema',\n url: 'https://pris.ly/db-introspect',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create driver\n const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const familyInstance = config.family.create({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensions: config.extensions ?? [],\n });\n\n // Validate contract IR if we loaded it\n if (contractIR) {\n contractIR = familyInstance.validateContractIR(contractIR);\n }\n\n // Call family instance introspect method\n let schemaIR: unknown;\n try {\n schemaIR = await withSpinner(\n () =>\n familyInstance.introspect({\n driver,\n contractIR,\n }),\n {\n message: 'Introspecting database schema...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from introspect() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to introspect database: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Optionally call toSchemaView if available\n let schemaView: CoreSchemaView | undefined;\n if (familyInstance.toSchemaView) {\n try {\n schemaView = familyInstance.toSchemaView(schemaIR);\n } catch (error) {\n // Schema view projection is optional - log but don't fail\n if (flags.verbose) {\n console.error(\n `Warning: Failed to project schema to view: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n }\n\n const totalTime = Date.now() - startTime;\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n // Build result envelope\n const introspectResult: IntrospectSchemaResult<unknown> = {\n ok: true,\n summary: 'Schema introspected successfully',\n target: {\n familyId: config.family.familyId,\n id: config.target.targetId,\n },\n schema: schemaIR,\n ...(configPath || options.db || config.db?.url\n ? {\n meta: {\n ...(configPath ? { configPath } : {}),\n ...(options.db || config.db?.url\n ? {\n dbUrl: (options.db ?? config.db?.url ?? '').replace(\n /:([^:@]+)@/,\n ':****@',\n ),\n }\n : {}),\n },\n }\n : {}),\n timings: {\n total: totalTime,\n },\n };\n\n return { introspectResult, schemaView };\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (value) => {\n const { introspectResult, schemaView } = value;\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatIntrospectJson(introspectResult));\n } else {\n // Human-readable output to stdout\n const output = formatIntrospectOutput(introspectResult, schemaView, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,6 @@
1
+ import {
2
+ assertFrameworkComponentsCompatible
3
+ } from "../chunk-YDE4ILKH.js";
1
4
  import {
2
5
  formatCommandHelp,
3
6
  formatSchemaVerifyJson,
@@ -8,7 +11,7 @@ import {
8
11
  performAction,
9
12
  setCommandDescriptions,
10
13
  withSpinner
11
- } from "../chunk-3EODSNGS.js";
14
+ } from "../chunk-ZKEJZ3NU.js";
12
15
  import {
13
16
  loadConfig
14
17
  } from "../chunk-HWYQOCAJ.js";
@@ -93,17 +96,23 @@ function createDbSchemaVerifyCommand() {
93
96
  driver: driverDescriptor,
94
97
  extensions: config.extensions ?? []
95
98
  });
96
- const typedFamilyInstance = familyInstance;
97
- const contractIR = typedFamilyInstance.validateContractIR(contractJson);
99
+ const rawComponents = [config.target, config.adapter, ...config.extensions ?? []];
100
+ const frameworkComponents = assertFrameworkComponentsCompatible(
101
+ config.family.familyId,
102
+ config.target.targetId,
103
+ rawComponents
104
+ );
105
+ const contractIR = familyInstance.validateContractIR(contractJson);
98
106
  let schemaVerifyResult;
99
107
  try {
100
108
  schemaVerifyResult = await withSpinner(
101
- () => typedFamilyInstance.schemaVerify({
109
+ () => familyInstance.schemaVerify({
102
110
  driver,
103
111
  contractIR,
104
112
  strict: options.strict ?? false,
105
113
  contractPath: contractPathAbsolute,
106
- configPath
114
+ configPath,
115
+ frameworkComponents
107
116
  }),
108
117
  {
109
118
  message: "Verifying database schema...",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/db-schema-verify.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type {\n FamilyInstance,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { performAction } from '../utils/result';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbSchemaVerifyOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly strict?: boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbSchemaVerifyCommand(): Command {\n const command = new Command('schema-verify');\n setCommandDescriptions(\n command,\n 'Check whether the database schema satisfies your contract',\n 'Verifies that your database schema satisfies the emitted contract. Compares table structures,\\n' +\n 'column types, constraints, and extensions. Reports any mismatches via a contract-shaped\\n' +\n 'verification tree. This is a read-only operation that does not modify the database.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('--strict', 'Strict mode: extra schema elements cause failures', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbSchemaVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n // Convert to relative path for display\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n const header = formatStyledHeader({\n command: 'db schema-verify',\n description: 'Check whether the database schema satisfies your contract',\n url: 'https://pris.ly/db-schema-verify',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file (file I/O)\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 throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw 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 const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create driver\n const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const familyInstance = config.family.create({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensions: config.extensions ?? [],\n });\n const typedFamilyInstance = familyInstance as FamilyInstance<string>;\n\n // Validate contract using instance validator\n const contractIR = typedFamilyInstance.validateContractIR(contractJson) as ContractIR;\n\n // Call family instance schemaVerify method\n let schemaVerifyResult: VerifyDatabaseSchemaResult;\n try {\n schemaVerifyResult = (await withSpinner(\n () =>\n typedFamilyInstance.schemaVerify({\n driver,\n contractIR,\n strict: options.strict ?? false,\n contractPath: contractPathAbsolute,\n configPath,\n }),\n {\n message: 'Verifying database schema...',\n flags,\n },\n )) as VerifyDatabaseSchemaResult;\n } catch (error) {\n // Wrap errors from schemaVerify() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify database schema: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n // Return result (don't throw for logical mismatches - handle exit code separately)\n return schemaVerifyResult;\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (schemaVerifyResult) => {\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n // Human-readable output to stdout\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n\n // For logical schema mismatches, check if verification passed\n // Infra errors already handled by handleResult (returns non-zero exit code)\n if (result.ok && !result.value.ok) {\n // Schema verification failed - exit with code 1\n process.exit(1);\n } else {\n // Success or infra error - use exit code from handleResult\n process.exit(exitCode);\n }\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,UAAU,eAAe;AAElC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAKP,SAAS,eAAe;AA8BjB,SAAS,8BAAuC;AACrD,QAAM,UAAU,IAAI,QAAQ,eAAe;AAC3C;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EAGF;AACA,UACG,cAAc;AAAA,IACb,YAAY,CAAC,QAAQ;AACnB,YAAM,QAAQ,iBAAiB,CAAC,CAAC;AACjC,aAAO,kBAAkB,EAAE,SAAS,KAAK,MAAM,CAAC;AAAA,IAClD;AAAA,EACF,CAAC,EACA,OAAO,cAAc,4BAA4B,EACjD,OAAO,mBAAmB,+BAA+B,EACzD,OAAO,mBAAmB,qCAAqC,KAAK,EACpE,OAAO,YAAY,qDAAqD,KAAK,EAC7E,OAAO,eAAe,yBAAyB,EAC/C,OAAO,iBAAiB,qCAAqC,EAC7D,OAAO,gBAAgB,4CAA4C,EACnE,OAAO,gBAAgB,0BAA0B,EACjD,OAAO,WAAW,oBAAoB,EACtC,OAAO,cAAc,sBAAsB,EAC3C,OAAO,OAAO,YAAmC;AAChD,UAAM,QAAQ,iBAAiB,OAAO;AAEtC,UAAM,SAAS,MAAM,cAAc,YAAY;AAE7C,YAAM,SAAS,MAAM,WAAW,QAAQ,MAAM;AAE9C,YAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,IAAI,GAAG,QAAQ,QAAQ,MAAM,CAAC,IAC/C;AACJ,YAAM,uBAAuB,OAAO,UAAU,SAC1C,QAAQ,OAAO,SAAS,MAAM,IAC9B,QAAQ,0BAA0B;AAEtC,YAAM,eAAe,SAAS,QAAQ,IAAI,GAAG,oBAAoB;AAGjE,UAAI,MAAM,SAAS,YAAY,CAAC,MAAM,OAAO;AAC3C,cAAM,UAAmD;AAAA,UACvD,EAAE,OAAO,UAAU,OAAO,WAAW;AAAA,UACrC,EAAE,OAAO,YAAY,OAAO,aAAa;AAAA,QAC3C;AACA,YAAI,QAAQ,IAAI;AACd,kBAAQ,KAAK,EAAE,OAAO,YAAY,OAAO,QAAQ,GAAG,CAAC;AAAA,QACvD;AACA,cAAM,SAAS,mBAAmB;AAAA,UAChC,SAAS;AAAA,UACT,aAAa;AAAA,UACb,KAAK;AAAA,UACL;AAAA,UACA;AAAA,QACF,CAAC;AACD,gBAAQ,IAAI,MAAM;AAAA,MACpB;AAGA,UAAI;AACJ,UAAI;AACF,8BAAsB,MAAM,SAAS,sBAAsB,OAAO;AAAA,MACpE,SAAS,OAAO;AACd,YAAI,iBAAiB,SAAU,MAA4B,SAAS,UAAU;AAC5E,gBAAM,kBAAkB,sBAAsB;AAAA,YAC5C,KAAK,8BAA8B,oBAAoB;AAAA,UACzD,CAAC;AAAA,QACH;AACA,cAAM,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;AAAA,UAC5E,KAAK,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC9F,CAAC;AAAA,MACH;AACA,YAAM,eAAe,KAAK,MAAM,mBAAmB;AAGnD,YAAM,QAAQ,QAAQ,MAAM,OAAO,IAAI;AACvC,UAAI,CAAC,OAAO;AACV,cAAM,yBAAyB;AAAA,MACjC;AAGA,UAAI,CAAC,OAAO,QAAQ;AAClB,cAAM,oBAAoB;AAAA,MAC5B;AAGA,YAAM,mBAAmB,OAAO;AAGhC,YAAM,SAAS,MAAM,YAAY,MAAM,iBAAiB,OAAO,KAAK,GAAG;AAAA,QACrE,SAAS;AAAA,QACT;AAAA,MACF,CAAC;AAED,UAAI;AAEF,cAAM,iBAAiB,OAAO,OAAO,OAAO;AAAA,UAC1C,QAAQ,OAAO;AAAA,UACf,SAAS,OAAO;AAAA,UAChB,QAAQ;AAAA,UACR,YAAY,OAAO,cAAc,CAAC;AAAA,QACpC,CAAC;AACD,cAAM,sBAAsB;AAG5B,cAAM,aAAa,oBAAoB,mBAAmB,YAAY;AAGtE,YAAI;AACJ,YAAI;AACF,+BAAsB,MAAM;AAAA,YAC1B,MACE,oBAAoB,aAAa;AAAA,cAC/B;AAAA,cACA;AAAA,cACA,QAAQ,QAAQ,UAAU;AAAA,cAC1B,cAAc;AAAA,cACd;AAAA,YACF,CAAC;AAAA,YACH;AAAA,cACE,SAAS;AAAA,cACT;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AAEd,gBAAM,aAAa,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;AAAA,YACzE,KAAK,qCAAqC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UAClG,CAAC;AAAA,QACH;AAGA,YAAI,CAAC,MAAM,SAAS,MAAM,SAAS,YAAY,QAAQ,OAAO,OAAO;AACnE,kBAAQ,IAAI,EAAE;AAAA,QAChB;AAGA,eAAO;AAAA,MACT,UAAE;AAEA,cAAM,OAAO,MAAM;AAAA,MACrB;AAAA,IACF,CAAC;AAGD,UAAM,WAAW,aAAa,QAAQ,OAAO,CAAC,uBAAuB;AAEnE,UAAI,MAAM,SAAS,UAAU;AAE3B,gBAAQ,IAAI,uBAAuB,kBAAkB,CAAC;AAAA,MACxD,OAAO;AAEL,cAAM,SAAS,yBAAyB,oBAAoB,KAAK;AACjE,YAAI,QAAQ;AACV,kBAAQ,IAAI,MAAM;AAAA,QACpB;AAAA,MACF;AAAA,IACF,CAAC;AAID,QAAI,OAAO,MAAM,CAAC,OAAO,MAAM,IAAI;AAEjC,cAAQ,KAAK,CAAC;AAAA,IAChB,OAAO;AAEL,cAAQ,KAAK,QAAQ;AAAA,IACvB;AAAA,EACF,CAAC;AAEH,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/commands/db-schema-verify.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport {\n errorDatabaseUrlRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n} from '@prisma-next/core-control-plane/errors';\nimport type { VerifyDatabaseSchemaResult } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatSchemaVerifyJson,\n formatSchemaVerifyOutput,\n formatStyledHeader,\n} from '../utils/output';\nimport { performAction } from '../utils/result';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface DbSchemaVerifyOptions {\n readonly db?: string;\n readonly config?: string;\n readonly json?: string | boolean;\n readonly strict?: boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createDbSchemaVerifyCommand(): Command {\n const command = new Command('schema-verify');\n setCommandDescriptions(\n command,\n 'Check whether the database schema satisfies your contract',\n 'Verifies that your database schema satisfies the emitted contract. Compares table structures,\\n' +\n 'column types, constraints, and extensions. Reports any mismatches via a contract-shaped\\n' +\n 'verification tree. This is a read-only operation that does not modify the database.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('--strict', 'Strict mode: extra schema elements cause failures', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: DbSchemaVerifyOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config (file I/O)\n const config = await loadConfig(options.config);\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = config.contract?.output\n ? resolve(config.contract.output)\n : resolve('src/prisma/contract.json');\n // Convert to relative path for display\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: options.db });\n }\n const header = formatStyledHeader({\n command: 'db schema-verify',\n description: 'Check whether the database schema satisfies your contract',\n url: 'https://pris.ly/db-schema-verify',\n details,\n flags,\n });\n console.log(header);\n }\n\n // Load contract file (file I/O)\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 throw errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n });\n }\n throw 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 const contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n\n // Resolve database URL\n const dbUrl = options.db ?? config.db?.url;\n if (!dbUrl) {\n throw errorDatabaseUrlRequired();\n }\n\n // Check for driver\n if (!config.driver) {\n throw errorDriverRequired();\n }\n\n // Store driver descriptor after null check\n const driverDescriptor = config.driver;\n\n // Create driver\n const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {\n message: 'Connecting to database...',\n flags,\n });\n\n try {\n // Create family instance\n const familyInstance = config.family.create({\n target: config.target,\n adapter: config.adapter,\n driver: driverDescriptor,\n extensions: config.extensions ?? [],\n });\n const rawComponents = [config.target, config.adapter, ...(config.extensions ?? [])];\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n rawComponents,\n );\n\n // Validate contract using instance validator\n const contractIR = familyInstance.validateContractIR(contractJson) as ContractIR;\n\n // Call family instance schemaVerify method\n let schemaVerifyResult: VerifyDatabaseSchemaResult;\n try {\n schemaVerifyResult = await withSpinner(\n () =>\n familyInstance.schemaVerify({\n driver,\n contractIR,\n strict: options.strict ?? false,\n contractPath: contractPathAbsolute,\n configPath,\n frameworkComponents,\n }),\n {\n message: 'Verifying database schema...',\n flags,\n },\n );\n } catch (error) {\n // Wrap errors from schemaVerify() in structured error\n throw errorRuntime(error instanceof Error ? error.message : String(error), {\n why: `Failed to verify database schema: ${error instanceof Error ? error.message : String(error)}`,\n });\n }\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n // Return result (don't throw for logical mismatches - handle exit code separately)\n return schemaVerifyResult;\n } finally {\n // Ensure driver connection is closed\n await driver.close();\n }\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (schemaVerifyResult) => {\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatSchemaVerifyJson(schemaVerifyResult));\n } else {\n // Human-readable output to stdout\n const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);\n if (output) {\n console.log(output);\n }\n }\n });\n\n // For logical schema mismatches, check if verification passed\n // Infra errors already handled by handleResult (returns non-zero exit code)\n if (result.ok && !result.value.ok) {\n // Schema verification failed - exit with code 1\n process.exit(1);\n } else {\n // Success or infra error - use exit code from handleResult\n process.exit(exitCode);\n }\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
@@ -1,3 +1,6 @@
1
+ import {
2
+ assertFrameworkComponentsCompatible
3
+ } from "../chunk-YDE4ILKH.js";
1
4
  import {
2
5
  formatCommandHelp,
3
6
  formatSchemaVerifyJson,
@@ -10,7 +13,7 @@ import {
10
13
  performAction,
11
14
  setCommandDescriptions,
12
15
  withSpinner
13
- } from "../chunk-3EODSNGS.js";
16
+ } from "../chunk-ZKEJZ3NU.js";
14
17
  import {
15
18
  loadConfig
16
19
  } from "../chunk-HWYQOCAJ.js";
@@ -92,20 +95,24 @@ function createDbSignCommand() {
92
95
  driver: driverDescriptor,
93
96
  extensions: config.extensions ?? []
94
97
  });
95
- const typedFamilyInstance = familyInstance;
96
- const contractIR = typedFamilyInstance.validateContractIR(contractJson);
98
+ const rawComponents = [config.target, config.adapter, ...config.extensions ?? []];
99
+ const frameworkComponents = assertFrameworkComponentsCompatible(
100
+ config.family.familyId,
101
+ config.target.targetId,
102
+ rawComponents
103
+ );
104
+ const contractIR = familyInstance.validateContractIR(contractJson);
97
105
  let schemaVerifyResult;
98
106
  try {
99
107
  schemaVerifyResult = await withSpinner(
100
- async () => {
101
- return await typedFamilyInstance.schemaVerify({
102
- driver,
103
- contractIR,
104
- strict: false,
105
- contractPath: contractPathAbsolute,
106
- configPath
107
- });
108
- },
108
+ () => familyInstance.schemaVerify({
109
+ driver,
110
+ contractIR,
111
+ strict: false,
112
+ contractPath: contractPathAbsolute,
113
+ configPath,
114
+ frameworkComponents
115
+ }),
109
116
  {
110
117
  message: "Verifying database satisfies contract",
111
118
  flags
@@ -122,14 +129,12 @@ function createDbSignCommand() {
122
129
  let signResult;
123
130
  try {
124
131
  signResult = await withSpinner(
125
- async () => {
126
- return await typedFamilyInstance.sign({
127
- driver,
128
- contractIR,
129
- contractPath: contractPathAbsolute,
130
- configPath
131
- });
132
- },
132
+ () => familyInstance.sign({
133
+ driver,
134
+ contractIR,
135
+ contractPath: contractPathAbsolute,
136
+ configPath
137
+ }),
133
138
  {
134
139
  message: "Signing database...",
135
140
  flags