@prisma-next/cli 0.5.0-dev.9 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +60 -25
  2. package/dist/cli-errors-B9OBbled.d.mts +3 -0
  3. package/dist/cli-errors-D3_sMh2K.mjs +33 -0
  4. package/dist/cli-errors-D3_sMh2K.mjs.map +1 -0
  5. package/dist/cli.mjs +16 -78
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/client-qVH-rEgd.mjs +1595 -0
  8. package/dist/client-qVH-rEgd.mjs.map +1 -0
  9. package/dist/{result-handler-Ba3zWQsI.mjs → command-helpers-BeZHkxV8.mjs} +70 -47
  10. package/dist/command-helpers-BeZHkxV8.mjs.map +1 -0
  11. package/dist/commands/contract-emit.d.mts.map +1 -1
  12. package/dist/commands/contract-emit.mjs +2 -4
  13. package/dist/commands/contract-infer.d.mts.map +1 -1
  14. package/dist/commands/contract-infer.mjs +2 -4
  15. package/dist/commands/db-init.d.mts.map +1 -1
  16. package/dist/commands/db-init.mjs +16 -13
  17. package/dist/commands/db-init.mjs.map +1 -1
  18. package/dist/commands/db-schema.d.mts.map +1 -1
  19. package/dist/commands/db-schema.mjs +6 -7
  20. package/dist/commands/db-schema.mjs.map +1 -1
  21. package/dist/commands/db-sign.d.mts.map +1 -1
  22. package/dist/commands/db-sign.mjs +9 -9
  23. package/dist/commands/db-sign.mjs.map +1 -1
  24. package/dist/commands/db-update.d.mts.map +1 -1
  25. package/dist/commands/db-update.mjs +15 -13
  26. package/dist/commands/db-update.mjs.map +1 -1
  27. package/dist/commands/db-verify.d.mts.map +1 -1
  28. package/dist/commands/db-verify.mjs +1 -321
  29. package/dist/commands/migration-apply.d.mts +28 -13
  30. package/dist/commands/migration-apply.d.mts.map +1 -1
  31. package/dist/commands/migration-apply.mjs +55 -151
  32. package/dist/commands/migration-apply.mjs.map +1 -1
  33. package/dist/commands/migration-new.d.mts +0 -1
  34. package/dist/commands/migration-new.d.mts.map +1 -1
  35. package/dist/commands/migration-new.mjs +34 -40
  36. package/dist/commands/migration-new.mjs.map +1 -1
  37. package/dist/commands/migration-plan.d.mts +33 -6
  38. package/dist/commands/migration-plan.d.mts.map +1 -1
  39. package/dist/commands/migration-plan.mjs +2 -348
  40. package/dist/commands/migration-ref.d.mts +1 -1
  41. package/dist/commands/migration-ref.d.mts.map +1 -1
  42. package/dist/commands/migration-ref.mjs +8 -12
  43. package/dist/commands/migration-ref.mjs.map +1 -1
  44. package/dist/commands/migration-show.d.mts +13 -7
  45. package/dist/commands/migration-show.d.mts.map +1 -1
  46. package/dist/commands/migration-show.mjs +35 -36
  47. package/dist/commands/migration-show.mjs.map +1 -1
  48. package/dist/commands/migration-status.d.mts +126 -5
  49. package/dist/commands/migration-status.d.mts.map +1 -1
  50. package/dist/commands/migration-status.mjs +2 -4
  51. package/dist/{config-loader-C25b63rJ.mjs → config-loader-B6sJjXTv.mjs} +3 -5
  52. package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
  53. package/dist/config-loader.d.mts +0 -1
  54. package/dist/config-loader.d.mts.map +1 -1
  55. package/dist/config-loader.mjs +2 -3
  56. package/dist/contract-emit-9DBda5Ou.mjs +150 -0
  57. package/dist/contract-emit-9DBda5Ou.mjs.map +1 -0
  58. package/dist/contract-emit-B77TsJqf.mjs +327 -0
  59. package/dist/contract-emit-B77TsJqf.mjs.map +1 -0
  60. package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-Dani0mMW.mjs} +4 -6
  61. package/dist/contract-enrichment-Dani0mMW.mjs.map +1 -0
  62. package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-BK9YFGEG.mjs} +13 -22
  63. package/dist/contract-infer-BK9YFGEG.mjs.map +1 -0
  64. package/dist/db-verify-C0y1PCO2.mjs +404 -0
  65. package/dist/db-verify-C0y1PCO2.mjs.map +1 -0
  66. package/dist/exports/config-types.mjs +1 -2
  67. package/dist/exports/control-api.d.mts +101 -586
  68. package/dist/exports/control-api.d.mts.map +1 -1
  69. package/dist/exports/control-api.mjs +4 -6
  70. package/dist/exports/index.d.mts.map +1 -1
  71. package/dist/exports/index.mjs +28 -30
  72. package/dist/exports/index.mjs.map +1 -1
  73. package/dist/exports/init-output.d.mts +2 -4
  74. package/dist/exports/init-output.d.mts.map +1 -1
  75. package/dist/exports/init-output.mjs +2 -3
  76. package/dist/extension-pack-inputs-C7xgE-vv.mjs +74 -0
  77. package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +1 -0
  78. package/dist/{framework-components-Cr--XBKy.mjs → framework-components-ChqVUxR-.mjs} +3 -4
  79. package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-ChqVUxR-.mjs.map} +1 -1
  80. package/dist/global-flags-Icqpxk23.d.mts +12 -0
  81. package/dist/global-flags-Icqpxk23.d.mts.map +1 -0
  82. package/dist/helpers-eqdN8tH6.mjs +25 -0
  83. package/dist/helpers-eqdN8tH6.mjs.map +1 -0
  84. package/dist/{init-C5220SY9.mjs → init-DETSgw3h.mjs} +40 -49
  85. package/dist/init-DETSgw3h.mjs.map +1 -0
  86. package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-CWYxGKlb.mjs} +10 -11
  87. package/dist/inspect-live-schema-CWYxGKlb.mjs.map +1 -0
  88. package/dist/migration-cli.d.mts +41 -12
  89. package/dist/migration-cli.d.mts.map +1 -1
  90. package/dist/migration-cli.mjs +309 -86
  91. package/dist/migration-cli.mjs.map +1 -1
  92. package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-B5dORFEv.mjs} +8 -9
  93. package/dist/migration-command-scaffold-B5dORFEv.mjs.map +1 -0
  94. package/dist/migration-plan-C6lVaHsO.mjs +554 -0
  95. package/dist/migration-plan-C6lVaHsO.mjs.map +1 -0
  96. package/dist/{migration-status-DUMiH8_G.mjs → migration-status-CZ-D5k7k.mjs} +272 -65
  97. package/dist/migration-status-CZ-D5k7k.mjs.map +1 -0
  98. package/dist/migrations-D_UJnpuW.mjs +216 -0
  99. package/dist/migrations-D_UJnpuW.mjs.map +1 -0
  100. package/dist/{output-BpcQrnnq.mjs → output-B16Kefzx.mjs} +9 -3
  101. package/dist/output-B16Kefzx.mjs.map +1 -0
  102. package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-DFfvZcYL.mjs} +2 -2
  103. package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-DFfvZcYL.mjs.map} +1 -1
  104. package/dist/result-handler-rmPVKIP2.mjs +25 -0
  105. package/dist/result-handler-rmPVKIP2.mjs.map +1 -0
  106. package/dist/rolldown-runtime-twds-ZHy.mjs +14 -0
  107. package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-C_hFNbAn.mjs} +4 -28
  108. package/dist/terminal-ui-C_hFNbAn.mjs.map +1 -0
  109. package/dist/types-D7x-IFLO.d.mts +858 -0
  110. package/dist/types-D7x-IFLO.d.mts.map +1 -0
  111. package/dist/{verify-Bkycc-Tf.mjs → verify-CiwNWM9N.mjs} +3 -4
  112. package/dist/verify-CiwNWM9N.mjs.map +1 -0
  113. package/package.json +28 -26
  114. package/src/cli.ts +32 -6
  115. package/src/commands/contract-emit.ts +67 -163
  116. package/src/commands/contract-infer.ts +7 -20
  117. package/src/commands/db-init.ts +15 -3
  118. package/src/commands/db-update.ts +9 -4
  119. package/src/commands/db-verify.ts +47 -15
  120. package/src/commands/init/index.ts +1 -1
  121. package/src/commands/init/init.ts +2 -2
  122. package/src/commands/init/templates/code-templates.ts +26 -18
  123. package/src/commands/inspect-live-schema.ts +10 -5
  124. package/src/commands/migration-apply.ts +114 -212
  125. package/src/commands/migration-new.ts +42 -45
  126. package/src/commands/migration-plan.ts +212 -72
  127. package/src/commands/migration-ref.ts +8 -7
  128. package/src/commands/migration-show.ts +60 -41
  129. package/src/commands/migration-status.ts +483 -64
  130. package/src/config-path-validation.ts +0 -1
  131. package/src/control-api/client.ts +85 -5
  132. package/src/control-api/contract-enrichment.ts +6 -4
  133. package/src/control-api/operations/apply-aggregate.ts +290 -0
  134. package/src/control-api/operations/contract-emit.ts +198 -115
  135. package/src/control-api/operations/db-apply-aggregate.ts +397 -0
  136. package/src/control-api/operations/db-init.ts +51 -253
  137. package/src/control-api/operations/db-update.ts +66 -183
  138. package/src/control-api/operations/db-verify.ts +342 -0
  139. package/src/control-api/operations/migration-apply.ts +424 -131
  140. package/src/control-api/types.ts +280 -29
  141. package/src/exports/control-api.ts +15 -3
  142. package/src/load-ts-contract.ts +28 -26
  143. package/src/migration-cli.ts +445 -122
  144. package/src/utils/cli-errors.ts +49 -2
  145. package/src/utils/combine-schema-results.ts +84 -0
  146. package/src/utils/command-helpers.ts +69 -25
  147. package/src/utils/contract-space-aggregate-loader.ts +204 -0
  148. package/src/utils/contract-space-extension-migrations-pass.ts +120 -0
  149. package/src/utils/contract-space-migrate-pass.ts +156 -0
  150. package/src/utils/emit-queue.ts +26 -0
  151. package/src/utils/extension-pack-inputs.ts +170 -0
  152. package/src/utils/formatters/graph-migration-mapper.ts +7 -3
  153. package/src/utils/formatters/migrations.ts +197 -61
  154. package/src/utils/publish-contract-artifact-pair.ts +134 -0
  155. package/dist/cli-errors-BFYgBH3L.d.mts +0 -4
  156. package/dist/cli-errors-Cd79vmTH.mjs +0 -5
  157. package/dist/client-CrsnY58k.mjs +0 -997
  158. package/dist/client-CrsnY58k.mjs.map +0 -1
  159. package/dist/commands/db-verify.mjs.map +0 -1
  160. package/dist/commands/migration-plan.mjs.map +0 -1
  161. package/dist/config-loader-C25b63rJ.mjs.map +0 -1
  162. package/dist/contract-emit--feXyNd7.mjs +0 -4
  163. package/dist/contract-emit-NJ01hiiv.mjs +0 -195
  164. package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
  165. package/dist/contract-emit-V5SSitUT.mjs +0 -122
  166. package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
  167. package/dist/contract-enrichment-CAOELa-H.mjs.map +0 -1
  168. package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
  169. package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
  170. package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
  171. package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
  172. package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
  173. package/dist/init-C5220SY9.mjs.map +0 -1
  174. package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
  175. package/dist/migration-command-scaffold-B3B09et6.mjs.map +0 -1
  176. package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
  177. package/dist/migrations-Bo5WtTla.mjs +0 -153
  178. package/dist/migrations-Bo5WtTla.mjs.map +0 -1
  179. package/dist/output-BpcQrnnq.mjs.map +0 -1
  180. package/dist/result-handler-Ba3zWQsI.mjs.map +0 -1
  181. package/dist/terminal-ui-C3ZLwQxK.mjs.map +0 -1
  182. package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
  183. package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
  184. package/dist/verify-Bkycc-Tf.mjs.map +0 -1
  185. package/src/control-api/operations/extract-operation-statements.ts +0 -14
  186. package/src/control-api/operations/extract-sql-ddl.ts +0 -47
