@prisma-next/cli 0.3.0-dev.12 → 0.3.0-dev.123

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 (215) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +470 -134
  3. package/dist/cli-errors-ByGuoqNj.mjs +3 -0
  4. package/dist/cli-errors-D6HxRn3A.d.mts +2 -0
  5. package/dist/cli.d.mts +1 -0
  6. package/dist/cli.js +1 -2350
  7. package/dist/cli.mjs +242 -0
  8. package/dist/cli.mjs.map +1 -0
  9. package/dist/client-612RJJD_.mjs +1069 -0
  10. package/dist/client-612RJJD_.mjs.map +1 -0
  11. package/dist/commands/contract-emit.d.mts +7 -0
  12. package/dist/commands/contract-emit.d.mts.map +1 -0
  13. package/dist/commands/contract-emit.mjs +8 -0
  14. package/dist/commands/contract-infer.d.mts +7 -0
  15. package/dist/commands/contract-infer.d.mts.map +1 -0
  16. package/dist/commands/contract-infer.mjs +9 -0
  17. package/dist/commands/db-init.d.mts +7 -0
  18. package/dist/commands/db-init.d.mts.map +1 -0
  19. package/dist/commands/db-init.mjs +125 -0
  20. package/dist/commands/db-init.mjs.map +1 -0
  21. package/dist/commands/db-schema.d.mts +7 -0
  22. package/dist/commands/db-schema.d.mts.map +1 -0
  23. package/dist/commands/db-schema.mjs +55 -0
  24. package/dist/commands/db-schema.mjs.map +1 -0
  25. package/dist/commands/db-sign.d.mts +7 -0
  26. package/dist/commands/db-sign.d.mts.map +1 -0
  27. package/dist/commands/db-sign.mjs +136 -0
  28. package/dist/commands/db-sign.mjs.map +1 -0
  29. package/dist/commands/db-update.d.mts +7 -0
  30. package/dist/commands/db-update.d.mts.map +1 -0
  31. package/dist/commands/db-update.mjs +122 -0
  32. package/dist/commands/db-update.mjs.map +1 -0
  33. package/dist/commands/db-verify.d.mts +7 -0
  34. package/dist/commands/db-verify.d.mts.map +1 -0
  35. package/dist/commands/db-verify.mjs +311 -0
  36. package/dist/commands/db-verify.mjs.map +1 -0
  37. package/dist/commands/migration-apply.d.mts +36 -0
  38. package/dist/commands/migration-apply.d.mts.map +1 -0
  39. package/dist/commands/migration-apply.mjs +241 -0
  40. package/dist/commands/migration-apply.mjs.map +1 -0
  41. package/dist/commands/migration-plan.d.mts +47 -0
  42. package/dist/commands/migration-plan.d.mts.map +1 -0
  43. package/dist/commands/migration-plan.mjs +288 -0
  44. package/dist/commands/migration-plan.mjs.map +1 -0
  45. package/dist/commands/migration-ref.d.mts +43 -0
  46. package/dist/commands/migration-ref.d.mts.map +1 -0
  47. package/dist/commands/migration-ref.mjs +194 -0
  48. package/dist/commands/migration-ref.mjs.map +1 -0
  49. package/dist/commands/migration-show.d.mts +28 -0
  50. package/dist/commands/migration-show.d.mts.map +1 -0
  51. package/dist/commands/migration-show.mjs +139 -0
  52. package/dist/commands/migration-show.mjs.map +1 -0
  53. package/dist/commands/migration-status.d.mts +85 -0
  54. package/dist/commands/migration-status.d.mts.map +1 -0
  55. package/dist/commands/migration-status.mjs +8 -0
  56. package/dist/commands/migration-verify.d.mts +16 -0
  57. package/dist/commands/migration-verify.d.mts.map +1 -0
  58. package/dist/commands/migration-verify.mjs +87 -0
  59. package/dist/commands/migration-verify.mjs.map +1 -0
  60. package/dist/config-loader-d_KF19Tw.mjs +43 -0
  61. package/dist/config-loader-d_KF19Tw.mjs.map +1 -0
  62. package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
  63. package/dist/config-loader.d.mts.map +1 -0
  64. package/dist/config-loader.mjs +3 -0
  65. package/dist/contract-emit-CVv7dbQ9.mjs +187 -0
  66. package/dist/contract-emit-CVv7dbQ9.mjs.map +1 -0
  67. package/dist/contract-infer-Bvw8u8Eu.mjs +83 -0
  68. package/dist/contract-infer-Bvw8u8Eu.mjs.map +1 -0
  69. package/dist/exports/config-types.d.mts +2 -0
  70. package/dist/exports/config-types.mjs +3 -0
  71. package/dist/exports/control-api.d.mts +626 -0
  72. package/dist/exports/control-api.d.mts.map +1 -0
  73. package/dist/exports/control-api.mjs +107 -0
  74. package/dist/exports/control-api.mjs.map +1 -0
  75. package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +10 -5
  76. package/dist/exports/index.d.mts.map +1 -0
  77. package/dist/exports/index.mjs +134 -0
  78. package/dist/exports/index.mjs.map +1 -0
  79. package/dist/extract-sql-ddl-Jf5blEO0.mjs +26 -0
  80. package/dist/extract-sql-ddl-Jf5blEO0.mjs.map +1 -0
  81. package/dist/framework-components-M2j-qPfr.mjs +59 -0
  82. package/dist/framework-components-M2j-qPfr.mjs.map +1 -0
  83. package/dist/inspect-live-schema-BQe5i4YE.mjs +90 -0
  84. package/dist/inspect-live-schema-BQe5i4YE.mjs.map +1 -0
  85. package/dist/migration-command-scaffold-SLrjcKXS.mjs +104 -0
  86. package/dist/migration-command-scaffold-SLrjcKXS.mjs.map +1 -0
  87. package/dist/migration-status-B7OVZ-Ka.mjs +1576 -0
  88. package/dist/migration-status-B7OVZ-Ka.mjs.map +1 -0
  89. package/dist/migrations-Db_ea9eE.mjs +173 -0
  90. package/dist/migrations-Db_ea9eE.mjs.map +1 -0
  91. package/dist/progress-adapter-DRNe2idZ.mjs +43 -0
  92. package/dist/progress-adapter-DRNe2idZ.mjs.map +1 -0
  93. package/dist/terminal-ui-DAcMBRKf.mjs +980 -0
  94. package/dist/terminal-ui-DAcMBRKf.mjs.map +1 -0
  95. package/dist/verify-DXKxBFvU.mjs +385 -0
  96. package/dist/verify-DXKxBFvU.mjs.map +1 -0
  97. package/package.json +85 -40
  98. package/src/cli.ts +109 -58
  99. package/src/commands/contract-emit.ts +236 -143
  100. package/src/commands/contract-infer-paths.ts +32 -0
  101. package/src/commands/contract-infer.ts +131 -0
  102. package/src/commands/db-init.ts +211 -425
  103. package/src/commands/db-schema.ts +77 -0
  104. package/src/commands/db-sign.ts +207 -228
  105. package/src/commands/db-update.ts +236 -0
  106. package/src/commands/db-verify.ts +484 -186
  107. package/src/commands/inspect-live-schema.ts +171 -0
  108. package/src/commands/migration-apply.ts +416 -0
  109. package/src/commands/migration-plan.ts +451 -0
  110. package/src/commands/migration-ref.ts +305 -0
  111. package/src/commands/migration-show.ts +246 -0
  112. package/src/commands/migration-status.ts +838 -0
  113. package/src/commands/migration-verify.ts +134 -0
  114. package/src/config-loader.ts +13 -3
  115. package/src/control-api/client.ts +614 -0
  116. package/src/control-api/contract-enrichment.ts +135 -0
  117. package/src/control-api/errors.ts +9 -0
  118. package/src/control-api/operations/contract-emit.ts +173 -0
  119. package/src/control-api/operations/db-init.ts +286 -0
  120. package/src/control-api/operations/db-update.ts +221 -0
  121. package/src/control-api/operations/extract-sql-ddl.ts +47 -0
  122. package/src/control-api/operations/migration-apply.ts +194 -0
  123. package/src/control-api/operations/migration-helpers.ts +49 -0
  124. package/src/control-api/types.ts +683 -0
  125. package/src/exports/config-types.ts +4 -3
  126. package/src/exports/control-api.ts +56 -0
  127. package/src/load-ts-contract.ts +16 -11
  128. package/src/utils/cli-errors.ts +5 -2
  129. package/src/utils/command-helpers.ts +293 -3
  130. package/src/utils/formatters/emit.ts +67 -0
  131. package/src/utils/formatters/errors.ts +82 -0
  132. package/src/utils/formatters/graph-migration-mapper.ts +220 -0
  133. package/src/utils/formatters/graph-render.ts +1317 -0
  134. package/src/utils/formatters/graph-types.ts +114 -0
  135. package/src/utils/formatters/help.ts +380 -0
  136. package/src/utils/formatters/helpers.ts +28 -0
  137. package/src/utils/formatters/migrations.ts +346 -0
  138. package/src/utils/formatters/styled.ts +212 -0
  139. package/src/utils/formatters/verify.ts +620 -0
  140. package/src/utils/global-flags.ts +41 -23
  141. package/src/utils/migration-command-scaffold.ts +187 -0
  142. package/src/utils/migration-types.ts +12 -0
  143. package/src/utils/progress-adapter.ts +75 -0
  144. package/src/utils/result-handler.ts +12 -13
  145. package/src/utils/shutdown.ts +92 -0
  146. package/src/utils/suggest-command.ts +31 -0
  147. package/src/utils/terminal-ui.ts +276 -0
  148. package/dist/chunk-BZMBKEEQ.js +0 -997
  149. package/dist/chunk-BZMBKEEQ.js.map +0 -1
  150. package/dist/chunk-CVNWLFXO.js +0 -91
  151. package/dist/chunk-CVNWLFXO.js.map +0 -1
  152. package/dist/chunk-HWYQOCAJ.js +0 -47
  153. package/dist/chunk-HWYQOCAJ.js.map +0 -1
  154. package/dist/chunk-QUPBU4KV.js +0 -131
  155. package/dist/chunk-QUPBU4KV.js.map +0 -1
  156. package/dist/cli.d.ts +0 -2
  157. package/dist/cli.d.ts.map +0 -1
  158. package/dist/cli.js.map +0 -1
  159. package/dist/commands/contract-emit.d.ts +0 -3
  160. package/dist/commands/contract-emit.d.ts.map +0 -1
  161. package/dist/commands/contract-emit.js +0 -9
  162. package/dist/commands/contract-emit.js.map +0 -1
  163. package/dist/commands/db-init.d.ts +0 -3
  164. package/dist/commands/db-init.d.ts.map +0 -1
  165. package/dist/commands/db-init.js +0 -337
  166. package/dist/commands/db-init.js.map +0 -1
  167. package/dist/commands/db-introspect.d.ts +0 -3
  168. package/dist/commands/db-introspect.d.ts.map +0 -1
  169. package/dist/commands/db-introspect.js +0 -186
  170. package/dist/commands/db-introspect.js.map +0 -1
  171. package/dist/commands/db-schema-verify.d.ts +0 -3
  172. package/dist/commands/db-schema-verify.d.ts.map +0 -1
  173. package/dist/commands/db-schema-verify.js +0 -160
  174. package/dist/commands/db-schema-verify.js.map +0 -1
  175. package/dist/commands/db-sign.d.ts +0 -3
  176. package/dist/commands/db-sign.d.ts.map +0 -1
  177. package/dist/commands/db-sign.js +0 -195
  178. package/dist/commands/db-sign.js.map +0 -1
  179. package/dist/commands/db-verify.d.ts +0 -3
  180. package/dist/commands/db-verify.d.ts.map +0 -1
  181. package/dist/commands/db-verify.js +0 -169
  182. package/dist/commands/db-verify.js.map +0 -1
  183. package/dist/config-loader.d.ts.map +0 -1
  184. package/dist/config-loader.js +0 -7
  185. package/dist/config-loader.js.map +0 -1
  186. package/dist/exports/config-types.d.ts +0 -3
  187. package/dist/exports/config-types.d.ts.map +0 -1
  188. package/dist/exports/config-types.js +0 -6
  189. package/dist/exports/config-types.js.map +0 -1
  190. package/dist/exports/index.d.ts +0 -4
  191. package/dist/exports/index.d.ts.map +0 -1
  192. package/dist/exports/index.js +0 -175
  193. package/dist/exports/index.js.map +0 -1
  194. package/dist/load-ts-contract.d.ts.map +0 -1
  195. package/dist/utils/action.d.ts +0 -16
  196. package/dist/utils/action.d.ts.map +0 -1
  197. package/dist/utils/cli-errors.d.ts +0 -7
  198. package/dist/utils/cli-errors.d.ts.map +0 -1
  199. package/dist/utils/command-helpers.d.ts +0 -12
  200. package/dist/utils/command-helpers.d.ts.map +0 -1
  201. package/dist/utils/framework-components.d.ts +0 -70
  202. package/dist/utils/framework-components.d.ts.map +0 -1
  203. package/dist/utils/global-flags.d.ts +0 -25
  204. package/dist/utils/global-flags.d.ts.map +0 -1
  205. package/dist/utils/output.d.ts +0 -142
  206. package/dist/utils/output.d.ts.map +0 -1
  207. package/dist/utils/result-handler.d.ts +0 -15
  208. package/dist/utils/result-handler.d.ts.map +0 -1
  209. package/dist/utils/spinner.d.ts +0 -29
  210. package/dist/utils/spinner.d.ts.map +0 -1
  211. package/src/commands/db-introspect.ts +0 -256
  212. package/src/commands/db-schema-verify.ts +0 -232
  213. package/src/utils/action.ts +0 -43
  214. package/src/utils/output.ts +0 -1471
  215. package/src/utils/spinner.ts +0 -67
