@prisma-next/cli 0.1.0-dev.3 → 0.1.0-dev.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import { Command as Command6 } from "commander";
4
+ import { Command as Command7 } from "commander";
5
5
 
6
6
  // src/commands/contract-emit.ts
7
7
  import { mkdirSync, writeFileSync } from "fs";
@@ -52,6 +52,45 @@ async function loadConfig(configPath) {
52
52
  }
53
53
  }
54
54
 
55
+ // src/utils/action.ts
56
+ import { notOk, ok } from "@prisma-next/utils/result";
57
+
58
+ // src/utils/cli-errors.ts
59
+ import {
60
+ CliStructuredError,
61
+ errorConfigFileNotFound as errorConfigFileNotFound2,
62
+ errorConfigValidation,
63
+ errorContractConfigMissing,
64
+ errorContractMissingExtensionPacks,
65
+ errorContractValidationFailed,
66
+ errorDatabaseUrlRequired,
67
+ errorDriverRequired,
68
+ errorFamilyReadMarkerSqlRequired,
69
+ errorFileNotFound,
70
+ errorHashMismatch,
71
+ errorJsonFormatNotSupported,
72
+ errorMarkerMissing,
73
+ errorMigrationPlanningFailed,
74
+ errorQueryRunnerFactoryRequired,
75
+ errorRuntime,
76
+ errorTargetMigrationNotSupported,
77
+ errorTargetMismatch,
78
+ errorUnexpected as errorUnexpected2
79
+ } from "@prisma-next/core-control-plane/errors";
80
+
81
+ // src/utils/action.ts
82
+ async function performAction(fn) {
83
+ try {
84
+ const value = await fn();
85
+ return ok(value);
86
+ } catch (error) {
87
+ if (error instanceof CliStructuredError) {
88
+ return notOk(error);
89
+ }
90
+ throw error;
91
+ }
92
+ }
93
+
55
94
  // src/utils/command-helpers.ts