@@ -13,6 +13,7 @@ import {
13
13
  } from '../utils/cli-errors';
14
14
  import type { MigrationCommandOptions } from '../utils/command-helpers';
15
15
  import {
16
+ resolveMigrationPaths,
16
17
  sanitizeErrorMessage,
17
18
  setCommandDescriptions,
18
19
  setCommandExamples,
@@ -111,14 +112,23 @@ async function executeDbInitCommand(
111
112
  if (!ctxResult.ok) {
112
113
  return ctxResult;
113
114
  }
114
- const { client, contractJson, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;
115
+ const { client, config, contractJson, dbConnection, onProgress, contractPathAbsolute } =
116
+ ctxResult.value;
117
+
118
+ // The aggregate loader (loader → planner → runner pipeline) catches
119
+ // layout / drift / disjointness violations on its own; the legacy
120
+ // per-space precheck + marker-check helpers are no longer needed at
121
+ // this surface. Marker-vs-on-disk drift surfaces through the planner's
122
+ // graph-walk strategy.
123
+ const { migrationsDir } = resolveMigrationPaths(options.config, config);
115
124
 
116
125
  try {
117
- // Call dbInit with connection and progress callback
126
+ await client.connect(dbConnection);
127
+
118
128
  const result = await client.dbInit({
119
129
  contract: contractJson,
120
130
  mode: options.dryRun ? 'plan' : 'apply',
121
- connection: dbConnection,
131
+ migrationsDir,
122
132
  onProgress,
123
133
  });
124
134
 
@@ -142,6 +152,7 @@ async function executeDbInitCommand(
142
152
  label: op.label,
143
153
  operationClass: op.operationClass,
144
154
  })),
155
+ ...ifDefined('preview', result.value.plan.preview),
145
156
  },
146
157
  ...(result.value.execution
147
158
  ? {
@@ -159,6 +170,7 @@ async function executeDbInitCommand(
159
170
  },
160
171
  }
161
172
  : {}),
173
+ ...ifDefined('perSpace', result.value.perSpace),
162
174
  summary: result.value.summary,
163
175
  timings: { total: Date.now() - startTime },
164
176
  };