package/README.md CHANGED
@@ -22,6 +22,7 @@ Provide a command-line interface that:
22
22
  - **Extension Pack Descriptor Assembly**: Collect adapter and extension descriptors for emission
23
23
  - **Help Output Formatting**: Custom styled help output with command trees and formatted descriptions
24
24
  - **Config Management**: Load and validate `prisma-next.config.ts` files using Arktype validation
25
+ - **CLI Binary Compatibility**: Build emits `dist/cli.mjs` and also writes a compatibility shim at `dist/cli.js`
25
26
 
26
27
  ### Wiring validation
27
28
 
@@ -31,9 +32,9 @@ This prevents runtime mismatches (for example: a contract that declares extensio
31
32
 
32
33
  Commands that enforce wiring validation:
33
34
  - **`db verify`**
34
- - **`db introspect`** (when a contract is provided)
35
35
  - **`db sign`**
36
36
  - **`db init`**
37
+ - **`db update`**
37
38
 
38
39
  If you hit a wiring validation error: add the required descriptors to `config.extensionPacks` (matched by descriptor `id`) and re-run the command.
39
40
 
@@ -56,17 +57,17 @@ Emit `contract.json` and `contract.d.ts` from `config.contract`.
56
57
 
57
58
  **Canonical command:**
58
59
  ```bash
59
- prisma-next contract emit [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
60
+ prisma-next contract emit [--config <path>] [--json] [-v] [-q] [--color/--no-color]
60
61
  ```
61
62
 
62
63
  **Config File Requirements:**
63
64
 
64
- The `contract emit` command requires a `driver` in the config (even though it doesn't use it) because `ControlFamilyDescriptor.create()` requires it for consistency:
65
+ The `contract emit` command does not require a `driver` in the config since it doesn't connect to a database:
65
66
 
66
67
  ```typescript
67
68
  import { defineConfig } from '@prisma-next/cli/config-types';
69
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
68
70
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
69
- import postgresDriver from '@prisma-next/driver-postgres/control';
70
71
  import postgres from '@prisma-next/target-postgres/control';
71
72
  import sql from '@prisma-next/family-sql/control';
72
73
  import { contract } from './prisma/contract';
@@ -75,13 +76,8 @@ export default defineConfig({
75
76
  family: sql,
76
77
  target: postgres,
77
78
  adapter: postgresAdapter,
78
- driver: postgresDriver, // Required even though emit doesn't use it
79
79
  extensionPacks: [],
80
- contract: {
81
- source: contract,
82
- output: 'src/prisma/contract.json',
83
- types: 'src/prisma/contract.d.ts',
84
- },
80
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
85
81
  });
86
82
  ```
87
83
 
@@ -91,7 +87,6 @@ Options:
91
87
  - `-q, --quiet`: Quiet mode (errors only)
92
88
  - `-v, --verbose`: Verbose output (debug info, timings)
93
89
  - `-vv, --trace`: Trace output (deep internals, stack traces)
94
- - `--timestamps`: Add timestamps to output
95
90
  - `--color/--no-color`: Force/disable color output
96
91
 
97
92
  Examples:
@@ -102,27 +97,30 @@ prisma-next contract emit
102
97
  # JSON output
103
98
  prisma-next contract emit --json
104
99
 
105
- # Verbose output with timestamps
106
- prisma-next contract emit -v --timestamps
100
+ # Verbose output
101
+ prisma-next contract emit -v
107
102
  ```
108
103
 
109
104
  ### `prisma-next db verify`
110
105
 
111
- Verify that a database instance matches the emitted contract by checking marker presence, hash equality, and target compatibility.
106
+ Verify that a database instance matches the emitted contract by checking the marker first and, by default, the live schema second.
112
107
 
113
108
  **Command:**
114
109
  ```bash
115
- prisma-next db verify [--db <url>] [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
110
+ prisma-next db verify [--db <url>] [--config <path>] [--marker-only | --schema-only] [--strict] [--json] [-v] [-q] [--color/--no-color]
116
111
  ```
117
112
 
118
113
  Options:
119
- - `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
114
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection` if set)
120
115
  - `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
116
+ - `--marker-only`: Skip schema verification and only check the database marker
117
+ - `--schema-only`: Skip marker verification and only check whether the live schema satisfies the contract
118
+ - `--strict`: When schema verification runs, schema elements not present in the contract are considered an error
119
+ - `--marker-only` cannot be combined with `--schema-only` or `--strict` (exit code 2, `PN-CLI-4012`). `--schema-only --strict` is valid.
121
120
  - `--json`: Output as JSON object
122
121
  - `-q, --quiet`: Quiet mode (errors only)
123
122
  - `-v, --verbose`: Verbose output (debug info, timings)
124
123
  - `-vv, --trace`: Trace output (deep internals, stack traces)
125
- - `--timestamps`: Add timestamps to output
126
124
  - `--color/--no-color`: Force/disable color output
127
125
 
128
126
  Examples:
@@ -133,11 +131,20 @@ prisma-next db verify
133
131
  # Specify database URL
134
132
  prisma-next db verify --db postgresql://user:pass@localhost/db
135
133
 
134
+ # Marker-only verification when callers accept the trade-off
135
+ prisma-next db verify --db postgresql://user:pass@localhost/db --marker-only
136
+
137
+ # Schema-only verification without relying on marker state
138
+ prisma-next db verify --db postgresql://user:pass@localhost/db --schema-only
139
+
140
+ # Strict schema verification (extras fail)
141
+ prisma-next db verify --db postgresql://user:pass@localhost/db --strict
142
+
136
143
  # JSON output
137
144
  prisma-next db verify --json
138
145
 
139
- # Verbose output with timestamps
140
- prisma-next db verify -v --timestamps
146
+ # Verbose output
147
+ prisma-next db verify -v
141
148
  ```
142
149
 
143
150
  **Config File Requirements:**
@@ -146,6 +153,7 @@ The `db verify` command requires a `driver` in the config to connect to the data
146
153
 
147
154
  ```typescript
148
155
  import { defineConfig } from '@prisma-next/cli/config-types';
156
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
149
157
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
150
158
  import postgresDriver from '@prisma-next/driver-postgres/control';
151
159
  import postgres from '@prisma-next/target-postgres/control';
@@ -158,13 +166,9 @@ export default defineConfig({
158
166
  adapter: postgresAdapter,
159
167
  driver: postgresDriver,
160
168
  extensionPacks: [],
161
- contract: {
162
- source: contract,
163
- output: 'src/prisma/contract.json',
164
- types: 'src/prisma/contract.d.ts',
165
- },
169
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
166
170
  db: {
167
- url: process.env.DATABASE_URL, // Optional: can also use --db flag
171
+ connection: process.env.DATABASE_URL, // Optional: can also use --db flag
168
172
  },
169
173
  });
170
174
  ```
@@ -173,52 +177,80 @@ export default defineConfig({
173
177
 
174
178
  1. **Load Contract**: Reads the emitted `contract.json` from `config.contract.output`
175
179
  2. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
176
- 3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`) to create a family instance
177
- 4. **Verify**: Calls `familyInstance.verify()` which:
180
+ 3. **Create Family Instance**: Creates a `ControlPlaneStack` via `createControlPlaneStack()` and passes it to `config.family.create(stack)` to create a family instance
181
+ 4. **Verify Marker**: Calls `familyInstance.verify()` which:
178
182
  - Reads the contract marker from the database
179
- - Compares marker presence: Returns `PN-RTM-3001` if marker is missing
180
- - Compares target compatibility: Returns `PN-RTM-3003` if contract target doesn't match config target
181
- - Compares core hash: Returns `PN-RTM-3002` if `coreHash` doesn't match
182
- - Compares profile hash: Returns `PN-RTM-3002` if `profileHash` doesn't match (when present)
183
+ - Compares marker presence: Returns `PN-RUN-3001` if marker is missing
184
+ - Compares target compatibility: Returns `PN-RUN-3003` if contract target doesn't match config target
185
+ - Compares storage hash: Returns `PN-RUN-3002` if `storageHash` doesn't match
186
+ - Compares profile hash: Returns `PN-RUN-3002` if `profileHash` doesn't match (when present)
183
187
  - Checks codec coverage (optional): Compares contract column types against supported codec types and reports missing codecs
188
+ 5. **Verify Schema (default)**: Unless `--marker-only` is provided, calls `familyInstance.schemaVerify()` to catch schema mismatches such as missing tables or columns after manual DDL. By default this runs in tolerant mode; `--strict` treats schema elements not present in the contract as an error.
189
+ 6. **Schema-only mode**: `--schema-only` skips marker verification entirely and runs only `schemaVerify()`. This is useful for brownfield adoption and corrupt-marker diagnosis.
184
190
 
185
191
  **Output Format (TTY):**
186
192
 
187
193
  Success:
188
- ```
189
- ✔ Database matches contract
190
- coreHash: sha256:abc123...
194
+ ```text
195
+ ✔ Database marker and schema match contract
196
+ verification: marker + schema
197
+ storageHash: sha256:abc123...
191
198
  profileHash: sha256:def456...
192
199
  ```
193
200
 
194
- Failure:
201
+ Marker-only success:
202
+ ```text
203
+ ✔ Database marker matches contract
204
+ verification: marker only (--marker-only)
205
+ storageHash: sha256:abc123...
206
+ profileHash: sha256:def456...
207
+
208
+ ⚠ Schema verification skipped because --marker-only was provided
195
209
  ```
196
- ✖ Marker missing (PN-RTM-3001)
210
+
211
+ Marker failure:
212
+ ```text
213
+ ✖ Marker missing (PN-RUN-3001)
197
214
  Why: Contract marker not found in database
198
215
  Fix: Run `prisma-next db sign --db <url>` to create marker
199
216
  ```
200
217
 
218
+ Schema drift failure:
219
+ `db verify` prints the schema verification tree / JSON payload and exits with code 1.
220
+
201
221
  **Output Format (JSON):**
202
222
 
203
223
  ```json
204
224
  {
205
225
  "ok": true,
206
- "summary": "Database matches contract",
226
+ "summary": "Database marker and schema match contract",
227
+ "mode": "full",
207
228
  "contract": {
208
- "coreHash": "sha256:abc123...",
229
+ "storageHash": "sha256:abc123...",
209
230
  "profileHash": "sha256:def456..."
210
231
  },
211
232
  "marker": {
212
- "coreHash": "sha256:abc123...",
233
+ "storageHash": "sha256:abc123...",
213
234
  "profileHash": "sha256:def456..."
214
235
  },
215
236
  "target": {
216
237
  "expected": "postgres"
217
238
  },
218
239
  "missingCodecs": [],
240
+ "schema": {
241
+ "summary": "Database schema satisfies contract",
242
+ "counts": {
243
+ "pass": 12,
244
+ "warn": 0,
245
+ "fail": 0,
246
+ "totalNodes": 12
247
+ },
248
+ "strict": false
249
+ },
219
250
  "meta": {
220
251
  "configPath": "/path/to/prisma-next.config.ts",
221
- "contractPath": "/path/to/src/prisma/contract.json"
252
+ "contractPath": "/path/to/src/prisma/contract.json",
253
+ "schemaVerification": "performed"
222
254
  },
223
255
  "timings": {
224
256
  "total": 42
@@ -229,22 +261,27 @@ Failure:
229
261
  **Error Codes:**
230
262
 
231
263
  - `PN-CLI-4010`: Missing driver in config — provide a driver descriptor
232
- - `PN-RTM-3001`: Marker missing - Contract marker not found in database
233
- - `PN-RTM-3002`: Hash mismatch - Contract hash does not match database marker
234
- - `PN-RTM-3003`: Target mismatch - Contract target does not match config target
264
+ - `PN-RUN-3001`: Marker missing - Contract marker not found in database
265
+ - `PN-RUN-3002`: Hash mismatch - Contract hash does not match database marker
266
+ - `PN-RUN-3003`: Target mismatch - Contract target does not match config target
267
+ - Exit code 1 with schema verification payload: Schema does not match the contract (default mode or `--schema-only`)
235
268
 
236
269
  **Family Requirements:**
237
270
 
238
- The family must provide a `create()` method in the family descriptor that returns a `ControlFamilyInstance` with a `verify()` method:
271
+ The family must provide a `create()` method in the family descriptor that accepts a `ControlPlaneStack` and returns a `ControlFamilyInstance` with a `verify()` method:
239
272
 
240
273
  ```typescript
241
- interface ControlFamilyDescriptor {
242
- create(options: {
243
- target: ControlTargetDescriptor;
244
- adapter: ControlAdapterDescriptor;
245
- driver: ControlDriverDescriptor;
246
- extensions: ControlExtensionDescriptor[];
247
- }): ControlFamilyInstance;
274
+ interface ControlFamilyDescriptor<TFamilyId, TFamilyInstance> {
275
+ create<TTargetId extends string>(
276
+ stack: ControlPlaneStack<TFamilyId, TTargetId>,
277
+ ): TFamilyInstance;
278
+ }
279
+
280
+ interface ControlPlaneStack<TFamilyId, TTargetId> {
281
+ readonly target: ControlTargetDescriptor<TFamilyId, TTargetId>;
282
+ readonly adapter: ControlAdapterDescriptor<TFamilyId, TTargetId>;
283
+ readonly driver: ControlDriverDescriptor<TFamilyId, TTargetId> | undefined;
284
+ readonly extensionPacks: readonly ControlExtensionDescriptor<TFamilyId, TTargetId>[];
248
285
  }
249
286
 
250
287
  interface ControlFamilyInstance {
@@ -258,48 +295,89 @@ interface ControlFamilyInstance {
258
295
  }
259
296
  ```
260
297
 
261
- The SQL family provides this via `@prisma-next/family-sql/control`. The `verify()` method handles reading the marker, comparing hashes, and checking codec coverage internally.
298
+ Use `createControlPlaneStack()` from `@prisma-next/core-control-plane/stack` to create the stack with sensible defaults (`driver` defaults to `undefined`, `extensionPacks` defaults to `[]`).
262
299
 
263
- ### `prisma-next db introspect`
300
+ The SQL family provides this via `@prisma-next/family-sql/control`. The `verify()` method handles marker checks, full `db verify` follows it with `schemaVerify()`, `--marker-only` skips that schema step, and `--schema-only` runs `schemaVerify()` without marker checks.
264
301
 
265
- Inspect the live database schema and display it as a human-readable tree or machine-consumable JSON.
302
+ ### `prisma-next db schema`
303
+
304
+ Inspect the live database schema and display it as a human-readable tree or machine-consumable JSON. This command is read-only and never writes files.
266
305
 
267
306
  **Command:**
268
307
  ```bash
269
- prisma-next db introspect [--db <url>] [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
308
+ prisma-next db schema [--db <url>] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
270
309
  ```
271
310
 
272
311
  Options:
273
- - `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
312
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection` if set)
274
313
  - `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
275
314
  - `--json`: Output as JSON object
276
315
  - `-q, --quiet`: Quiet mode (errors only)
277
316
  - `-v, --verbose`: Verbose output (debug info, timings)
278
317
  - `-vv, --trace`: Trace output (deep internals, stack traces)
279
- - `--timestamps`: Add timestamps to output
280
318
  - `--color/--no-color`: Force/disable color output
281
319
 
282
320
  Examples:
283
321
  ```bash
284
322
  # Use config defaults
285
- prisma-next db introspect
323
+ prisma-next db schema
286
324
 
287
325
  # Specify database URL
288
- prisma-next db introspect --db postgresql://user:pass@localhost/db
326
+ prisma-next db schema --db postgresql://user:pass@localhost/db
289
327
 
290
328
  # JSON output
291
- prisma-next db introspect --json
329
+ prisma-next db schema --json
330
+
331
+ # Verbose output
332
+ prisma-next db schema -v
333
+ ```
334
+
335
+ ### `prisma-next contract infer`
336
+
337
+ Inspect the live database schema and write an inferred PSL contract to disk. Use this for brownfield adoption when you want a starting `contract.prisma` before running `contract emit` and `db sign`.
338
+
339
+ **Command:**
340
+ ```bash
341
+ prisma-next contract infer [--db <url>] [--config <path>] [--output <path>] [--json] [-v] [-q] [--color/--no-color]
342
+ ```
343
+
344
+ Options:
345
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection` if set)
346
+ - `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
347
+ - `--output <path>`: Write the inferred PSL contract to the specified path
348
+ - `--json`: Output a JSON result envelope (includes `psl.path`)
349
+ - `-q, --quiet`: Quiet mode (errors only)
350
+ - `-v, --verbose`: Verbose output (debug info, timings)
351
+ - `-vv, --trace`: Trace output (deep internals, stack traces)
352
+ - `--color/--no-color`: Force/disable color output
353
+
354
+ Examples:
355
+ ```bash
356
+ # Infer contract.prisma next to the configured contract.json output
357
+ prisma-next contract infer
358
+
359
+ # Specify database URL
360
+ prisma-next contract infer --db postgresql://user:pass@localhost/db
361
+
362
+ # Override the output path
363
+ prisma-next contract infer --output ./prisma/contract.prisma
292
364
 
293
- # Verbose output with timestamps
294
- prisma-next db introspect -v --timestamps
365
+ # JSON output
366
+ prisma-next contract infer --json
295
367
  ```
296
368
 
369
+ By default, `contract infer` writes to:
370
+ 1. `--output <path>`, if provided
371
+ 2. `contract.prisma` next to `config.contract.output`
372
+ 3. `contract.prisma` in the current working directory
373
+
297
374
  **Config File Requirements:**
298
375
 
299
- The `db introspect` command requires a `driver` in the config to connect to the database:
376
+ Both `db schema` and `contract infer` require a `driver` in the config to connect to the database:
300
377
 
301
378
  ```typescript
302
379
  import { defineConfig } from '@prisma-next/cli/config-types';
380
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
303
381
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
304
382
  import postgresDriver from '@prisma-next/driver-postgres/control';
305
383
  import postgres from '@prisma-next/target-postgres/control';
@@ -312,7 +390,7 @@ export default defineConfig({
312
390
  driver: postgresDriver,
313
391
  extensionPacks: [],
314
392
  db: {
315
- url: process.env.DATABASE_URL, // Optional: can also use --db flag
393
+ connection: process.env.DATABASE_URL, // Optional: can also use --db flag
316
394
  },
317
395
  });
318
396
  ```
@@ -320,7 +398,7 @@ export default defineConfig({
320
398
  **Introspection Process:**
321
399
 
322
400
  1. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
323
- 2. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`) to create a family instance
401
+ 2. **Create Family Instance**: Creates a `ControlPlaneStack` via `createControlPlaneStack()` and passes it to `config.family.create(stack)` to create a family instance
324
402
  3. **Introspect**: Calls `familyInstance.introspect()` which:
325
403
  - Queries the database catalog to discover schema structure
326
404
  - Returns a family-specific schema IR (e.g., `SqlSchemaIR` for SQL family)
@@ -387,7 +465,7 @@ sql schema (tables: 2)
387
465
 
388
466
  **Error Codes:**
389
467
  - `PN-CLI-4010`: Missing driver in config — provide a driver descriptor
390
- - `PN-CLI-4005`: Missing database URL — provide `--db <url>` or set `db.url` in config
468
+ - `PN-CLI-4005`: Missing database connection — provide `--db <url>` or set `db.connection` in config
391
469
 
392
470
  **Family Requirements:**
393
471
 
@@ -417,17 +495,16 @@ Mark the database as matching the emitted contract by writing or updating the co
417
495
 
418
496
  **Command:**
419
497
  ```bash
420
- prisma-next db sign [--db <url>] [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
498
+ prisma-next db sign [--db <url>] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
421
499
  ```
422
500
 
423
501
  Options:
424
- - `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
502
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection` if set)
425
503
  - `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
426
504
  - `--json`: Output as JSON object
427
505
  - `-q, --quiet`: Quiet mode (errors only)
428
506
  - `-v, --verbose`: Verbose output (debug info, timings)
429
507
  - `-vv, --trace`: Trace output (deep internals, stack traces)
430
- - `--timestamps`: Add timestamps to output
431
508
  - `--color/--no-color`: Force/disable color output
432
509
 
433
510
  Examples:
@@ -441,8 +518,8 @@ prisma-next db sign --db postgresql://user:pass@localhost/db
441
518
  # JSON output
442
519
  prisma-next db sign --json
443
520
 
444
- # Verbose output with timestamps
445
- prisma-next db sign -v --timestamps
521
+ # Verbose output
522
+ prisma-next db sign -v
446
523
  ```