56
95
  function setCommandDescriptions(command, shortDescription, longDescription) {
57
96
  command.description(shortDescription);
@@ -165,6 +204,36 @@ function formatErrorOutput(error, flags) {
165
204
  const whereLine = error.where.line ? `${error.where.path}:${error.where.line}` : error.where.path;
166
205
  lines.push(`${prefix}${formatDimText(` Where: ${whereLine}`)}`);
167
206
  }
207
+ if (error.meta?.["conflicts"]) {
208
+ const conflicts = error.meta["conflicts"];
209
+ if (conflicts.length > 0) {
210
+ const maxToShow = isVerbose(flags, 1) ? conflicts.length : Math.min(3, conflicts.length);
211
+ const header = isVerbose(flags, 1) ? " Conflicts:" : ` Conflicts (showing ${maxToShow} of ${conflicts.length}):`;
212
+ lines.push(`${prefix}${formatDimText(header)}`);
213
+ for (const conflict of conflicts.slice(0, maxToShow)) {
214
+ lines.push(`${prefix}${formatDimText(` - [${conflict.kind}] ${conflict.summary}`)}`);
215
+ }
216
+ if (!isVerbose(flags, 1) && conflicts.length > maxToShow) {
217
+ lines.push(`${prefix}${formatDimText(" Re-run with -v/--verbose to see all conflicts")}`);
218
+ }
219
+ }
220
+ }
221
+ if (error.meta?.["issues"]) {
222
+ const issues = error.meta["issues"];
223
+ if (issues.length > 0) {
224
+ const maxToShow = isVerbose(flags, 1) ? issues.length : Math.min(3, issues.length);
225
+ const header = isVerbose(flags, 1) ? " Issues:" : ` Issues (showing ${maxToShow} of ${issues.length}):`;
226
+ lines.push(`${prefix}${formatDimText(header)}`);
227
+ for (const issue of issues.slice(0, maxToShow)) {
228
+ const kind = issue.kind ?? "issue";
229
+ const message = issue.message ?? "";
230
+ lines.push(`${prefix}${formatDimText(` - [${kind}] ${message}`)}`);
231
+ }
232
+ if (!isVerbose(flags, 1) && issues.length > maxToShow) {
233
+ lines.push(`${prefix}${formatDimText(" Re-run with -v/--verbose to see all issues")}`);
234
+ }
235
+ }
236
+ }
168
237
  if (error.docsUrl && isVerbose(flags, 1)) {
169
238
  lines.push(formatDimText(error.docsUrl));
170
239
  }
@@ -598,6 +667,69 @@ function formatSignOutput(result, flags) {
598
667
  function formatSignJson(result) {
599
668
  return JSON.stringify(result, null, 2);
600
669
  }
670
+ function formatDbInitPlanOutput(result, flags) {
671
+ if (flags.quiet) {
672
+ return "";
673
+ }
674
+ const lines = [];
675
+ const prefix = createPrefix(flags);
676
+ const useColor = flags.color !== false;
677
+ const formatGreen = createColorFormatter(useColor, green);
678
+ const formatDimText = (text) => formatDim(useColor, text);
679
+ const operationCount = result.plan?.operations.length ?? 0;
680
+ lines.push(`${prefix}${formatGreen("\u2714")} Planned ${operationCount} operation(s)`);
681
+ if (result.plan?.operations && result.plan.operations.length > 0) {
682
+ lines.push(`${prefix}${formatDimText("\u2502")}`);
683
+ for (let i = 0; i < result.plan.operations.length; i++) {
684
+ const op = result.plan.operations[i];
685
+ if (!op) continue;
686
+ const isLast = i === result.plan.operations.length - 1;
687
+ const treeChar = isLast ? "\u2514" : "\u251C";
688
+ const opClass = formatDimText(`[${op.operationClass}]`);
689
+ lines.push(`${prefix}${formatDimText(treeChar)}\u2500 ${op.label} ${opClass}`);
690
+ }
691
+ }
692
+ if (result.plan?.destination) {
693
+ lines.push(`${prefix}`);
694
+ lines.push(
695
+ `${prefix}${formatDimText(`Destination hash: ${result.plan.destination.coreHash}`)}`
696
+ );
697
+ }
698
+ if (isVerbose(flags, 1)) {
699
+ lines.push(`${prefix}${formatDimText(`Total time: ${result.timings.total}ms`)}`);
700
+ }
701
+ lines.push(`${prefix}`);
702
+ lines.push(`${prefix}${formatDimText("This is a dry run. No changes were applied.")}`);
703
+ lines.push(`${prefix}${formatDimText("Run without --plan to apply changes.")}`);
704
+ return lines.join("\n");
705
+ }
706
+ function formatDbInitApplyOutput(result, flags) {
707
+ if (flags.quiet) {
708
+ return "";
709
+ }
710
+ const lines = [];
711
+ const prefix = createPrefix(flags);
712
+ const useColor = flags.color !== false;
713
+ const formatGreen = createColorFormatter(useColor, green);
714
+ const formatDimText = (text) => formatDim(useColor, text);
715
+ if (result.ok) {
716
+ const executed = result.execution?.operationsExecuted ?? 0;
717
+ lines.push(`${prefix}${formatGreen("\u2714")} Applied ${executed} operation(s)`);
718
+ if (result.marker) {
719
+ lines.push(`${prefix}${formatDimText(` Marker written: ${result.marker.coreHash}`)}`);
720
+ if (result.marker.profileHash) {
721
+ lines.push(`${prefix}${formatDimText(` Profile hash: ${result.marker.profileHash}`)}`);
722
+ }
723
+ }
724
+ if (isVerbose(flags, 1)) {
725
+ lines.push(`${prefix}${formatDimText(` Total time: ${result.timings.total}ms`)}`);
726
+ }
727
+ }
728
+ return lines.join("\n");
729
+ }
730
+ function formatDbInitJson(result) {
731
+ return JSON.stringify(result, null, 2);
732
+ }
601
733
  var LEFT_COLUMN_WIDTH = 20;
602
734
  var RIGHT_COLUMN_MIN_WIDTH = 40;
603
735
  var RIGHT_COLUMN_MAX_WIDTH = 90;
@@ -908,44 +1040,6 @@ function formatRootHelp(options) {
908
1040
  `;
909
1041
  }
910
1042
 
911
- // src/utils/cli-errors.ts
912
- import {
913
- CliStructuredError,
914
- errorConfigFileNotFound as errorConfigFileNotFound2,
915
- errorConfigValidation,
916
- errorContractConfigMissing,
917
- errorContractValidationFailed,
918
- errorDatabaseUrlRequired,
919
- errorDriverRequired,
920
- errorFamilyReadMarkerSqlRequired,
921
- errorFileNotFound,
922
- errorHashMismatch,
923
- errorMarkerMissing,
924
- errorQueryRunnerFactoryRequired,
925
- errorRuntime,
926
- errorTargetMismatch,
927
- errorUnexpected as errorUnexpected2
928
- } from "@prisma-next/core-control-plane/errors";
929
-
930
- // src/utils/result.ts
931
- function ok(value) {
932
- return { ok: true, value };
933
- }
934
- function err(error) {
935
- return { ok: false, error };
936
- }
937
- async function performAction(fn) {
938
- try {
939
- const value = await fn();
940
- return ok(value);
941
- } catch (error) {
942
- if (error instanceof CliStructuredError) {
943
- return err(error);
944
- }
945
- throw error;
946
- }
947
- }
948
-
949
1043
  // src/utils/result-handler.ts
950
1044
  function handleResult(result, flags, onSuccess) {
951
1045
  if (result.ok) {
@@ -954,59 +1048,36 @@ function handleResult(result, flags, onSuccess) {
954
1048
  }
955
1049
  return 0;
956
1050
  }
957
- const envelope = result.error.toEnvelope();
958
- if (flags.json === "object") {
1051
+ const envelope = result.failure.toEnvelope();
1052
+ if (flags.json) {
959
1053
  console.error(formatErrorJson(envelope));
960
1054
  } else {
961
1055
  console.error(formatErrorOutput(envelope, flags));
962
1056
  }
963
- const exitCode = result.error.domain === "CLI" ? 2 : 1;
1057
+ const exitCode = result.failure.domain === "CLI" ? 2 : 1;
964
1058
  return exitCode;
965
1059
  }
966
1060
 
967
1061
  // src/utils/spinner.ts
968
1062
  import ora from "ora";
969
1063
  async function withSpinner(operation, options) {
970
- const { message, flags, delayThreshold = 100 } = options;
1064
+ const { message, flags } = options;
971
1065
  const shouldShowSpinner = !flags.quiet && flags.json !== "object" && process.stdout.isTTY;
972
1066
  if (!shouldShowSpinner) {
973
1067
  return operation();
974
1068
  }
975
1069
  const startTime = Date.now();
976
- let spinner = null;
977
- let timeoutId = null;
978
- let operationCompleted = false;
979
- timeoutId = setTimeout(() => {
980
- if (!operationCompleted) {
981
- spinner = ora({
982
- text: message,
983
- color: flags.color !== false ? "cyan" : false
984
- }).start();
985
- }
986
- }, delayThreshold);
1070
+ const spinner = ora({
1071
+ text: message,
1072
+ color: flags.color !== false ? "cyan" : false
1073
+ }).start();
987
1074
  try {
988
1075
  const result = await operation();
989
- operationCompleted = true;
990
- if (timeoutId) {
991
- clearTimeout(timeoutId);
992
- timeoutId = null;
993
- }
994
- if (spinner !== null) {
995
- const elapsed = Date.now() - startTime;
996
- spinner.succeed(`${message} (${elapsed}ms)`);
997
- }
1076
+ const elapsed = Date.now() - startTime;
1077
+ spinner.succeed(`${message} (${elapsed}ms)`);
998
1078
  return result;
999
1079
  } catch (error) {
1000
- operationCompleted = true;
1001
- if (timeoutId) {
1002
- clearTimeout(timeoutId);
1003
- timeoutId = null;
1004
- }
1005
- if (spinner !== null) {
1006
- spinner.fail(
1007
- `${message} failed: ${error instanceof Error ? error.message : String(error)}`
1008
- );
1009
- }
1080
+ spinner.fail(`${message} failed: ${error instanceof Error ? error.message : String(error)}`);
1010
1081
  throw error;
1011
1082
  }
1012
1083
  }
@@ -1067,7 +1138,7 @@ function createContractEmitCommand() {
1067
1138
  target: config.target,
1068
1139
  adapter: config.adapter,
1069
1140
  driver: config.driver,
1070
- extensions: config.extensions ?? []
1141
+ extensionPacks: config.extensionPacks ?? []
1071
1142
  });
1072
1143
  let contractRaw;
1073
1144
  if (typeof contractConfig.source === "function") {
@@ -1121,18 +1192,413 @@ function createContractEmitCommand() {
1121
1192
  return command;
1122
1193
  }
1123
1194
 
1124
- // src/commands/db-introspect.ts
1195
+ // src/commands/db-init.ts
1125
1196
  import { readFile } from "fs/promises";
1126
1197
  import { relative as relative3, resolve as resolve3 } from "path";
1198
+ import { redactDatabaseUrl } from "@prisma-next/utils/redact-db-url";
1199
+ import { Command as Command2 } from "commander";
1200
+
1201
+ // src/utils/framework-components.ts
1202
+ import {
1203
+ checkContractComponentRequirements
1204
+ } from "@prisma-next/contract/framework-components";
1205
+ function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId, frameworkComponents) {
1206
+ for (let i = 0; i < frameworkComponents.length; i++) {
1207
+ const component = frameworkComponents[i];
1208
+ if (typeof component !== "object" || component === null) {
1209
+ throw errorConfigValidation("frameworkComponents[]", {
1210
+ why: `Framework component at index ${i} must be an object`
1211
+ });
1212
+ }
1213
+ const record = component;
1214
+ if (!Object.hasOwn(record, "kind")) {
1215
+ throw errorConfigValidation("frameworkComponents[].kind", {
1216
+ why: `Framework component at index ${i} must have 'kind' property`
1217
+ });
1218
+ }
1219
+ const kind = record["kind"];
1220
+ if (kind !== "target" && kind !== "adapter" && kind !== "extension" && kind !== "driver") {
1221
+ throw errorConfigValidation("frameworkComponents[].kind", {
1222
+ why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`
1223
+ });
1224
+ }
1225
+ if (!Object.hasOwn(record, "familyId")) {
1226
+ throw errorConfigValidation("frameworkComponents[].familyId", {
1227
+ why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`
1228
+ });
1229
+ }
1230
+ const familyId = record["familyId"];
1231
+ if (familyId !== expectedFamilyId) {
1232
+ throw errorConfigValidation("frameworkComponents[].familyId", {
1233
+ why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`
1234
+ });
1235
+ }
1236
+ if (!Object.hasOwn(record, "targetId")) {
1237
+ throw errorConfigValidation("frameworkComponents[].targetId", {
1238
+ why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`
1239
+ });
1240
+ }
1241
+ const targetId = record["targetId"];
1242
+ if (targetId !== expectedTargetId) {
1243
+ throw errorConfigValidation("frameworkComponents[].targetId", {
1244
+ why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`
1245
+ });
1246
+ }
1247
+ }
1248
+ return frameworkComponents;
1249
+ }
1250
+ function assertContractRequirementsSatisfied({
1251
+ contract,
1252
+ family,
1253
+ target,
1254
+ adapter,
1255
+ extensionPacks
1256
+ }) {
1257
+ const providedComponentIds = /* @__PURE__ */ new Set([target.id, adapter.id]);
1258
+ for (const extension of extensionPacks ?? []) {
1259
+ providedComponentIds.add(extension.id);
1260
+ }
1261
+ const result = checkContractComponentRequirements({
1262
+ contract,
1263
+ expectedTargetFamily: family.familyId,
1264
+ expectedTargetId: target.targetId,
1265
+ providedComponentIds
1266
+ });
1267
+ if (result.familyMismatch) {
1268
+ throw errorConfigValidation("contract.targetFamily", {
1269
+ why: `Contract was emitted for family '${result.familyMismatch.actual}' but CLI config is wired to '${result.familyMismatch.expected}'.`
1270
+ });
1271
+ }
1272
+ if (result.targetMismatch) {
1273
+ throw errorConfigValidation("contract.target", {
1274
+ why: `Contract target '${result.targetMismatch.actual}' does not match CLI target '${result.targetMismatch.expected}'.`
1275
+ });
1276
+ }
1277
+ if (result.missingExtensionPackIds.length > 0) {
1278
+ throw errorContractMissingExtensionPacks({
1279
+ missingExtensionPacks: result.missingExtensionPackIds,
1280
+ providedComponentIds: [...providedComponentIds]
1281
+ });
1282
+ }
1283
+ }
1284
+
1285
+ // src/commands/db-init.ts
1286
+ function createDbInitCommand() {
1287
+ const command = new Command2("init");
1288
+ setCommandDescriptions(
1289
+ command,
1290
+ "Bootstrap a database to match the current contract and write the contract marker",
1291
+ "Initializes a database to match your emitted contract using additive-only operations.\nCreates any missing tables, columns, indexes, and constraints defined in your contract.\nLeaves existing compatible structures in place, surfaces conflicts when destructive changes\nwould be required, and writes a contract marker to track the database state. Use --plan to\npreview changes without applying."
1292
+ );
1293
+ command.configureHelp({
1294
+ formatHelp: (cmd) => {
1295
+ const flags = parseGlobalFlags({});
1296
+ return formatCommandHelp({ command: cmd, flags });
1297
+ }
1298
+ }).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)", 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) => {
1299
+ const flags = parseGlobalFlags(options);
1300
+ const startTime = Date.now();
1301
+ const result = await performAction(async () => {
1302
+ if (flags.json === "ndjson") {
1303
+ throw errorJsonFormatNotSupported({
1304
+ command: "db init",
1305
+ format: "ndjson",
1306
+ supportedFormats: ["object"]
1307
+ });
1308
+ }
1309
+ const config = await loadConfig(options.config);
1310
+ const configPath = options.config ? relative3(process.cwd(), resolve3(options.config)) : "prisma-next.config.ts";
1311
+ const contractPathAbsolute = config.contract?.output ? resolve3(config.contract.output) : resolve3("src/prisma/contract.json");
1312
+ const contractPath = relative3(process.cwd(), contractPathAbsolute);
1313
+ if (flags.json !== "object" && !flags.quiet) {
1314
+ const details = [
1315
+ { label: "config", value: configPath },
1316
+ { label: "contract", value: contractPath }
1317
+ ];
1318
+ if (options.db) {
1319
+ details.push({ label: "database", value: options.db });
1320
+ }
1321
+ if (options.plan) {
1322
+ details.push({ label: "mode", value: "plan (dry run)" });
1323
+ }
1324
+ const header = formatStyledHeader({
1325
+ command: "db init",
1326
+ description: "Bootstrap a database to match the current contract",
1327
+ url: "https://pris.ly/db-init",
1328
+ details,
1329
+ flags
1330
+ });
1331
+ console.log(header);
1332
+ }
1333
+ let contractJsonContent;
1334
+ try {
1335
+ contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
1336
+ } catch (error) {
1337
+ if (error instanceof Error && error.code === "ENOENT") {
1338
+ throw errorFileNotFound(contractPathAbsolute, {
1339
+ why: `Contract file not found at ${contractPathAbsolute}`,
1340
+ fix: `Run \`prisma-next contract emit\` to generate ${contractPath}, or update \`config.contract.output\` in ${configPath}`
1341
+ });
1342
+ }
1343
+ throw errorUnexpected2(error instanceof Error ? error.message : String(error), {
1344
+ why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`
1345
+ });
1346
+ }
1347
+ let contractJson;
1348
+ try {
1349
+ contractJson = JSON.parse(contractJsonContent);
1350
+ } catch (error) {
1351
+ throw errorContractValidationFailed(
1352
+ `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,
1353
+ { where: { path: contractPathAbsolute } }
1354
+ );
1355
+ }
1356
+ const dbUrl = options.db ?? config.db?.url;
1357
+ if (!dbUrl) {
1358
+ throw errorDatabaseUrlRequired({
1359
+ why: `Database URL is required for db init (set db.url in ${configPath}, or pass --db <url>)`
1360
+ });
1361
+ }
1362
+ if (!config.driver) {
1363
+ throw errorDriverRequired({ why: "Config.driver is required for db init" });
1364
+ }
1365
+ const driverDescriptor = config.driver;
1366
+ if (!config.target.migrations) {
1367
+ throw errorTargetMigrationNotSupported({
1368
+ why: `Target "${config.target.id}" does not support migrations`
1369
+ });
1370
+ }
1371
+ const migrations = config.target.migrations;
1372
+ let driver;
1373
+ try {
1374
+ driver = await withSpinner(() => driverDescriptor.create(dbUrl), {
1375
+ message: "Connecting to database...",
1376
+ flags
1377
+ });
1378
+ } catch (error) {
1379
+ const message = error instanceof Error ? error.message : String(error);
1380
+ const code = error.code;
1381
+ const redacted = redactDatabaseUrl(dbUrl);
1382
+ throw errorRuntime("Database connection failed", {
1383
+ why: message,
1384
+ fix: "Verify the database URL, ensure the database is reachable, and confirm credentials/permissions",
1385
+ meta: {
1386
+ ...typeof code !== "undefined" ? { code } : {},
1387
+ ...redacted
1388
+ }
1389
+ });
1390
+ }
1391
+ try {
1392
+ const familyInstance = config.family.create({
1393
+ target: config.target,
1394
+ adapter: config.adapter,
1395
+ driver: driverDescriptor,
1396
+ extensionPacks: config.extensionPacks ?? []
1397
+ });
1398
+ const rawComponents = [config.target, config.adapter, ...config.extensionPacks ?? []];
1399
+ const frameworkComponents = assertFrameworkComponentsCompatible(
1400
+ config.family.familyId,
1401
+ config.target.targetId,
1402
+ rawComponents
1403
+ );
1404
+ const contractIR = familyInstance.validateContractIR(contractJson);
1405
+ assertContractRequirementsSatisfied({
1406
+ contract: contractIR,
1407
+ family: config.family,
1408
+ target: config.target,
1409
+ adapter: config.adapter,
1410
+ extensionPacks: config.extensionPacks
1411
+ });
1412
+ const planner = migrations.createPlanner(familyInstance);
1413
+ const runner = migrations.createRunner(familyInstance);
1414
+ const schemaIR = await withSpinner(() => familyInstance.introspect({ driver }), {
1415
+ message: "Introspecting database schema...",
1416
+ flags
1417
+ });
1418
+ const policy = { allowedOperationClasses: ["additive"] };
1419
+ const plannerResult = await withSpinner(
1420
+ async () => planner.plan({
1421
+ contract: contractIR,
1422
+ schema: schemaIR,
1423
+ policy,
1424
+ frameworkComponents
1425
+ }),
1426
+ {
1427
+ message: "Planning migration...",
1428
+ flags
1429
+ }
1430
+ );
1431
+ if (plannerResult.kind === "failure") {
1432
+ throw errorMigrationPlanningFailed({ conflicts: plannerResult.conflicts });
1433
+ }
1434
+ const migrationPlan = plannerResult.plan;
1435
+ const existingMarker = await familyInstance.readMarker({ driver });
1436
+ if (existingMarker) {
1437
+ const markerMatchesDestination = existingMarker.coreHash === migrationPlan.destination.coreHash && (!migrationPlan.destination.profileHash || existingMarker.profileHash === migrationPlan.destination.profileHash);
1438
+ if (markerMatchesDestination) {
1439
+ const dbInitResult2 = {
1440
+ ok: true,
1441
+ mode: options.plan ? "plan" : "apply",
1442
+ plan: {
1443
+ targetId: migrationPlan.targetId,
1444
+ destination: migrationPlan.destination,
1445
+ operations: []
1446
+ },
1447
+ ...options.plan ? {} : {
1448
+ execution: { operationsPlanned: 0, operationsExecuted: 0 },
1449
+ marker: {
1450
+ coreHash: existingMarker.coreHash,
1451
+ profileHash: existingMarker.profileHash
1452
+ }
1453
+ },
1454
+ summary: "Database already at target contract state",
1455
+ timings: { total: Date.now() - startTime }
1456
+ };
1457
+ return dbInitResult2;
1458
+ }
1459
+ const coreHashMismatch = existingMarker.coreHash !== migrationPlan.destination.coreHash;
1460
+ const profileHashMismatch = migrationPlan.destination.profileHash && existingMarker.profileHash !== migrationPlan.destination.profileHash;
1461
+ const mismatchParts = [];
1462
+ if (coreHashMismatch) {
1463
+ mismatchParts.push(
1464
+ `coreHash (marker: ${existingMarker.coreHash}, destination: ${migrationPlan.destination.coreHash})`
1465
+ );
1466
+ }
1467
+ if (profileHashMismatch) {
1468
+ mismatchParts.push(
1469
+ `profileHash (marker: ${existingMarker.profileHash}, destination: ${migrationPlan.destination.profileHash})`
1470
+ );
1471
+ }
1472
+ throw errorRuntime(
1473
+ `Existing contract marker does not match plan destination. Mismatch in ${mismatchParts.join(" and ")}.`,
1474
+ {
1475
+ why: "Database has an existing contract marker that does not match the target contract",
1476
+ fix: "If bootstrapping, drop/reset the database then re-run `prisma-next db init`; otherwise reconcile schema/marker using your migration workflow",
1477
+ meta: {
1478
+ code: "MARKER_ORIGIN_MISMATCH",
1479
+ markerCoreHash: existingMarker.coreHash,
1480
+ destinationCoreHash: migrationPlan.destination.coreHash,
1481
+ ...existingMarker.profileHash ? { markerProfileHash: existingMarker.profileHash } : {},
1482
+ ...migrationPlan.destination.profileHash ? { destinationProfileHash: migrationPlan.destination.profileHash } : {}
1483
+ }
1484
+ }
1485
+ );
1486
+ }
1487
+ if (options.plan) {
1488
+ const dbInitResult2 = {
1489
+ ok: true,
1490
+ mode: "plan",
1491
+ plan: {
1492
+ targetId: migrationPlan.targetId,
1493
+ destination: migrationPlan.destination,
1494
+ operations: migrationPlan.operations.map((op) => ({
1495
+ id: op.id,
1496
+ label: op.label,
1497
+ operationClass: op.operationClass
1498
+ }))
1499
+ },
1500
+ summary: `Planned ${migrationPlan.operations.length} operation(s)`,
1501
+ timings: { total: Date.now() - startTime }
1502
+ };
1503
+ return dbInitResult2;
1504
+ }
1505
+ if (!flags.quiet && flags.json !== "object") {
1506
+ console.log("Applying migration plan and verifying schema...");
1507
+ }
1508
+ const callbacks = {
1509
+ onOperationStart: (op) => {
1510
+ if (!flags.quiet && flags.json !== "object") {
1511
+ console.log(` \u2192 ${op.label}...`);
1512
+ }
1513
+ },
1514
+ onOperationComplete: (_op) => {
1515
+ }
1516
+ };
1517
+ const runnerResult = await runner.execute({
1518
+ plan: migrationPlan,
1519
+ driver,
1520
+ destinationContract: contractIR,
1521
+ policy,
1522
+ callbacks,
1523
+ // db init plans and applies back-to-back from a fresh introspection, so per-operation
1524
+ // pre/postchecks and the idempotency probe are usually redundant overhead. We still
1525
+ // enforce marker/origin compatibility and a full schema verification after apply.
1526
+ executionChecks: {
1527
+ prechecks: false,
1528
+ postchecks: false,
1529
+ idempotencyChecks: false
1530
+ },
1531
+ frameworkComponents
1532
+ });
1533
+ if (!runnerResult.ok) {
1534
+ const meta = {
1535
+ code: runnerResult.failure.code,
1536
+ ...runnerResult.failure.meta ?? {}
1537
+ };
1538
+ const sqlState = typeof meta["sqlState"] === "string" ? meta["sqlState"] : void 0;
1539
+ const fix = sqlState === "42501" ? "Grant the database user sufficient privileges (insufficient_privilege), or run db init as a more privileged role" : runnerResult.failure.code === "SCHEMA_VERIFY_FAILED" ? "Fix the schema mismatch (db init is additive-only), or drop/reset the database and re-run `prisma-next db init`" : void 0;
1540
+ throw errorRuntime(runnerResult.failure.summary, {
1541
+ why: runnerResult.failure.why ?? `Migration runner failed: ${runnerResult.failure.code}`,
1542
+ ...fix ? { fix } : {},
1543
+ meta
1544
+ });
1545
+ }
1546
+ const execution = runnerResult.value;
1547
+ const dbInitResult = {
1548
+ ok: true,
1549
+ mode: "apply",
1550
+ plan: {
1551
+ targetId: migrationPlan.targetId,
1552
+ destination: migrationPlan.destination,
1553
+ operations: migrationPlan.operations.map((op) => ({
1554
+ id: op.id,
1555
+ label: op.label,
1556
+ operationClass: op.operationClass
1557
+ }))
1558
+ },
1559
+ execution: {
1560
+ operationsPlanned: execution.operationsPlanned,
1561
+ operationsExecuted: execution.operationsExecuted
1562
+ },
1563
+ marker: migrationPlan.destination.profileHash ? {
1564
+ coreHash: migrationPlan.destination.coreHash,
1565
+ profileHash: migrationPlan.destination.profileHash
1566
+ } : { coreHash: migrationPlan.destination.coreHash },
1567
+ summary: `Applied ${execution.operationsExecuted} operation(s), marker written`,
1568
+ timings: { total: Date.now() - startTime }
1569
+ };
1570
+ return dbInitResult;
1571
+ } finally {
1572
+ await driver.close();
1573
+ }
1574
+ });
1575
+ const exitCode = handleResult(result, flags, (dbInitResult) => {
1576
+ if (flags.json === "object") {
1577
+ console.log(formatDbInitJson(dbInitResult));
1578
+ } else {
1579
+ const output = dbInitResult.mode === "plan" ? formatDbInitPlanOutput(dbInitResult, flags) : formatDbInitApplyOutput(dbInitResult, flags);
1580
+ if (output) {
1581
+ console.log(output);
1582
+ }
1583
+ }
1584
+ });
1585
+ process.exit(exitCode);
1586
+ });
1587
+ return command;
1588
+ }
1589
+
1590
+ // src/commands/db-introspect.ts
1591
+ import { readFile as readFile2 } from "fs/promises";
1592
+ import { relative as relative4, resolve as resolve4 } from "path";
1127
1593
  import {
1128
1594
  errorDatabaseUrlRequired as errorDatabaseUrlRequired2,
1129
1595
  errorDriverRequired as errorDriverRequired2,
1130
1596
  errorRuntime as errorRuntime2,
1131
1597
  errorUnexpected as errorUnexpected3
1132
1598
  } from "@prisma-next/core-control-plane/errors";
