@prisma-next/cli 0.4.2 → 0.4.4

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 (130) hide show
  1. package/README.md +56 -21
  2. package/dist/cli-errors-By1iVE3z.mjs +34 -0
  3. package/dist/cli-errors-By1iVE3z.mjs.map +1 -0
  4. package/dist/{cli-errors-BFYgBH3L.d.mts → cli-errors-DDeVsP2Y.d.mts} +1 -0
  5. package/dist/cli.mjs +19 -16
  6. package/dist/cli.mjs.map +1 -1
  7. package/dist/{client-CrsnY58k.mjs → client-1JqqkiC7.mjs} +45 -20
  8. package/dist/client-1JqqkiC7.mjs.map +1 -0
  9. package/dist/commands/contract-emit.d.mts.map +1 -1
  10. package/dist/commands/contract-emit.mjs +7 -7
  11. package/dist/commands/contract-infer.d.mts.map +1 -1
  12. package/dist/commands/contract-infer.mjs +8 -8
  13. package/dist/commands/db-init.d.mts.map +1 -1
  14. package/dist/commands/db-init.mjs +11 -10
  15. package/dist/commands/db-init.mjs.map +1 -1
  16. package/dist/commands/db-schema.mjs +8 -8
  17. package/dist/commands/db-sign.mjs +8 -8
  18. package/dist/commands/db-update.mjs +10 -10
  19. package/dist/commands/db-update.mjs.map +1 -1
  20. package/dist/commands/db-verify.mjs +10 -10
  21. package/dist/commands/migration-apply.d.mts +5 -2
  22. package/dist/commands/migration-apply.d.mts.map +1 -1
  23. package/dist/commands/migration-apply.mjs +56 -57
  24. package/dist/commands/migration-apply.mjs.map +1 -1
  25. package/dist/commands/migration-new.d.mts.map +1 -1
  26. package/dist/commands/migration-new.mjs +26 -32
  27. package/dist/commands/migration-new.mjs.map +1 -1
  28. package/dist/commands/migration-plan.d.mts +14 -5
  29. package/dist/commands/migration-plan.d.mts.map +1 -1
  30. package/dist/commands/migration-plan.mjs +45 -48
  31. package/dist/commands/migration-plan.mjs.map +1 -1
  32. package/dist/commands/migration-ref.d.mts +1 -1
  33. package/dist/commands/migration-ref.d.mts.map +1 -1
  34. package/dist/commands/migration-ref.mjs +6 -10
  35. package/dist/commands/migration-ref.mjs.map +1 -1
  36. package/dist/commands/migration-show.d.mts +13 -7
  37. package/dist/commands/migration-show.d.mts.map +1 -1
  38. package/dist/commands/migration-show.mjs +28 -29
  39. package/dist/commands/migration-show.mjs.map +1 -1
  40. package/dist/commands/migration-status.d.mts +23 -5
  41. package/dist/commands/migration-status.d.mts.map +1 -1
  42. package/dist/commands/migration-status.mjs +8 -8
  43. package/dist/{config-loader-C25b63rJ.mjs → config-loader-ih8ViDb_.mjs} +2 -2
  44. package/dist/config-loader-ih8ViDb_.mjs.map +1 -0
  45. package/dist/config-loader.mjs +1 -1
  46. package/dist/contract-emit-DS5NzZh2.mjs +6 -0
  47. package/dist/contract-emit-RZBWzkop.mjs +329 -0
  48. package/dist/contract-emit-RZBWzkop.mjs.map +1 -0
  49. package/dist/contract-emit-rt_Nmdwq.mjs +150 -0
  50. package/dist/contract-emit-rt_Nmdwq.mjs.map +1 -0
  51. package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-4Ptgw3Pe.mjs} +1 -1
  52. package/dist/{contract-enrichment-CAOELa-H.mjs.map → contract-enrichment-4Ptgw3Pe.mjs.map} +1 -1
  53. package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-Cf5J2wVg.mjs} +11 -19
  54. package/dist/contract-infer-Cf5J2wVg.mjs.map +1 -0
  55. package/dist/exports/control-api.d.mts +86 -21
  56. package/dist/exports/control-api.d.mts.map +1 -1
  57. package/dist/exports/control-api.mjs +7 -7
  58. package/dist/exports/index.mjs +8 -8
  59. package/dist/{framework-components-Cr--XBKy.mjs → framework-components-Bgcre3Z6.mjs} +2 -2
  60. package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-Bgcre3Z6.mjs.map} +1 -1
  61. package/dist/{init-m8x0UoPY.mjs → init-DAbQMxIR.mjs} +5 -5
  62. package/dist/{init-m8x0UoPY.mjs.map → init-DAbQMxIR.mjs.map} +1 -1
  63. package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-LWtXfxm_.mjs} +9 -9
  64. package/dist/inspect-live-schema-LWtXfxm_.mjs.map +1 -0
  65. package/dist/migration-cli.d.mts +41 -11
  66. package/dist/migration-cli.d.mts.map +1 -1
  67. package/dist/migration-cli.mjs +308 -84
  68. package/dist/migration-cli.mjs.map +1 -1
  69. package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-CU452v9h.mjs} +7 -7
  70. package/dist/{migration-command-scaffold-B3B09et6.mjs.map → migration-command-scaffold-CU452v9h.mjs.map} +1 -1
  71. package/dist/{migration-status-DUMiH8_G.mjs → migration-status-DoPrFIOQ.mjs} +114 -57
  72. package/dist/migration-status-DoPrFIOQ.mjs.map +1 -0
  73. package/dist/{migrations-Bo5WtTla.mjs → migrations-MEoKMiV5.mjs} +42 -21
  74. package/dist/migrations-MEoKMiV5.mjs.map +1 -0
  75. package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-DgRGldpT.mjs} +1 -1
  76. package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-DgRGldpT.mjs.map} +1 -1
  77. package/dist/{result-handler-Ba3zWQsI.mjs → result-handler-Ch6hVnOo.mjs} +34 -19
  78. package/dist/{result-handler-Ba3zWQsI.mjs.map → result-handler-Ch6hVnOo.mjs.map} +1 -1
  79. package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-u2YgKghu.mjs} +1 -1
  80. package/dist/{terminal-ui-C3ZLwQxK.mjs.map → terminal-ui-u2YgKghu.mjs.map} +1 -1
  81. package/dist/{verify-Bkycc-Tf.mjs → verify-BT9tgCOH.mjs} +2 -2
  82. package/dist/{verify-Bkycc-Tf.mjs.map → verify-BT9tgCOH.mjs.map} +1 -1
  83. package/package.json +18 -17
  84. package/src/cli.ts +32 -6
  85. package/src/commands/contract-emit.ts +67 -163
  86. package/src/commands/contract-infer.ts +7 -20
  87. package/src/commands/db-init.ts +1 -0
  88. package/src/commands/db-update.ts +1 -1
  89. package/src/commands/inspect-live-schema.ts +10 -5
  90. package/src/commands/migration-apply.ts +84 -63
  91. package/src/commands/migration-new.ts +28 -34
  92. package/src/commands/migration-plan.ts +80 -56
  93. package/src/commands/migration-ref.ts +8 -7
  94. package/src/commands/migration-show.ts +53 -36
  95. package/src/commands/migration-status.ts +194 -58
  96. package/src/config-path-validation.ts +0 -1
  97. package/src/control-api/client.ts +21 -0
  98. package/src/control-api/operations/contract-emit.ts +198 -115
  99. package/src/control-api/operations/db-init.ts +10 -6
  100. package/src/control-api/operations/db-update.ts +10 -6
  101. package/src/control-api/operations/migration-apply.ts +30 -9
  102. package/src/control-api/types.ts +69 -7
  103. package/src/exports/control-api.ts +2 -1
  104. package/src/migration-cli.ts +445 -122
  105. package/src/utils/cli-errors.ts +49 -2
  106. package/src/utils/command-helpers.ts +45 -23
  107. package/src/utils/emit-queue.ts +26 -0
  108. package/src/utils/formatters/graph-migration-mapper.ts +7 -3
  109. package/src/utils/formatters/migrations.ts +62 -26
  110. package/src/utils/publish-contract-artifact-pair.ts +134 -0
  111. package/dist/cli-errors-Cd79vmTH.mjs +0 -5
  112. package/dist/client-CrsnY58k.mjs.map +0 -1
  113. package/dist/config-loader-C25b63rJ.mjs.map +0 -1
  114. package/dist/contract-emit-DxgyXrqV.mjs +0 -6
  115. package/dist/contract-emit-NJ01hiiv.mjs +0 -195
  116. package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
  117. package/dist/contract-emit-V5SSitUT.mjs +0 -122
  118. package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
  119. package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
  120. package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
  121. package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
  122. package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
  123. package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
  124. package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
  125. package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
  126. package/dist/migrations-Bo5WtTla.mjs.map +0 -1
  127. package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
  128. package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
  129. package/src/control-api/operations/extract-operation-statements.ts +0 -14
  130. package/src/control-api/operations/extract-sql-ddl.ts +0 -47