447
524
 
448
525
  **Config File Requirements:**
@@ -463,13 +540,9 @@ export default defineConfig({
463
540
  adapter: postgresAdapter,
464
541
  driver: postgresDriver,
465
542
  extensionPacks: [],
466
- contract: {
467
- source: contract,
468
- output: 'src/prisma/contract.json',
469
- types: 'src/prisma/contract.d.ts',
470
- },
543
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
471
544
  db: {
472
- url: process.env.DATABASE_URL, // Optional: can also use --db flag
545
+ connection: process.env.DATABASE_URL, // Optional: can also use --db flag
473
546
  },
474
547
  });
475
548
  ```
@@ -478,7 +551,7 @@ export default defineConfig({
478
551
 
479
552
  1. **Load Contract**: Reads the emitted `contract.json` from `config.contract.output`
480
553
  2. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
481
- 3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`) to create a family instance
554
+ 3. **Create Family Instance**: Creates a `ControlPlaneStack` via `createControlPlaneStack()` and passes it to `config.family.create(stack)` to create a family instance
482
555
  4. **Schema Verification (Precondition)**: Calls `familyInstance.schemaVerify()` to verify the database schema matches the contract:
483
556
  - If verification fails: Prints schema verification output and exits with code 1 (marker is not written)
484
557
  - If verification passes: Proceeds to marker signing