1133
- import { Command as Command2 } from "commander";
1599
+ import { Command as Command3 } from "commander";
1134
1600
  function createDbIntrospectCommand() {
1135
- const command = new Command2("introspect");
1601
+ const command = new Command3("introspect");
1136
1602
  setCommandDescriptions(
1137
1603
  command,
1138
1604
  "Inspect the database schema",
@@ -1148,14 +1614,13 @@ function createDbIntrospectCommand() {
1148
1614
  const result = await performAction(async () => {
1149
1615
  const startTime = Date.now();
1150
1616
  const config = await loadConfig(options.config);
1151
- const configPath = options.config ? relative3(process.cwd(), resolve3(options.config)) : "prisma-next.config.ts";
1617
+ const configPath = options.config ? relative4(process.cwd(), resolve4(options.config)) : "prisma-next.config.ts";
1152
1618
  let contractIR;
1153
1619
  if (config.contract?.output) {
1154
- const contractPath = resolve3(config.contract.output);
1620
+ const contractPath = resolve4(config.contract.output);
1155
1621
  try {
1156
- const contractJsonContent = await readFile(contractPath, "utf-8");
1157
- const contractJson = JSON.parse(contractJsonContent);
1158
- contractIR = contractJson;
1622
+ const contractJsonContent = await readFile2(contractPath, "utf-8");
1623
+ contractIR = JSON.parse(contractJsonContent);
1159
1624
  } catch (error) {
1160
1625
  if (error instanceof Error && error.code !== "ENOENT") {
1161
1626
  throw errorUnexpected3(error.message, {
@@ -1201,16 +1666,23 @@ function createDbIntrospectCommand() {
1201
1666
  target: config.target,
1202
1667
  adapter: config.adapter,
1203
1668
  driver: driverDescriptor,
1204
- extensions: config.extensions ?? []
1669
+ extensionPacks: config.extensionPacks ?? []
1205
1670
  });
1206
- const typedFamilyInstance = familyInstance;
1207
1671
  if (contractIR) {
1208
- contractIR = typedFamilyInstance.validateContractIR(contractIR);
1672
+ const validatedContract = familyInstance.validateContractIR(contractIR);
1673
+ assertContractRequirementsSatisfied({
1674
+ contract: validatedContract,
1675
+ family: config.family,
1676
+ target: config.target,
1677
+ adapter: config.adapter,
1678
+ extensionPacks: config.extensionPacks
1679
+ });
1680
+ contractIR = validatedContract;
1209
1681
  }
1210
1682
  let schemaIR;
1211
1683
  try {
1212
1684
  schemaIR = await withSpinner(
1213
- () => typedFamilyInstance.introspect({
1685
+ () => familyInstance.introspect({
1214
1686
  driver,
1215
1687
  contractIR
1216
1688
  }),
@@ -1225,9 +1697,9 @@ function createDbIntrospectCommand() {
1225
1697
  });
1226
1698
  }
1227
1699
  let schemaView;
1228
- if (typedFamilyInstance.toSchemaView) {
1700
+ if (familyInstance.toSchemaView) {
1229
1701
  try {
1230
- schemaView = typedFamilyInstance.toSchemaView(schemaIR);
1702
+ schemaView = familyInstance.toSchemaView(schemaIR);
1231
1703
  } catch (error) {
1232
1704
  if (flags.verbose) {
1233
1705
  console.error(
@@ -1285,8 +1757,8 @@ function createDbIntrospectCommand() {
1285
1757
  }
1286
1758
 
1287
1759
  // src/commands/db-schema-verify.ts
1288
- import { readFile as readFile2 } from "fs/promises";
1289
- import { relative as relative4, resolve as resolve4 } from "path";
1760
+ import { readFile as readFile3 } from "fs/promises";
1761
+ import { relative as relative5, resolve as resolve5 } from "path";
1290
1762
  import {
1291
1763
  errorDatabaseUrlRequired as errorDatabaseUrlRequired3,
1292
1764
  errorDriverRequired as errorDriverRequired3,
@@ -1294,9 +1766,9 @@ import {
1294
1766
  errorRuntime as errorRuntime3,
1295
1767
  errorUnexpected as errorUnexpected4
1296
1768
  } from "@prisma-next/core-control-plane/errors";
1297
- import { Command as Command3 } from "commander";
1769
+ import { Command as Command4 } from "commander";
1298
1770
  function createDbSchemaVerifyCommand() {
1299
- const command = new Command3("schema-verify");
1771
+ const command = new Command4("schema-verify");
1300
1772
  setCommandDescriptions(
1301
1773
  command,
1302
1774
  "Check whether the database schema satisfies your contract",
@@ -1311,9 +1783,9 @@ function createDbSchemaVerifyCommand() {
1311
1783
  const flags = parseGlobalFlags(options);
1312
1784
  const result = await performAction(async () => {
1313
1785
  const config = await loadConfig(options.config);
1314
- const configPath = options.config ? relative4(process.cwd(), resolve4(options.config)) : "prisma-next.config.ts";
1315
- const contractPathAbsolute = config.contract?.output ? resolve4(config.contract.output) : resolve4("src/prisma/contract.json");
1316
- const contractPath = relative4(process.cwd(), contractPathAbsolute);
1786
+ const configPath = options.config ? relative5(process.cwd(), resolve5(options.config)) : "prisma-next.config.ts";
1787
+ const contractPathAbsolute = config.contract?.output ? resolve5(config.contract.output) : resolve5("src/prisma/contract.json");
1788
+ const contractPath = relative5(process.cwd(), contractPathAbsolute);
1317
1789
  if (flags.json !== "object" && !flags.quiet) {
1318
1790
  const details = [
1319
1791
  { label: "config", value: configPath },
@@ -1333,7 +1805,7 @@ function createDbSchemaVerifyCommand() {
1333
1805
  }
1334
1806
  let contractJsonContent;
1335
1807
  try {
1336
- contractJsonContent = await readFile2(contractPathAbsolute, "utf-8");
1808
+ contractJsonContent = await readFile3(contractPathAbsolute, "utf-8");
1337
1809
  } catch (error) {
1338
1810
  if (error instanceof Error && error.code === "ENOENT") {
1339
1811
  throw errorFileNotFound2(contractPathAbsolute, {
@@ -1345,36 +1817,49 @@ function createDbSchemaVerifyCommand() {
1345
1817
  });
1346
1818
  }
1347
1819
  const contractJson = JSON.parse(contractJsonContent);
1348
- const dbUrl = options.db ?? config.db?.url;
1349
- if (!dbUrl) {
1350
- throw errorDatabaseUrlRequired3();
1351
- }
1352
1820
  if (!config.driver) {
1353
1821
  throw errorDriverRequired3();
1354
1822
  }
1355
1823
  const driverDescriptor = config.driver;
1824
+ const familyInstance = config.family.create({
1825
+ target: config.target,
1826
+ adapter: config.adapter,
1827
+ driver: driverDescriptor,
1828
+ extensionPacks: config.extensionPacks ?? []
1829
+ });
1830
+ const contractIR = familyInstance.validateContractIR(contractJson);
1831
+ assertContractRequirementsSatisfied({
1832
+ contract: contractIR,
1833
+ family: config.family,
1834
+ target: config.target,
1835
+ adapter: config.adapter,
1836
+ extensionPacks: config.extensionPacks
1837
+ });
1838
+ const dbUrl = options.db ?? config.db?.url;
1839
+ if (!dbUrl) {
1840
+ throw errorDatabaseUrlRequired3();
1841
+ }
1356
1842
  const driver = await withSpinner(() => driverDescriptor.create(dbUrl), {
1357
1843
  message: "Connecting to database...",
1358
1844
  flags
1359
1845
  });
1360
1846
  try {
1361
- const familyInstance = config.family.create({
1362
- target: config.target,
1363
- adapter: config.adapter,
1364
- driver: driverDescriptor,
1365
- extensions: config.extensions ?? []
1366
- });
1367
- const typedFamilyInstance = familyInstance;
1368
- const contractIR = typedFamilyInstance.validateContractIR(contractJson);
1847
+ const rawComponents = [config.target, config.adapter, ...config.extensionPacks ?? []];
1848
+ const frameworkComponents = assertFrameworkComponentsCompatible(
1849
+ config.family.familyId,
1850
+ config.target.targetId,
1851
+ rawComponents
1852
+ );
1369
1853
  let schemaVerifyResult;
1370
1854
  try {
1371
1855
  schemaVerifyResult = await withSpinner(
1372
- () => typedFamilyInstance.schemaVerify({
1856
+ () => familyInstance.schemaVerify({
1373
1857
  driver,
1374
1858
  contractIR,
1375
1859
  strict: options.strict ?? false,
1376
1860
  contractPath: contractPathAbsolute,
1377
- configPath
1861
+ configPath,
1862
+ frameworkComponents
1378
1863
  }),
1379
1864
  {
1380
1865
  message: "Verifying database schema...",
@@ -1414,8 +1899,8 @@ function createDbSchemaVerifyCommand() {
1414
1899
  }
1415
1900
 
1416
1901
  // src/commands/db-sign.ts
1417
- import { readFile as readFile3 } from "fs/promises";
1418
- import { relative as relative5, resolve as resolve5 } from "path";
1902
+ import { readFile as readFile4 } from "fs/promises";
1903
+ import { relative as relative6, resolve as resolve6 } from "path";
1419
1904
  import {
1420
1905
  errorDatabaseUrlRequired as errorDatabaseUrlRequired4,
1421
1906
  errorDriverRequired as errorDriverRequired4,
@@ -1423,9 +1908,9 @@ import {
1423
1908
  errorRuntime as errorRuntime4,
1424
1909
  errorUnexpected as errorUnexpected5
1425
1910
  } from "@prisma-next/core-control-plane/errors";
1426
- import { Command as Command4 } from "commander";
1911
+ import { Command as Command5 } from "commander";
1427
1912
  function createDbSignCommand() {
1428
- const command = new Command4("sign");
1913
+ const command = new Command5("sign");
1429
1914
  setCommandDescriptions(
1430
1915
  command,
1431
1916
  "Sign the database with your contract so you can safely run queries",
@@ -1440,9 +1925,9 @@ function createDbSignCommand() {
1440
1925
  const flags = parseGlobalFlags(options);
1441
1926
  const result = await performAction(async () => {
1442
1927
  const config = await loadConfig(options.config);
1443
- const configPath = options.config ? relative5(process.cwd(), resolve5(options.config)) : "prisma-next.config.ts";
1444
- const contractPathAbsolute = config.contract?.output ? resolve5(config.contract.output) : resolve5("src/prisma/contract.json");
1445
- const contractPath = relative5(process.cwd(), contractPathAbsolute);
1928
+ const configPath = options.config ? relative6(process.cwd(), resolve6(options.config)) : "prisma-next.config.ts";
1929
+ const contractPathAbsolute = config.contract?.output ? resolve6(config.contract.output) : resolve6("src/prisma/contract.json");
1930
+ const contractPath = relative6(process.cwd(), contractPathAbsolute);
1446
1931
  if (flags.json !== "object" && !flags.quiet) {
1447
1932
  const details = [
1448
1933
  { label: "config", value: configPath },
@@ -1462,7 +1947,7 @@ function createDbSignCommand() {
1462
1947
  }
1463
1948
  let contractJsonContent;
1464
1949
  try {
1465
- contractJsonContent = await readFile3(contractPathAbsolute, "utf-8");
1950
+ contractJsonContent = await readFile4(contractPathAbsolute, "utf-8");
1466
1951
  } catch (error) {
1467
1952
  if (error instanceof Error && error.code === "ENOENT") {
1468
1953
  throw errorFileNotFound3(contractPathAbsolute, {
@@ -1482,28 +1967,39 @@ function createDbSignCommand() {
1482
1967
  throw errorDriverRequired4();
1483
1968
  }
1484
1969
  const driverDescriptor = config.driver;
1970
+ const familyInstance = config.family.create({
1971
+ target: config.target,
1972
+ adapter: config.adapter,
1973
+ driver: driverDescriptor,
1974
+ extensionPacks: config.extensionPacks ?? []
1975
+ });
1976
+ const contractIR = familyInstance.validateContractIR(contractJson);
1977
+ assertContractRequirementsSatisfied({
1978
+ contract: contractIR,
1979
+ family: config.family,
1980
+ target: config.target,
1981
+ adapter: config.adapter,
1982
+ extensionPacks: config.extensionPacks
1983
+ });
1984
+ const rawComponents = [config.target, config.adapter, ...config.extensionPacks ?? []];
1985
+ const frameworkComponents = assertFrameworkComponentsCompatible(
1986
+ config.family.familyId,
1987
+ config.target.targetId,
1988
+ rawComponents
1989
+ );
1485
1990
  const driver = await driverDescriptor.create(dbUrl);
1486
1991
  try {
1487
- const familyInstance = config.family.create({
1488
- target: config.target,
1489
- adapter: config.adapter,
1490
- driver: driverDescriptor,
1491
- extensions: config.extensions ?? []
1492
- });
1493
- const typedFamilyInstance = familyInstance;
1494
- const contractIR = typedFamilyInstance.validateContractIR(contractJson);
1495
1992
  let schemaVerifyResult;
1496
1993
  try {
1497
1994
  schemaVerifyResult = await withSpinner(
1498
- async () => {
1499
- return await typedFamilyInstance.schemaVerify({
1500
- driver,
1501
- contractIR,
1502
- strict: false,
1503
- contractPath: contractPathAbsolute,
1504
- configPath
1505
- });
1506
- },
1995
+ () => familyInstance.schemaVerify({
1996
+ driver,
1997
+ contractIR,
1998
+ strict: false,
1999
+ contractPath: contractPathAbsolute,
2000
+ configPath,
2001
+ frameworkComponents
2002
+ }),
1507
2003
  {
1508
2004
  message: "Verifying database satisfies contract",
1509
2005
  flags
@@ -1520,14 +2016,12 @@ function createDbSignCommand() {
1520
2016
  let signResult;
1521
2017
  try {
1522
2018
  signResult = await withSpinner(
1523
- async () => {
1524
- return await typedFamilyInstance.sign({
1525
- driver,
1526
- contractIR,
1527
- contractPath: contractPathAbsolute,
1528
- configPath
1529
- });
1530
- },
2019
+ () => familyInstance.sign({
2020
+ driver,
2021
+ contractIR,
2022
+ contractPath: contractPathAbsolute,
2023
+ configPath
2024
+ }),
1531
2025
  {
1532
2026
  message: "Signing database...",
1533
2027
  flags
@@ -1580,8 +2074,8 @@ function createDbSignCommand() {
1580
2074
  }
1581
2075
 
1582
2076
  // src/commands/db-verify.ts
1583
- import { readFile as readFile4 } from "fs/promises";
1584
- import { relative as relative6, resolve as resolve6 } from "path";
2077
+ import { readFile as readFile5 } from "fs/promises";
2078
+ import { relative as relative7, resolve as resolve7 } from "path";
1585
2079
  import {
1586
2080
  errorDatabaseUrlRequired as errorDatabaseUrlRequired5,
1587
2081
  errorDriverRequired as errorDriverRequired5,
@@ -1592,9 +2086,9 @@ import {
1592
2086
  errorTargetMismatch as errorTargetMismatch2,
1593
2087
  errorUnexpected as errorUnexpected6
1594
2088
  } from "@prisma-next/core-control-plane/errors";
1595
- import { Command as Command5 } from "commander";
2089
+ import { Command as Command6 } from "commander";
1596
2090
  function createDbVerifyCommand() {
1597
- const command = new Command5("verify");
2091
+ const command = new Command6("verify");
1598
2092
  setCommandDescriptions(
1599
2093
  command,
1600
2094
  "Check whether the database has been signed with your contract",
@@ -1609,9 +2103,9 @@ function createDbVerifyCommand() {
1609
2103
  const flags = parseGlobalFlags(options);
1610
2104
  const result = await performAction(async () => {
1611
2105
  const config = await loadConfig(options.config);
1612
- const configPath = options.config ? relative6(process.cwd(), resolve6(options.config)) : "prisma-next.config.ts";
1613
- const contractPathAbsolute = config.contract?.output ? resolve6(config.contract.output) : resolve6("src/prisma/contract.json");
1614
- const contractPath = relative6(process.cwd(), contractPathAbsolute);
2106
+ const configPath = options.config ? relative7(process.cwd(), resolve7(options.config)) : "prisma-next.config.ts";
2107
+ const contractPathAbsolute = config.contract?.output ? resolve7(config.contract.output) : resolve7("src/prisma/contract.json");
2108
+ const contractPath = relative7(process.cwd(), contractPathAbsolute);
1615
2109
  if (flags.json !== "object" && !flags.quiet) {
1616
2110
  const details = [
1617
2111
  { label: "config", value: configPath },
@@ -1631,7 +2125,7 @@ function createDbVerifyCommand() {
1631
2125
  }
1632
2126
  let contractJsonContent;
1633
2127
  try {
1634
- contractJsonContent = await readFile4(contractPathAbsolute, "utf-8");
2128
+ contractJsonContent = await readFile5(contractPathAbsolute, "utf-8");
1635
2129
  } catch (error) {
1636
2130
  if (error instanceof Error && error.code === "ENOENT") {
1637
2131
  throw errorFileNotFound4(contractPathAbsolute, {
@@ -1660,14 +2154,20 @@ function createDbVerifyCommand() {
1660
2154
  target: config.target,
1661
2155
  adapter: config.adapter,
1662
2156
  driver: driverDescriptor,
1663
- extensions: config.extensions ?? []
2157
+ extensionPacks: config.extensionPacks ?? []
2158
+ });
2159
+ const contractIR = familyInstance.validateContractIR(contractJson);
2160
+ assertContractRequirementsSatisfied({
2161
+ contract: contractIR,
2162
+ family: config.family,
2163
+ target: config.target,
2164
+ adapter: config.adapter,
2165
+ extensionPacks: config.extensionPacks
1664
2166
  });
1665
- const typedFamilyInstance = familyInstance;
1666
- const contractIR = typedFamilyInstance.validateContractIR(contractJson);
1667
2167
  let verifyResult;
1668
2168
  try {
1669
2169
  verifyResult = await withSpinner(
1670
- () => typedFamilyInstance.verify({
2170
+ () => familyInstance.verify({
1671
2171
  driver,
1672
2172
  contractIR,
1673
2173
  expectedTargetId: config.target.targetId,
@@ -1726,7 +2226,7 @@ function createDbVerifyCommand() {
1726
2226
  }
1727
2227
 
1728
2228
  // src/cli.ts
1729
- var program = new Command6();
2229
+ var program = new Command7();
1730
2230
  program.name("prisma-next").description("Prisma Next CLI").version("0.0.1");
1731
2231
  var versionOption = program.options.find((opt) => opt.flags.includes("--version"));
1732
2232
  if (versionOption) {
@@ -1746,11 +2246,11 @@ program.configureHelp({
1746
2246
  formatHelp: rootHelpFormatter,
1747
2247
  subcommandDescription: () => ""
1748
2248
  });
1749
- program.exitOverride((err2) => {
1750
- if (err2) {
1751
- const errorCode = err2.code;
1752
- const errorMessage = String(err2.message ?? "");
1753
- const errorName = err2.name ?? "";
2249
+ program.exitOverride((err) => {
2250
+ if (err) {
2251
+ const errorCode = err.code;
2252
+ const errorMessage = String(err.message ?? "");
2253
+ const errorName = err.name ?? "";
1754
2254
  const isUnknownCommandError = errorCode === "commander.unknownCommand" || errorCode === "commander.unknownArgument" || errorName === "CommanderError" && (errorMessage.includes("unknown command") || errorMessage.includes("unknown argument"));
1755
2255
  if (isUnknownCommandError) {
1756
2256
  const flags = parseGlobalFlags({});
@@ -1782,15 +2282,15 @@ program.exitOverride((err2) => {
1782
2282
  process.exit(0);
1783
2283
  return;
1784
2284
  }
1785
- console.error(`Unhandled error: ${err2.message}`);
1786
- if (err2.stack) {
1787
- console.error(err2.stack);
2285
+ console.error(`Unhandled error: ${err.message}`);
2286
+ if (err.stack) {
2287
+ console.error(err.stack);
1788
2288
  }
1789
2289
  process.exit(1);
1790
2290
  }
1791
2291
  process.exit(0);
1792
2292
  });
1793
- var contractCommand = new Command6("contract");
2293
+ var contractCommand = new Command7("contract");
1794
2294
  setCommandDescriptions(
1795
2295
  contractCommand,
1796
2296
  "Contract management commands",
@@ -1806,7 +2306,7 @@ contractCommand.configureHelp({
1806
2306
  var contractEmitCommand = createContractEmitCommand();
1807
2307
  contractCommand.addCommand(contractEmitCommand);
1808
2308
  program.addCommand(contractCommand);
1809
- var dbCommand = new Command6("db");
2309
+ var dbCommand = new Command7("db");
1810
2310
  setCommandDescriptions(
1811
2311
  dbCommand,
1812
2312
  "Database management commands",
@@ -1821,6 +2321,8 @@ dbCommand.configureHelp({
1821
2321
  });
1822
2322
  var dbVerifyCommand = createDbVerifyCommand();
1823
2323
  dbCommand.addCommand(dbVerifyCommand);
2324
+ var dbInitCommand = createDbInitCommand();
2325
+ dbCommand.addCommand(dbInitCommand);
1824
2326
  var dbIntrospectCommand = createDbIntrospectCommand();
1825
2327
  dbCommand.addCommand(dbIntrospectCommand);
1826
2328
  var dbSchemaVerifyCommand = createDbSchemaVerifyCommand();
@@ -1828,7 +2330,7 @@ dbCommand.addCommand(dbSchemaVerifyCommand);
1828
2330
  var dbSignCommand = createDbSignCommand();
1829
2331
  dbCommand.addCommand(dbSignCommand);
1830
2332
  program.addCommand(dbCommand);
1831
- var helpCommand = new Command6("help").description("Show usage instructions").configureHelp({
2333
+ var helpCommand = new Command7("help").description("Show usage instructions").configureHelp({
1832
2334
  formatHelp: (cmd) => {
1833
2335
  const flags = parseGlobalFlags({});
1834
2336
  return formatCommandHelp({ command: cmd, flags });