package/README.md CHANGED
@@ -951,12 +951,12 @@ prisma-next migration plan [--config <path>] [--name <slug>] [--from <hash>] [--
951
951
  2. Reads existing migrations from `config.migrations.dir` (default: `migrations/`)
952
952
  3. Determines the starting point: `--from <hash>` if provided, otherwise the latest migration target
953
953
  4. Diffs the starting contract against the new contract using the target's migration planner
954
- 5. Scaffolds a new migration package: `migration.ts` (containing `placeholder(...)` lambdas for any data transforms), `migration.json` (with a content-addressed `migrationId` over the planned ops, or over `[]` when the planner could not lower any calls because of placeholders), `ops.json` (the planned ops, or `[]` in the placeholder-blocked case), and contract bookends. The package is **always** fully attested — there is no draft state on disk.
955
- 6. If the plan has unfilled `placeholder(...)` slots, the command returns a successful `pendingPlaceholders` envelope (a warning, not a failure) asking the developer to fill in the slots before re-emitting. The on-disk `ops.json` is `[]` and `migrationId` is the hash of `(manifest, [])`, so applying the migration as-written will not advance the storage hash to the intended destination — the runner's destination-hash post-check surfaces this as a state mismatch. After filling in the placeholders, run `node migrations/<dir>/migration.ts` to re-emit `ops.json` and the corresponding `migrationId`. `PN-MIG-2001` is raised only at self-emit time when a slot is still unfilled.
954
+ 5. Scaffolds a new migration package: `migration.ts` (containing `placeholder(...)` lambdas for any data transforms), `migration.json` (with a content-addressed `migrationHash` over the planned ops, or over `[]` when the planner could not lower any calls because of placeholders), `ops.json` (the planned ops, or `[]` in the placeholder-blocked case), and contract bookends. The package is **always** fully attested — there is no draft state on disk.
955
+ 6. If the plan has unfilled `placeholder(...)` slots, the command returns a successful `pendingPlaceholders` envelope (a warning, not a failure) asking the developer to fill in the slots before re-emitting. The on-disk `ops.json` is `[]` and `migrationHash` is the hash of `(metadata, [])`, so applying the migration as-written will not advance the storage hash to the intended destination — the runner's destination-hash post-check surfaces this as a state mismatch. After filling in the placeholders, run `node migrations/<dir>/migration.ts` to re-emit `ops.json` and the corresponding `migrationHash`. `PN-MIG-2001` is raised only at self-emit time when a slot is still unfilled.
956
956
 
957
957
  **Outputs:**
958
958
  - `migrations/<dir>/migration.ts` — editable migration source (with `placeholder(...)` slots when the planner inserted them)
959
- - `migrations/<dir>/migration.json` — fully attested manifest (`migrationId: string`, never null)
959
+ - `migrations/<dir>/migration.json` — fully attested metadata (`migrationHash: string`, never null)
960
960
  - `migrations/<dir>/ops.json` — planned operations (empty list `[]` if placeholders blocked the planner)
961
961
  - `migrations/<dir>/start-contract.{json,d.ts}` — bookend from the "from" side (when applicable)
962
962
  - `migrations/<dir>/end-contract.{json,d.ts}` — bookend from the "to" side
@@ -965,14 +965,14 @@ prisma-next migration plan [--config <path>] [--name <slug>] [--from <hash>] [--
965
965
 
966
966
  ### `prisma-next migration show`
967
967
 
968
- 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.
968
+ Display a migration package's operations, DDL preview, and metadata. Accepts a directory path, a hash prefix (git-style matching against `migrationHash`), or defaults to the latest migration.
969
969
 
970
970
  ```bash
971
971
  prisma-next migration show [target] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
972
972
  ```
973
973
 
974
974
  **Options:**
975
- - `[target]`: Migration directory path or migrationId hash prefix (defaults to latest)
975
+ - `[target]`: Migration directory path or `migrationHash` prefix (defaults to latest)
976
976
  - `--config <path>`: Path to `prisma-next.config.ts`
977
977
  - `--json`: Output as JSON object
978
978
  - `-q, --quiet`: Quiet mode (errors only)
@@ -980,7 +980,7 @@ prisma-next migration show [target] [--config <path>] [--json] [-v] [-q] [--colo
980
980
 
981
981
  **What it does:**
982
982
  1. If `target` is a path (contains `/` or `\`), reads that directory directly
983
- 2. If `target` is a hash prefix, scans all attested migrations and matches against `migrationId`
983
+ 2. If `target` is a hash prefix, scans all attested migrations and matches against `migrationHash`
984
984
  3. If no target, defaults to the latest migration
985
985
  4. Displays operations with operation class badges, destructive warnings, and DDL preview
986
986
 
@@ -1034,15 +1034,14 @@ prisma-next migration apply [--db <url>] [--ref <name>] [--config <path>] [--jso
1034
1034
  - `-v, --verbose`: Verbose output (debug info, timings)
1035
1035
 
1036
1036
  **What it does:**
1037
- 1. Reads migration packages from `config.migrations.dir` (every package is attested — there is no on-disk draft state)
1038
- 2. **Defense in depth:** rehashes `(manifest, ops)` for each loaded bundle and confirms it matches the stored `migrationId`. If a bundle has been hand-edited or partially written since emit, apply aborts with a structured runtime error pointing at the offending directory and asks the developer to re-run `node migrations/<dir>/migration.ts` (or restore from version control).
1039
- 3. Reconstructs the migration graph from all loaded bundles
1040
- 4. Determines the destination hash: from `--ref` (via `refs.json`) or from `contract.json`
1041
- 5. Connects to the database and reads the current marker hash
1042
- 6. Finds the shortest path from the marker hash to the destination using graph pathfinding
1043
- 7. Executes each pending migration in order using the target's `MigrationRunner`
1044
- 8. Each migration runs in its own transaction with prechecks, postchecks, and idempotency checks enabled
1045
- 9. After each migration, the runner verifies the schema and updates the marker/ledger
1037
+ 1. Reads migration packages from `config.migrations.dir`. Every package is attested — there is no on-disk draft state. The loader (`readMigrationPackage` in `@prisma-next/migration-tools/io`) rehashes `(metadata, ops)` for each `MigrationPackage` it returns and confirms the result matches the stored `migrationHash`. If a package has been hand-edited or partially written since emit, the load fails with `MIGRATION.HASH_MISMATCH` pointing at the offending directory and asks the developer to re-run `node migrations/<dir>/migration.ts` (or restore from version control).
1038
+ 2. Reconstructs the migration graph from all loaded packages
1039
+ 3. Determines the destination hash: from `--ref` (via `refs.json`) or from `contract.json`
1040
+ 4. Connects to the database and reads the current marker hash
1041
+ 5. Finds the shortest path from the marker hash to the destination using graph pathfinding
1042
+ 6. Executes each pending migration in order using the target's `MigrationRunner`
1043
+ 7. Each migration runs in its own transaction with prechecks, postchecks, and idempotency checks enabled
1044
+ 8. After each migration, the runner verifies the schema and updates the marker/ledger
1046
1045
 
1047
1046
  **Config requirements:** Requires `driver` and `db.connection` (or `--db`). `migrations.dir` is optional and defaults to `migrations/`.
1048
1047
 
@@ -1050,7 +1049,7 @@ prisma-next migration apply [--db <url>] [--ref <name>] [--config <path>] [--jso
1050
1049
 
1051
1050
  **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.
1052
1051
 
1053
- ### Emitting `ops.json` and computing `migrationId`
1052
+ ### Emitting `ops.json` and computing `migrationHash`
1054
1053
 
1055
1054
  There is no dedicated CLI command for emitting a migration — migrations
1056
1055
  self-emit. After scaffolding (via `migration plan` or `migration new`),
@@ -1061,7 +1060,9 @@ run `migration.ts` directly with Node to produce `ops.json` and attest
1061
1060
  node migrations/<dir>/migration.ts
1062
1061
  ```
1063
1062
 
1064
- The scaffolded `migration.ts` calls `MigrationCLI.run(import.meta.url, ...)` from `@prisma-next/cli/migration-cli` when invoked as the entrypoint. (Postgres scaffolds re-export `MigrationCLI` through `@prisma-next/target-postgres/migration` so a Postgres `migration.ts` only needs the single facade import; Mongo scaffolds still pull from `@prisma-next/cli/migration-cli` directly.) The CLI entrypoint loads `prisma-next.config.ts`, assembles a `ControlStack`, instantiates the migration with that stack (so `dataTransform` and other adapter-aware helpers can materialize a real adapter), and serializes operations to `ops.json` while writing the content-addressed `migrationId` into `migration.json`. If `migration.ts` contains unfilled `placeholder()` slots, the script exits with `PN-MIG-2001` and reports the slot to fill in.
1063
+ The scaffolded `migration.ts` calls `MigrationCLI.run(import.meta.url, ...)` from `@prisma-next/cli/migration-cli` when invoked as the entrypoint. (Postgres scaffolds re-export `MigrationCLI` through `@prisma-next/target-postgres/migration` so a Postgres `migration.ts` only needs the single facade import; Mongo scaffolds still pull from `@prisma-next/cli/migration-cli` directly.) The CLI entrypoint loads `prisma-next.config.ts`, assembles a `ControlStack`, instantiates the migration with that stack (so `dataTransform` and other adapter-aware helpers can materialize a real adapter), and serializes operations to `ops.json` while writing the content-addressed `migrationHash` into `migration.json`. If `migration.ts` contains unfilled `placeholder()` slots, the script exits with `PN-MIG-2001` and reports the slot to fill in.
1064
+
1065
+ `MigrationCLI.run` accepts an optional third argument `{ argv?, stdout?, stderr? }` for in-process testability (default: `process.argv` / `process.stdout` / `process.stderr`) and returns the exit code as a `Promise<number>`. The flag surface is `--help` / `--dry-run` / `--config <path>`, parsed by [`clipanion`](https://github.com/arcanis/clipanion). The main multi-command surface (`prisma-next contract emit`, `db verify`, etc.) uses Commander; the per-migration `MigrationCLI.run` entrypoint uses clipanion to keep authored migration files lightweight and in-process testable.
1065
1066
 
1066
1067
  ### `prisma-next migration ref`
1067
1068
 
@@ -1093,17 +1094,22 @@ flowchart TD
1093
1094
  CMD_EMIT[Emit Command]
1094
1095
  CMD_DB[DB Commands]
1095
1096
  CMD_MIG[Migration Commands]
1096
- LOAD[TS Contract Loader]
1097
+ EXEC_EMIT[executeContractEmit]
1098
+ PUBLISH[publishContractArtifactPair]
1097
1099
  EMIT[Emitter]
1098
1100
  CTRL[Control Client]
1099
1101
  MIG_TOOLS["@prisma-next/migration-tools"]
1100
1102
  FS[File System]
1103
+ VITE["@prisma-next/vite-plugin-contract-emit"]
1101
1104
 
1102
1105
  CLI --> CMD_EMIT
1103
1106
  CLI --> CMD_DB
1104
1107
  CLI --> CMD_MIG
1105
- CMD_EMIT --> LOAD
1106
- LOAD --> EMIT
1108
+ CMD_EMIT --> EXEC_EMIT
1109
+ VITE --> EXEC_EMIT
1110
+ EXEC_EMIT --> EMIT
1111
+ EXEC_EMIT --> PUBLISH
1112
+ PUBLISH --> FS
1107
1113
  CMD_DB --> CTRL
1108
1114
  CMD_MIG --> CTRL
1109
1115
  CMD_MIG --> MIG_TOOLS
@@ -1111,6 +1117,35 @@ flowchart TD
1111
1117
  CTRL --> FS
1112
1118
  ```
1113
1119
 
1120
+ ## Canonical Contract Emit Path
1121
+
1122
+ > **For agents/contributors**: `executeContractEmit` is the SINGLE publication path
1123
+ > for `contract.json` + `contract.d.ts`. The CLI command (`prisma-next contract
1124
+ > emit`) and the Vite plugin (`@prisma-next/vite-plugin-contract-emit`) both
1125
+ > call into it. Do NOT re-implement the load → emit → publish dance in a new
1126
+ > caller; if you need additional behavior, extend `ContractEmitOptions` /
1127
+ > `ContractEmitResult` and update `executeContractEmit` itself.
1128
+
1129
+ How it composes:
1130
+
1131
+ - The whole flow (load config → resolve source → emit bytes → publish) is
1132
+ serialized per output JSON path via `queueEmitByOutput`
1133
+ (`src/utils/emit-queue.ts`). Concurrent calls for the same output line up
1134
+ FIFO; concurrent calls for distinct outputs run in parallel. Last submission
1135
+ wins on disk.
1136
+ - Within a single emit, `publishContractArtifactPair`
1137
+ (`src/utils/publish-contract-artifact-pair.ts`) stages temp files, renames
1138
+ `contract.d.ts` before `contract.json`, and attempts to restore the previous
1139
+ pair if either rename fails — so type-only consumers never observe a
1140
+ mismatched pair.
1141
+ - Long-lived hosts (Vite dev server, watch CLIs) must call `disposeEmitQueue`
1142
+ on shutdown to drop the per-output queue state, otherwise the module-global
1143
+ queue map leaks one entry per unique output path.
1144
+
1145
+ The `validateContractDeps` warning is returned in `ContractEmitResult.validationWarning`
1146
+ rather than written to stderr by the operation — callers (CLI, Vite plugin) decide
1147
+ how to render it (`ui.warn`, plugin logger, etc.).
1148
+
1114
1149
  ## Config Validation and Normalization
1115
1150
 
1116
1151
  The `defineConfig()` function validates and normalizes configs using Arktype:
@@ -1266,7 +1301,7 @@ export default defineConfig({
1266
1301
  - **`commander`**: CLI argument parsing and command routing
1267
1302
  - **`esbuild`**: Bundling TypeScript contract files with import allowlisting
1268
1303
  - **`@prisma-next/emitter`**: Contract emission engine (returns strings)
1269
- - **`@prisma-next/migration-tools`**: On-disk migration I/O, attestation, and history reconstruction
1304
+ - **`@prisma-next/migration-tools`**: On-disk migration I/O, hash verification, and history reconstruction
1270
1305
  - **`@prisma-next/framework-components`**: Control plane types, migration operation types, control stack (via `./control`)
1271
1306
  - **`@prisma-next/errors`**: Error types and factories (via `./control`)
1272
1307
 
@@ -0,0 +1,34 @@
1
+ import { CliStructuredError as CliStructuredError$1, errorConfigValidation as errorConfigValidation$1, errorContractConfigMissing as errorContractConfigMissing$1, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDriverRequired, errorFileNotFound, errorMigrationPlanningFailed, errorTargetMigrationNotSupported, errorUnexpected as errorUnexpected$1 } from "@prisma-next/errors/control";
2
+ import { ERROR_CODE_DESTRUCTIVE_CHANGES, errorDestructiveChanges, errorHashMismatch, errorMarkerMissing, errorRunnerFailed, errorRuntime, errorRuntime as errorRuntime$1, errorTargetMismatch } from "@prisma-next/errors/execution";
3
+ import "@prisma-next/errors/migration";
4
+
5
+ //#region src/utils/cli-errors.ts
6
+ /**
7
+ * Maps a `MigrationToolsError` raised by the migration-tools loader/graph
8
+ * surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,
9
+ * `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.
10
+ *
11
+ * The full `error.details` payload is forwarded into `meta` so machine
12
+ * consumers (`--json`) see structural fields like `dir`, `storedHash`,
13
+ * `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable
14
+ * `code`. The user-visible `summary`/`why`/`fix` text is unchanged.
15
+ *
16
+ * Callers are expected to gate on `MigrationToolsError.is(error)` first
17
+ * (mirroring the original inline pattern); non-`MigrationToolsError`
18
+ * values are caller-classified (rethrow, wrap with command-specific
19
+ * `errorUnexpected`, etc.).
20
+ */
21
+ function mapMigrationToolsError(error) {
22
+ return errorRuntime(error.message, {
23
+ why: error.why,
24
+ fix: error.fix,
25
+ meta: {
26
+ code: error.code,
27
+ ...error.details ?? {}
28
+ }
29
+ });
30
+ }
31
+
32
+ //#endregion
33
+ export { errorUnexpected$1 as _, errorContractValidationFailed as a, errorDriverRequired as c, errorMarkerMissing as d, errorMigrationPlanningFailed as f, errorTargetMismatch as g, errorTargetMigrationNotSupported as h, errorContractConfigMissing$1 as i, errorFileNotFound as l, errorRuntime$1 as m, ERROR_CODE_DESTRUCTIVE_CHANGES as n, errorDatabaseConnectionRequired as o, errorRunnerFailed as p, errorConfigValidation$1 as r, errorDestructiveChanges as s, CliStructuredError$1 as t, errorHashMismatch as u, mapMigrationToolsError as v };
34
+ //# sourceMappingURL=cli-errors-By1iVE3z.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-errors-By1iVE3z.mjs","names":[],"sources":["../src/utils/cli-errors.ts"],"sourcesContent":["/**\n * Re-export all domain error factories from @prisma-next/errors for convenience.\n * CLI-specific errors (e.g., Commander argument validation in the main CLI, or\n * clipanion parse errors in the migration-file CLI) can be added here if needed.\n */\nexport type { CliErrorConflict, CliErrorEnvelope } from '@prisma-next/errors/control';\n\nimport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport type { MigrationToolsError } from '@prisma-next/migration-tools/errors';\n\nexport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n};\nexport {\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorDestructiveChanges,\n errorHashMismatch,\n errorMarkerMissing,\n errorMarkerRequired,\n errorRunnerFailed,\n errorRuntime,\n errorSchemaVerificationFailed,\n errorTargetMismatch,\n} from '@prisma-next/errors/execution';\nexport {\n errorMigrationFileMissing,\n errorMigrationInvalidDefaultExport,\n errorMigrationPlanNotArray,\n errorUnfilledPlaceholder,\n placeholder,\n} from '@prisma-next/errors/migration';\n\n/**\n * Maps a `MigrationToolsError` raised by the migration-tools loader/graph\n * surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,\n * `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.\n *\n * The full `error.details` payload is forwarded into `meta` so machine\n * consumers (`--json`) see structural fields like `dir`, `storedHash`,\n * `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable\n * `code`. The user-visible `summary`/`why`/`fix` text is unchanged.\n *\n * Callers are expected to gate on `MigrationToolsError.is(error)` first\n * (mirroring the original inline pattern); non-`MigrationToolsError`\n * values are caller-classified (rethrow, wrap with command-specific\n * `errorUnexpected`, etc.).\n */\nexport function mapMigrationToolsError(error: MigrationToolsError): CliStructuredError {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgFA,SAAgB,uBAAuB,OAAgD;AACrF,QAAO,aAAa,MAAM,SAAS;EACjC,KAAK,MAAM;EACX,KAAK,MAAM;EACX,MAAM;GAAE,MAAM,MAAM;GAAM,GAAI,MAAM,WAAW,EAAE;GAAG;EACrD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { CliStructuredError as CliStructuredError$1 } from "@prisma-next/errors/control";
2
2
  import "@prisma-next/errors/execution";
3
3
  import "@prisma-next/errors/migration";
4
+ import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
4
5
  export { CliStructuredError$1 as t };
package/dist/cli.mjs CHANGED
@@ -1,18 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import "./config-loader-C25b63rJ.mjs";
4
- import "./cli-errors-Cd79vmTH.mjs";
5
- import "./framework-components-Cr--XBKy.mjs";
6
- import "./client-CrsnY58k.mjs";
7
- import { n as installShutdownHandlers } from "./terminal-ui-C3ZLwQxK.mjs";
8
- import { d as setCommandExamples, g as formatRootHelp, h as formatCommandHelp, m as parseGlobalFlags, n as addGlobalOptions, u as setCommandDescriptions } from "./result-handler-Ba3zWQsI.mjs";
9
- import { t as createContractEmitCommand } from "./contract-emit-NJ01hiiv.mjs";
10
- import { t as createContractInferCommand } from "./contract-infer-D9cC3rJm.mjs";
11
- import "./inspect-live-schema-yrHAvG71.mjs";
12
- import "./migrations-Bo5WtTla.mjs";
13
- import "./migration-command-scaffold-B3B09et6.mjs";
3
+ import "./config-loader-ih8ViDb_.mjs";
4
+ import "./cli-errors-By1iVE3z.mjs";
5
+ import "./contract-emit-RZBWzkop.mjs";
6
+ import "./framework-components-Bgcre3Z6.mjs";
7
+ import { n as installShutdownHandlers } from "./terminal-ui-u2YgKghu.mjs";
8
+ import { _ as formatCommandHelp, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, n as addGlobalOptions, v as formatRootHelp } from "./result-handler-Ch6hVnOo.mjs";
9
+ import { t as createContractEmitCommand } from "./contract-emit-rt_Nmdwq.mjs";
10
+ import { t as createContractInferCommand } from "./contract-infer-Cf5J2wVg.mjs";
11
+ import "./client-1JqqkiC7.mjs";
12
+ import "./inspect-live-schema-LWtXfxm_.mjs";
13
+ import "./migrations-MEoKMiV5.mjs";
14
+ import "./migration-command-scaffold-CU452v9h.mjs";
14
15
  import { createDbInitCommand } from "./commands/db-init.mjs";
15
- import "./verify-Bkycc-Tf.mjs";
16
+ import "./verify-BT9tgCOH.mjs";
16
17
  import { createDbSchemaCommand } from "./commands/db-schema.mjs";
17
18
  import { createDbSignCommand } from "./commands/db-sign.mjs";
18
19
  import { createDbUpdateCommand } from "./commands/db-update.mjs";
@@ -22,7 +23,7 @@ import { createMigrationNewCommand } from "./commands/migration-new.mjs";
22
23
  import { createMigrationPlanCommand } from "./commands/migration-plan.mjs";
23
24
  import { createMigrationRefCommand } from "./commands/migration-ref.mjs";
24
25
  import { createMigrationShowCommand } from "./commands/migration-show.mjs";
25
- import { t as createMigrationStatusCommand } from "./migration-status-DUMiH8_G.mjs";
26
+ import { t as createMigrationStatusCommand } from "./migration-status-DoPrFIOQ.mjs";
26
27
  import { Command } from "commander";
27
28
  import { distance } from "closest-match";
28
29
 
@@ -104,7 +105,7 @@ Exit codes (see CLI Style Guide § Exit Codes):
104
105
  "prisma-next init --no-install # skip pnpm/npm install + emit"
105
106
  ]);
106
107
  return addGlobalOptions(command).option("--target <db>", "Database target: postgres or mongodb").option("--authoring <style>", "Schema authoring style: psl or typescript").option("--schema-path <path>", "Where to write the starter schema (default: prisma/contract.prisma)").option("--force", "Overwrite an existing scaffold without prompting").option("--write-env", "Write a .env file from .env.example (gitignored; default: only .env.example)").option("--probe-db", "Connect to DATABASE_URL once and check the server version against the target minimum (opt-in; off by default)").option("--strict-probe", "Treat a failed --probe-db as fatal (no-op without --probe-db; init is offline-by-default)").option("--no-install", "Skip dependency installation and contract emission").action(async (options) => {
107
- const { runInit } = await import("./init-m8x0UoPY.mjs");
108
+ const { runInit } = await import("./init-DAbQMxIR.mjs");
108
109
  const flags = parseGlobalFlags(options);
109
110
  const canPrompt = deriveCanPrompt({
110
111
  flagsInteractive: flags.interactive,
@@ -185,7 +186,9 @@ const versionOption = program.options.find((opt) => opt.flags.includes("--versio
185
186
  if (versionOption) versionOption.description = "Output the version number";
186
187
  program.configureOutput({
187
188
  writeErr: () => {},
188
- writeOut: () => {}
189
+ writeOut: (str) => {
190
+ process.stdout.write(str);
191
+ }
189
192
  });
190
193
  const rootHelpFormatter = (cmd) => {
191
194
  return formatRootHelp({
@@ -316,7 +319,7 @@ const helpCommand = new Command("help").description("Show usage instructions").c
316
319
  program,
317
320
  flags: parseGlobalFlags({})
318
321
  });
319
- process.stderr.write(`${helpText}\n`);
322
+ process.stdout.write(`${helpText}\n`);
320
323
  process.exit(0);
321
324
  });
322
325
  program.addCommand(helpCommand);
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/commands/init/exit-codes.ts","../src/commands/init/index.ts","../src/utils/suggest-command.ts","../src/cli.ts"],"sourcesContent":["/**\n * Stable exit codes for the `init` command.\n *\n * These are part of the command's public contract. AI agents and CI scripts\n * branch on them (FR1.6), so the values must remain stable across versions.\n *\n * Codes 0–3 are the CLI-wide reserved values per the [CLI Style Guide\n * Exit Codes section](../../../../../../../docs/CLI%20Style%20Guide.md#exit-codes):\n * `OK = 0`, `INTERNAL_ERROR = 1`, `PRECONDITION = 2`, `USER_ABORTED = 3`.\n * Codes 4 and 5 are command-specific outcomes for `init`'s two fallible\n * side effects (install + emit). Documented in `--help` via\n * `setCommandDescriptions` in `./index.ts`.\n */\n\nexport const INIT_EXIT_OK = 0;\n\n/**\n * Anything we did not anticipate — a bug in prisma-next, not something\n * the caller did wrong. Includes the structured error code `5009`\n * (invalid output document) and any unrecognised internal error code,\n * so callers can distinguish \"tool is broken\" from \"your invocation\n * was wrong\" (`PRECONDITION = 2`). Maps to the generic \"RUN\" error\n * domain.\n */\nexport const INIT_EXIT_INTERNAL_ERROR = 1;\n\n/**\n * Preconditions not met. The caller asked for something we cannot do\n * without more input or a different environment. Examples:\n * - missing `package.json` / `deno.json`\n * - non-interactive mode without enough flags to proceed\n * - re-init without `--force` in non-interactive mode\n */\nexport const INIT_EXIT_PRECONDITION = 2;\n\n/**\n * The user actively aborted an interactive prompt (Ctrl-C, declined the\n * re-init confirmation, etc.). Distinct from PRECONDITION because the user\n * was given the choice and made it; no diagnostic is needed.\n */\nexport const INIT_EXIT_USER_ABORTED = 3;\n\n/**\n * Dependency installation step failed without a recoverable fallback.\n * `init` automatically falls back from `pnpm` to `npm` on a recognised\n * workspace/catalog leak (FR7.2); this code is returned only when the\n * fallback also fails, or when the package manager is not pnpm and the\n * single attempt failed. Files written before the install step (config,\n * schema, db client, etc.) remain on disk so the user can fix the\n * environment and re-run; the error envelope's `meta.filesWritten` lists\n * them.\n */\nexport const INIT_EXIT_INSTALL_FAILED = 4;\n\n/**\n * Contract emit step failed after a successful install. Files written\n * before emit (including any installed dependencies) are still on disk;\n * the user can fix the underlying issue (typically a contract syntax\n * error or a missing extension pack) and re-run `prisma-next contract\n * emit` manually.\n */\nexport const INIT_EXIT_EMIT_FAILED = 5;\n","import { Command } from 'commander';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../../utils/command-helpers';\nimport { type CommonCommandOptions, parseGlobalFlags } from '../../utils/global-flags';\nimport {\n INIT_EXIT_EMIT_FAILED,\n INIT_EXIT_INSTALL_FAILED,\n INIT_EXIT_INTERNAL_ERROR,\n INIT_EXIT_OK,\n INIT_EXIT_PRECONDITION,\n INIT_EXIT_USER_ABORTED,\n} from './exit-codes';\n\n/**\n * Commander.js parsed options for `init`. The init-specific options live\n * alongside the inherited `CommonCommandOptions` global flags.\n *\n * `target` and `authoring` are typed as plain `string` here because\n * Commander.js does not enforce enums at parse time — the validation /\n * normalisation happens in `inputs.ts::resolveInitInputs`, which can\n * raise a structured `errorInitInvalidFlagValue` with the full set of\n * allowed values.\n */\ninterface InitCommandOptions extends CommonCommandOptions {\n readonly target?: string;\n readonly authoring?: string;\n readonly schemaPath?: string;\n readonly force?: boolean;\n readonly writeEnv?: boolean;\n readonly probeDb?: boolean;\n readonly strictProbe?: boolean;\n readonly install?: boolean;\n}\n\nexport function createInitCommand(): Command {\n const command = new Command('init');\n setCommandDescriptions(\n command,\n 'Initialize a new Prisma Next project',\n 'Scaffolds config, schema, and runtime files, installs dependencies,\\n' +\n 'and emits the contract. Gets you from zero to typed queries in one step.\\n' +\n '\\n' +\n 'Run interactively for a guided experience, or supply --target / --authoring\\n' +\n 'and --yes for a fully scriptable run (CI, AI coding agents, automation).\\n' +\n '\\n' +\n 'Exit codes (see CLI Style Guide § Exit Codes):\\n' +\n ` ${INIT_EXIT_OK} OK Init succeeded.\\n` +\n ` ${INIT_EXIT_INTERNAL_ERROR} INTERNAL_ERROR Unexpected bug in prisma-next (please report).\\n` +\n ` ${INIT_EXIT_PRECONDITION} PRECONDITION Bad flags / missing prerequisite (e.g. no package.json).\\n` +\n ` ${INIT_EXIT_USER_ABORTED} USER_ABORTED User cancelled an interactive prompt.\\n` +\n ` ${INIT_EXIT_INSTALL_FAILED} INSTALL_FAILED Dependency installation failed (init-specific).\\n` +\n ` ${INIT_EXIT_EMIT_FAILED} EMIT_FAILED \\`contract emit\\` failed after install (init-specific).`,\n );\n setCommandExamples(command, [\n 'prisma-next init',\n 'prisma-next init --yes --target postgres --authoring psl',\n 'prisma-next init --yes --target mongodb --authoring typescript --json',\n 'prisma-next init --yes --force --target postgres --authoring psl # overwrite an existing scaffold',\n 'prisma-next init --no-install # skip pnpm/npm install + emit',\n ]);\n\n return addGlobalOptions(command)\n .option('--target <db>', 'Database target: postgres or mongodb')\n .option('--authoring <style>', 'Schema authoring style: psl or typescript')\n .option(\n '--schema-path <path>',\n 'Where to write the starter schema (default: prisma/contract.prisma)',\n )\n .option('--force', 'Overwrite an existing scaffold without prompting')\n .option(\n '--write-env',\n 'Write a .env file from .env.example (gitignored; default: only .env.example)',\n )\n .option(\n '--probe-db',\n 'Connect to DATABASE_URL once and check the server version against the target minimum (opt-in; off by default)',\n )\n .option(\n '--strict-probe',\n 'Treat a failed --probe-db as fatal (no-op without --probe-db; init is offline-by-default)',\n )\n .option('--no-install', 'Skip dependency installation and contract emission')\n .action(async (options: InitCommandOptions) => {\n const { runInit } = await import('./init');\n const flags = parseGlobalFlags(options);\n const canPrompt = deriveCanPrompt({\n flagsInteractive: flags.interactive,\n optionInteractive: options.interactive,\n stdinIsTTY: Boolean(process.stdin.isTTY),\n });\n const exitCode = await runInit(process.cwd(), { options, flags, canPrompt });\n process.exit(exitCode);\n });\n}\n\n/**\n * Bridges the action handler's two TTY checks (stdout via `flags`, stdin\n * via `process.stdin.isTTY`) into the `canPrompt` boolean `runInit`\n * consumes.\n *\n * Per the [Style Guide § Interactivity](../../../../../../../docs/CLI%20Style%20Guide.md#interactivity):\n *\n * - `flags.interactive` governs *decoration* (TerminalUI, intro/outro,\n * spinners) and is derived from stdout-TTY by `parseGlobalFlags`,\n * honouring `--interactive` / `--no-interactive`.\n * - Prompting additionally requires a stdin TTY — closing stdin is a\n * common signal in CI / agent environments even when stdout stays\n * attached.\n * - `--interactive` is the explicit override: when the user passes it,\n * we honour it (e.g. testing flows where stdin is stubbed).\n *\n * Exported so callers and tests can derive the same value without\n * touching `process` globals — F14 of the M1/M2 review.\n */\nexport function deriveCanPrompt(opts: {\n readonly flagsInteractive: boolean | undefined;\n readonly optionInteractive: boolean | undefined;\n readonly stdinIsTTY: boolean;\n}): boolean {\n if (opts.optionInteractive === true) return true;\n if (opts.flagsInteractive === false) return false;\n return opts.stdinIsTTY;\n}\n","import { distance } from 'closest-match';\n\n/**\n * Suggests similar command names for a mistyped input.\n *\n * Uses Levenshtein distance to find close matches. Only suggests commands\n * within a reasonable distance threshold (40% of the input length, minimum 2).\n * Returns up to 3 suggestions in case of ties.\n *\n * @returns Array of suggested command names (empty if nothing is close enough).\n */\nexport function suggestCommands(input: string, candidates: readonly string[]): string[] {\n if (candidates.length === 0) return [];\n\n // Threshold: at most 40% of the input length (min 2) to avoid absurd suggestions\n const maxDistance = Math.max(2, Math.ceil(input.length * 0.4));\n\n const scored = candidates\n .map((name) => ({ name, dist: distance(input, name) }))\n .filter((entry) => entry.dist <= maxDistance)\n .sort((a, b) => a.dist - b.dist);\n\n if (scored.length === 0) return [];\n\n // Take the best distance, then include ties (up to 3)\n const bestDist = scored[0]!.dist;\n return scored\n .filter((entry) => entry.dist === bestDist)\n .slice(0, 3)\n .map((entry) => entry.name);\n}\n","import { Command } from 'commander';\nimport { createContractEmitCommand } from './commands/contract-emit';\nimport { createContractInferCommand } from './commands/contract-infer';\nimport { createInitCommand } from './commands/init';\nimport { installShutdownHandlers } from './utils/shutdown';\n\n// Install SIGINT/SIGTERM handlers before anything else\ninstallShutdownHandlers();\n\nimport { createDbInitCommand } from './commands/db-init';\nimport { createDbSchemaCommand } from './commands/db-schema';\nimport { createDbSignCommand } from './commands/db-sign';\nimport { createDbUpdateCommand } from './commands/db-update';\nimport { createDbVerifyCommand } from './commands/db-verify';\nimport { createMigrationApplyCommand } from './commands/migration-apply';\nimport { createMigrationNewCommand } from './commands/migration-new';\nimport { createMigrationPlanCommand } from './commands/migration-plan';\nimport { createMigrationRefCommand } from './commands/migration-ref';\nimport { createMigrationShowCommand } from './commands/migration-show';\nimport { createMigrationStatusCommand } from './commands/migration-status';\nimport { setCommandDescriptions } from './utils/command-helpers';\nimport { formatCommandHelp, formatRootHelp } from './utils/formatters/help';\nimport { parseGlobalFlags } from './utils/global-flags';\nimport { suggestCommands } from './utils/suggest-command';\n\n/**\n * Formats the \"Did you mean ...?\" hint for an unknown command.\n */\nfunction formatSuggestion(input: string, candidates: readonly string[]): string {\n const suggestions = suggestCommands(\n input,\n candidates.map((c) => c),\n );\n if (suggestions.length === 0) return '';\n if (suggestions.length === 1) return `\\nDid you mean ${suggestions[0]}?\\n`;\n return `\\nDid you mean one of these?\\n${suggestions.map((s) => ` ${s}`).join('\\n')}\\n`;\n}\n\nconst program = new Command();\n\nprogram.name('prisma-next').description('Prisma Next CLI').version('0.0.1');\n\n// Override version option description to match capitalization style\nconst versionOption = program.options.find((opt) => opt.flags.includes('--version'));\nif (versionOption) {\n versionOption.description = 'Output the version number';\n}\n\nprogram.configureOutput({\n writeErr: () => {\n // Suppress all default error output - we handle errors in exitOverride\n },\n writeOut: () => {\n // Suppress all default output - our custom formatters handle everything\n },\n});\n\n// Customize root help output to use our styled format\nconst rootHelpFormatter = (cmd: Command) => {\n const flags = parseGlobalFlags({});\n return formatRootHelp({ program: cmd, flags });\n};\n\nprogram.configureHelp({\n formatHelp: rootHelpFormatter,\n subcommandDescription: () => '',\n});\n\n// Override exit to handle unhandled errors (fail fast cases)\n// Commands handle structured errors themselves via process.exit()\nprogram.exitOverride((err) => {\n if (err) {\n const errorCode = (err as { code?: string }).code;\n const errorMessage = String(err.message ?? '');\n const errorName = err.name ?? '';\n\n // Unknown command/argument → exit 2 (CLI usage error)\n const isUnknownCommandError =\n errorCode === 'commander.unknownCommand' ||\n errorCode === 'commander.unknownArgument' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));\n if (isUnknownCommandError) {\n const flags = parseGlobalFlags({});\n const match = errorMessage.match(/unknown command ['\"]([^'\"]+)['\"]/);\n const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';\n\n const firstArg = process.argv[2];\n const parentCommand = firstArg\n ? program.commands.find((cmd) => cmd.name() === firstArg)\n : undefined;\n\n if (parentCommand && commandName !== firstArg) {\n const subNames = parentCommand.commands.map((c) => c.name());\n process.stderr.write(\n `Unknown command: ${commandName}${formatSuggestion(commandName!, subNames)}\\n`,\n );\n const helpText = formatCommandHelp({ command: parentCommand, flags });\n process.stderr.write(`${helpText}\\n`);\n } else {\n const topNames = program.commands.map((c) => c.name());\n process.stderr.write(\n `Unknown command: ${commandName}${formatSuggestion(commandName!, topNames)}\\n`,\n );\n const helpText = formatRootHelp({ program, flags });\n process.stderr.write(`${helpText}\\n`);\n }\n process.exit(2);\n return;\n }\n\n // Help requests → exit 0\n const isHelpError =\n errorCode === 'commander.help' ||\n errorCode === 'commander.helpDisplayed' ||\n errorCode === 'outputHelp' ||\n errorMessage === '(outputHelp)' ||\n errorMessage.includes('outputHelp') ||\n (errorName === 'CommanderError' && errorMessage.includes('outputHelp'));\n if (isHelpError) {\n process.exit(0);\n return;\n }\n\n // Missing required arguments → exit 2 (CLI usage error)\n const isMissingArgumentError =\n errorCode === 'commander.missingArgument' ||\n errorCode === 'commander.missingMandatoryOptionValue' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('missing') || errorMessage.includes('required')));\n if (isMissingArgumentError) {\n process.exit(2);\n return;\n }\n\n // Unhandled error → exit 1\n process.stderr.write(`Unhandled error: ${err.message}\\n`);\n if (err.stack) {\n process.stderr.write(`${err.stack}\\n`);\n }\n process.exit(1);\n }\n process.exit(0);\n});\n\n// Register contract subcommand\nconst contractCommand = new Command('contract');\nsetCommandDescriptions(\n contractCommand,\n 'Contract management commands',\n 'Define and emit your application data contract. The contract describes your schema as a\\n' +\n 'declarative data structure that can be signed and verified against your database.',\n);\ncontractCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add emit subcommand to contract\nconst contractEmitCommand = createContractEmitCommand();\ncontractCommand.addCommand(contractEmitCommand);\n\n// Add infer subcommand to contract\nconst contractInferCommand = createContractInferCommand();\ncontractCommand.addCommand(contractInferCommand);\n\n// Register contract command\nprogram.addCommand(contractCommand);\n\n// Register db subcommand\nconst dbCommand = new Command('db');\nsetCommandDescriptions(\n dbCommand,\n 'Database management commands',\n 'Verify and sign your database with your contract. Ensure your database schema matches\\n' +\n 'your contract, and sign it to record the contract hash for future verification.',\n);\ndbCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add verify subcommand to db\nconst dbVerifyCommand = createDbVerifyCommand();\ndbCommand.addCommand(dbVerifyCommand);\n\n// Add init subcommand to db\nconst dbInitCommand = createDbInitCommand();\ndbCommand.addCommand(dbInitCommand);\n\n// Add update subcommand to db\nconst dbUpdateCommand = createDbUpdateCommand();\ndbCommand.addCommand(dbUpdateCommand);\n\n// Add schema subcommand to db\nconst dbSchemaCommand = createDbSchemaCommand();\ndbCommand.addCommand(dbSchemaCommand);\n\n// Add sign subcommand to db\nconst dbSignCommand = createDbSignCommand();\ndbCommand.addCommand(dbSignCommand);\n\n// Register db command\nprogram.addCommand(dbCommand);\n\n// Register migration subcommand\nconst migrationCommand = new Command('migration');\nsetCommandDescriptions(\n migrationCommand,\n 'On-disk migration management commands',\n 'Plan, apply, and scaffold on-disk migration packages. Migrations are\\n' +\n 'contract-to-contract edges stored as versioned directories under migrations/.',\n);\nmigrationCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\nconst migrationPlanCommand = createMigrationPlanCommand();\nmigrationCommand.addCommand(migrationPlanCommand);\n\nconst migrationNewCommand = createMigrationNewCommand();\nmigrationCommand.addCommand(migrationNewCommand);\n\nconst migrationShowCommand = createMigrationShowCommand();\nmigrationCommand.addCommand(migrationShowCommand);\n\nconst migrationStatusCommand = createMigrationStatusCommand();\nmigrationCommand.addCommand(migrationStatusCommand);\n\nconst migrationApplyCommand = createMigrationApplyCommand();\nmigrationCommand.addCommand(migrationApplyCommand);\n\nconst migrationRefCommand = createMigrationRefCommand();\nmigrationCommand.addCommand(migrationRefCommand);\n\nprogram.addCommand(migrationCommand);\n\n// Register init command (top-level, not nested)\nconst initCommand = createInitCommand();\nprogram.addCommand(initCommand);\n\n// Create help command\nconst helpCommand = new Command('help')\n .description('Show usage instructions')\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // Help is decoration → stderr\n process.stderr.write(`${helpText}\\n`);\n process.exit(0);\n });\n\nprogram.addCommand(helpCommand);\n\n// Set help as the default action when no command is provided\nprogram.action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n process.stderr.write(`${helpText}\\n`);\n process.exit(0);\n});\n\n// Check if a command was invoked with no arguments (just the command name)\n// or if an unrecognized command was provided\nconst args = process.argv.slice(2);\nif (args.length > 0) {\n const commandName = args[0];\n // Handle version option explicitly since we suppress default output\n if (commandName === '--version' || commandName === '-V') {\n // Version is data → stdout\n process.stdout.write(`${program.version()}\\n`);\n process.exit(0);\n }\n // Skip command check for global options like --help, -h\n const isGlobalOption = commandName === '--help' || commandName === '-h';\n if (!isGlobalOption) {\n // Check if this is a recognized command\n const command = program.commands.find((cmd) => cmd.name() === commandName);\n\n if (!command) {\n // Unrecognized command → exit 2 (CLI usage error)\n const flags = parseGlobalFlags({});\n const topNames = program.commands.map((c) => c.name());\n process.stderr.write(\n `Unknown command: ${commandName}${formatSuggestion(commandName!, topNames)}\\n`,\n );\n const helpText = formatRootHelp({ program, flags });\n process.stderr.write(`${helpText}\\n`);\n process.exit(2);\n } else if (command.commands.length > 0 && args.length === 1) {\n // Parent command called with no subcommand - show help and exit with 0\n const flags = parseGlobalFlags({});\n const helpText = formatCommandHelp({ command, flags });\n process.stderr.write(`${helpText}\\n`);\n process.exit(0);\n }\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/commands/init/exit-codes.ts","../src/commands/init/index.ts","../src/utils/suggest-command.ts","../src/cli.ts"],"sourcesContent":["/**\n * Stable exit codes for the `init` command.\n *\n * These are part of the command's public contract. AI agents and CI scripts\n * branch on them (FR1.6), so the values must remain stable across versions.\n *\n * Codes 0–3 are the CLI-wide reserved values per the [CLI Style Guide\n * Exit Codes section](../../../../../../../docs/CLI%20Style%20Guide.md#exit-codes):\n * `OK = 0`, `INTERNAL_ERROR = 1`, `PRECONDITION = 2`, `USER_ABORTED = 3`.\n * Codes 4 and 5 are command-specific outcomes for `init`'s two fallible\n * side effects (install + emit). Documented in `--help` via\n * `setCommandDescriptions` in `./index.ts`.\n */\n\nexport const INIT_EXIT_OK = 0;\n\n/**\n * Anything we did not anticipate — a bug in prisma-next, not something\n * the caller did wrong. Includes the structured error code `5009`\n * (invalid output document) and any unrecognised internal error code,\n * so callers can distinguish \"tool is broken\" from \"your invocation\n * was wrong\" (`PRECONDITION = 2`). Maps to the generic \"RUN\" error\n * domain.\n */\nexport const INIT_EXIT_INTERNAL_ERROR = 1;\n\n/**\n * Preconditions not met. The caller asked for something we cannot do\n * without more input or a different environment. Examples:\n * - missing `package.json` / `deno.json`\n * - non-interactive mode without enough flags to proceed\n * - re-init without `--force` in non-interactive mode\n */\nexport const INIT_EXIT_PRECONDITION = 2;\n\n/**\n * The user actively aborted an interactive prompt (Ctrl-C, declined the\n * re-init confirmation, etc.). Distinct from PRECONDITION because the user\n * was given the choice and made it; no diagnostic is needed.\n */\nexport const INIT_EXIT_USER_ABORTED = 3;\n\n/**\n * Dependency installation step failed without a recoverable fallback.\n * `init` automatically falls back from `pnpm` to `npm` on a recognised\n * workspace/catalog leak (FR7.2); this code is returned only when the\n * fallback also fails, or when the package manager is not pnpm and the\n * single attempt failed. Files written before the install step (config,\n * schema, db client, etc.) remain on disk so the user can fix the\n * environment and re-run; the error envelope's `meta.filesWritten` lists\n * them.\n */\nexport const INIT_EXIT_INSTALL_FAILED = 4;\n\n/**\n * Contract emit step failed after a successful install. Files written\n * before emit (including any installed dependencies) are still on disk;\n * the user can fix the underlying issue (typically a contract syntax\n * error or a missing extension pack) and re-run `prisma-next contract\n * emit` manually.\n */\nexport const INIT_EXIT_EMIT_FAILED = 5;\n","import { Command } from 'commander';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../../utils/command-helpers';\nimport { type CommonCommandOptions, parseGlobalFlags } from '../../utils/global-flags';\nimport {\n INIT_EXIT_EMIT_FAILED,\n INIT_EXIT_INSTALL_FAILED,\n INIT_EXIT_INTERNAL_ERROR,\n INIT_EXIT_OK,\n INIT_EXIT_PRECONDITION,\n INIT_EXIT_USER_ABORTED,\n} from './exit-codes';\n\n/**\n * Commander.js parsed options for `init`. The init-specific options live\n * alongside the inherited `CommonCommandOptions` global flags.\n *\n * `target` and `authoring` are typed as plain `string` here because\n * Commander.js does not enforce enums at parse time — the validation /\n * normalisation happens in `inputs.ts::resolveInitInputs`, which can\n * raise a structured `errorInitInvalidFlagValue` with the full set of\n * allowed values.\n */\ninterface InitCommandOptions extends CommonCommandOptions {\n readonly target?: string;\n readonly authoring?: string;\n readonly schemaPath?: string;\n readonly force?: boolean;\n readonly writeEnv?: boolean;\n readonly probeDb?: boolean;\n readonly strictProbe?: boolean;\n readonly install?: boolean;\n}\n\nexport function createInitCommand(): Command {\n const command = new Command('init');\n setCommandDescriptions(\n command,\n 'Initialize a new Prisma Next project',\n 'Scaffolds config, schema, and runtime files, installs dependencies,\\n' +\n 'and emits the contract. Gets you from zero to typed queries in one step.\\n' +\n '\\n' +\n 'Run interactively for a guided experience, or supply --target / --authoring\\n' +\n 'and --yes for a fully scriptable run (CI, AI coding agents, automation).\\n' +\n '\\n' +\n 'Exit codes (see CLI Style Guide § Exit Codes):\\n' +\n ` ${INIT_EXIT_OK} OK Init succeeded.\\n` +\n ` ${INIT_EXIT_INTERNAL_ERROR} INTERNAL_ERROR Unexpected bug in prisma-next (please report).\\n` +\n ` ${INIT_EXIT_PRECONDITION} PRECONDITION Bad flags / missing prerequisite (e.g. no package.json).\\n` +\n ` ${INIT_EXIT_USER_ABORTED} USER_ABORTED User cancelled an interactive prompt.\\n` +\n ` ${INIT_EXIT_INSTALL_FAILED} INSTALL_FAILED Dependency installation failed (init-specific).\\n` +\n ` ${INIT_EXIT_EMIT_FAILED} EMIT_FAILED \\`contract emit\\` failed after install (init-specific).`,\n );\n setCommandExamples(command, [\n 'prisma-next init',\n 'prisma-next init --yes --target postgres --authoring psl',\n 'prisma-next init --yes --target mongodb --authoring typescript --json',\n 'prisma-next init --yes --force --target postgres --authoring psl # overwrite an existing scaffold',\n 'prisma-next init --no-install # skip pnpm/npm install + emit',\n ]);\n\n return addGlobalOptions(command)\n .option('--target <db>', 'Database target: postgres or mongodb')\n .option('--authoring <style>', 'Schema authoring style: psl or typescript')\n .option(\n '--schema-path <path>',\n 'Where to write the starter schema (default: prisma/contract.prisma)',\n )\n .option('--force', 'Overwrite an existing scaffold without prompting')\n .option(\n '--write-env',\n 'Write a .env file from .env.example (gitignored; default: only .env.example)',\n )\n .option(\n '--probe-db',\n 'Connect to DATABASE_URL once and check the server version against the target minimum (opt-in; off by default)',\n )\n .option(\n '--strict-probe',\n 'Treat a failed --probe-db as fatal (no-op without --probe-db; init is offline-by-default)',\n )\n .option('--no-install', 'Skip dependency installation and contract emission')\n .action(async (options: InitCommandOptions) => {\n const { runInit } = await import('./init');\n const flags = parseGlobalFlags(options);\n const canPrompt = deriveCanPrompt({\n flagsInteractive: flags.interactive,\n optionInteractive: options.interactive,\n stdinIsTTY: Boolean(process.stdin.isTTY),\n });\n const exitCode = await runInit(process.cwd(), { options, flags, canPrompt });\n process.exit(exitCode);\n });\n}\n\n/**\n * Bridges the action handler's two TTY checks (stdout via `flags`, stdin\n * via `process.stdin.isTTY`) into the `canPrompt` boolean `runInit`\n * consumes.\n *\n * Per the [Style Guide § Interactivity](../../../../../../../docs/CLI%20Style%20Guide.md#interactivity):\n *\n * - `flags.interactive` governs *decoration* (TerminalUI, intro/outro,\n * spinners) and is derived from stdout-TTY by `parseGlobalFlags`,\n * honouring `--interactive` / `--no-interactive`.\n * - Prompting additionally requires a stdin TTY — closing stdin is a\n * common signal in CI / agent environments even when stdout stays\n * attached.\n * - `--interactive` is the explicit override: when the user passes it,\n * we honour it (e.g. testing flows where stdin is stubbed).\n *\n * Exported so callers and tests can derive the same value without\n * touching `process` globals — F14 of the M1/M2 review.\n */\nexport function deriveCanPrompt(opts: {\n readonly flagsInteractive: boolean | undefined;\n readonly optionInteractive: boolean | undefined;\n readonly stdinIsTTY: boolean;\n}): boolean {\n if (opts.optionInteractive === true) return true;\n if (opts.flagsInteractive === false) return false;\n return opts.stdinIsTTY;\n}\n","import { distance } from 'closest-match';\n\n/**\n * Suggests similar command names for a mistyped input.\n *\n * Uses Levenshtein distance to find close matches. Only suggests commands\n * within a reasonable distance threshold (40% of the input length, minimum 2).\n * Returns up to 3 suggestions in case of ties.\n *\n * @returns Array of suggested command names (empty if nothing is close enough).\n */\nexport function suggestCommands(input: string, candidates: readonly string[]): string[] {\n if (candidates.length === 0) return [];\n\n // Threshold: at most 40% of the input length (min 2) to avoid absurd suggestions\n const maxDistance = Math.max(2, Math.ceil(input.length * 0.4));\n\n const scored = candidates\n .map((name) => ({ name, dist: distance(input, name) }))\n .filter((entry) => entry.dist <= maxDistance)\n .sort((a, b) => a.dist - b.dist);\n\n if (scored.length === 0) return [];\n\n // Take the best distance, then include ties (up to 3)\n const bestDist = scored[0]!.dist;\n return scored\n .filter((entry) => entry.dist === bestDist)\n .slice(0, 3)\n .map((entry) => entry.name);\n}\n","import { Command } from 'commander';\nimport { createContractEmitCommand } from './commands/contract-emit';\nimport { createContractInferCommand } from './commands/contract-infer';\nimport { createInitCommand } from './commands/init';\nimport { installShutdownHandlers } from './utils/shutdown';\n\n// Install SIGINT/SIGTERM handlers before anything else\ninstallShutdownHandlers();\n\nimport { createDbInitCommand } from './commands/db-init';\nimport { createDbSchemaCommand } from './commands/db-schema';\nimport { createDbSignCommand } from './commands/db-sign';\nimport { createDbUpdateCommand } from './commands/db-update';\nimport { createDbVerifyCommand } from './commands/db-verify';\nimport { createMigrationApplyCommand } from './commands/migration-apply';\nimport { createMigrationNewCommand } from './commands/migration-new';\nimport { createMigrationPlanCommand } from './commands/migration-plan';\nimport { createMigrationRefCommand } from './commands/migration-ref';\nimport { createMigrationShowCommand } from './commands/migration-show';\nimport { createMigrationStatusCommand } from './commands/migration-status';\nimport { setCommandDescriptions } from './utils/command-helpers';\nimport { formatCommandHelp, formatRootHelp } from './utils/formatters/help';\nimport { parseGlobalFlags } from './utils/global-flags';\nimport { suggestCommands } from './utils/suggest-command';\n\n/**\n * Formats the \"Did you mean ...?\" hint for an unknown command.\n */\nfunction formatSuggestion(input: string, candidates: readonly string[]): string {\n const suggestions = suggestCommands(\n input,\n candidates.map((c) => c),\n );\n if (suggestions.length === 0) return '';\n if (suggestions.length === 1) return `\\nDid you mean ${suggestions[0]}?\\n`;\n return `\\nDid you mean one of these?\\n${suggestions.map((s) => ` ${s}`).join('\\n')}\\n`;\n}\n\nconst program = new Command();\n\nprogram.name('prisma-next').description('Prisma Next CLI').version('0.0.1');\n\n// Override version option description to match capitalization style\nconst versionOption = program.options.find((opt) => opt.flags.includes('--version'));\nif (versionOption) {\n versionOption.description = 'Output the version number';\n}\n\nprogram.configureOutput({\n writeErr: () => {\n // Suppress all default error output - we handle errors in exitOverride\n },\n writeOut: (str) => {\n // Commander routes explicitly-requested `--help` (success-path help)\n // through writeOut; per the Style Guide § Output Conventions rule 8,\n // user-requested help is data and goes to stdout. Error-path help\n // (e.g. usage shown after an unknown command) goes through writeErr,\n // which stays suppressed because we render that ourselves with the\n // matching error envelope.\n //\n // Explicit `--version` is short-circuited before `program.parse()`\n // (see the argv pre-scan at the bottom of this file), so it does not\n // reach this writer.\n process.stdout.write(str);\n },\n});\n\n// Customize root help output to use our styled format\nconst rootHelpFormatter = (cmd: Command) => {\n const flags = parseGlobalFlags({});\n return formatRootHelp({ program: cmd, flags });\n};\n\nprogram.configureHelp({\n formatHelp: rootHelpFormatter,\n subcommandDescription: () => '',\n});\n\n// Override exit to handle unhandled errors (fail fast cases)\n// Commands handle structured errors themselves via process.exit()\nprogram.exitOverride((err) => {\n if (err) {\n const errorCode = (err as { code?: string }).code;\n const errorMessage = String(err.message ?? '');\n const errorName = err.name ?? '';\n\n // Unknown command/argument → exit 2 (CLI usage error)\n const isUnknownCommandError =\n errorCode === 'commander.unknownCommand' ||\n errorCode === 'commander.unknownArgument' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));\n if (isUnknownCommandError) {\n const flags = parseGlobalFlags({});\n const match = errorMessage.match(/unknown command ['\"]([^'\"]+)['\"]/);\n const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';\n\n const firstArg = process.argv[2];\n const parentCommand = firstArg\n ? program.commands.find((cmd) => cmd.name() === firstArg)\n : undefined;\n\n if (parentCommand && commandName !== firstArg) {\n const subNames = parentCommand.commands.map((c) => c.name());\n process.stderr.write(\n `Unknown command: ${commandName}${formatSuggestion(commandName!, subNames)}\\n`,\n );\n const helpText = formatCommandHelp({ command: parentCommand, flags });\n process.stderr.write(`${helpText}\\n`);\n } else {\n const topNames = program.commands.map((c) => c.name());\n process.stderr.write(\n `Unknown command: ${commandName}${formatSuggestion(commandName!, topNames)}\\n`,\n );\n const helpText = formatRootHelp({ program, flags });\n process.stderr.write(`${helpText}\\n`);\n }\n process.exit(2);\n return;\n }\n\n // Help requests → exit 0\n const isHelpError =\n errorCode === 'commander.help' ||\n errorCode === 'commander.helpDisplayed' ||\n errorCode === 'outputHelp' ||\n errorMessage === '(outputHelp)' ||\n errorMessage.includes('outputHelp') ||\n (errorName === 'CommanderError' && errorMessage.includes('outputHelp'));\n if (isHelpError) {\n process.exit(0);\n return;\n }\n\n // Missing required arguments → exit 2 (CLI usage error)\n const isMissingArgumentError =\n errorCode === 'commander.missingArgument' ||\n errorCode === 'commander.missingMandatoryOptionValue' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('missing') || errorMessage.includes('required')));\n if (isMissingArgumentError) {\n process.exit(2);\n return;\n }\n\n // Unhandled error → exit 1\n process.stderr.write(`Unhandled error: ${err.message}\\n`);\n if (err.stack) {\n process.stderr.write(`${err.stack}\\n`);\n }\n process.exit(1);\n }\n process.exit(0);\n});\n\n// Register contract subcommand\nconst contractCommand = new Command('contract');\nsetCommandDescriptions(\n contractCommand,\n 'Contract management commands',\n 'Define and emit your application data contract. The contract describes your schema as a\\n' +\n 'declarative data structure that can be signed and verified against your database.',\n);\ncontractCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add emit subcommand to contract\nconst contractEmitCommand = createContractEmitCommand();\ncontractCommand.addCommand(contractEmitCommand);\n\n// Add infer subcommand to contract\nconst contractInferCommand = createContractInferCommand();\ncontractCommand.addCommand(contractInferCommand);\n\n// Register contract command\nprogram.addCommand(contractCommand);\n\n// Register db subcommand\nconst dbCommand = new Command('db');\nsetCommandDescriptions(\n dbCommand,\n 'Database management commands',\n 'Verify and sign your database with your contract. Ensure your database schema matches\\n' +\n 'your contract, and sign it to record the contract hash for future verification.',\n);\ndbCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add verify subcommand to db\nconst dbVerifyCommand = createDbVerifyCommand();\ndbCommand.addCommand(dbVerifyCommand);\n\n// Add init subcommand to db\nconst dbInitCommand = createDbInitCommand();\ndbCommand.addCommand(dbInitCommand);\n\n// Add update subcommand to db\nconst dbUpdateCommand = createDbUpdateCommand();\ndbCommand.addCommand(dbUpdateCommand);\n\n// Add schema subcommand to db\nconst dbSchemaCommand = createDbSchemaCommand();\ndbCommand.addCommand(dbSchemaCommand);\n\n// Add sign subcommand to db\nconst dbSignCommand = createDbSignCommand();\ndbCommand.addCommand(dbSignCommand);\n\n// Register db command\nprogram.addCommand(dbCommand);\n\n// Register migration subcommand\nconst migrationCommand = new Command('migration');\nsetCommandDescriptions(\n migrationCommand,\n 'On-disk migration management commands',\n 'Plan, apply, and scaffold on-disk migration packages. Migrations are\\n' +\n 'contract-to-contract edges stored as versioned directories under migrations/.',\n);\nmigrationCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\nconst migrationPlanCommand = createMigrationPlanCommand();\nmigrationCommand.addCommand(migrationPlanCommand);\n\nconst migrationNewCommand = createMigrationNewCommand();\nmigrationCommand.addCommand(migrationNewCommand);\n\nconst migrationShowCommand = createMigrationShowCommand();\nmigrationCommand.addCommand(migrationShowCommand);\n\nconst migrationStatusCommand = createMigrationStatusCommand();\nmigrationCommand.addCommand(migrationStatusCommand);\n\nconst migrationApplyCommand = createMigrationApplyCommand();\nmigrationCommand.addCommand(migrationApplyCommand);\n\nconst migrationRefCommand = createMigrationRefCommand();\nmigrationCommand.addCommand(migrationRefCommand);\n\nprogram.addCommand(migrationCommand);\n\n// Register init command (top-level, not nested)\nconst initCommand = createInitCommand();\nprogram.addCommand(initCommand);\n\n// Create help command\nconst helpCommand = new Command('help')\n .description('Show usage instructions')\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // The `help` command was invoked explicitly: help is the data the\n // caller asked for. Per Style Guide § Output Conventions rule 8,\n // explicit help goes to stdout with exit code 0.\n process.stdout.write(`${helpText}\\n`);\n process.exit(0);\n });\n\nprogram.addCommand(helpCommand);\n\n// Set help as the default action when no command is provided. The user\n// did not invoke `--help`; we are voluntarily showing usage to help them\n// recover from an underspecified invocation, so the help text is\n// decoration around an implicit \"what did you want me to do?\" and goes\n// to stderr (Style Guide § Output Conventions rule 8).\n//\n// FOLLOW-UP: the exit code here is 0 today, but a no-arg invocation is\n// arguably a usage error (PRECONDITION → exit 2) for consistency with\n// the unknown-command path. Out of scope for the explicit-help routing\n// work; revisit when tightening exit-code semantics across the CLI.\nprogram.action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n process.stderr.write(`${helpText}\\n`);\n process.exit(0);\n});\n\n// Check if a command was invoked with no arguments (just the command name)\n// or if an unrecognized command was provided\nconst args = process.argv.slice(2);\nif (args.length > 0) {\n const commandName = args[0];\n // Handle version option explicitly since we suppress default output\n if (commandName === '--version' || commandName === '-V') {\n // Version is data → stdout\n process.stdout.write(`${program.version()}\\n`);\n process.exit(0);\n }\n // Skip command check for global options like --help, -h\n const isGlobalOption = commandName === '--help' || commandName === '-h';\n if (!isGlobalOption) {\n // Check if this is a recognized command\n const command = program.commands.find((cmd) => cmd.name() === commandName);\n\n if (!command) {\n // Unrecognized command → exit 2 (CLI usage error)\n const flags = parseGlobalFlags({});\n const topNames = program.commands.map((c) => c.name());\n process.stderr.write(\n `Unknown command: ${commandName}${formatSuggestion(commandName!, topNames)}\\n`,\n );\n const helpText = formatRootHelp({ program, flags });\n process.stderr.write(`${helpText}\\n`);\n process.exit(2);\n } else if (command.commands.length > 0 && args.length === 1) {\n // Parent command called with no subcommand. Same shape as the\n // no-args case above: the user did not request help, we are\n // voluntarily rendering it as decoration around an underspecified\n // invocation, so it goes to stderr per Style Guide § Output\n // Conventions rule 8. Exit code 0 today; the FOLLOW-UP note on\n // `program.action` applies here too (arguably should be 2).\n const flags = parseGlobalFlags({});\n const helpText = formatCommandHelp({ command, flags });\n process.stderr.write(`${helpText}\\n`);\n process.exit(0);\n }\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
@@ -1,10 +1,9 @@
1
- import { t as assertFrameworkComponentsCompatible } from "./framework-components-Cr--XBKy.mjs";
2
- import { t as enrichContract } from "./contract-enrichment-CAOELa-H.mjs";
3
- import { t as extractOperationStatements } from "./extract-operation-statements-DsFfxXVZ.mjs";
1
+ import { t as assertFrameworkComponentsCompatible } from "./framework-components-Bgcre3Z6.mjs";
2
+ import { t as enrichContract } from "./contract-enrichment-4Ptgw3Pe.mjs";
4
3
  import { emit } from "@prisma-next/emitter";
5
- import { notOk, ok } from "@prisma-next/utils/result";
6
4
  import { ifDefined } from "@prisma-next/utils/defined";
7
- import { createControlStack, hasMigrations, hasSchemaView } from "@prisma-next/framework-components/control";
5
+ import { notOk, ok } from "@prisma-next/utils/result";
6
+ import { createControlStack, hasMigrations, hasOperationPreview, hasPslContractInfer, hasSchemaView } from "@prisma-next/framework-components/control";
8
7
  import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
9
8
 
10
9
  //#region src/control-api/errors.ts
@@ -99,7 +98,7 @@ async function executeDbInit(options) {
99
98
  contract,
100
99
  schema: schemaIR,
101
100
  policy,
102
- fromHash: "",
101
+ fromContract: null,
103
102
  frameworkComponents
104
103
  });
105
104
  if (plannerResult.kind === "failure") {
@@ -187,12 +186,12 @@ async function executeDbInit(options) {
187
186
  outcome: "ok"
188
187
  });
189
188
  if (mode === "plan") {
190
- const planSql = extractOperationStatements(familyInstance.familyId, migrationPlan.operations);
189
+ const preview = hasOperationPreview(familyInstance) ? familyInstance.toOperationPreview(migrationPlan.operations) : void 0;
191
190
  return ok({
192
191
  mode: "plan",
193
192
  plan: {
194
193
  operations: stripOperations(migrationPlan.operations),
195
- ...ifDefined("sql", planSql)
194
+ ...ifDefined("preview", preview)
196
195
  },
197
196
  destination: {
198
197
  storageHash: migrationPlan.destination.storageHash,
@@ -308,7 +307,7 @@ async function executeDbUpdate(options) {
308
307
  contract,
309
308
  schema: schemaIR,
310
309
  policy,
311
- fromHash: "",
310
+ fromContract: null,
312
311
  frameworkComponents
313
312
  });
314
313
  if (plannerResult.kind === "failure") {
@@ -334,12 +333,12 @@ async function executeDbUpdate(options) {
334
333
  });
335
334
  const migrationPlan = plannerResult.plan;
336
335
  if (mode === "plan") {
337
- const planSql = extractOperationStatements(familyInstance.familyId, migrationPlan.operations);
336
+ const preview = hasOperationPreview(familyInstance) ? familyInstance.toOperationPreview(migrationPlan.operations) : void 0;
338
337
  return ok({
339
338
  mode: "plan",
340
339
  plan: {
341
340
  operations: stripOperations(migrationPlan.operations),
342
- ...planSql !== void 0 ? { sql: planSql } : {}
341
+ ...ifDefined("preview", preview)
343
342
  },
344
343
  destination: {
345
344
  storageHash: migrationPlan.destination.storageHash,
@@ -425,6 +424,21 @@ async function executeDbUpdate(options) {
425
424
 
426
425
  //#endregion
427
426
  //#region src/control-api/operations/migration-apply.ts
427
+ /**
428
+ * Apply a sequence of migration packages against the configured driver.
429
+ *
430
+ * Validates the path's continuity (origin → ... → destination, no gaps),
431
+ * then drives the family/target's migration runner over each package's
432
+ * operations in order, surfacing per-migration progress through `onProgress`.
433
+ *
434
+ * The `pendingMigrations` parameter is trusted input. Callers are responsible
435
+ * for upstream verification of the originating migration packages — typically
436
+ * by loading them via `readMigrationPackage` from
437
+ * `@prisma-next/migration-tools/io`, which performs hash-integrity checks at
438
+ * the load boundary. This operation does not re-verify the packages and
439
+ * assumes the `(metadata, ops)` pairs on disk have not been tampered with
440
+ * since emit.
441
+ */
428
442
  async function executeMigrationApply(options) {
429
443
  const { driver, familyInstance, originHash, destinationHash, pendingMigrations, migrations, frameworkComponents, targetId, onProgress } = options;
430
444
  if (pendingMigrations.length === 0) {
@@ -446,31 +460,33 @@ async function executeMigrationApply(options) {
446
460
  }
447
461
  const firstMigration = pendingMigrations[0];
448
462
  const lastMigration = pendingMigrations[pendingMigrations.length - 1];
449
- if (firstMigration.from !== originHash || lastMigration.to !== destinationHash) return notOk({
463
+ const firstFromMarker = firstMigration.from ?? EMPTY_CONTRACT_HASH;
464
+ if (firstFromMarker !== originHash || lastMigration.to !== destinationHash) return notOk({
450
465
  code: "MIGRATION_PATH_NOT_FOUND",
451
466
  summary: "Migration apply path does not match requested origin and destination",
452
- why: `Path resolved as ${firstMigration.from} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,
467
+ why: `Path resolved as ${firstFromMarker} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,
453
468
  meta: {
454
469
  originHash,
455
470
  destinationHash,
456
- pathOrigin: firstMigration.from,
471
+ pathOrigin: firstFromMarker,
457
472
  pathDestination: lastMigration.to
458
473
  }
459
474
  });
460
475
  for (let i = 1; i < pendingMigrations.length; i++) {
461
476
  const previous = pendingMigrations[i - 1];
462
477
  const current = pendingMigrations[i];
463
- if (previous.to !== current.from) return notOk({
478
+ const currentFromMarker = current.from ?? EMPTY_CONTRACT_HASH;
479
+ if (previous.to !== currentFromMarker) return notOk({
464
480
  code: "MIGRATION_PATH_NOT_FOUND",
465
481
  summary: "Migration apply path contains a discontinuity between adjacent migrations",
466
- why: `Migration "${previous.dirName}" ends at ${previous.to}, but next migration "${current.dirName}" starts at ${current.from}`,
482
+ why: `Migration "${previous.dirName}" ends at ${previous.to}, but next migration "${current.dirName}" starts at ${currentFromMarker}`,
467
483
  meta: {
468
484
  originHash,
469
485
  destinationHash,
470
486
  previousDirName: previous.dirName,
471
487
  previousTo: previous.to,
472
488
  currentDirName: current.dirName,
473
- currentFrom: current.from,
489
+ currentFrom: currentFromMarker,
474
490
  discontinuityIndex: i
475
491
  }
476
492
  });
@@ -494,9 +510,10 @@ async function executeMigrationApply(options) {
494
510
  ] };
495
511
  const plan = {
496
512
  targetId,
497
- origin: migration.from === EMPTY_CONTRACT_HASH ? null : { storageHash: migration.from },
513
+ origin: migration.from === null ? null : { storageHash: migration.from },
498
514
  destination: { storageHash: migration.to },
499
- operations
515
+ operations,
516
+ providedInvariants: migration.providedInvariants
500
517
  };
501
518
  const destinationContract = familyInstance.validateContract(migration.toContract);
502
519
  const runnerResult = await runner.execute({
@@ -871,6 +888,14 @@ var ControlClientImpl = class {
871
888
  this.init();
872
889
  if (this.familyInstance && hasSchemaView(this.familyInstance)) return this.familyInstance.toSchemaView(schemaIR);
873
890
  }
891
+ inferPslContract(schemaIR) {
892
+ this.init();
893
+ if (this.familyInstance && hasPslContractInfer(this.familyInstance)) return this.familyInstance.inferPslContract(schemaIR);
894
+ }
895
+ toOperationPreview(operations) {
896
+ this.init();
897
+ if (this.familyInstance && hasOperationPreview(this.familyInstance)) return this.familyInstance.toOperationPreview(operations);
898
+ }
874
899
  async emit(options) {
875
900
  const { onProgress, contractConfig } = options;
876
901
  this.init();
@@ -994,4 +1019,4 @@ var ControlClientImpl = class {
994
1019
 
995
1020
  //#endregion
996
1021
  export { ContractValidationError as n, createControlClient as t };
997
- //# sourceMappingURL=client-CrsnY58k.mjs.map
1022
+ //# sourceMappingURL=client-1JqqkiC7.mjs.map