@@ -495,7 +568,7 @@ export default defineConfig({
495
568
  Success (new marker):
496
569
  ```
497
570
  ✔ Database signed (marker created)
498
- coreHash: sha256:abc123...
571
+ storageHash: sha256:abc123...
499
572
  profileHash: sha256:def456...
500
573
  Total time: 42ms
501
574
  ```
@@ -503,16 +576,16 @@ Success (new marker):
503
576
  Success (updated marker):
504
577
  ```
505
578
  ✔ Database signed (marker updated from sha256:old-hash)
506
- coreHash: sha256:abc123...
579
+ storageHash: sha256:abc123...
507
580
  profileHash: sha256:def456...
508
- previous coreHash: sha256:old-hash
581
+ previous storageHash: sha256:old-hash
509
582
  Total time: 42ms
510
583
  ```
511
584
 
512
585
  Success (already up-to-date):
513
586
  ```
514
587
  ✔ Database already signed with this contract
515
- coreHash: sha256:abc123...
588
+ storageHash: sha256:abc123...
516
589
  profileHash: sha256:def456...
517
590
  Total time: 42ms
518
591
  ```
@@ -530,7 +603,7 @@ Failure (schema mismatch):
530
603
  "ok": true,
531
604
  "summary": "Database signed (marker created)",
532
605
  "contract": {
533
- "coreHash": "sha256:abc123...",
606
+ "storageHash": "sha256:abc123...",
534
607
  "profileHash": "sha256:def456..."
535
608
  },
536
609
  "target": {
@@ -557,7 +630,7 @@ For updated markers:
557
630
  "ok": true,
558
631
  "summary": "Database signed (marker updated from sha256:old-hash)",
559
632
  "contract": {
560
- "coreHash": "sha256:abc123...",
633
+ "storageHash": "sha256:abc123...",
561
634
  "profileHash": "sha256:def456..."
562
635
  },
563
636
  "target": {
@@ -568,7 +641,7 @@ For updated markers:
568
641
  "created": false,
569
642
  "updated": true,
570
643
  "previous": {
571
- "coreHash": "sha256:old-hash",
644
+ "storageHash": "sha256:old-hash",
572
645
  "profileHash": "sha256:old-profile-hash"
573
646
  }
574
647
  },
@@ -584,12 +657,11 @@ For updated markers:
584
657
 
585
658
  **Error Codes:**
586
659
  - `PN-CLI-4010`: Missing driver in config — provide a driver descriptor
587
- - `PN-CLI-4005`: Missing database URL — provide `--db <url>` or set `db.url` in config
660
+ - `PN-CLI-4005`: Missing database connection — provide `--db <url>` or set `db.connection` in config
588
661
  - Exit code 1: Schema verification failed — database schema does not match contract (marker is not written)
589
662
 
590
663
  **Relationship to Other Commands:**
591
- - **`db schema-verify`**: `db sign` calls `schemaVerify` as a precondition before writing the marker. If schema verification fails, `db sign` exits without writing the marker.
592
- - **`db verify`**: `db verify` checks that the marker exists and matches the contract. `db sign` writes the marker that `db verify` checks.
664
+ - **`db verify`**: `db verify` checks that the marker exists and matches the contract, then runs schema verification by default. `db sign` writes the marker that `db verify` checks. Use `db verify --marker-only` for marker-only verification and `db verify --schema-only` to inspect only the live schema.
593
665
 
594
666
  **Idempotency:**
595
667
  The `db sign` command is idempotent and safe to run multiple times:
@@ -627,18 +699,17 @@ Initialize a database schema from the contract. This command plans and applies *
627
699
 
628
700
  **Command:**
629
701
  ```bash
630
- prisma-next db init [--db <url>] [--config <path>] [--plan] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
702
+ prisma-next db init [--db <url>] [--config <path>] [--dry-run] [--json] [-v] [-q] [--color/--no-color]
631
703
  ```
632
704
 
633
705
  Options:
634
- - `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
706
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection` if set)
635
707
  - `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
636
- - `--plan`: Only show the migration plan, do not apply it
708
+ - `--dry-run`: Only show the migration plan, do not apply it
637
709
  - `--json [format]`: Output as JSON (`object` only; `ndjson` is not supported for this command)
638
710
  - `-q, --quiet`: Quiet mode (errors only)
639
711
  - `-v, --verbose`: Verbose output (debug info, timings)
640
712
  - `-vv, --trace`: Trace output (deep internals, stack traces)
641
- - `--timestamps`: Add timestamps to output
642
713
  - `--color/--no-color`: Force/disable color output
643
714
 
644
715
  Examples:
@@ -647,7 +718,7 @@ Examples:
647
718
  prisma-next db init
648
719
 
649
720
  # Preview migration plan without applying
650
- prisma-next db init --plan
721
+ prisma-next db init --dry-run
651
722
 
652
723
  # Specify database URL
653
724
  prisma-next db init --db postgresql://user:pass@localhost/db
@@ -662,6 +733,7 @@ The `db init` command requires a `driver` in the config to connect to the databa
662
733
 
663
734
  ```typescript
664
735
  import { defineConfig } from '@prisma-next/cli/config-types';
736
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
665
737
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
666
738
  import postgresDriver from '@prisma-next/driver-postgres/control';
667
739
  import postgres from '@prisma-next/target-postgres/control';
@@ -674,13 +746,9 @@ export default defineConfig({
674
746
  adapter: postgresAdapter,
675
747
  driver: postgresDriver,
676
748
  extensionPacks: [],
677
- contract: {
678
- source: contract,
679
- output: 'src/prisma/contract.json',
680
- types: 'src/prisma/contract.d.ts',
681
- },
749
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
682
750
  db: {
683
- url: process.env.DATABASE_URL, // Optional: can also use --db flag
751
+ connection: process.env.DATABASE_URL, // Optional: can also use --db flag
684
752
  },
685
753
  });
686
754
  ```
@@ -689,7 +757,7 @@ export default defineConfig({
689
757
 
690
758
  1. **Load Contract**: Reads the emitted `contract.json` from `config.contract.output`
691
759
  2. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
692
- 3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`)
760
+ 3. **Create Family Instance**: Creates a `ControlPlaneStack` via `createControlPlaneStack()` and passes it to `config.family.create(stack)` to create a family instance
693
761
  4. **Introspect Schema**: Calls `familyInstance.introspect()` to get the current database schema IR
694
762
  5. **Validate wiring**: Ensures the contract is compatible with the CLI config:
695
763
  - `contract.targetFamily` matches `config.family.familyId`
@@ -699,7 +767,7 @@ export default defineConfig({
699
767
  7. **Plan Migration**: Calls `planner.plan()` with the contract IR, schema IR, additive-only policy, and `frameworkComponents` (the active target/adapter/extension descriptors)
700
768
  - On conflict: Returns a structured failure with conflict list
701
769
  - On success: Returns a migration plan with operations
702
- 8. **Apply Migration** (if not `--plan`):
770
+ 8. **Apply Migration** (if not `--dry-run`):
703
771
  - Calls `runner.execute()` to apply the plan
704
772
  - After execution, verifies schema matches contract
705
773
  - Writes contract marker (and records a ledger entry via the target runner)
@@ -722,7 +790,7 @@ prisma-next db init ➜ Bootstrap a database to match the current contract
722
790
  Destination hash: sha256:abc123...
723
791
 
724
792
  This is a dry run. No changes were applied.
725
- Run without --plan to apply changes.
793
+ Run without --dry-run to apply changes.
726
794
  ```
727
795
 
728
796
  **Output Format (TTY - Apply Mode):**
@@ -750,7 +818,7 @@ Applying migration plan and verifying schema...
750
818
  "plan": {
751
819
  "targetId": "postgres",
752
820
  "destination": {
753
- "coreHash": "sha256:abc123..."
821
+ "storageHash": "sha256:abc123..."
754
822
  },
755
823
  "operations": [
756
824
  {
@@ -765,7 +833,7 @@ Applying migration plan and verifying schema...
765
833
  "operationsExecuted": 4
766
834
  },
767
835
  "marker": {
768
- "coreHash": "sha256:abc123..."
836
+ "storageHash": "sha256:abc123..."
769
837
  }
770
838
  }
771
839
  ```
@@ -777,12 +845,33 @@ Applying migration plan and verifying schema...
777
845
  - `PN-CLI-4010`: Missing driver in config
778
846
  - `PN-CLI-4020`: Migration planning failed (conflicts)
779
847
  - `PN-CLI-4021`: Target does not support migrations
780
- - `PN-RTM-3000`: Runtime error (includes marker mismatch failures)
848
+ - `PN-RUN-3000`: Runtime error (includes marker mismatch failures)
781
849
 
782
850
  **Behavior Notes:**
783
851
 
784
852
  - If the database already has a marker that matches the destination contract, `db init` succeeds as a noop (0 operations planned/executed).
785
- - If the database has a marker that does **not** match the destination contract, `db init` fails (including in `--plan` mode). Use `db init` for bootstrapping; use your migration workflow to reconcile existing databases.
853
+ - If the database has a marker that does **not** match the destination contract, `db init` fails (including in `--dry-run` mode). Use `db init` for bootstrapping; use your migration workflow to reconcile existing databases.
854
+
855
+ ### `prisma-next db update`
856
+
857
+ Update your database schema to match the currently emitted contract.
858
+
859
+ `db update` differs from `db init`:
860
+
861
+ - Works on any database, whether or not it has been initialized with `db init` (creates the signature table if missing)
862
+ - Allows `additive`, `widening`, and `destructive` operation classes where supported by planner/runner
863
+ - Disables per-operation runner execution checks by default (precheck/postcheck/idempotency)
864
+ - In `--dry-run` mode for SQL targets, prints a DDL preview derived from planned operations
865
+ - In interactive mode, destructive plans require confirmation before apply
866
+ - In non-interactive mode, destructive plans fail unless `-y, --yes` is provided
867
+
868
+ **Command:**
869
+ ```bash
870
+ prisma-next db update [--db <url>] [--config <path>] [--dry-run] [-y|--yes] [--interactive|--no-interactive] [--json] [-v] [-q] [--color/--no-color]
871
+ ```
872
+
873
+ **Error codes (additional to shared CLI/runtime codes):**
874
+ - `RUNNER_FAILED`: runner rejected apply (origin mismatch, failed checks, policy failures, or execution errors)
786
875
 
787
876
  **Config File (`prisma-next.config.ts`):**
788
877
 
@@ -797,6 +886,7 @@ The CLI uses a config file to specify the target family, target, adapter, extens
797
886
 
798
887
  ```typescript
799
888
  import { defineConfig } from '@prisma-next/cli/config-types';
889
+ import { typescriptContract } from '@prisma-next/sql-contract-ts/config-types';
800
890
  import postgresAdapter from '@prisma-next/adapter-postgres/control';
801
891
  import postgres from '@prisma-next/target-postgres/control';
802
892
  import sql from '@prisma-next/family-sql/control';
@@ -807,42 +897,192 @@ export default defineConfig({
807
897
  target: postgres,
808
898
  adapter: postgresAdapter,
809
899
  extensionPacks: [],
810
- contract: {
811
- source: contract, // Can be a value or a function: () => import('./contract').then(m => m.contract)
812
- output: 'src/prisma/contract.json', // Optional: defaults to 'src/prisma/contract.json'
813
- types: 'src/prisma/contract.d.ts', // Optional: defaults to output with .d.ts extension
814
- },
900
+ contract: typescriptContract(contract, 'src/prisma/contract.json'),
815
901
  });
816
902
  ```
817
903
 
818
- The `contract.source` field can be:
819
- - A direct value: `source: contract`
820
- - A synchronous function: `source: () => contract`
821
- - An asynchronous function: `source: () => import('./contract').then(m => m.contract)`
904
+ Prefer helper utilities for authoring mode selection:
905
+ - `typescriptContract(contractIR, outputPath?)` from `@prisma-next/sql-contract-ts/config-types` for TS-authored contracts
906
+ - `prismaContract(schemaPath, { output?, target? })` from `@prisma-next/sql-contract-psl/provider` for PSL-authored providers
907
+ - Provider failures are returned as structured diagnostics for CLI rendering
822
908
 
823
909
  The `contract.output` field specifies the path to `contract.json`. This is the canonical location where other CLI commands can find the contract JSON artifact. Defaults to `'src/prisma/contract.json'` if not specified.
824
910
 
825
- The `contract.types` field specifies the path to `contract.d.ts`. Defaults to `output` with `.d.ts` extension (replaces `.json` with `.d.ts` if output ends with `.json`, otherwise appends `contract.d.ts` to the directory containing output).
911
+ `contract.d.ts` is always colocated with `contract.json` and derived from `contract.output` (`contract.json` `contract.d.ts`).
826
912
 
827
913
  **Output:**
828
914
  - `contract.json`: Includes `_generated` metadata field indicating it's a generated artifact (excluded from canonicalization/hashing)
829
915
  - `contract.d.ts`: Includes warning header comments indicating it's a generated file
830
916
 
917
+ ### `prisma-next migration plan`
918
+
919
+ Plan a migration from contract changes. Compares the emitted contract against the latest on-disk migration state and produces a new migration package with the required operations. No database connection is needed — fully offline.
920
+
921
+ ```bash
922
+ prisma-next migration plan [--config <path>] [--name <slug>] [--from <hash>] [--json] [-v] [-q] [--color/--no-color]
923
+ ```
924
+
925
+ **Options:**
926
+ - `--config <path>`: Path to `prisma-next.config.ts`
927
+ - `--name <slug>`: Name slug for the migration directory (default: `migration`)
928
+ - `--from <hash>`: Explicit starting contract hash (overrides latest migration target detection)
929
+ - `--json`: Output as JSON object
930
+ - `-q, --quiet`: Quiet mode (errors only)
931
+ - `-v, --verbose`: Verbose output (debug info, timings)
932
+
933
+ **What it does:**
934
+ 1. Loads config and reads `contract.json` (the "to" contract)
935
+ 2. Reads existing migrations from `config.migrations.dir` (default: `migrations/`)
936
+ 3. Determines the starting point: `--from <hash>` if provided, otherwise the latest migration target
937
+ 4. Diffs the starting contract against the new contract using the target's migration planner
938
+ 5. Writes a new migration package (`migration.json` + `ops.json`) and attests the `migrationId`
939
+
940
+ **Branching with `--from`:** Use `--from` to create a migration edge from a specific contract hash instead of the latest migration target. This enables branched migration graphs where multiple environments diverge from a common ancestor.
941
+
942
+ ### `prisma-next migration show`
943
+
944
+ Display a migration package's operations, DDL preview, and metadata. Accepts a directory path, a hash prefix (git-style matching against `migrationId`), or defaults to the latest migration.
945
+
946
+ ```bash
947
+ prisma-next migration show [target] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
948
+ ```
949
+
950
+ **Options:**
951
+ - `[target]`: Migration directory path or migrationId hash prefix (defaults to latest)
952
+ - `--config <path>`: Path to `prisma-next.config.ts`
953
+ - `--json`: Output as JSON object
954
+ - `-q, --quiet`: Quiet mode (errors only)
955
+ - `-v, --verbose`: Verbose output
956
+
957
+ **What it does:**
958
+ 1. If `target` is a path (contains `/` or `\`), reads that directory directly
959
+ 2. If `target` is a hash prefix, scans all attested migrations and matches against `migrationId`
960
+ 3. If no target, defaults to the latest migration
961
+ 4. Displays operations with operation class badges, destructive warnings, and DDL preview
962
+
963
+ **Destructive warnings:** When a migration contains destructive operations (e.g., `DROP TABLE`, `ALTER COLUMN TYPE`), the output includes a prominent `⚠` warning about potential data loss.
964
+
965
+ ### `prisma-next migration status`
966
+
967
+ Show the migration graph and applied status. Adapts based on context:
968
+
969
+ - **With DB connection**: Shows applied/pending markers and "you are here" indicators
970
+ - **Without DB connection**: Shows the graph structure from disk only
971
+ - **With `--ref`**: Targets a specific ref instead of the contract hash; all refs from `refs.json` are rendered on the graph
972
+
973
+ ```bash
974
+ prisma-next migration status [--db <url>] [--ref <name>] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
975
+ ```
976
+
977
+ **Options:**
978
+ - `--db <url>`: Database connection string (enables online mode)
979
+ - `--ref <name>`: Target a named ref from `migrations/refs.json` instead of the current contract hash
980
+ - `--config <path>`: Path to `prisma-next.config.ts`
981
+ - `--json`: Output as JSON object
982
+ - `-q, --quiet`: Quiet mode (errors only)
983
+ - `-v, --verbose`: Verbose output
984
+
985
+ **What it does:**
986
+ 1. Reads migration packages from disk and reconstructs the migration graph
987
+ 2. Loads all refs from `migrations/refs.json` (if present) and renders them on the graph
988
+ 3. If `--ref` is provided, uses the ref's hash as the target instead of the contract hash; the active ref is highlighted in bold, other refs are dimmed
989
+ 4. If a DB connection is available, reads the marker to determine applied/pending status and shows distance from the ref target (e.g., "2 edge(s) behind ref")
990
+ 5. Displays the graph with `◄ DB`, `◄ Contract`, and `◄ ref:<name>` markers
991
+ 6. Shows operation summaries with destructive operation highlighting
992
+ 7. In `--ref` mode, the `CONTRACT.AHEAD` warning is suppressed — contract being ahead of a ref target is expected in multi-environment workflows
993
+
994
+ **Branched graphs:** When the migration graph has multiple branches (divergence), status reports an `AMBIGUOUS_TARGET` error with the divergence point and branch details. Use `--ref` to target a specific branch.
995
+
996
+ ### `prisma-next migration apply`
997
+
998
+ Apply planned migrations to the database. Executes previously planned migrations (created by `migration plan`). Compares the database marker against the migration graph to determine which migrations are pending, then executes them sequentially. Each migration runs in its own transaction. Does not plan new migrations — run `migration plan` first.
999
+
1000
+ ```bash
1001
+ prisma-next migration apply [--db <url>] [--ref <name>] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
1002
+ ```
1003
+
1004
+ **Options:**
1005
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection`)
1006
+ - `--ref <name>`: Target a named ref from `migrations/refs.json` instead of the current contract hash
1007
+ - `--config <path>`: Path to `prisma-next.config.ts`
1008
+ - `--json`: Output as JSON object
1009
+ - `-q, --quiet`: Quiet mode (errors only)
1010
+ - `-v, --verbose`: Verbose output (debug info, timings)
1011
+
1012
+ **What it does:**
1013
+ 1. Reads attested migration packages from `config.migrations.dir`
1014
+ 2. Reconstructs the migration graph (skips drafts with `migrationId: null`)
1015
+ 3. Determines the destination hash: from `--ref` (via `refs.json`) or from `contract.json`
1016
+ 4. Connects to the database and reads the current marker hash
1017
+ 5. Finds the shortest path from the marker hash to the destination using graph pathfinding
1018
+ 6. Executes each pending migration in order using the target's `MigrationRunner`
1019
+ 7. Each migration runs in its own transaction with prechecks, postchecks, and idempotency checks enabled
1020
+ 8. After each migration, the runner verifies the schema and updates the marker/ledger
1021
+
1022
+ **Config requirements:** Requires `driver` and `db.connection` (or `--db`). `migrations.dir` is optional and defaults to `migrations/`.
1023
+
1024
+ **Resume semantics:** If a migration fails, previously applied migrations are preserved. Re-running `migration apply` resumes from the last successful migration.
1025
+
1026
+ **Ref-based routing:** With `--ref`, apply targets the ref's hash instead of the contract hash. This enables multi-environment workflows where staging and production track different points in the migration graph.
1027
+
1028
+ ### `prisma-next migration verify`
1029
+
1030
+ Verify a migration package's integrity by recomputing the content-addressed `migrationId`.
1031
+
1032
+ ```bash
1033
+ prisma-next migration verify --dir <path>
1034
+ ```
1035
+
1036
+ - **Verified**: stored `migrationId` matches recomputed value
1037
+ - **Draft**: `migrationId` is null — automatically attests the package
1038
+ - **Mismatch**: package has been modified since attestation (command exits non-zero)
1039
+
1040
+ ### `prisma-next migration ref`
1041
+
1042
+ Manage named refs in `migrations/refs.json`. Refs map logical environment names (e.g., `staging`, `production`) to contract hashes, enabling multi-environment migration workflows where different environments track different points in the migration graph.
1043
+
1044
+ ```bash
1045
+ prisma-next migration ref set <name> <hash> # Set a ref to a contract hash
1046
+ prisma-next migration ref get <name> # Get the hash for a ref
1047
+ prisma-next migration ref delete <name> # Delete a ref
1048
+ prisma-next migration ref list # List all refs
1049
+ ```
1050
+
1051
+ **Options (all subcommands):**
1052
+ - `--config <path>`: Path to `prisma-next.config.ts`
1053
+ - `--json`: Output as JSON object
1054
+ - `-q, --quiet`: Quiet mode (errors only)
1055
+
1056
+ **Ref naming rules:** Lowercase alphanumeric with hyphens or forward slashes (e.g., `staging`, `prod/us-east`). No `.` or `..` segments.
1057
+
1058
+ **Ref values:** Must be valid contract hashes (`sha256:<64 hex chars>` or `sha256:empty`).
1059
+
1060
+ **Atomic writes:** `refs.json` is written atomically via temp file + rename to prevent corruption from concurrent writes.
1061
+
831
1062
  ## Architecture
832
1063
 
833
1064
  ```mermaid
834
1065
  flowchart TD
835
1066
  CLI[CLI Entry Point]
836
- CMD[Emit Command]
1067
+ CMD_EMIT[Emit Command]
1068
+ CMD_DB[DB Commands]
1069
+ CMD_MIG[Migration Commands]
837
1070
  LOAD[TS Contract Loader]
838
1071
  EMIT[Emitter]
1072
+ CTRL[Control Client]
1073
+ MIG_TOOLS["@prisma-next/migration-tools"]
839
1074
  FS[File System]
840
1075
 
841
- CLI --> CMD
842
- CMD --> LOAD
1076
+ CLI --> CMD_EMIT
1077
+ CLI --> CMD_DB
1078
+ CLI --> CMD_MIG
1079
+ CMD_EMIT --> LOAD
843
1080
  LOAD --> EMIT
844
- EMIT --> CMD
845
- CMD --> FS
1081
+ CMD_DB --> CTRL
1082
+ CMD_MIG --> CTRL
1083
+ CMD_MIG --> MIG_TOOLS
1084
+ MIG_TOOLS --> FS
1085
+ CTRL --> FS
846
1086
  ```
847
1087
 
848
1088
  ## Config Validation and Normalization
@@ -864,19 +1104,20 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern
864
1104
  - Exit codes: 0 (success), 1 (runtime error), 2 (usage/config error)
865
1105
  - **Error Handling**: Uses `exitOverride()` to catch unhandled errors (non-structured errors that fail fast) and print stack traces. Commands handle structured errors themselves via `process.exit()`.
866
1106
  - **Command Taxonomy**: Groups commands by domain/plane (e.g., `contract emit`)
867
- - **Help Formatting**: Uses `configureHelp()` to customize help output with styled format matching normal command output. Root help shows "prisma-next" title with command tree; command help shows "prisma-next <command> ➜ <description>" with options and docs URLs. See `utils/output.ts` for help formatters.
1107
+ - **Help Formatting**: Uses `configureHelp()` to customize help output with styled format matching normal command output. Root help shows "prisma-next" title with command tree; command help shows "prisma-next <command> ➜ <description>" with options and docs URLs. See `utils/formatters/help.ts` for help formatters.
868
1108
  - **Command Descriptions**: See the “Command Descriptions” section above for `setCommandDescriptions()` usage.
869
1109
 
870
1110
  ### Contract Emit Command (`commands/contract-emit.ts`)
871
1111
  - Canonical command implementation using commander
872
- - Supports global flags (JSON, verbosity, color, timestamps)
873
- - **Error Handling**: Uses structured errors (`CliStructuredError`), Result pattern (`performAction`), and `process.exit()`. Commands wrap logic in `performAction()`, process results with `handleResult()`, and call `process.exit(exitCode)` directly. See `.cursor/rules/cli-error-handling.mdc` for details.
1112
+ - Supports global flags (JSON, verbosity, color, interactive, yes)
1113
+ - **Error Handling**: Uses structured errors (`CliStructuredError`), Result pattern, and `process.exit()`. Commands return `Result<T, CliStructuredError>`, process results with `handleResult()`, and call `process.exit(exitCode)` directly. See `.cursor/rules/cli-error-handling.mdc` for details.
874
1114
  - Loads the user's config module (`prisma-next.config.ts`)
875
- - Resolves contract from config:
876
- - Uses `config.contract.source` (supports sync and async functions)
877
- - User's config is responsible for loading the contract (can use `loadContractFromTs` or any other method)
1115
+ - Resolves contract from provider:
1116
+ - Calls `config.contract.source()` and expects `Result<ContractIR, Diagnostics>`
1117
+ - Source-specific parsing/loading stays inside providers
1118
+ - Provider diagnostics are surfaced as actionable CLI failures
878
1119
  - Throws error if `config.contract` is missing
879
- - Uses artifact paths from `config.contract.output/types` (already normalized by `defineConfig()` with defaults applied)
1120
+ - Uses artifact path from `config.contract.output` (already normalized by `defineConfig()` with defaults applied)
880
1121
  - Creates family instance via `config.family.create()` (assembles operation registry, type imports, extension IDs)
881
1122
  - Calls `familyInstance.emitContract()` with raw contract (instance handles stripping mappings and validation internally)
882
1123
  - Outputs human-readable or JSON format based on flags
@@ -890,12 +1131,12 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern
890
1131
 
891
1132
  ### Error Handling (`utils/errors.ts`, `utils/cli-errors.ts`, `utils/result.ts`, `utils/result-handler.ts`)
892
1133
  - **Structured Errors**: Call sites throw `CliStructuredError` instances with full context (why, fix, docsUrl, etc.)
893
- - **Result Pattern**: Commands wrap logic in `performAction()` which only catches `CliStructuredError` instances
1134
+ - **Result Pattern**: Commands return `Result<T, CliStructuredError>` and use `handleResult()` for output and exit codes
894
1135
  - **Error Conversion**: `CliStructuredError.toEnvelope()` converts errors to envelopes for output formatting
895
1136
  - **Result Processing**: `handleResult()` processes Results, formats output, and returns exit codes
896
1137
  - **Exit Codes**:
897
1138
  - Usage/config errors (PN-CLI-4001-4007) → exit code 2
898
- - Runtime errors (PN-RTM-3xxx) → exit code 1
1139
+ - Runtime errors (PN-RUN-3xxx) → exit code 1
899
1140
  - Success → exit code 0
900
1141
  - **Fail Fast**: Non-structured errors propagate and are caught by Commander.js's `exitOverride()` with stack traces
901
1142
  - See `.cursor/rules/cli-error-handling.mdc` for detailed patterns
@@ -905,7 +1146,7 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern
905
1146
  - **Removed**: `pack-assembly.ts` has been removed. Pack assembly is now handled by family instances. For SQL family, tests can import pack-based helpers directly from `packages/2-sql/3-tooling/family/src/core/assembly.ts` using relative paths.
906
1147
  - Assembly logic is family-specific and owned by each family's instance implementation (e.g., `createSqlFamilyInstance` in `@prisma-next/family-sql`).
907
1148
 
908
- ### Output Formatting (`utils/output.ts`)
1149
+ ### Output Formatting (`utils/formatters/`)
909
1150
  - **Command Output Formatters**: Format human-readable output for commands (emit, verify, etc.)
910
1151
  - Paths are shown as relative paths from current working directory (using `relative(process.cwd(), path)`)
911
1152
  - Success indicators use consistent checkmark (✔) throughout
@@ -947,7 +1188,7 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern
947
1188
  - `types.storage`: Storage type bindings (`typeId`, `nativeType`, etc.) used in authoring/emission.
948
1189
  - **`operations`**: Operation signatures the component contributes (extensions), used for type generation and (optionally) validation/lowering.
949
1190
  - **Component-specific metadata**:
950
- - Extensions may also include control-plane-only metadata like `databaseDependencies` (used by verify/schema-verify and not required at runtime).
1191
+ - Extensions may also include control-plane-only metadata like `databaseDependencies` (used by verify and schema verification flows and not required at runtime).
951
1192
 
952
1193
  Unlike the older **manifest-based IR** approach (separate JSON manifests + a parsing/validation step to build an IR), descriptors are imported directly from packages (e.g., `@prisma-next/*/control`). This removes a file-format boundary and keeps the data and its types co-located.
953
1194
  - Benefits: fewer moving parts (no JSON parsing), easier refactors (TypeScript catches drift), and clearer ownership (the package exports the canonical descriptor object).
@@ -999,6 +1240,8 @@ export default defineConfig({
999
1240
  - **`commander`**: CLI argument parsing and command routing
1000
1241
  - **`esbuild`**: Bundling TypeScript contract files with import allowlisting
1001
1242
  - **`@prisma-next/emitter`**: Contract emission engine (returns strings)
1243
+ - **`@prisma-next/migration-tools`**: On-disk migration I/O, attestation, and history reconstruction
1244
+ - **`@prisma-next/core-control-plane`**: Config types, migration operation types, error types, control plane stack
1002
1245
 
1003
1246
  ## Design Decisions
1004
1247
 
@@ -1058,18 +1301,111 @@ pnpm test:integration # Run integration tests only
1058
1301
  pnpm test:e2e # Run e2e tests only
1059
1302
  ```
1060
1303
 
1304
+ ## Programmatic Control API
1305
+
1306
+ The CLI package provides a programmatic control client for running control-plane operations without using the command line. This is useful for:
1307
+
1308
+ - Integration with build tools and CI pipelines
1309
+ - Custom orchestration workflows
1310
+ - Test automation
1311
+ - Programmatic database management
1312
+
1313
+ ### Basic Usage
1314
+
1315
+ ```typescript
1316
+ import { createControlClient } from '@prisma-next/cli/control-api';
1317
+ import sql from '@prisma-next/family-sql/control';
1318
+ import postgres from '@prisma-next/target-postgres/control';
1319
+ import postgresAdapter from '@prisma-next/adapter-postgres/control';
1320
+ import postgresDriver from '@prisma-next/driver-postgres/control';
1321
+
1322
+ // Create a control client with framework component descriptors
1323
+ const client = createControlClient({
1324
+ family: sql,
1325
+ target: postgres,
1326
+ adapter: postgresAdapter,
1327
+ driver: postgresDriver,
1328
+ extensionPacks: [],
1329
+ });
1330
+
1331
+ try {
1332
+ // Connect to database
1333
+ await client.connect(databaseUrl);
1334
+
1335
+ // Run operations
1336
+ const verifyResult = await client.verify({ contractIR });
1337
+ const initResult = await client.dbInit({ contractIR, mode: 'apply' });
1338
+ const updateResult = await client.dbUpdate({ contractIR, mode: 'apply' });
1339
+ const introspectResult = await client.introspect();
1340
+ } finally {
1341
+ // Clean up
1342
+ await client.close();
1343
+ }
1344
+ ```
1345
+
1346
+ ### Available Operations
1347
+
1348
+ | Method | Description |
1349
+ |--------|-------------|
1350
+ | `connect(url)` | Establishes database connection |
1351
+ | `close()` | Closes connection (idempotent) |
1352
+ | `readMarker()` | Reads contract marker from database (null if none) |
1353
+ | `verify(options)` | Verifies database marker matches contract |
1354
+ | `schemaVerify(options)` | Verifies database schema satisfies contract |
1355
+ | `sign(options)` | Writes contract marker to database |
1356
+ | `dbInit(options)` | Initializes database schema from contract |
1357
+ | `dbUpdate(options)` | Updates database schema to match contract |
1358
+ | `migrationApply(options)` | Applies pre-planned migration edges to database |
1359
+ | `introspect(options)` | Introspects database schema |
1360
+
1361
+ ### Result Types
1362
+
1363
+ Operations return structured result types:
1364
+
1365
+ - `readMarker()` → `ContractMarkerRecord | null`
1366
+ - `verify()` → `VerifyDatabaseResult`
1367
+ - `schemaVerify()` → `VerifyDatabaseSchemaResult`
1368
+ - `sign()` → `SignDatabaseResult`
1369
+ - `dbInit()` → `Result<DbInitSuccess, DbInitFailure>` (uses Result pattern)
1370
+ - `dbUpdate()` → `Result<DbUpdateSuccess, DbUpdateFailure>` (uses Result pattern)
1371
+ - `migrationApply()` → `Result<MigrationApplySuccess, MigrationApplyFailure>` (uses Result pattern)
1372
+ - `introspect()` → Schema IR (family-specific)
1373
+
1374
+ ### Error Handling
1375
+
1376
+ - **Connection errors**: Thrown as exceptions from `connect()`
1377
+ - **Not connected errors**: Thrown if operations called before `connect()`
1378
+ - **Driver not configured**: Thrown if driver is not provided in options
1379
+ - **Operation failures**: Returned as structured results (not thrown)
1380
+
1381
+ ### Key Differences from CLI
1382
+
1383
+ | Aspect | CLI | Control API |
1384
+ |--------|-----|-------------|
1385
+ | Config | Reads `prisma-next.config.ts` | Accepts descriptors directly |
1386
+ | File I/O | Reads contract.json from disk | Accepts contract IR directly |
1387
+ | Output | Formats for console | Returns structured data |
1388
+ | Exit codes | Uses `process.exit()` | Returns results/throws |
1389
+
1061
1390
  ## Entrypoints
1062
1391
 
1063
1392
  The CLI package exports several subpaths for different use cases:
1064
1393
 
1065
1394
  - **`@prisma-next/cli`** (main export): Exports `loadContractFromTs` and `createContractEmitCommand`
1066
1395
  - **`@prisma-next/cli/config-types`**: Exports `defineConfig` and config types
1396
+ - **`@prisma-next/cli/control-api`**: Exports `createControlClient` and control API types
1067
1397
  - **`@prisma-next/cli/commands/db-init`**: Exports `createDbInitCommand`
1068
- - **`@prisma-next/cli/commands/db-introspect`**: Exports `createDbIntrospectCommand`
1069
- - **`@prisma-next/cli/commands/db-schema-verify`**: Exports `createDbSchemaVerifyCommand`
1398
+ - **`@prisma-next/cli/commands/db-update`**: Exports `createDbUpdateCommand`
1399
+ - **`@prisma-next/cli/commands/db-schema`**: Exports `createDbSchemaCommand`
1070
1400
  - **`@prisma-next/cli/commands/db-sign`**: Exports `createDbSignCommand`
1071
1401
  - **`@prisma-next/cli/commands/db-verify`**: Exports `createDbVerifyCommand`
1072
1402
  - **`@prisma-next/cli/commands/contract-emit`**: Exports `createContractEmitCommand`
1403
+ - **`@prisma-next/cli/commands/contract-infer`**: Exports `createContractInferCommand`
1404
+ - **`@prisma-next/cli/commands/migration-plan`**: Exports `createMigrationPlanCommand`
1405
+ - **`@prisma-next/cli/commands/migration-show`**: Exports `createMigrationShowCommand`
1406
+ - **`@prisma-next/cli/commands/migration-status`**: Exports `createMigrationStatusCommand`
1407
+ - **`@prisma-next/cli/commands/migration-apply`**: Exports `createMigrationApplyCommand`
1408
+ - **`@prisma-next/cli/commands/migration-verify`**: Exports `createMigrationVerifyCommand`
1073
1409
  - **`@prisma-next/cli/config-loader`**: Exports `loadConfig` function
1074
1410
 
1075
1411
  **Important**: `loadContractFromTs` is exported from the main package (`@prisma-next/cli`). See `.cursor/rules/cli-package-exports.mdc` for import patterns.