@@ -14,6 +14,7 @@ import {
14
14
  } from '../utils/cli-errors';
15
15
  import type { MigrationCommandOptions } from '../utils/command-helpers';
16
16
  import {
17
+ resolveMigrationPaths,
17
18
  sanitizeErrorMessage,
18
19
  setCommandDescriptions,
19
20
  setCommandExamples,
@@ -80,14 +81,17 @@ async function executeDbUpdateCommand(
80
81
  if (!ctxResult.ok) {
81
82
  return ctxResult;
82
83
  }
83
- const { client, contractJson, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;
84
+ const { client, config, contractJson, dbConnection, onProgress, contractPathAbsolute } =
85
+ ctxResult.value;
86
+ const { migrationsDir } = resolveMigrationPaths(options.config, config);
84
87
 
85
88
  try {
86
- // Call dbUpdate with connection and progress callback
89
+ await client.connect(dbConnection);
90
+
87
91
  const result = await client.dbUpdate({
88
92
  contract: contractJson,
89
93
  mode: options.dryRun ? 'plan' : 'apply',
90
- connection: dbConnection,
94
+ migrationsDir,
91
95
  ...(flags.yes ? { acceptDataLoss: true } : {}),
92
96
  onProgress,
93
97
  });
@@ -112,7 +116,7 @@ async function executeDbUpdateCommand(
112
116
  label: op.label,
113
117
  operationClass: op.operationClass,
114
118
  })),
115
- ...ifDefined('sql', result.value.plan.sql),
119
+ ...ifDefined('preview', result.value.plan.preview),
116
120
  },
117
121
  ...ifDefined(
118
122
  'execution',
@@ -132,6 +136,7 @@ async function executeDbUpdateCommand(
132
136
  }
133
137
  : undefined,
134
138
  ),
139
+ ...ifDefined('perSpace', result.value.perSpace),
135
140
  summary: result.value.summary,
136
141
  timings: { total: Date.now() - startTime },
137
142
  };
@@ -27,10 +27,12 @@ import {
27
27
  errorTargetMismatch,
28
28
  errorUnexpected,
29
29
  } from '../utils/cli-errors';
30
+ import { combineSchemaResults } from '../utils/combine-schema-results';
30
31
  import {
31
32
  addGlobalOptions,
32
33
  maskConnectionUrl,
33
34
  resolveContractPath,
35
+ resolveMigrationPaths,
34
36
  setCommandDescriptions,
35
37
  setCommandExamples,
36
38
  } from '../utils/command-helpers';
@@ -346,22 +348,42 @@ async function executeDbVerifyCommand(
346
348
  const setupResult = await resolveVerifySetup(paths, options, mode);
347
349
  if (!setupResult.ok) return setupResult;
348
350
  const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
351
+ const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);
349
352
 
350
353
  const client = createVerifyClient(setupResult.value);
351
354
  const onProgress = createProgressAdapter({ ui, flags });
352
355
 
353
356
  try {
357
+ // Single-contract marker verification preserved for the existing
358
+ // marker / target / hash failure surface (`PN-RUN-3001/3002/3003`).
359
+ // The aggregate verifier (run below for the per-space marker /
360
+ // schema checks) does not duplicate this: it concerns itself with
361
+ // marker-vs-on-disk and orphan-marker drift, not the
362
+ // hash-mismatch-against-the-app-contract lane that today's
363
+ // `client.verify` covers.
354
364
  const verifyResult = await client.verify({
355
365
  contract: contractJson,
356
366
  connection: dbConnection,
357
367
  onProgress,
358
368
  });
359
369
 
360
- // If verification failed, map to CLI structured error
361
370
  if (!verifyResult.ok) {
362
371
  return notOk(mapVerifyFailure(verifyResult));
363
372
  }
364
373
 
374
+ // Aggregate verifier (loader → verifier pipeline). Runs the layout
375
+ // precheck, marker-aware per-space verifier, and (full mode only)
376
+ // per-space pre-projected schema verification (closes F23).
377
+ const aggregateResult = await client.dbVerify({
378
+ contract: contractJson,
379
+ migrationsDir,
380
+ strict: options.strict ?? false,
381
+ skipSchema: mode === 'marker-only',
382
+ skipMarker: false,
383
+ onProgress,
384
+ });
385
+ if (!aggregateResult.ok) return notOk(aggregateResult.failure);
386
+
365
387
  if (mode === 'marker-only') {
366
388
  return ok({
367
389
  ok: true,
@@ -381,14 +403,13 @@ async function executeDbVerifyCommand(
381
403
  });
382
404
  }
383
405
 
384
- const schemaVerifyResult = await client.schemaVerify({
385
- contract: contractJson,
386
- strict: options.strict ?? false,
387
- onProgress,
388
- });
389
-
390
- if (!schemaVerifyResult.ok) {
391
- return notOk(schemaVerifyResult);
406
+ const combined = combineSchemaResults(
407
+ aggregateResult.value.schemaResults,
408
+ aggregateResult.value.appSpaceId,
409
+ options.strict ?? false,
410
+ );
411
+ if (!combined.ok) {
412
+ return notOk(combined);
392
413
  }
393
414
 
394
415
  return ok({
@@ -401,9 +422,9 @@ async function executeDbVerifyCommand(
401
422
  ...ifDefined('missingCodecs', verifyResult.missingCodecs),
402
423
  ...ifDefined('codecCoverageSkipped', verifyResult.codecCoverageSkipped),
403
424
  schema: {
404
- summary: schemaVerifyResult.summary,
405
- counts: schemaVerifyResult.schema.counts,
406
- strict: schemaVerifyResult.meta?.strict ?? false,
425
+ summary: combined.summary,
426
+ counts: combined.schema.counts,
427
+ strict: combined.meta?.strict ?? false,
407
428
  },
408
429
  meta: {
409
430
  ...(verifyResult.meta ?? {}),
@@ -429,19 +450,30 @@ async function executeDbSchemaOnlyVerifyCommand(
429
450
  const setupResult = await resolveVerifySetup(paths, options, 'schema-only');
430
451
  if (!setupResult.ok) return setupResult;
431
452
  const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
453
+ const { migrationsDir } = resolveMigrationPaths(options.config, setupResult.value.config);
432
454
 
433
455
  const client = createVerifyClient(setupResult.value);
434
456
  const onProgress = createProgressAdapter({ ui, flags });
435
457
 
436
458
  try {
437
- const schemaVerifyResult = await client.schemaVerify({
459
+ await client.connect(dbConnection);
460
+ const aggregateResult = await client.dbVerify({
438
461
  contract: contractJson,
462
+ migrationsDir,
439
463
  strict: options.strict ?? false,
440
- connection: dbConnection,
464
+ skipSchema: false,
465
+ skipMarker: true,
441
466
  onProgress,
442
467
  });
468
+ if (!aggregateResult.ok) return notOk(aggregateResult.failure);
443
469
 
444
- return ok(schemaVerifyResult);
470
+ return ok(
471
+ combineSchemaResults(
472
+ aggregateResult.value.schemaResults,
473
+ aggregateResult.value.appSpaceId,
474
+ options.strict ?? false,
475
+ ),
476
+ );
445
477
  } catch (error) {
446
478
  return wrapVerifyError(error, contractPathAbsolute, 'db verify --schema-only');
447
479
  } finally {
@@ -113,7 +113,7 @@ export function createInitCommand(): Command {
113
113
  * we honour it (e.g. testing flows where stdin is stubbed).
114
114
  *
115
115
  * Exported so callers and tests can derive the same value without
116
- * touching `process` globals — F14 of the M1/M2 review.
116
+ * touching `process` globals.
117
117
  */
118
118
  export function deriveCanPrompt(opts: {
119
119
  readonly flagsInteractive: boolean | undefined;
@@ -569,7 +569,7 @@ async function runInstall(ctx: {
569
569
  /**
570
570
  * FR2.1 — set when the user already declares `@types/node` directly in
571
571
  * `dependencies` or `devDependencies`. We then skip adding it so a
572
- * pinned major (e.g. `^18` for a Node 18 runtime) survives `init`
572
+ * locked major (e.g. `^18` for a Node 18 runtime) survives `init`
573
573
  * unchanged. Transitive presence is intentionally ignored: detecting
574
574
  * it requires lockfile introspection and the realistic clobber risk
575
575
  * is the direct-pin case.
@@ -585,7 +585,7 @@ async function runInstall(ctx: {
585
585
  // Pin it as a devDep rather than relying on a transitive resolution
586
586
  // through `dotenv` (whose types bundle is internal and not guaranteed
587
587
  // across versions). Skip when the user already declares `@types/node`
588
- // directly so a pinned major (e.g. `^18` for a Node 18 runtime) is
588
+ // directly so a locked major (e.g. `^18` for a Node 18 runtime) is
589
589
  // preserved. Listed last so the install log still leads with the
590
590
  // user-relevant `prisma-next` line.
591
591
  const devDeps = hasTypesNode ? ['prisma-next'] : ['prisma-next', '@types/node'];
@@ -62,12 +62,12 @@ model User {
62
62
 
63
63
  function schemaSampleTsPostgres(): string {
64
64
  return `\`\`\`typescript
65
- import sqlFamily from '@prisma-next/family-sql/pack';
66
- import { defineContract } from '@prisma-next/sql-contract-ts/contract-builder';
67
- import postgresPack from '@prisma-next/target-postgres/pack';
65
+ import { defineContract } from '@prisma-next/postgres/contract-builder';
66
+ import sqlFamily from '@prisma-next/postgres/family';
67
+ import postgresTarget from '@prisma-next/postgres/target';
68
68
 
69
69
  export const contract = defineContract(
70
- { family: sqlFamily, target: postgresPack },
70
+ { family: sqlFamily, target: postgresTarget },
71
71
  ({ field, model }) => ({
72
72
  models: {
73
73
  User: model('User', {
@@ -85,9 +85,9 @@ export const contract = defineContract(
85
85
 
86
86
  function schemaSampleTsMongo(): string {
87
87
  return `\`\`\`typescript
88
- import mongoFamily from '@prisma-next/family-mongo/pack';
89
- import { defineContract } from '@prisma-next/mongo-contract-ts/contract-builder';
90
- import mongoTarget from '@prisma-next/target-mongo/pack';
88
+ import { defineContract } from '@prisma-next/mongo/contract-builder';
89
+ import mongoFamily from '@prisma-next/mongo/family';
90
+ import mongoTarget from '@prisma-next/mongo/target';
91
91
 
92
92
  export const contract = defineContract(
93
93
  { family: mongoFamily, target: mongoTarget },
@@ -108,12 +108,15 @@ export const contract = defineContract(
108
108
  }
109
109
 
110
110
  function starterSchemaPslPostgres(): string {
111
- return `model User {
111
+ return `// use prisma-next
112
+
113
+ model User {
112
114
  id Int @id @default(autoincrement())
113
115
  email String @unique
114
116
  name String?
115
117
  posts Post[]
116
118
  createdAt DateTime @default(now())
119
+ updatedAt temporal.updatedAt()
117
120
  }
118
121
 
119
122
  model Post {
@@ -123,12 +126,15 @@ model Post {
123
126
  author User @relation(fields: [authorId], references: [id])
124
127
  authorId Int
125
128
  createdAt DateTime @default(now())
129
+ updatedAt temporal.updatedAt()
126
130
  }
127
131
  `;
128
132
  }
129
133
 
130
134
  function starterSchemaPslMongo(): string {
131
- return `model User {
135
+ return `// use prisma-next
136
+
137
+ model User {
132
138
  id ObjectId @id @map("_id")
133
139
  email String @unique
134
140
  name String?
@@ -148,12 +154,12 @@ model Post {
148
154
  }
149
155
 
150
156
  function starterSchemaTsPostgres(): string {
151
- return `import sqlFamily from '@prisma-next/family-sql/pack';
152
- import { defineContract } from '@prisma-next/sql-contract-ts/contract-builder';
153
- import postgresPack from '@prisma-next/target-postgres/pack';
157
+ return `import { defineContract } from '@prisma-next/postgres/contract-builder';
158
+ import sqlFamily from '@prisma-next/postgres/family';
159
+ import postgresTarget from '@prisma-next/postgres/target';
154
160
 
155
161
  export const contract = defineContract(
156
- { family: sqlFamily, target: postgresPack },
162
+ { family: sqlFamily, target: postgresTarget },
157
163
  ({ field, model, rel }) => ({
158
164
  models: {
159
165
  User: model('User', {
@@ -161,7 +167,8 @@ export const contract = defineContract(
161
167
  id: field.id.uuidv7(),
162
168
  email: field.text().unique(),
163
169
  name: field.text().optional(),
164
- createdAt: field.createdAt(),
170
+ createdAt: field.temporal.createdAt(),
171
+ updatedAt: field.temporal.updatedAt(),
165
172
  },
166
173
  relations: {
167
174
  posts: rel.hasMany('Post', { by: 'authorId' }),
@@ -174,7 +181,8 @@ export const contract = defineContract(
174
181
  title: field.text(),
175
182
  content: field.text().optional(),
176
183
  authorId: field.uuid(),
177
- createdAt: field.createdAt(),
184
+ createdAt: field.temporal.createdAt(),
185
+ updatedAt: field.temporal.updatedAt(),
178
186
  },
179
187
  relations: {
180
188
  author: rel.belongsTo('User', { from: 'authorId', to: 'id' }),
@@ -187,9 +195,9 @@ export const contract = defineContract(
187
195
  }
188
196
 
189
197
  function starterSchemaTsMongo(): string {
190
- return `import mongoFamily from '@prisma-next/family-mongo/pack';
191
- import { defineContract } from '@prisma-next/mongo-contract-ts/contract-builder';
192
- import mongoTarget from '@prisma-next/target-mongo/pack';
198
+ return `import { defineContract } from '@prisma-next/mongo/contract-builder';
199
+ import mongoFamily from '@prisma-next/mongo/family';
200
+ import mongoTarget from '@prisma-next/mongo/target';
193
201
 
194
202
  export const contract = defineContract(
195
203
  { family: mongoFamily, target: mongoTarget },
@@ -1,5 +1,5 @@
1
1
  import type { CoreSchemaView } from '@prisma-next/framework-components/control';
2
- import { validatePrintableSqlSchemaIR } from '@prisma-next/psl-printer';
2
+ import type { PslDocumentAst } from '@prisma-next/framework-components/psl-ast';
3
3
  import { notOk, ok, type Result } from '@prisma-next/utils/result';
4
4
  import { relative, resolve } from 'pathe';
5
5
  import { loadConfig } from '../config-loader';
@@ -33,6 +33,12 @@ export interface InspectLiveSchemaResult {
33
33
  readonly config: LoadedCliConfig;
34
34
  readonly schema: unknown;
35
35
  readonly schemaView: CoreSchemaView | undefined;
36
+ /**
37
+ * PSL AST inferred from the introspected schema, when the configured family
38
+ * implements `PslContractInferCapable`. `undefined` for families that do not
39
+ * support inference (e.g. Mongo today).
40
+ */
41
+ readonly pslContractAst: PslDocumentAst | undefined;
36
42
  readonly target: {
37
43
  readonly familyId: string;
38
44
  readonly id: string;
@@ -122,14 +128,12 @@ export async function inspectLiveSchema(
122
128
  const onProgress = createProgressAdapter({ ui, flags });
123
129
 
124
130
  try {
125
- const schemaIR = await client.introspect({
131
+ const schema = await client.introspect({
126
132
  connection: dbConnection,
127
133
  onProgress,
128
134
  });
129
- // TODO(TML-2251): Remove SQL-specific branching — SQL should use the same family-agnostic path as Mongo.
130
- const schema =
131
- config.family.familyId === 'sql' ? validatePrintableSqlSchemaIR(schemaIR) : schemaIR;
132
135
  const schemaView = client.toSchemaView(schema);
136
+ const pslContractAst = client.inferPslContract(schema);
133
137
 
134
138
  const dbUrl = typeof dbConnection === 'string' ? maskConnectionUrl(dbConnection) : undefined;
135
139
 
@@ -137,6 +141,7 @@ export async function inspectLiveSchema(
137
141
  config,
138
142
  schema,
139
143
  schemaView,
144
+ pslContractAst,
140
145
  target: {
141
146
  familyId: config.family.familyId,
142
147
  id: config.target.targetId,