@prisma-next/cli 0.12.0-dev.9 → 0.13.0-dev.1

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 (214) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.mjs +180 -163
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/{client-KgJorIvG.mjs → client-CJzuo5wX.mjs} +222 -107
  5. package/dist/client-CJzuo5wX.mjs.map +1 -0
  6. package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-DGMvGBeX.mjs} +318 -25
  7. package/dist/command-helpers-DGMvGBeX.mjs.map +1 -0
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +1 -1
  10. package/dist/commands/contract-infer.d.mts.map +1 -1
  11. package/dist/commands/contract-infer.mjs +1 -1
  12. package/dist/commands/db-init.d.mts.map +1 -1
  13. package/dist/commands/db-init.mjs +4 -5
  14. package/dist/commands/db-init.mjs.map +1 -1
  15. package/dist/commands/db-schema.d.mts.map +1 -1
  16. package/dist/commands/db-schema.mjs +3 -3
  17. package/dist/commands/db-schema.mjs.map +1 -1
  18. package/dist/commands/db-sign.d.mts.map +1 -1
  19. package/dist/commands/db-sign.mjs +6 -6
  20. package/dist/commands/db-sign.mjs.map +1 -1
  21. package/dist/commands/db-update.d.mts.map +1 -1
  22. package/dist/commands/db-update.mjs +10 -7
  23. package/dist/commands/db-update.mjs.map +1 -1
  24. package/dist/commands/db-verify.d.mts.map +1 -1
  25. package/dist/commands/db-verify.mjs +1 -1
  26. package/dist/commands/migrate.d.mts +37 -3
  27. package/dist/commands/migrate.d.mts.map +1 -1
  28. package/dist/commands/migrate.mjs +298 -12
  29. package/dist/commands/migrate.mjs.map +1 -1
  30. package/dist/commands/migration-check.d.mts +55 -13
  31. package/dist/commands/migration-check.d.mts.map +1 -1
  32. package/dist/commands/migration-check.mjs +3 -2
  33. package/dist/commands/migration-graph.d.mts +16 -25
  34. package/dist/commands/migration-graph.d.mts.map +1 -1
  35. package/dist/commands/migration-graph.mjs +185 -2
  36. package/dist/commands/migration-graph.mjs.map +1 -0
  37. package/dist/commands/migration-list.d.mts +26 -27
  38. package/dist/commands/migration-list.d.mts.map +1 -1
  39. package/dist/commands/migration-list.mjs +2 -190
  40. package/dist/commands/migration-log.d.mts +9 -19
  41. package/dist/commands/migration-log.d.mts.map +1 -1
  42. package/dist/commands/migration-log.mjs +1 -137
  43. package/dist/commands/migration-new.d.mts.map +1 -1
  44. package/dist/commands/migration-new.mjs +6 -5
  45. package/dist/commands/migration-new.mjs.map +1 -1
  46. package/dist/commands/migration-plan.d.mts +1 -1
  47. package/dist/commands/migration-plan.d.mts.map +1 -1
  48. package/dist/commands/migration-plan.mjs +1 -1
  49. package/dist/commands/migration-show.d.mts +17 -21
  50. package/dist/commands/migration-show.d.mts.map +1 -1
  51. package/dist/commands/migration-show.mjs +24 -36
  52. package/dist/commands/migration-show.mjs.map +1 -1
  53. package/dist/commands/migration-status.d.mts +42 -144
  54. package/dist/commands/migration-status.d.mts.map +1 -1
  55. package/dist/commands/migration-status.mjs +3 -759
  56. package/dist/commands/ref.d.mts +1 -1
  57. package/dist/commands/ref.d.mts.map +1 -1
  58. package/dist/commands/ref.mjs +4 -4
  59. package/dist/commands/ref.mjs.map +1 -1
  60. package/dist/commands/telemetry/index.d.mts +7 -0
  61. package/dist/commands/telemetry/index.d.mts.map +1 -0
  62. package/dist/commands/telemetry/index.mjs +2 -0
  63. package/dist/{config-loader-B6sJjXTv.mjs → config-loader-p9JMrekQ.mjs} +1 -1
  64. package/dist/{config-loader-B6sJjXTv.mjs.map → config-loader-p9JMrekQ.mjs.map} +1 -1
  65. package/dist/config-loader.mjs +1 -1
  66. package/dist/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-CFXsstzm.mjs} +2 -2
  67. package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-CFXsstzm.mjs.map} +1 -1
  68. package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-B_qriF8B.mjs} +5 -5
  69. package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-B_qriF8B.mjs.map} +1 -1
  70. package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-C8HmtboH.mjs} +12 -7
  71. package/dist/contract-emit-C8HmtboH.mjs.map +1 -0
  72. package/dist/{contract-enrichment-a0V5Y_mL.mjs → contract-enrichment-gn9sWbPw.mjs} +1 -1
  73. package/dist/{contract-enrichment-a0V5Y_mL.mjs.map → contract-enrichment-gn9sWbPw.mjs.map} +1 -1
  74. package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-BYT_ra_U.mjs} +5 -5
  75. package/dist/contract-infer-BYT_ra_U.mjs.map +1 -0
  76. package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-ClI1KN6d.mjs} +5 -5
  77. package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-ClI1KN6d.mjs.map} +1 -1
  78. package/dist/{db-verify-v_vUKXTU.mjs → db-verify-C24FKhb7.mjs} +6 -6
  79. package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-C24FKhb7.mjs.map} +1 -1
  80. package/dist/exports/control-api.d.mts +5 -3
  81. package/dist/exports/control-api.d.mts.map +1 -1
  82. package/dist/exports/control-api.mjs +3 -3
  83. package/dist/exports/index.mjs +1 -1
  84. package/dist/exports/index.mjs.map +1 -1
  85. package/dist/exports/init-output.d.mts +1 -3
  86. package/dist/exports/init-output.d.mts.map +1 -1
  87. package/dist/exports/init-output.mjs +1 -1
  88. package/dist/{extension-pack-inputs-IDvjRCi3.mjs → extension-pack-inputs-1ySHqxKG.mjs} +1 -1
  89. package/dist/{extension-pack-inputs-IDvjRCi3.mjs.map → extension-pack-inputs-1ySHqxKG.mjs.map} +1 -1
  90. package/dist/{framework-components-fYXjz_in.mjs → framework-components-YVQHhPH7.mjs} +2 -2
  91. package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-YVQHhPH7.mjs.map} +1 -1
  92. package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-BpoOYtNZ.d.mts} +1 -1
  93. package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-BpoOYtNZ.d.mts.map} +1 -1
  94. package/dist/{init-Cv9UzWL5.mjs → init-0HwB-Vh8.mjs} +5 -58
  95. package/dist/init-0HwB-Vh8.mjs.map +1 -0
  96. package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-DF6IwcDl.mjs} +7 -5
  97. package/dist/inspect-live-schema-DF6IwcDl.mjs.map +1 -0
  98. package/dist/migration-check-soB5uZEQ.mjs +573 -0
  99. package/dist/migration-check-soB5uZEQ.mjs.map +1 -0
  100. package/dist/migration-cli.mjs +1 -1
  101. package/dist/migration-cli.mjs.map +1 -1
  102. package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-DA-Lhx6o.mjs} +5 -5
  103. package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-DA-Lhx6o.mjs.map} +1 -1
  104. package/dist/migration-graph-command-render-CEez7YUK.mjs +1960 -0
  105. package/dist/migration-graph-command-render-CEez7YUK.mjs.map +1 -0
  106. package/dist/migration-list-DlJJ_38Z.mjs +230 -0
  107. package/dist/migration-list-DlJJ_38Z.mjs.map +1 -0
  108. package/dist/migration-log-CG0qQAFm.mjs +222 -0
  109. package/dist/migration-log-CG0qQAFm.mjs.map +1 -0
  110. package/dist/migration-path-target-Ce6OZImp.mjs +38 -0
  111. package/dist/migration-path-target-Ce6OZImp.mjs.map +1 -0
  112. package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-z5Ing-TD.mjs} +9 -8
  113. package/dist/migration-plan-z5Ing-TD.mjs.map +1 -0
  114. package/dist/migration-status-CgWSoI_g.mjs +446 -0
  115. package/dist/migration-status-CgWSoI_g.mjs.map +1 -0
  116. package/dist/{output-B60Gw5fu.mjs → output-mEQ74_nd.mjs} +1 -1
  117. package/dist/{output-B60Gw5fu.mjs.map → output-mEQ74_nd.mjs.map} +1 -1
  118. package/dist/{progress-adapter-C644QK8l.mjs → progress-adapter-CjAeTxY_.mjs} +1 -1
  119. package/dist/{progress-adapter-C644QK8l.mjs.map → progress-adapter-CjAeTxY_.mjs.map} +1 -1
  120. package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-BkXlikCA.mjs} +1 -1
  121. package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-BkXlikCA.mjs.map} +1 -1
  122. package/dist/schemas-CeGMYFYX.d.mts +191 -0
  123. package/dist/schemas-CeGMYFYX.d.mts.map +1 -0
  124. package/dist/schemas-KhXMzNA_.mjs +112 -0
  125. package/dist/schemas-KhXMzNA_.mjs.map +1 -0
  126. package/dist/telemetry-BIM4beEO.mjs +122 -0
  127. package/dist/telemetry-BIM4beEO.mjs.map +1 -0
  128. package/dist/{terminal-ui-5Y6mrg93.d.mts → terminal-ui-DGRNFWna.d.mts} +1 -1
  129. package/dist/terminal-ui-DGRNFWna.d.mts.map +1 -0
  130. package/dist/{types-Dt_SfqFm.d.mts → types-C_tYiJYx.d.mts} +53 -31
  131. package/dist/types-C_tYiJYx.d.mts.map +1 -0
  132. package/dist/{verify-DCA9Sldu.mjs → verify-DcOYZ1tH.mjs} +2 -2
  133. package/dist/{verify-DCA9Sldu.mjs.map → verify-DcOYZ1tH.mjs.map} +1 -1
  134. package/package.json +26 -22
  135. package/src/cli.ts +5 -0
  136. package/src/commands/contract-infer.ts +2 -2
  137. package/src/commands/db-update.ts +7 -1
  138. package/src/commands/init/index.ts +6 -35
  139. package/src/commands/init/init.ts +1 -14
  140. package/src/commands/init/inputs.ts +0 -75
  141. package/src/commands/inspect-live-schema.ts +10 -0
  142. package/src/commands/json/schemas.ts +195 -0
  143. package/src/commands/migrate.ts +527 -8
  144. package/src/commands/migration-check.ts +469 -134
  145. package/src/commands/migration-graph.ts +151 -119
  146. package/src/commands/migration-list.ts +72 -39
  147. package/src/commands/migration-log.ts +52 -102
  148. package/src/commands/migration-new.ts +2 -1
  149. package/src/commands/migration-plan.ts +2 -1
  150. package/src/commands/migration-show.ts +31 -66
  151. package/src/commands/migration-status-overlay.ts +61 -0
  152. package/src/commands/migration-status.ts +458 -1066
  153. package/src/commands/telemetry/index.ts +107 -0
  154. package/src/commands/telemetry/status.ts +67 -0
  155. package/src/control-api/client.ts +70 -9
  156. package/src/control-api/operations/contract-emit.ts +22 -2
  157. package/src/control-api/operations/db-init.ts +6 -3
  158. package/src/control-api/operations/{db-apply.ts → db-run.ts} +55 -14
  159. package/src/control-api/operations/db-update.ts +7 -4
  160. package/src/control-api/operations/db-verify.ts +15 -5
  161. package/src/control-api/operations/{migration-apply.ts → migrate.ts} +181 -80
  162. package/src/control-api/operations/{apply.ts → run-migration.ts} +33 -27
  163. package/src/control-api/types.ts +56 -29
  164. package/src/utils/cli-errors.ts +70 -2
  165. package/src/utils/formatters/errors.ts +11 -0
  166. package/src/utils/formatters/migration-graph-command-render.ts +239 -0
  167. package/src/utils/formatters/migration-graph-grid-layout.ts +1134 -0
  168. package/src/utils/formatters/migration-graph-labels.ts +408 -0
  169. package/src/utils/formatters/migration-graph-model.ts +103 -0
  170. package/src/utils/formatters/migration-graph-occlusion-render.ts +258 -0
  171. package/src/utils/formatters/migration-graph-rows.ts +128 -15
  172. package/src/utils/formatters/migration-graph-space-render.ts +188 -0
  173. package/src/utils/formatters/migration-list-data-column.ts +4 -91
  174. package/src/utils/formatters/migration-list-graph-topology.ts +72 -94
  175. package/src/utils/formatters/migration-list-render.ts +135 -71
  176. package/src/utils/formatters/migration-list-styler.ts +46 -5
  177. package/src/utils/formatters/migration-list-types.ts +5 -21
  178. package/src/utils/formatters/migration-log-table.ts +205 -0
  179. package/src/utils/formatters/migrations.ts +33 -11
  180. package/src/utils/global-flags.ts +35 -0
  181. package/src/utils/integrity-violation-to-check-failure.ts +28 -19
  182. package/src/utils/legend.ts +38 -0
  183. package/src/utils/migration-path-target.ts +60 -0
  184. package/src/utils/telemetry.ts +68 -32
  185. package/dist/client-KgJorIvG.mjs.map +0 -1
  186. package/dist/command-helpers-Bbw1GbwL.mjs.map +0 -1
  187. package/dist/commands/migration-list.mjs.map +0 -1
  188. package/dist/commands/migration-log.mjs.map +0 -1
  189. package/dist/commands/migration-status.mjs.map +0 -1
  190. package/dist/contract-emit-D-4jrNve.mjs.map +0 -1
  191. package/dist/contract-infer-D8uEbJuu.mjs.map +0 -1
  192. package/dist/graph-render-rFAqZujX.mjs +0 -1081
  193. package/dist/graph-render-rFAqZujX.mjs.map +0 -1
  194. package/dist/init-Cv9UzWL5.mjs.map +0 -1
  195. package/dist/inspect-live-schema-C6ohV_oQ.mjs.map +0 -1
  196. package/dist/migration-check-BiBJoYYW.mjs +0 -341
  197. package/dist/migration-check-BiBJoYYW.mjs.map +0 -1
  198. package/dist/migration-graph-C9WC-7eO.mjs +0 -1478
  199. package/dist/migration-graph-C9WC-7eO.mjs.map +0 -1
  200. package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
  201. package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
  202. package/dist/migration-plan-9DJ7q7_z.mjs.map +0 -1
  203. package/dist/migration-types-D2FW63pr.d.mts +0 -15
  204. package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
  205. package/dist/migrations-Cv2jxNNK.mjs +0 -228
  206. package/dist/migrations-Cv2jxNNK.mjs.map +0 -1
  207. package/dist/terminal-ui-5Y6mrg93.d.mts.map +0 -1
  208. package/dist/types-Dt_SfqFm.d.mts.map +0 -1
  209. package/src/utils/formatters/graph-migration-mapper.ts +0 -235
  210. package/src/utils/formatters/graph-render.ts +0 -1323
  211. package/src/utils/formatters/graph-types.ts +0 -120
  212. package/src/utils/formatters/migration-graph-lane-colors.ts +0 -31
  213. package/src/utils/formatters/migration-graph-layout.ts +0 -1141
  214. package/src/utils/formatters/migration-graph-tree-render.ts +0 -768
@@ -1 +0,0 @@
1
- {"version":3,"file":"command-helpers-Bbw1GbwL.mjs","names":["LEFT_COLUMN_WIDTH","createPrismaNextBadge","formatHeaderLine","formatReadMoreLine","isCI","ciInfoIsCI","CliStructuredError","isCI","errorRuntime","APP_SPACE_ID"],"sources":["../src/utils/cli-errors.ts","../src/utils/formatters/helpers.ts","../src/utils/formatters/styled.ts","../src/utils/formatters/help.ts","../src/utils/is-ci.ts","../src/utils/formatters/errors.ts","../src/utils/result-handler.ts","../src/utils/glyph-mode.ts","../src/utils/shutdown.ts","../src/utils/terminal-ui.ts","../src/utils/global-flags.ts","../src/utils/command-helpers.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 errorInvalidOutputFormat,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorOutputFormatMutex,\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';\nimport type { RefResolutionError } from '@prisma-next/migration-tools/ref-resolution';\nimport type { MigrationApplyFailure } from '../control-api/types';\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';\nexport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorInvalidOutputFormat,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorOutputFormatMutex,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n};\n\nexport function errorRefSetHashNotInGraph(\n resolvedHash: string,\n reachableHashes: readonly string[],\n graphTipHash: string | null,\n): CliStructuredError {\n const reachableList =\n reachableHashes.length > 0 ? reachableHashes.join(', ') : '(none — migration graph is empty)';\n const fix =\n reachableHashes.length > 0\n ? graphTipHash !== null\n ? `Set the ref to a graph-node hash such as ${graphTipHash}, or run \\`prisma-next migration plan\\` to extend the graph.`\n : 'Set the ref to a hash that appears in the migration graph.'\n : 'Run `prisma-next migration plan` first.';\n return errorRuntime(`Resolved contract hash is not in the migration graph: ${resolvedHash}`, {\n why:\n reachableHashes.length > 0\n ? `The migration graph reaches ${reachableList}; resolved ${resolvedHash} isn't a graph node.`\n : 'The migration graph is empty — no hashes reachable.',\n fix,\n meta: {\n code: 'MIGRATION.HASH_NOT_IN_GRAPH',\n resolvedHash,\n reachableHashes: [...reachableHashes],\n ...(graphTipHash !== null ? { graphTipHash } : {}),\n },\n });\n}\n\nexport function errorRefSetEmptySentinel(hash: string): CliStructuredError {\n return errorRuntime(`Cannot set ref to the empty-database sentinel: ${hash}`, {\n why: 'The empty-database sentinel is a planner internal; it is not a valid ref target.',\n fix: 'Set the ref to a contract hash from the migration graph, or use another ref name.',\n meta: {\n code: 'MIGRATION.REF_SET_EMPTY_SENTINEL',\n hash,\n },\n });\n}\n\n/**\n * `--space <id>` was given a value that doesn't satisfy the contract-space\n * naming rule (`[a-z][a-z0-9_-]{0,63}` per `isValidSpaceId`). Fires before\n * any fs work — the input is syntactically rejected the same way an on-disk\n * directory with that name would be skipped by the enumerator.\n */\nexport function errorInvalidSpaceId(spaceId: string): CliStructuredError {\n return errorRuntime(`Invalid contract space id: ${spaceId}`, {\n why: 'Contract space ids must match [a-z][a-z0-9_-]{0,63} (lowercase, starts with a letter, max 64 characters — the rule applied to every on-disk space directory).',\n fix: 'Pass a space id that matches the directory naming rule, or omit --space to list every space.',\n meta: {\n code: 'MIGRATION.INVALID_SPACE_ID',\n spaceId,\n },\n });\n}\n\n/**\n * `migration list --space <id>` was given a contract-space id that has no\n * directory under `migrations/`. Distinct from \"the space exists but is\n * empty\" — that path renders the empty-state line and exits 0 per the\n * slice spec § Empty-state. This error fires only when `<projectMigrationsDir>/<spaceId>`\n * does not exist on disk.\n *\n * `availableSpaces` lists the contract-space directory names actually\n * present, sorted lex-asc, so the diagnostic can suggest a near match\n * without making the user reach for `ls`.\n */\nexport function errorSpaceNotFound(\n spaceId: string,\n availableSpaces: readonly string[],\n): CliStructuredError {\n const availableList =\n availableSpaces.length > 0\n ? availableSpaces.join(', ')\n : '(none — no contract spaces on disk yet)';\n const fix =\n availableSpaces.length > 0\n ? `Pick one of: ${availableList}. Run \\`prisma-next migration list\\` (no --space) to see every space's migrations.`\n : 'Author a migration with `prisma-next migration new` to create the first contract-space directory.';\n return errorRuntime(`Unknown contract space: ${spaceId}`, {\n why: `No directory named \"${spaceId}\" exists under the migrations root.`,\n fix,\n meta: {\n code: 'MIGRATION.SPACE_NOT_FOUND',\n spaceId,\n availableSpaces: [...availableSpaces],\n },\n });\n}\n\nexport function errorRefSetBundleNotFound(hash: string): CliStructuredError {\n return errorRuntime(`No migration bundle matches graph-node hash ${hash}`, {\n why: `The hash is a graph node but no on-disk bundle has metadata.to = ${hash}.`,\n fix: 'Run `pnpm fixtures:check`, or re-emit the migration that produces this hash so its bundle is restored.',\n meta: {\n code: 'MIGRATION.REF_SET_BUNDLE_NOT_FOUND',\n hash,\n },\n });\n}\n\nexport function errorPlanForgotTheFlag(\n resolvedHash: string,\n reachableRefs: ReadonlyArray<{ readonly name: string; readonly hash: string }>,\n graphTipHash: string | null,\n): CliStructuredError {\n const reachableList =\n reachableRefs.length > 0\n ? reachableRefs.map((r) => `${r.name} (${r.hash})`).join(', ')\n : '(none)';\n const refFix =\n reachableRefs.length > 0\n ? `Run migration plan with ${reachableRefs.map((r) => `--from ${r.name}`).join(' or ')}.`\n : graphTipHash !== null\n ? `Run migration plan --from ${graphTipHash}.`\n : 'Commit pending migrations first, then run migration plan.';\n return errorRuntime(`Resolved from-hash is not in the migration graph: ${resolvedHash}`, {\n why: `The migration graph reaches ${reachableList}; resolved ${resolvedHash} isn't a graph node.`,\n fix: refFix,\n meta: {\n code: 'MIGRATION.HASH_NOT_IN_GRAPH',\n resolvedHash,\n reachableRefs: reachableRefs.map((r) => r.name),\n ...(graphTipHash !== null ? { graphTipHash } : {}),\n },\n });\n}\n\nexport function errorSnapshotMissing(\n identifier: string,\n options?: { readonly viaRef?: boolean },\n): CliStructuredError {\n const viaRef = options?.viaRef !== false;\n const fix = viaRef\n ? `Run \"prisma-next db update --advance-ref ${identifier}\" to repopulate the snapshot, or \"prisma-next ref delete ${identifier}\" to clear the orphan pointer.`\n : `No contract source exists for hash \"${identifier}\" on an empty migration graph. Use --from with a ref name that has a paired snapshot, or run db update first.`;\n return errorRuntime(\n viaRef\n ? `Ref \"${identifier}\" has no paired contract snapshot`\n : `No contract source for from-hash \"${identifier}\"`,\n {\n why: viaRef\n ? `Ref \"${identifier}\" exists but its paired snapshot files are missing.`\n : `Hash \"${identifier}\" is not a graph node and no paired ref snapshot supplies a contract.`,\n fix,\n meta: {\n code: 'MIGRATION.SNAPSHOT_MISSING',\n identifier,\n viaRef,\n },\n },\n );\n}\n\nexport function errorMarkerMismatch(\n markerHash: string,\n reachableHashes: readonly string[],\n graphTip: string | null,\n): CliStructuredError {\n const reachableList =\n reachableHashes.length > 0 ? reachableHashes.join(', ') : '(none — migration graph is empty)';\n const planFromFix =\n graphTip !== null\n ? `Run \\`prisma-next migration plan --from ${graphTip}\\` if the live marker is canonical and the on-disk graph needs catching up.`\n : 'Run `prisma-next migration plan` if the live marker is canonical and the on-disk graph needs catching up.';\n return errorRuntime('Database marker is not reachable in the on-disk migration graph', {\n why: `DB marker is ${markerHash}, but the on-disk migration graph reaches: ${reachableList}.`,\n fix: [\n planFromFix,\n `Run \\`prisma-next ref set db ${markerHash}\\` if the on-disk graph is canonical and the local \\`db\\` ref drifted.`,\n 'Investigate whether the database was migrated by an out-of-band process.',\n ].join('\\n'),\n meta: {\n code: 'MIGRATION.MARKER_MISMATCH',\n markerHash,\n reachableHashes: [...reachableHashes],\n ...(graphTip !== null ? { graphTip } : {}),\n },\n });\n}\n\nexport function errorPathUnreachable(failure: MigrationApplyFailure): CliStructuredError {\n const meta = failure.meta ?? {};\n const fromHashMeta = typeof meta['fromHash'] === 'string' ? meta['fromHash'] : null;\n // `buildPathNotFoundFailure` uses this sentinel in meta when the live marker is null.\n const planFromHash = fromHashMeta === '<empty>' ? null : fromHashMeta;\n const targetHash =\n typeof meta['targetHash'] === 'string'\n ? meta['targetHash']\n : typeof meta['target'] === 'string'\n ? meta['target']\n : null;\n const deadEnds = meta['deadEnds'];\n const deadEndsSuffix =\n Array.isArray(deadEnds) && deadEnds.length > 0\n ? ` Dead-ends: ${deadEnds.map(String).join(', ')}.`\n : '';\n // Plan-then-apply recovery. The planner destination is the missing edge's\n // target; `migration plan --to` (built for arbitrary targets) makes this a\n // real command, so the diagnostic that sends you here is now honest.\n const planCommand = (() => {\n if (planFromHash !== null && targetHash !== null) {\n return `prisma-next migration plan --from ${planFromHash} --to ${targetHash} --name <slug>`;\n }\n if (targetHash !== null) {\n return `prisma-next migration plan --to ${targetHash} --name <slug>`;\n }\n if (planFromHash !== null) {\n return `prisma-next migration plan --from ${planFromHash} --name <slug>`;\n }\n return 'prisma-next migration plan';\n })();\n const applyCommand =\n targetHash !== null ? `prisma-next migrate --to ${targetHash}` : 'prisma-next migrate';\n return errorRuntime(failure.summary, {\n why:\n failure.why ??\n `Cannot reach target \"${targetHash ?? '<unknown>'}\" from current marker \"${fromHashMeta ?? '<unknown>'}\".${deadEndsSuffix}`,\n fix: [\n 'Plan the missing edge, then apply it:',\n ` 1. ${planCommand}`,\n ` 2. ${applyCommand}`,\n 'A rollback (reverse) plan is expected to contain destructive (DROP) operations — review them before applying.',\n 'Narrower cases (rename inference, re-adding a NOT NULL column without a safe default, or a type change that needs data) may additionally need a hint in the planned migration.',\n 'Inspect the on-disk graph with `prisma-next migration list`, or `prisma-next migration show <bundle>` for any bundle in the path you expected.',\n ].join('\\n'),\n meta: {\n ...meta,\n code: 'MIGRATION.PATH_UNREACHABLE',\n },\n });\n}\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\n/**\n * Maps a `RefResolutionError` from the contract/migration reference\n * resolver into a CLI structured error envelope.\n */\nexport function mapRefResolutionError(error: RefResolutionError): CliStructuredError {\n switch (error.kind) {\n case 'not-found':\n return errorRuntime(`Not a known ${error.grammar} reference: \"${error.input}\"`, {\n why: `No ${error.grammar} matching \"${error.input}\" exists in the migration graph or refs index.`,\n fix:\n error.grammar === 'contract'\n ? 'Provide a valid contract hash, ref name, or migration directory name.'\n : 'Provide a valid migration directory name or migration hash.',\n meta: { input: error.input, grammar: error.grammar },\n });\n case 'ambiguous':\n return errorRuntime(`Ambiguous ${error.grammar} reference: \"${error.input}\"`, {\n why: `\"${error.input}\" matches multiple ${error.grammar}s: ${error.candidates.join(', ')}`,\n fix: 'Provide a longer prefix or use the full hash to disambiguate.',\n meta: { input: error.input, candidates: error.candidates, grammar: error.grammar },\n });\n case 'wrong-grammar':\n return errorRuntime(error.message, {\n why: error.message,\n fix: error.fix,\n meta: { input: error.input, expectedGrammar: error.expectedGrammar },\n });\n case 'invalid-format':\n return errorRuntime(`Invalid reference format: \"${error.input}\"`, {\n why: error.reason,\n fix: 'Provide a valid contract hash, ref name, or migration directory name.',\n meta: { input: error.input },\n });\n }\n}\n","import { dim } from 'colorette';\n\nimport type { GlobalFlags } from '../global-flags';\n\n/**\n * Checks if verbose output is enabled at the specified level.\n */\nexport function isVerbose(flags: GlobalFlags, level: 1 | 2): boolean {\n return (flags.verbose ?? 0) >= level;\n}\n\n/**\n * Creates a color-aware formatter function.\n * Returns a function that applies the color only if colors are enabled.\n */\nexport function createColorFormatter<T extends (text: string) => string>(\n useColor: boolean,\n colorFn: T,\n): (text: string) => string {\n return useColor ? colorFn : (text: string) => text;\n}\n\n/**\n * Formats text with dim styling if colors are enabled.\n */\nexport function formatDim(useColor: boolean, text: string): string {\n return useColor ? dim(text) : text;\n}\n","import { blue, bold, cyan, green } from 'colorette';\nimport type { Command } from 'commander';\nimport stringWidth from 'string-width';\nimport stripAnsi from 'strip-ansi';\n\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim } from './helpers';\n\n// ============================================================================\n// Styled Output Formatters\n// ============================================================================\n\n/**\n * Fixed width for left column in help output.\n */\nconst LEFT_COLUMN_WIDTH = 20;\n\n/**\n * Creates an arrow segment badge with green background and white text.\n * Body: green background with white \"prisma-next\" text\n * Tip: dark grey arrow pointing right (Powerline separator)\n */\nfunction createPrismaNextBadge(useColor: boolean): string {\n if (!useColor) {\n return 'prisma-next';\n }\n return bold('prisma-next');\n}\n\n/**\n * Creates a padding function.\n */\nfunction createPadFunction(): (s: string, w: number) => string {\n return (s: string, w: number) => s + ' '.repeat(Math.max(0, w - s.length));\n}\n\n/**\n * Formats a header line: brand + operation + intent\n */\nfunction formatHeaderLine(options: {\n readonly brand: string;\n readonly operation: string;\n readonly intent: string;\n}): string {\n if (options.operation) {\n return `${options.brand} ${options.operation} → ${options.intent}`;\n }\n return `${options.brand} ${options.intent}`;\n}\n\n/**\n * Formats a \"Read more\" URL line.\n * The \"Read more\" label is in default color (not cyan), and the URL is blue.\n */\nfunction formatReadMoreLine(options: {\n readonly url: string;\n readonly maxLabelWidth: number;\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n}): string {\n const pad = createPadFunction();\n const labelPadded = pad('Read more', options.maxLabelWidth);\n // Label is default color (not cyan)\n const valueColored = options.useColor ? blue(options.url) : options.url;\n return `${options.formatDimText('│')} ${labelPadded} ${valueColored}`;\n}\n\n/**\n * Pads text to a fixed width, accounting for ANSI escape codes.\n * Uses string-width to measure the actual display width.\n */\nexport function padToFixedWidth(text: string, width: number): string {\n const actualWidth = stringWidth(text);\n const padding = Math.max(0, width - actualWidth);\n return text + ' '.repeat(padding);\n}\n\n/**\n * Renders a command tree structure.\n * Handles both single-level (subcommands of a command) and multi-level (top-level commands with subcommands) trees.\n */\nexport function renderCommandTree(options: {\n readonly commands: readonly Command[];\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n readonly hasItemsAfter: boolean;\n readonly continuationPrefix?: string;\n}): string[] {\n const { commands, useColor, formatDimText, hasItemsAfter, continuationPrefix } = options;\n const lines: string[] = [];\n\n if (commands.length === 0) {\n return lines;\n }\n\n // Format each command\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (!cmd) continue;\n\n const subcommands = cmd.commands.filter((subcmd) => !subcmd.name().startsWith('_'));\n const isLastCommand = i === commands.length - 1;\n\n if (subcommands.length > 0) {\n // Command with subcommands - show command name, then tree-structured subcommands\n const treeChar = isLastCommand && !hasItemsAfter ? formatDimText('└') : formatDimText('├');\n // For top-level command, pad name to fixed width (accounting for \"| |-- \" = 5 chars)\n const treePrefix = `${treeChar}─ `;\n const treePrefixWidth = stringWidth(stripAnsi(treePrefix));\n const remainingWidth = LEFT_COLUMN_WIDTH - treePrefixWidth;\n const commandNamePadded = padToFixedWidth(cmd.name(), remainingWidth);\n const commandNameColored = useColor ? cyan(commandNamePadded) : commandNamePadded;\n lines.push(`${formatDimText('│')} ${treePrefix}${commandNameColored}`);\n\n for (let j = 0; j < subcommands.length; j++) {\n const subcmd = subcommands[j];\n if (!subcmd) continue;\n\n const isLastSubcommand = j === subcommands.length - 1;\n const shortDescription = subcmd.description() || '';\n\n // Use tree characters: -- for last subcommand, |-- for others\n const treeChar = isLastSubcommand ? '└' : '├';\n const continuation =\n continuationPrefix ??\n (isLastCommand && isLastSubcommand && !hasItemsAfter ? ' ' : formatDimText('│'));\n // For subcommands, account for \"| | -- \" = 7 chars (or \"| -- \" = 6 chars if continuation is space)\n const continuationStr = continuation === ' ' ? ' ' : continuation;\n const subTreePrefix = `${continuationStr} ${formatDimText(treeChar)}─ `;\n const subTreePrefixWidth = stringWidth(stripAnsi(subTreePrefix));\n const subRemainingWidth = LEFT_COLUMN_WIDTH - subTreePrefixWidth;\n const subcommandNamePadded = padToFixedWidth(subcmd.name(), subRemainingWidth);\n const subcommandNameColored = useColor ? cyan(subcommandNamePadded) : subcommandNamePadded;\n lines.push(\n `${formatDimText('│')} ${subTreePrefix}${subcommandNameColored} ${shortDescription}`,\n );\n }\n } else {\n // Standalone command - show command name and description on same line\n const treeChar = isLastCommand && !hasItemsAfter ? formatDimText('└') : formatDimText('├');\n const treePrefix = `${treeChar}─ `;\n const treePrefixWidth = stringWidth(stripAnsi(treePrefix));\n const remainingWidth = LEFT_COLUMN_WIDTH - treePrefixWidth;\n const commandNamePadded = padToFixedWidth(cmd.name(), remainingWidth);\n const commandNameColored = useColor ? cyan(commandNamePadded) : commandNamePadded;\n const shortDescription = cmd.description() || '';\n lines.push(`${formatDimText('│')} ${treePrefix}${commandNameColored} ${shortDescription}`);\n }\n }\n\n return lines;\n}\n\n/**\n * Formats the header in the new experimental visual style.\n * This header appears at the start of command output, showing the operation,\n * intent, documentation link, and parameters.\n */\nexport function formatStyledHeader(options: {\n readonly command: string;\n readonly description: string;\n readonly url?: string;\n readonly details: ReadonlyArray<{ readonly label: string; readonly value: string }>;\n readonly flags: GlobalFlags;\n}): string {\n const lines: string[] = [];\n const useColor = options.flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Header: arrow + operation badge + intent\n const brand = createPrismaNextBadge(useColor);\n // Use full command path (e.g., \"contract emit\" not just \"emit\")\n const operation = useColor ? bold(options.command) : options.command;\n const intent = formatDimText(options.description);\n lines.push(formatHeaderLine({ brand, operation, intent }));\n lines.push(formatDimText('│')); // Vertical line separator between command and params\n\n // Format details using fixed left column width (same style as help text options)\n for (const detail of options.details) {\n // Add colon to label, then pad to fixed width using padToFixedWidth for ANSI-aware padding\n const labelWithColon = `${detail.label}:`;\n const labelPadded = padToFixedWidth(labelWithColon, LEFT_COLUMN_WIDTH);\n const labelColored = useColor ? cyan(labelPadded) : labelPadded;\n lines.push(`${formatDimText('│')} ${labelColored} ${detail.value}`);\n }\n\n // Add \"Read more\" URL if present (same style as help text)\n if (options.url) {\n lines.push(formatDimText('│')); // Separator line before \"Read more\"\n lines.push(\n formatReadMoreLine({\n url: options.url,\n maxLabelWidth: LEFT_COLUMN_WIDTH,\n useColor,\n formatDimText,\n }),\n );\n }\n\n lines.push(formatDimText('└'));\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Formats a success message in the styled output format.\n */\nexport function formatSuccessMessage(flags: GlobalFlags): string {\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n return `${formatGreen('✔')} Success`;\n}\n","import { blue, bold, cyan, dim, green, magenta } from 'colorette';\nimport type { Command } from 'commander';\nimport wrapAnsi from 'wrap-ansi';\n\nimport { getCommandExamples, getCommandSeeAlso, getLongDescription } from '../command-helpers';\nimport type { GlobalFlags } from '../global-flags';\nimport { formatDim } from './helpers';\nimport { padToFixedWidth, renderCommandTree } from './styled';\n\n// ============================================================================\n// Help Output Formatters\n// ============================================================================\n\n/**\n * Fixed width for left column in help output.\n * Must match the value in styled.ts.\n */\nconst LEFT_COLUMN_WIDTH = 20;\n\n/**\n * Minimum width for right column wrapping in help output.\n */\nconst RIGHT_COLUMN_MIN_WIDTH = 40;\n\n/**\n * Maximum width for right column wrapping in help output (when terminal is wide enough).\n */\nconst RIGHT_COLUMN_MAX_WIDTH = 90;\n\n/**\n * Gets the terminal width, or returns a default if not available.\n */\nfunction getTerminalWidth(): number {\n // Help text goes to stderr, so prefer stderr columns. Fall back to stdout, then CLI_WIDTH env.\n const terminalWidth = process.stderr.columns || process.stdout.columns;\n const envWidth = Number.parseInt(process.env['CLI_WIDTH'] || '', 10);\n return terminalWidth || (Number.isFinite(envWidth) ? envWidth : 80);\n}\n\n/**\n * Calculates the available width for the right column based on terminal width.\n */\nfunction calculateRightColumnWidth(): number {\n const terminalWidth = getTerminalWidth();\n const availableWidth = terminalWidth - 2 - LEFT_COLUMN_WIDTH - 2;\n return Math.max(RIGHT_COLUMN_MIN_WIDTH, Math.min(availableWidth, RIGHT_COLUMN_MAX_WIDTH));\n}\n\n/**\n * Creates the CLI brand badge.\n */\nfunction createPrismaNextBadge(useColor: boolean): string {\n return useColor ? bold('prisma-next') : 'prisma-next';\n}\n\n/**\n * Formats a header line: brand + operation + intent\n */\nfunction formatHeaderLine(options: {\n readonly brand: string;\n readonly operation: string;\n readonly intent: string;\n}): string {\n if (options.operation) {\n return `${options.brand} ${options.operation} → ${options.intent}`;\n }\n return `${options.brand} ${options.intent}`;\n}\n\n/**\n * Wraps text to fit within a specified width using wrap-ansi.\n */\nfunction wrapTextAnsi(text: string, width: number): string[] {\n const wrapped = wrapAnsi(text, width, { hard: false, trim: true });\n return wrapped.split('\\n');\n}\n\n/**\n * Formats a default value as \"default: <value>\" with dimming.\n */\nfunction formatDefaultValue(value: unknown, useColor: boolean): string {\n const valueStr = String(value);\n const defaultText = `default: ${valueStr}`;\n return useColor ? dim(defaultText) : defaultText;\n}\n\n/**\n * Formats a \"Read more\" URL line.\n */\nfunction formatReadMoreLine(options: {\n readonly url: string;\n readonly maxLabelWidth: number;\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n}): string {\n const labelPadded = `Read more${' '.repeat(Math.max(0, options.maxLabelWidth - 'Read more'.length))}`;\n const valueColored = options.useColor ? blue(options.url) : options.url;\n return `${options.formatDimText('│')} ${labelPadded} ${valueColored}`;\n}\n\n/**\n * Formats multiline description with \"Prisma Next\" in green.\n */\nfunction formatMultilineDescription(options: {\n readonly descriptionLines: readonly string[];\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n}): string[] {\n const lines: string[] = [];\n const formatGreen = (text: string) => (options.useColor ? green(text) : text);\n\n const rightColumnWidth = calculateRightColumnWidth();\n const totalWidth = 2 + LEFT_COLUMN_WIDTH + 2 + rightColumnWidth;\n const wrapWidth = totalWidth - 2;\n\n for (const descLine of options.descriptionLines) {\n const formattedLine = descLine.replace(/Prisma Next/g, (match) => formatGreen(match));\n const wrappedLines = wrapTextAnsi(formattedLine, wrapWidth);\n for (const wrappedLine of wrappedLines) {\n lines.push(`${options.formatDimText('│')} ${wrappedLine}`);\n }\n }\n return lines;\n}\n\n/**\n * Maps command paths to their documentation URLs.\n */\nfunction getCommandDocsUrl(commandPath: string): string | undefined {\n const docsMap: Record<string, string> = {\n 'contract emit': 'https://pris.ly/contract-emit',\n 'contract infer': 'https://pris.ly/contract-infer',\n 'db schema': 'https://pris.ly/db-schema',\n 'db verify': 'https://pris.ly/db-verify',\n 'db update': 'https://pris.ly/db-update',\n 'migration plan': 'https://pris.ly/migration-plan',\n migrate: 'https://pris.ly/migrate',\n 'migration show': 'https://pris.ly/migration-show',\n 'migration status': 'https://pris.ly/migration-status',\n };\n return docsMap[commandPath];\n}\n\n/**\n * Builds the full command path from a command and its parents.\n */\nfunction buildCommandPath(command: Command): string {\n const parts: string[] = [];\n let current: Command | undefined = command;\n while (current && current.name() !== 'prisma-next') {\n parts.unshift(current.name());\n current = current.parent ?? undefined;\n }\n return parts.join(' ');\n}\n\n/**\n * Formats help output for a command using the styled format.\n */\nexport function formatCommandHelp(options: {\n readonly command: Command;\n readonly flags: GlobalFlags;\n}): string {\n const { command, flags } = options;\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Build full command path (e.g., \"db verify\")\n const commandPath = buildCommandPath(command);\n const shortDescription = command.description() || '';\n const longDescription = getLongDescription(command);\n\n // Include positional arguments in the header line\n const argsSuffix = command.registeredArguments\n .map((arg) => (arg.required ? `<${arg.name()}>` : `[${arg.name()}]`))\n .join(' ');\n const brand = createPrismaNextBadge(useColor);\n const commandWithArgs = argsSuffix ? `${commandPath} ${argsSuffix}` : commandPath;\n const operation = useColor ? bold(commandWithArgs) : commandWithArgs;\n const intent = formatDimText(shortDescription);\n lines.push(formatHeaderLine({ brand, operation, intent }));\n lines.push(formatDimText('│'));\n\n // Extract options and format them\n const optionsList = command.options.map((opt) => {\n const description = opt.description || '';\n // Commander.js stores default value in defaultValue property\n const defaultValue = (opt as { defaultValue?: unknown }).defaultValue;\n return { flags: opt.flags, description, defaultValue };\n });\n\n // Extract subcommands if any\n const subcommands = command.commands.filter((cmd) => !cmd.name().startsWith('_'));\n\n // Format subcommands as a tree if present\n if (subcommands.length > 0) {\n const hasItemsAfter = optionsList.length > 0;\n const treeLines = renderCommandTree({\n commands: subcommands,\n useColor,\n formatDimText,\n hasItemsAfter,\n });\n lines.push(...treeLines);\n }\n\n // Add separator between subcommands and options if both exist\n if (subcommands.length > 0 && optionsList.length > 0) {\n lines.push(formatDimText('│'));\n }\n\n // Format options with fixed width, wrapping, and default values\n if (optionsList.length > 0) {\n for (const opt of optionsList) {\n // Format flag with fixed 30-char width\n const flagsPadded = padToFixedWidth(opt.flags, LEFT_COLUMN_WIDTH);\n let flagsColored = flagsPadded;\n if (useColor) {\n // Color placeholders in magenta, then wrap in cyan\n flagsColored = flagsPadded.replace(/(<[^>]+>)/g, (match: string) => magenta(match));\n flagsColored = cyan(flagsColored);\n }\n\n // Wrap description based on terminal width\n const rightColumnWidth = calculateRightColumnWidth();\n const wrappedDescription = wrapTextAnsi(opt.description, rightColumnWidth);\n\n // First line: flag + first line of description\n lines.push(`${formatDimText('│')} ${flagsColored} ${wrappedDescription[0] || ''}`);\n\n // Continuation lines: empty label (30 spaces) + wrapped lines\n for (let i = 1; i < wrappedDescription.length; i++) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${wrappedDescription[i] || ''}`);\n }\n\n // Default value line (if present)\n if (opt.defaultValue !== undefined) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n const defaultText = formatDefaultValue(opt.defaultValue, useColor);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${defaultText}`);\n }\n }\n }\n\n // Add docs URL if available (with separator line before it)\n const docsUrl = getCommandDocsUrl(commandPath);\n if (docsUrl) {\n lines.push(formatDimText('│')); // Separator line between params and docs\n lines.push(\n formatReadMoreLine({\n url: docsUrl,\n maxLabelWidth: LEFT_COLUMN_WIDTH,\n useColor,\n formatDimText,\n }),\n );\n }\n\n // Examples (copy-pastable)\n const examples = getCommandExamples(command);\n if (examples && examples.length > 0) {\n lines.push(formatDimText('│'));\n lines.push(`${formatDimText('│')} ${formatDimText('Examples:')}`);\n for (const example of examples) {\n lines.push(`${formatDimText('│')} ${useColor ? dim('$') : '$'} ${example}`);\n }\n }\n\n // See also (cross-references to related commands)\n const seeAlso = getCommandSeeAlso(command);\n if (seeAlso && seeAlso.length > 0) {\n lines.push(formatDimText('│'));\n lines.push(`${formatDimText('│')} ${formatDimText('See also:')}`);\n for (const ref of seeAlso) {\n lines.push(`${formatDimText('│')} ${ref.verb} ${formatDimText(ref.oneLiner)}`);\n }\n }\n\n // Multi-line description (if present) - shown after all other content\n if (longDescription) {\n lines.push(formatDimText('│'));\n const descriptionLines = longDescription.split('\\n').filter((line) => line.trim().length > 0);\n lines.push(...formatMultilineDescription({ descriptionLines, useColor, formatDimText }));\n }\n\n lines.push(formatDimText('└'));\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Formats help output for the root program using the styled format.\n */\nexport function formatRootHelp(options: {\n readonly program: Command;\n readonly flags: GlobalFlags;\n}): string {\n const { program, flags } = options;\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Header: \"prisma-next -> Manage your data layer\"\n const brand = createPrismaNextBadge(useColor);\n const shortDescription = 'Manage your data layer';\n const intent = formatDimText(shortDescription);\n lines.push(formatHeaderLine({ brand, operation: '', intent }));\n lines.push(formatDimText('│')); // Vertical line separator after header\n\n // Extract top-level commands (exclude hidden commands starting with '_' and the 'help' command)\n const topLevelCommands = program.commands.filter(\n (cmd) => !cmd.name().startsWith('_') && cmd.name() !== 'help',\n );\n\n // Extract global options (needed to determine if last command)\n const globalOptions = program.options.map((opt) => {\n const description = opt.description || '';\n // Commander.js stores default value in defaultValue property\n const defaultValue = (opt as { defaultValue?: unknown }).defaultValue;\n return { flags: opt.flags, description, defaultValue };\n });\n\n // Build command tree\n if (topLevelCommands.length > 0) {\n const hasItemsAfter = globalOptions.length > 0;\n const treeLines = renderCommandTree({\n commands: topLevelCommands,\n useColor,\n formatDimText,\n hasItemsAfter,\n });\n lines.push(...treeLines);\n }\n\n // Add separator between commands and options if both exist\n if (topLevelCommands.length > 0 && globalOptions.length > 0) {\n lines.push(formatDimText('│'));\n }\n\n // Format global options with fixed width, wrapping, and default values\n if (globalOptions.length > 0) {\n for (const opt of globalOptions) {\n // Format flag with fixed 30-char width\n const flagsPadded = padToFixedWidth(opt.flags, LEFT_COLUMN_WIDTH);\n let flagsColored = flagsPadded;\n if (useColor) {\n // Color placeholders in magenta, then wrap in cyan\n flagsColored = flagsPadded.replace(/(<[^>]+>)/g, (match: string) => magenta(match));\n flagsColored = cyan(flagsColored);\n }\n\n // Wrap description based on terminal width\n const rightColumnWidth = calculateRightColumnWidth();\n const wrappedDescription = wrapTextAnsi(opt.description, rightColumnWidth);\n\n // First line: flag + first line of description\n lines.push(`${formatDimText('│')} ${flagsColored} ${wrappedDescription[0] || ''}`);\n\n // Continuation lines: empty label (30 spaces) + wrapped lines\n for (let i = 1; i < wrappedDescription.length; i++) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${wrappedDescription[i] || ''}`);\n }\n\n // Default value line (if present)\n if (opt.defaultValue !== undefined) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n const defaultText = formatDefaultValue(opt.defaultValue, useColor);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${defaultText}`);\n }\n }\n }\n\n // Multi-line description (white, not dimmed, with \"Prisma Next\" in green) - shown at bottom\n const formatGreen = (text: string) => (useColor ? green(text) : text);\n const descriptionLines = [\n `Use ${formatGreen('Prisma Next')} to define your data layer as a contract. Sign your database and application with the same contract to guarantee compatibility. Plan and apply migrations to safely evolve your schema.`,\n ];\n if (descriptionLines.length > 0) {\n lines.push(formatDimText('│')); // Separator line before description\n lines.push(...formatMultilineDescription({ descriptionLines, useColor, formatDimText }));\n }\n\n lines.push(formatDimText('└'));\n\n return `${lines.join('\\n')}\\n`;\n}\n","import { isCI as ciInfoIsCI } from 'ci-info';\n\n/**\n * Returns true when the process is running in any CI environment recognised\n * by the `ci-info` package. The single source of truth for CI detection\n * across this CLI — colour-output suppression and telemetry-skip both call\n * this helper, so neither path drifts from the other when a new CI provider\n * is added upstream.\n *\n * `ci-info` checks the standard `CI=true` marker plus dozens of\n * provider-specific environment variables (Buildkite, Jenkins, Drone,\n * Bitbucket Pipelines, Azure Pipelines, AWS CodeBuild, …) that the raw\n * `process.env.CI` read misses.\n *\n */\nexport function isCI(): boolean {\n return ciInfoIsCI;\n}\n","import { red } from 'colorette';\n\nimport type { CliErrorConflict, CliErrorEnvelope } from '../cli-errors';\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim, isVerbose } from './helpers';\n\n/**\n * Formats error output for human-readable display.\n */\nexport function formatErrorOutput(error: CliErrorEnvelope, flags: GlobalFlags): string {\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatRed = createColorFormatter(useColor, red);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n lines.push(`${formatRed('✖')} ${error.summary} (${error.code})`);\n\n if (error.why) {\n lines.push(`${formatDimText(` Why: ${error.why}`)}`);\n }\n if (error.fix) {\n lines.push(`${formatDimText(` Fix: ${error.fix}`)}`);\n }\n if (error.where?.path) {\n const whereLine = error.where.line\n ? `${error.where.path}:${error.where.line}`\n : error.where.path;\n lines.push(`${formatDimText(` Where: ${whereLine}`)}`);\n }\n // Show conflicts list if present (always show a short list; show full list when verbose)\n if (error.meta?.['conflicts']) {\n const conflicts = error.meta['conflicts'] as readonly CliErrorConflict[];\n if (conflicts.length > 0) {\n const maxToShow = isVerbose(flags, 1) ? conflicts.length : Math.min(3, conflicts.length);\n const header = isVerbose(flags, 1)\n ? ' Conflicts:'\n : ` Conflicts (showing ${maxToShow} of ${conflicts.length}):`;\n lines.push(`${formatDimText(header)}`);\n for (const conflict of conflicts.slice(0, maxToShow)) {\n lines.push(`${formatDimText(` - [${conflict.kind}] ${conflict.summary}`)}`);\n }\n if (!isVerbose(flags, 1) && conflicts.length > maxToShow) {\n lines.push(`${formatDimText(' Re-run with -v/--verbose to see all conflicts')}`);\n }\n }\n }\n // Show issues list if present (always show a short list; show full list when verbose)\n if (error.meta?.['issues']) {\n const issues = error.meta['issues'] as readonly { kind?: string; message?: string }[];\n if (issues.length > 0) {\n const maxToShow = isVerbose(flags, 1) ? issues.length : Math.min(3, issues.length);\n const header = isVerbose(flags, 1)\n ? ' Issues:'\n : ` Issues (showing ${maxToShow} of ${issues.length}):`;\n lines.push(`${formatDimText(header)}`);\n for (const issue of issues.slice(0, maxToShow)) {\n const kind = issue.kind ?? 'issue';\n const message = issue.message ?? '';\n lines.push(`${formatDimText(` - [${kind}] ${message}`)}`);\n }\n if (!isVerbose(flags, 1) && issues.length > maxToShow) {\n lines.push(`${formatDimText(' Re-run with -v/--verbose to see all issues')}`);\n }\n }\n }\n if (error.docsUrl && isVerbose(flags, 1)) {\n lines.push(formatDimText(error.docsUrl));\n }\n if (isVerbose(flags, 2) && error.meta) {\n lines.push(`${formatDimText(` Meta: ${JSON.stringify(error.meta, null, 2)}`)}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats error output as JSON.\n */\nexport function formatErrorJson(error: CliErrorEnvelope): string {\n return JSON.stringify(error, null, 2);\n}\n","import type { Result } from '@prisma-next/utils/result';\nimport type { CliStructuredError } from './cli-errors';\nimport { formatErrorJson, formatErrorOutput } from './formatters/errors';\nimport type { GlobalFlags } from './global-flags';\nimport type { TerminalUI } from './terminal-ui';\n\n/**\n * Processes a CLI command result, handling both success and error cases.\n * Formats output appropriately and returns the exit code.\n * Never throws - returns exit code for commands to use with process.exit().\n *\n * Error output:\n * - JSON mode: JSON error to stdout (piped) via ui.output(), human sees nothing on stderr.\n * - Interactive: human-readable error to stderr.\n */\nexport function handleResult<T>(\n result: Result<T, CliStructuredError>,\n flags: GlobalFlags,\n ui: TerminalUI,\n onSuccess?: (value: T) => void,\n): number {\n if (result.ok) {\n if (onSuccess) {\n onSuccess(result.value);\n }\n return 0;\n }\n\n // Convert to CLI envelope\n const envelope = result.failure.toEnvelope();\n\n if (flags.json) {\n // JSON error → stdout only\n ui.output(formatErrorJson(envelope));\n } else {\n // Human-readable error → stderr\n ui.error(formatErrorOutput(envelope, flags));\n }\n\n // Infer exit code from error domain: CLI errors = 2, RUN errors = 1\n const exitCode = result.failure.domain === 'CLI' ? 2 : 1;\n return exitCode;\n}\n","export type GlyphMode = 'unicode' | 'ascii';\n\nexport interface GlyphModeInput {\n readonly isTTY: boolean;\n readonly env: Readonly<Record<string, string | undefined>>;\n}\n\nfunction localeString(env: Readonly<Record<string, string | undefined>>): string {\n return env['LC_ALL'] ?? env['LC_CTYPE'] ?? env['LANG'] ?? '';\n}\n\nfunction isUtf8Locale(env: Readonly<Record<string, string | undefined>>): boolean {\n const locale = localeString(env);\n if (locale.length === 0) return false;\n return /UTF-8|utf8/i.test(locale);\n}\n\nexport function detectGlyphMode(input: GlyphModeInput): GlyphMode {\n if (!input.isTTY) return 'ascii';\n if (!isUtf8Locale(input.env)) return 'ascii';\n return 'unicode';\n}\n","/**\n * Global shutdown controller for graceful SIGINT/SIGTERM handling.\n *\n * The CLI installs signal handlers once at startup. When a signal fires:\n * 1. The AbortController is aborted — in-flight async work (DB queries, emit) can check `signal.aborted`.\n * 2. A 3-second grace timer starts — gives `finally` blocks time to close connections.\n * 3. If the process hasn't exited by then, force-exit with code 130 (128 + SIGINT).\n * 4. A second signal during the grace period force-exits immediately.\n */\n\n/**\n * Creates a shutdown handler with its own AbortController.\n * Exposed for testing — production code uses the singleton below.\n */\nexport interface ShutdownHandler {\n readonly signal: AbortSignal;\n readonly isShuttingDown: () => boolean;\n readonly onSignal: () => void;\n readonly clearGraceTimer: () => void;\n}\n\nexport function createShutdownHandler(options?: {\n readonly exit?: (code: number) => void;\n readonly gracePeriodMs?: number;\n}): ShutdownHandler {\n const exit = options?.exit ?? ((code: number) => process.exit(code));\n const gracePeriodMs = options?.gracePeriodMs ?? 3000;\n\n const controller = new AbortController();\n let shuttingDown = false;\n let graceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const onSignal = () => {\n if (shuttingDown) {\n // Second signal — force exit\n exit(130);\n return;\n }\n shuttingDown = true;\n controller.abort();\n\n // Give finally blocks time to clean up, then force-exit\n graceTimer = setTimeout(() => exit(130), gracePeriodMs);\n graceTimer.unref();\n };\n\n return {\n signal: controller.signal,\n isShuttingDown: () => shuttingDown,\n onSignal,\n clearGraceTimer: () => {\n if (graceTimer !== undefined) {\n clearTimeout(graceTimer);\n graceTimer = undefined;\n }\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Singleton for production use\n// ---------------------------------------------------------------------------\n\nconst globalHandler = createShutdownHandler();\n\n/**\n * The global AbortSignal. Pass this to any async operation that should\n * be cancellable on Ctrl+C (e.g., DB queries, long-running emit).\n */\nexport const shutdownSignal: AbortSignal = globalHandler.signal;\n\n/**\n * Whether a shutdown has been initiated.\n */\nexport function isShuttingDown(): boolean {\n return globalHandler.isShuttingDown();\n}\n\n/**\n * Installs SIGINT and SIGTERM handlers. Call once at CLI startup.\n *\n * - First signal: aborts the controller, starts a 3s grace timer.\n * - Second signal: force-exits immediately.\n */\nlet installed = false;\n\nexport function installShutdownHandlers(): void {\n if (installed) return;\n installed = true;\n process.on('SIGINT', globalHandler.onSignal);\n process.on('SIGTERM', globalHandler.onSignal);\n}\n","import * as clack from '@clack/prompts';\nimport { bold, cyan, dim, green, red, yellow } from 'colorette';\nimport type { GlobalFlags } from './global-flags';\nimport { detectGlyphMode, type GlyphMode, type GlyphModeInput } from './glyph-mode';\nimport { shutdownSignal } from './shutdown';\n\nexport interface TerminalUIRuntime extends GlyphModeInput {}\n\n/**\n * Composable CLI output abstraction.\n *\n * Follows the Unix convention of separating data from decoration:\n * - **stdout** — data output only (`ui.output()`). This is what scripts and pipes capture.\n * - **stderr** — all decoration (spinners, logs, notes, intro/outro). Visible in terminal, invisible in pipes.\n *\n * Rules:\n * 1. All methods except `output()` and `error()` write to stderr only in interactive mode.\n * 2. `output(data)` always writes to stdout — if a command calls it, there is data to emit.\n * 3. `error()` always writes to stderr — errors matter even when piped.\n * 4. Decoration is suppressed when piped unless `--format pretty` was explicit (`forcePretty`).\n * 5. Never write data to stderr — decoration methods are for human context only.\n * 6. Never write decoration to stdout — it breaks pipes, `$(...)` captures, and `> file` redirects.\n */\nexport class TerminalUI {\n /**\n * True when stdout is a TTY (interactive terminal).\n * False when piped (e.g., `prisma-next db verify | jq`).\n */\n readonly isInteractive: boolean;\n\n /**\n * Whether color output is enabled.\n */\n readonly useColor: boolean;\n\n /**\n * When true, decoration methods write even on non-TTY stdout\n * (explicit `--format pretty`).\n */\n readonly forcePretty: boolean;\n\n /**\n * Whether stdout is a TTY — used for migration-list graph glyph detection.\n */\n readonly stdoutIsTTY: boolean;\n\n /**\n * Process environment snapshot for locale-aware glyph detection.\n */\n readonly env: Readonly<Record<string, string | undefined>>;\n\n private static readonly stderrOpts = { output: process.stderr } as const;\n\n constructor(options?: {\n readonly color?: boolean | undefined;\n readonly interactive?: boolean | undefined;\n readonly forcePretty?: boolean | undefined;\n readonly stdoutIsTTY?: boolean | undefined;\n readonly env?: Readonly<Record<string, string | undefined>> | undefined;\n }) {\n // --interactive/--no-interactive override TTY detection\n this.isInteractive = options?.interactive ?? !!process.stdout.isTTY;\n this.forcePretty = options?.forcePretty ?? false;\n this.useColor = options?.color ?? (this.isInteractive || this.forcePretty);\n this.stdoutIsTTY = options?.stdoutIsTTY ?? !!process.stdout.isTTY;\n this.env = options?.env ?? process.env;\n }\n\n get isTTY(): boolean {\n return this.stdoutIsTTY;\n }\n\n /**\n * Resolve glyph mode for migration list/tree output. `--ascii` forces ASCII;\n * otherwise delegates to the pure {@link detectGlyphMode} helper.\n */\n resolveGlyphMode(forceAscii: boolean): GlyphMode {\n if (forceAscii) {\n return 'ascii';\n }\n return detectGlyphMode(this.glyphModeInput());\n }\n\n glyphModeInput(): GlyphModeInput {\n return { isTTY: this.stdoutIsTTY, env: this.env };\n }\n\n private get shouldDecorate(): boolean {\n return this.isInteractive || this.forcePretty;\n }\n\n // ---------------------------------------------------------------------------\n // Decoration → stderr (interactive mode, or explicit --format pretty)\n // ---------------------------------------------------------------------------\n\n /**\n * Log a message line to stderr. No-op when piped unless forcePretty.\n */\n log(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.message(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log a success message to stderr. No-op when piped unless forcePretty.\n */\n success(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.success(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log a warning message to stderr. No-op when piped unless forcePretty.\n */\n warn(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.warn(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log an error message to stderr. Always writes (errors matter even in pipes).\n */\n error(message: string): void {\n clack.log.error(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log an info message to stderr. No-op when piped unless forcePretty.\n */\n info(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.info(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log a step message to stderr. No-op when piped unless forcePretty.\n */\n step(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.step(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Display a note box on stderr. No-op when piped unless forcePretty.\n */\n note(message: string, title?: string): void {\n if (!this.shouldDecorate) return;\n clack.note(message, title, TerminalUI.stderrOpts);\n }\n\n /**\n * Display intro banner on stderr. No-op when piped unless forcePretty.\n */\n intro(title?: string): void {\n if (!this.shouldDecorate) return;\n clack.intro(title, TerminalUI.stderrOpts);\n }\n\n /**\n * Display outro banner on stderr. No-op when piped unless forcePretty.\n */\n outro(message?: string): void {\n if (!this.shouldDecorate) return;\n clack.outro(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Create a Clack spinner on stderr with a 100ms delay threshold.\n * The spinner only appears if the operation takes longer than the threshold,\n * avoiding flicker for fast operations. Returns a no-op spinner when not decorating.\n */\n spinner(delayMs = 100): clack.SpinnerResult {\n const noop: clack.SpinnerResult = {\n start: () => {},\n stop: () => {},\n cancel: () => {},\n error: () => {},\n message: () => {},\n clear: () => {},\n get isCancelled() {\n return false;\n },\n };\n\n if (!this.shouldDecorate) {\n return noop;\n }\n\n // Wrap the real spinner with a delay: only show it after `delayMs`\n let inner: clack.SpinnerResult | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let pendingMsg: string | undefined;\n let settled = false;\n\n const ensureCleared = () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n };\n\n // Cancel the spinner if a shutdown signal fires\n const onAbort = () => {\n if (!settled) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.cancel('Interrupted');\n }\n }\n };\n if (!shutdownSignal.aborted) {\n shutdownSignal.addEventListener('abort', onAbort, { once: true });\n }\n\n return {\n start(msg?: string) {\n pendingMsg = msg;\n timer = setTimeout(() => {\n if (!settled) {\n inner = clack.spinner(TerminalUI.stderrOpts);\n inner.start(pendingMsg);\n }\n }, delayMs);\n },\n stop(msg?: string) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.stop(msg);\n }\n },\n cancel(msg?: string) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.cancel(msg);\n }\n },\n error(msg?: string) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.error(msg);\n }\n },\n message(msg?: string) {\n pendingMsg = msg;\n if (inner) {\n inner.message(msg);\n }\n },\n clear() {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.clear();\n }\n },\n get isCancelled() {\n return inner?.isCancelled ?? false;\n },\n };\n }\n\n /**\n * Prompt for yes/no confirmation on stderr. Returns true if confirmed.\n * In non-interactive mode or when cancelled (Ctrl-C), returns false.\n */\n async confirm(message: string): Promise<boolean> {\n if (!this.isInteractive) return false;\n const result = await clack.confirm({\n message,\n ...TerminalUI.stderrOpts,\n });\n if (clack.isCancel(result)) return false;\n return result;\n }\n\n /**\n * Write a raw line to stderr. No-op when piped unless forcePretty.\n * Use for decoration that doesn't fit Clack's log format (e.g. styled headers).\n */\n stderr(message: string): void {\n if (!this.shouldDecorate) return;\n process.stderr.write(`${message}\\n`);\n }\n\n // ---------------------------------------------------------------------------\n // Data → stdout (only when piped)\n // ---------------------------------------------------------------------------\n\n /**\n * Write machine-readable data to stdout.\n * Always writes — if a command calls output(), there is data to emit.\n *\n * This is what scripts and pipes capture: `prisma-next db verify --json | jq .ok`\n */\n output(data: string): void {\n process.stdout.write(`${data}\\n`);\n }\n\n // ---------------------------------------------------------------------------\n // Color helpers\n // ---------------------------------------------------------------------------\n\n green(text: string): string {\n return this.useColor ? green(text) : text;\n }\n red(text: string): string {\n return this.useColor ? red(text) : text;\n }\n cyan(text: string): string {\n return this.useColor ? cyan(text) : text;\n }\n dim(text: string): string {\n return this.useColor ? dim(text) : text;\n }\n bold(text: string): string {\n return this.useColor ? bold(text) : text;\n }\n yellow(text: string): string {\n return this.useColor ? yellow(text) : text;\n }\n}\n\nexport function createTerminalUI(\n flags: GlobalFlags,\n runtime?: Partial<TerminalUIRuntime>,\n): TerminalUI {\n return new TerminalUI({\n color: flags.color,\n interactive: flags.interactive,\n forcePretty: flags.format === 'pretty' && flags.explicitFormat,\n stdoutIsTTY: runtime?.isTTY,\n env: runtime?.env,\n });\n}\n","import { notOk } from '@prisma-next/utils/result';\nimport { CliStructuredError, errorInvalidOutputFormat, errorOutputFormatMutex } from './cli-errors';\nimport { isCI } from './is-ci';\nimport { handleResult } from './result-handler';\nimport { createTerminalUI } from './terminal-ui';\n\nexport type OutputFormat = 'pretty' | 'json';\n\nexport interface GlobalFlags {\n readonly format: OutputFormat;\n readonly explicitFormat: boolean;\n readonly json?: boolean;\n readonly quiet?: boolean;\n readonly verbose?: number;\n readonly color?: boolean;\n readonly interactive?: boolean;\n readonly yes?: boolean;\n}\n\n/**\n * Common options parsed by Commander.js for every command.\n * Extend this for command-specific options instead of duplicating these fields.\n */\nexport interface CommonCommandOptions {\n readonly format?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly trace?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n readonly interactive?: boolean;\n readonly 'no-interactive'?: boolean;\n readonly yes?: boolean;\n readonly y?: boolean;\n}\n\nfunction isJsonFlagSet(json: string | boolean | undefined): boolean {\n return json === true;\n}\n\ninterface ResolvedOutputFormat {\n readonly format: OutputFormat;\n readonly explicitFormat: boolean;\n}\n\nfunction resolveOutputFormat(options: CommonCommandOptions): ResolvedOutputFormat {\n const formatOption = options.format;\n const jsonFlag = isJsonFlagSet(options.json);\n\n if (formatOption !== undefined) {\n if (formatOption !== 'pretty' && formatOption !== 'json') {\n throw errorInvalidOutputFormat(formatOption);\n }\n if (jsonFlag && formatOption === 'pretty') {\n throw errorOutputFormatMutex();\n }\n return { format: formatOption, explicitFormat: true };\n }\n\n if (jsonFlag) {\n return { format: 'json', explicitFormat: false };\n }\n\n if (!process.stdout.isTTY) {\n return { format: 'json', explicitFormat: false };\n }\n\n return { format: 'pretty', explicitFormat: false };\n}\n\nfunction inferJsonModeForParseError(options: CommonCommandOptions): boolean {\n if (options.format === 'json') {\n return true;\n }\n if (isJsonFlagSet(options.json) && options.format !== 'pretty') {\n return true;\n }\n if (options.format !== undefined) {\n return false;\n }\n return !process.stdout.isTTY;\n}\n\nfunction emitGlobalFlagParseError(error: CliStructuredError, options: CommonCommandOptions): never {\n const jsonMode = inferJsonModeForParseError(options);\n const flags: GlobalFlags = {\n format: jsonMode ? 'json' : 'pretty',\n explicitFormat: false,\n ...(jsonMode ? { json: true } : {}),\n color: false,\n verbose: 0,\n interactive: false,\n };\n const ui = createTerminalUI(flags);\n const exitCode = handleResult(notOk(error), flags, ui);\n process.exit(exitCode);\n}\n\n/**\n * Parses global flags from CLI options.\n * Handles verbosity flags (-v, --trace), output format (--format, --json),\n * quiet mode, color, interactivity (--interactive/--no-interactive), and\n * auto-accept (-y/--yes).\n *\n * On invalid or conflicting format flags, prints a structured CLI error\n * envelope and exits with code 2.\n */\nexport function parseGlobalFlagsOrExit(options: CommonCommandOptions): GlobalFlags {\n try {\n return parseGlobalFlags(options);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n emitGlobalFlagParseError(error, options);\n }\n throw error;\n }\n}\n\n/**\n * Parses global flags from CLI options.\n * Handles verbosity flags (-v, --trace), output format (--format, --json),\n * quiet mode, color, interactivity (--interactive/--no-interactive), and\n * auto-accept (-y/--yes).\n *\n * Throws {@link CliStructuredError} for invalid or conflicting format flags.\n */\nexport function parseGlobalFlags(options: CommonCommandOptions): GlobalFlags {\n const { format, explicitFormat } = resolveOutputFormat(options);\n const flags: {\n format: OutputFormat;\n explicitFormat: boolean;\n json?: boolean;\n quiet?: boolean;\n verbose?: number;\n color?: boolean;\n interactive?: boolean;\n yes?: boolean;\n } = { format, explicitFormat };\n\n if (format === 'json') {\n flags.json = true;\n }\n\n if (options.quiet || options.q) {\n flags.quiet = true;\n }\n\n if (options.trace || process.env['PRISMA_NEXT_TRACE'] === '1') {\n flags.verbose = 2;\n } else if (options.verbose || options.v || process.env['PRISMA_NEXT_DEBUG'] === '1') {\n flags.verbose = 1;\n } else {\n flags.verbose = 0;\n }\n\n if (process.env['NO_COLOR'] || flags.json) {\n flags.color = false;\n } else if (options['no-color']) {\n flags.color = false;\n } else if (options.color !== undefined) {\n flags.color = options.color;\n } else {\n flags.color = process.stdout.isTTY && !isCI();\n }\n\n if (options['no-interactive']) {\n flags.interactive = false;\n } else if (options.interactive !== undefined) {\n flags.interactive = options.interactive;\n } else {\n flags.interactive = !!process.stdout.isTTY;\n }\n\n if (options.yes || options.y) {\n flags.yes = true;\n }\n\n return flags as GlobalFlags;\n}\n","import { readFile } from 'node:fs/promises';\nimport type { ControlTargetDescriptor } from '@prisma-next/framework-components/control';\nimport { hasMigrations } from '@prisma-next/framework-components/control';\nimport type { NoInvariantPathStructuralEdge } from '@prisma-next/migration-tools/errors';\nimport type { MigrationEdge, MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport type { PathDecision } from '@prisma-next/migration-tools/migration-graph';\nimport { APP_SPACE_ID, spaceMigrationDirectory } from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { errorRuntime } from './cli-errors';\nimport { formatCommandHelp } from './formatters/help';\nimport type { CommonCommandOptions } from './global-flags';\nimport { parseGlobalFlags } from './global-flags';\n\nconst longDescriptions = new WeakMap<Command, string>();\nconst commandExamples = new WeakMap<Command, readonly string[]>();\nconst commandSeeAlso = new WeakMap<\n Command,\n readonly { readonly verb: string; readonly oneLiner: string }[]\n>();\n\n/**\n * Sets both short and long descriptions for a command.\n * The short description is used in command trees and headers.\n * The long description is shown at the bottom of help output.\n */\nexport function setCommandDescriptions(\n command: Command,\n shortDescription: string,\n longDescription?: string,\n): Command {\n command.description(shortDescription);\n if (longDescription) {\n longDescriptions.set(command, longDescription);\n }\n return command;\n}\n\n/**\n * Sets copy-pastable examples for a command, shown in help text.\n */\nexport function setCommandExamples(command: Command, examples: readonly string[]): Command {\n commandExamples.set(command, examples);\n return command;\n}\n\n/**\n * Gets the long description from a command if it was set via setCommandDescriptions.\n */\nexport function getLongDescription(command: Command): string | undefined {\n return longDescriptions.get(command);\n}\n\n/**\n * Gets examples from a command if set via setCommandExamples.\n */\nexport function getCommandExamples(command: Command): readonly string[] | undefined {\n return commandExamples.get(command);\n}\n\n/**\n * Sets cross-references to related commands, rendered in a \"See also\"\n * section below the Examples block in help output.\n */\nexport function setCommandSeeAlso(\n command: Command,\n refs: readonly { readonly verb: string; readonly oneLiner: string }[],\n): Command {\n commandSeeAlso.set(command, refs);\n return command;\n}\n\n/**\n * Gets the see-also cross-references from a command.\n */\nexport function getCommandSeeAlso(\n command: Command,\n): readonly { readonly verb: string; readonly oneLiner: string }[] | undefined {\n return commandSeeAlso.get(command);\n}\n\n/**\n * Shared CLI options interface for migration commands (db init, db update).\n * These are the Commander.js parsed options common to both commands.\n */\nexport interface MigrationCommandOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly dryRun?: boolean;\n}\n\n/**\n * Resolves the absolute path to contract.json from the config.\n */\nexport function resolveContractPath(config: { contract?: { output?: string } }): string {\n if (config.contract?.output === undefined) {\n throw errorRuntime('config.contract.output is required to resolve the contract path', {\n why: 'CLI commands read the emitted contract from config.contract.output; the config has no value to read.',\n fix: 'Ensure your prisma-next.config.ts goes through `defineConfig()`, which normalises a default output when the provider supplies an input path, or set `contract.output` explicitly.',\n });\n }\n return resolve(config.contract.output);\n}\n\n/**\n * Resolves the migrations directory and config path from CLI options.\n * Shared by migrate, migration-plan, and migration-status.\n *\n * - `migrationsDir` is the project's top-level `migrations/` directory\n * (the root that the aggregate loader walks for every contract space).\n * - `appMigrationsDir` is the app subspace directory under it\n * (`<migrationsDir>/<APP_SPACE_ID>/`). Every per-app reader / writer\n * (`migration new`, `migration plan`, `migrate`,\n * `migration status`, `migration show`, `migration ref`) operates on\n * this directory. Extensions own their own `migrations/<spaceId>/`.\n * - `refsDir` is the app's refs directory (`<appMigrationsDir>/refs/`).\n * The framework does not maintain refs at the migrations root.\n */\nexport function resolveMigrationPaths(\n configOption: string | undefined,\n config: { migrations?: { dir?: string } },\n): {\n configPath: string;\n migrationsDir: string;\n migrationsRelative: string;\n appMigrationsDir: string;\n appMigrationsRelative: string;\n refsDir: string;\n} {\n const configPath = configOption\n ? relative(process.cwd(), resolve(configOption))\n : 'prisma-next.config.ts';\n const migrationsDir = resolve(\n configOption ? resolve(configOption, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n const appMigrationsDir = spaceMigrationDirectory(migrationsDir, APP_SPACE_ID);\n const appMigrationsRelative = relative(process.cwd(), appMigrationsDir);\n const refsDir = resolve(appMigrationsDir, 'refs');\n return {\n configPath,\n migrationsDir,\n migrationsRelative,\n appMigrationsDir,\n appMigrationsRelative,\n refsDir,\n };\n}\n\n/**\n * Slim representation of a PathDecision for CLI JSON output.\n * Strips internal fields (createdAt) from path entries.\n */\nexport interface PathDecisionResult {\n readonly fromHash: string;\n readonly toHash: string;\n readonly alternativeCount: number;\n readonly tieBreakReasons: readonly string[];\n readonly refName?: string;\n readonly requiredInvariants: readonly string[];\n readonly satisfiedInvariants: readonly string[];\n readonly selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly invariants: readonly string[];\n }[];\n}\n\nexport function collectDeclaredInvariants(graph: MigrationGraph): ReadonlySet<string> {\n const declared = new Set<string>();\n for (const edges of graph.forwardChain.values()) {\n for (const edge of edges) {\n for (const inv of edge.invariants) {\n declared.add(inv);\n }\n }\n }\n return declared;\n}\n\n/**\n * Maps a `MigrationEdge` to the structural-edge shape used in the\n * `MIGRATION.NO_INVARIANT_PATH` error envelope. Shared between\n * `migrate` and `migration status` so both commands surface\n * the same JSON wire shape when an invariant-aware route is unsatisfiable.\n */\nexport function toStructuralEdge(edge: MigrationEdge): NoInvariantPathStructuralEdge {\n return {\n dirName: edge.dirName,\n migrationHash: edge.migrationHash,\n from: edge.from,\n to: edge.to,\n invariants: edge.invariants,\n };\n}\n\n/**\n * Maps a PathDecision to the slim CLI output representation.\n */\nexport function toPathDecisionResult(decision: PathDecision): PathDecisionResult {\n return {\n fromHash: decision.fromHash,\n toHash: decision.toHash,\n alternativeCount: decision.alternativeCount,\n tieBreakReasons: decision.tieBreakReasons,\n requiredInvariants: decision.requiredInvariants ?? [],\n satisfiedInvariants: decision.satisfiedInvariants ?? [],\n ...ifDefined('refName', decision.refName),\n selectedPath: decision.selectedPath.map((entry) => ({\n dirName: entry.dirName,\n migrationHash: entry.migrationHash,\n from: entry.from,\n to: entry.to,\n invariants: entry.invariants,\n })),\n };\n}\n\nexport function targetSupportsMigrations(target: ControlTargetDescriptor<string, string>): boolean {\n return hasMigrations(target);\n}\n\nexport function getTargetMigrations(target: ControlTargetDescriptor<string, string>) {\n return hasMigrations(target) ? target.migrations : undefined;\n}\n\n/**\n * The subset of the emitted contract.json that the framework layer can\n * safely type. The emitter adds these fields on top of the family-specific\n * storage/models/relations. Other fields exist in the JSON but are opaque\n * at this layer — the index signature preserves them for downstream\n * consumers that operate at the family level (e.g., the control client).\n */\nexport interface ContractEnvelope {\n readonly storageHash: string;\n readonly schemaVersion: string;\n readonly target: string;\n readonly targetFamily: string;\n readonly profileHash?: string;\n readonly [key: string]: unknown;\n}\n\n/**\n * Reads and parses contract.json, validating the framework-level envelope\n * fields (storageHash, schemaVersion, target, targetFamily).\n *\n * Family-specific validation (storage structure, codec mappings, etc.)\n * happens downstream in the control client via the family instance.\n */\nexport async function readContractEnvelope(config: {\n contract?: { output?: string };\n}): Promise<ContractEnvelope> {\n const contractPath = resolveContractPath(config);\n const content = await readFile(contractPath, 'utf-8');\n const json = JSON.parse(content) as Record<string, unknown>;\n\n const { schemaVersion, target, targetFamily, profileHash } = json;\n const storage = json['storage'] as Record<string, unknown> | undefined;\n const storageHash = storage?.['storageHash'];\n\n if (typeof storageHash !== 'string') {\n throw new Error(\n `Contract at ${relative(process.cwd(), contractPath)} is missing a valid storage.storageHash. Run \\`prisma-next contract emit\\` to regenerate.`,\n );\n }\n if (typeof schemaVersion !== 'string') {\n throw new Error(\n `Contract at ${relative(process.cwd(), contractPath)} is missing schemaVersion.`,\n );\n }\n if (typeof target !== 'string') {\n throw new Error(`Contract at ${relative(process.cwd(), contractPath)} is missing target.`);\n }\n if (typeof targetFamily !== 'string') {\n throw new Error(\n `Contract at ${relative(process.cwd(), contractPath)} is missing targetFamily.`,\n );\n }\n\n return {\n ...json,\n storageHash,\n schemaVersion,\n target,\n targetFamily,\n ...(typeof profileHash === 'string' ? { profileHash } : {}),\n };\n}\n\n/**\n * Masks credentials in a database connection URL.\n * Handles standard URLs (username + password + query params) and libpq-style key=value strings.\n */\nexport function maskConnectionUrl(url: string): string {\n try {\n const parsed = new URL(url);\n if (parsed.username) {\n parsed.username = '****';\n }\n if (parsed.password) {\n parsed.password = '****';\n }\n // Also mask password in query parameters (e.g., ?password=secret, ?sslpassword=secret)\n for (const key of [...parsed.searchParams.keys()]) {\n if (/password/i.test(key)) {\n parsed.searchParams.set(key, '****');\n }\n }\n return parsed.toString();\n } catch {\n // Fallback for libpq-style key=value connection strings (e.g., \"host=localhost password=secret user=admin\")\n return url\n .replace(/password\\s*=\\s*\\S+/gi, 'password=****')\n .replace(/user\\s*=\\s*\\S+/gi, 'user=****');\n }\n}\n\n/**\n * Strips raw connection URL fragments from an error message to prevent credential leakage.\n * Call this before surfacing driver errors to the user.\n */\nexport function sanitizeErrorMessage(message: string, connectionUrl?: string): string {\n if (!connectionUrl) {\n return message;\n }\n try {\n const parsed = new URL(connectionUrl);\n // Replace the full URL (with and without trailing slash)\n let sanitized = message;\n sanitized = sanitized.replaceAll(connectionUrl, maskConnectionUrl(connectionUrl));\n // Also replace the password and username individually if they appear\n if (parsed.password) {\n sanitized = sanitized.replaceAll(parsed.password, '****');\n }\n if (parsed.username) {\n sanitized = sanitized.replaceAll(parsed.username, '****');\n }\n return sanitized;\n } catch {\n // For libpq-style strings, mask password and user values in the message\n return message\n .replace(/password\\s*=\\s*\\S+/gi, 'password=****')\n .replace(/user\\s*=\\s*\\S+/gi, 'user=****');\n }\n}\n\n/**\n * Registers the global CLI options shared by every command:\n * --format, --json, -q/--quiet, -v/--verbose, --trace, --color, --no-color,\n * --interactive, --no-interactive, -y/--yes.\n *\n * Also sets up the styled help formatter.\n */\nexport function addGlobalOptions(command: Command): Command {\n return command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option(\n '--format <pretty|json>',\n 'Output format (default: pretty, or json when stdout is not a TTY)',\n )\n .option('--json', 'Output as JSON (alias for --format json)')\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('--trace', 'Trace output: deep internals, stack traces')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .option('--interactive', 'Force interactive mode')\n .option('--no-interactive', 'Disable interactive prompts')\n .option('-y, --yes', 'Auto-accept prompts');\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration-list.mjs","names":[],"sources":["../../src/commands/migration-list.ts"],"sourcesContent":["import type {\n ContractSpaceAggregate,\n ContractSpaceMember,\n} from '@prisma-next/migration-tools/aggregate';\nimport { HEAD_REF_NAME, refsByContractHash } from '@prisma-next/migration-tools/refs';\nimport {\n APP_SPACE_ID,\n isValidSpaceId,\n listContractSpaceDirectories,\n RESERVED_SPACE_SUBDIR_NAMES,\n} from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliStructuredError,\n errorInvalidSpaceId,\n errorSpaceNotFound,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport {\n buildMigrationListTopologyBySpace,\n renderMigrationListWithStyle,\n} from '../utils/formatters/migration-list-render';\nimport { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';\nimport type {\n MigrationListEntry,\n MigrationListResult,\n MigrationSpaceListEntry,\n} from '../utils/formatters/migration-list-types';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport type { GlyphMode } from '../utils/glyph-mode';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\nfunction compareSpaceIds(a: string, b: string): number {\n if (a === APP_SPACE_ID) return b === APP_SPACE_ID ? 0 : -1;\n if (b === APP_SPACE_ID) return 1;\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\nfunction compareDirNamesDescending(a: MigrationListEntry, b: MigrationListEntry): number {\n if (a.dirName < b.dirName) return 1;\n if (a.dirName > b.dirName) return -1;\n return 0;\n}\n\n/**\n * Ref names decorating a space's destination contract hashes. The\n * tolerant `member.refs` deliberately omits the structural `head.json`;\n * for extension spaces the old enumerator surfaced it as a `head`\n * decoration on the tip migration, so fold `member.headRef` back in to\n * keep that output. The app space synthesises its head, so it carries\n * no on-disk `head` ref to restore.\n */\nfunction listRefsByContractHash(\n member: ContractSpaceMember,\n): ReadonlyMap<string, readonly string[]> {\n const byHash = new Map(refsByContractHash(member.refs));\n if (member.spaceId !== APP_SPACE_ID && member.headRef !== null) {\n const hash = member.headRef.hash;\n const bucket = byHash.get(hash) ?? [];\n if (!bucket.includes(HEAD_REF_NAME)) {\n byHash.set(hash, [...bucket, HEAD_REF_NAME].sort());\n }\n }\n return byHash;\n}\n\nasync function orderedOnDiskSpaceIds(projectMigrationsDir: string): Promise<readonly string[]> {\n const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);\n return candidateDirs\n .filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name))\n .filter(isValidSpaceId)\n .sort(compareSpaceIds);\n}\n\n/**\n * Project the loaded {@link ContractSpaceAggregate} into the render-ready\n * {@link MigrationSpaceListEntry} rows `migration list` displays.\n *\n * Space membership matches the on-disk contract-space directories (not the\n * aggregate's always-present synthesized app member when `migrations/app/`\n * is absent); package and ref data come from `aggregate.space(id)`.\n */\nexport async function migrationSpaceListEntriesFromAggregate(\n aggregate: ContractSpaceAggregate,\n projectMigrationsDir: string,\n): Promise<readonly MigrationSpaceListEntry[]> {\n const spaceIds = await orderedOnDiskSpaceIds(projectMigrationsDir);\n const spaces: MigrationSpaceListEntry[] = [];\n\n for (const spaceId of spaceIds) {\n const member = aggregate.space(spaceId);\n if (member === undefined) {\n continue;\n }\n const refsByHash = listRefsByContractHash(member);\n const migrations: MigrationListEntry[] = member.packages\n .map((pkg) => ({\n dirName: pkg.dirName,\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n operationCount: pkg.ops.length,\n createdAt: pkg.metadata.createdAt,\n refs: refsByHash.get(pkg.metadata.to) ?? [],\n providedInvariants: pkg.metadata.providedInvariants,\n }))\n .sort(compareDirNamesDescending);\n\n spaces.push({ spaceId, migrations });\n }\n\n return spaces;\n}\n\ninterface MigrationListOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n readonly ascii?: boolean;\n}\n\nexport interface MigrationListHumanRenderOptions {\n readonly glyphMode: GlyphMode;\n readonly useColor: boolean;\n}\n\nexport function renderMigrationListHumanOutput(\n result: MigrationListResult,\n options: MigrationListHumanRenderOptions,\n): string {\n const styler = createAnsiMigrationListStyler({ useColor: options.useColor });\n const topologyBySpaceId = buildMigrationListTopologyBySpace(result);\n return renderMigrationListWithStyle(result, styler, options.glyphMode, topologyBySpaceId);\n}\n\n/**\n * Inputs for {@link runMigrationList} — the policy core of `migration list`\n * that tests exercise directly.\n *\n * The core does not call `loadConfig`, parse CLI flags, render a styled\n * header, or write to any stream. Enumeration is supplied by the caller\n * (the CLI shell builds it from {@link migrationSpaceListEntriesFromAggregate}).\n */\nexport interface RunMigrationListInputs {\n readonly spaces: readonly MigrationSpaceListEntry[];\n readonly spaceFilter?: string;\n}\n\nfunction computeSummary(spaces: readonly MigrationSpaceListEntry[]): string {\n const totalMigrations = spaces.reduce((count, space) => count + space.migrations.length, 0);\n if (spaces.length <= 1) {\n return `${totalMigrations} migration(s) on disk`;\n }\n return `${totalMigrations} migration(s) across ${spaces.length} contract space(s)`;\n}\n\n/**\n * Policy core of `migration list`: validates `--space`, narrows the\n * pre-enumerated spaces, and assembles a {@link MigrationListResult}.\n *\n * - `migrations/` missing or contains no valid space directories →\n * caller passes `spaces: []`; this synthesizes `[{ spaceId: APP_SPACE_ID, migrations: [] }]`.\n * - `--space <id>` on an existing-but-empty space → `{ spaceId, migrations: [] }` in the input.\n * - `--space <id>` on a non-existent (or reserved) space → `SPACE_NOT_FOUND`.\n */\nexport function runMigrationList(\n inputs: RunMigrationListInputs,\n): Result<MigrationListResult, CliStructuredError> {\n const { spaces, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\n }\n\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()));\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n const resultSpaces: readonly MigrationSpaceListEntry[] =\n scopedSpaces.length === 0 ? [{ spaceId: APP_SPACE_ID, migrations: [] }] : scopedSpaces;\n\n return ok({\n ok: true,\n spaces: resultSpaces,\n summary: computeSummary(resultSpaces),\n });\n}\n\n/**\n * CLI shell: loads config, resolves paths, prints the styled header on\n * stderr (interactive mode only), and delegates to {@link runMigrationList}.\n * Kept intentionally thin so the unit-testable surface lives in the core.\n */\nexport async function executeMigrationListCommand(\n options: MigrationListOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationListResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration list',\n description: 'List on-disk migrations, latest first, per contract space',\n details: [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ...(options.space !== undefined ? [{ label: 'space', value: options.space }] : []),\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n const loaded = await buildReadAggregate(config, { migrationsDir });\n if (!loaded.ok) {\n return notOk(loaded.failure);\n }\n\n const spaces = await migrationSpaceListEntriesFromAggregate(\n loaded.value.aggregate,\n migrationsDir,\n );\n\n return runMigrationList({\n spaces,\n ...ifDefined('spaceFilter', options.space),\n });\n}\n\nexport function createMigrationListCommand(): Command {\n const command = new Command('list');\n setCommandDescriptions(\n command,\n 'List on-disk migrations, latest first, per contract space',\n 'Enumerates every on-disk migration under migrations/<space>/ for every\\n' +\n 'contract space found on disk, latest first. Offline — does not consult\\n' +\n 'the database. Each row leads with a kind glyph (* forward, ↩ rollback,\\n' +\n '⟲ self), then dirName, then source → destination contract hashes\\n' +\n '(7-char git-style). Self-edges show a single hash. Invariants render as\\n' +\n '{...}; refs on the destination as (production, db). Pass --space <id>\\n' +\n 'to narrow to one contract space. --ascii forces ASCII kind glyphs\\n' +\n '(orthogonal to --no-color).',\n );\n setCommandExamples(command, [\n 'prisma-next migration list',\n 'prisma-next migration list --space app',\n 'prisma-next migration list --ascii',\n 'prisma-next migration list --json',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration status', oneLiner: 'Show migration path and pending status' },\n { verb: 'migration log', oneLiner: 'Show executed migration history' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n { verb: 'migration show', oneLiner: 'Display migration package contents' },\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--space <id>', 'Narrow output to a single contract space')\n .option('--ascii', 'Use ASCII kind glyphs (pipe-friendly)')\n .action(async (options: MigrationListOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const result = await executeMigrationListCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (listResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(listResult, null, 2));\n } else if (!flags.quiet) {\n ui.output(\n renderMigrationListHumanOutput(listResult, {\n glyphMode: ui.resolveGlyphMode(options.ascii === true),\n useColor: ui.useColor,\n }),\n );\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":";;;;;;;;;;AA6CA,SAAS,gBAAgB,GAAW,GAAmB;CACrD,IAAI,MAAM,cAAc,OAAO,MAAM,eAAe,IAAI;CACxD,IAAI,MAAM,cAAc,OAAO;CAC/B,IAAI,IAAI,GAAG,OAAO;CAClB,IAAI,IAAI,GAAG,OAAO;CAClB,OAAO;AACT;AAEA,SAAS,0BAA0B,GAAuB,GAA+B;CACvF,IAAI,EAAE,UAAU,EAAE,SAAS,OAAO;CAClC,IAAI,EAAE,UAAU,EAAE,SAAS,OAAO;CAClC,OAAO;AACT;;;;;;;;;AAUA,SAAS,uBACP,QACwC;CACxC,MAAM,SAAS,IAAI,IAAI,mBAAmB,OAAO,IAAI,CAAC;CACtD,IAAI,OAAO,YAAY,gBAAgB,OAAO,YAAY,MAAM;EAC9D,MAAM,OAAO,OAAO,QAAQ;EAC5B,MAAM,SAAS,OAAO,IAAI,IAAI,KAAK,CAAC;EACpC,IAAI,CAAC,OAAO,SAAS,aAAa,GAChC,OAAO,IAAI,MAAM,CAAC,GAAG,QAAQ,aAAa,EAAE,KAAK,CAAC;CAEtD;CACA,OAAO;AACT;AAEA,eAAe,sBAAsB,sBAA0D;CAE7F,QAAO,MADqB,6BAA6B,oBAAoB,GAE1E,QAAQ,SAAS,CAAC,4BAA4B,IAAI,IAAI,CAAC,EACvD,OAAO,cAAc,EACrB,KAAK,eAAe;AACzB;;;;;;;;;AAUA,eAAsB,uCACpB,WACA,sBAC6C;CAC7C,MAAM,WAAW,MAAM,sBAAsB,oBAAoB;CACjE,MAAM,SAAoC,CAAC;CAE3C,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,UAAU,MAAM,OAAO;EACtC,IAAI,WAAW,KAAA,GACb;EAEF,MAAM,aAAa,uBAAuB,MAAM;EAChD,MAAM,aAAmC,OAAO,SAC7C,KAAK,SAAS;GACb,SAAS,IAAI;GACb,MAAM,IAAI,SAAS;GACnB,IAAI,IAAI,SAAS;GACjB,eAAe,IAAI,SAAS;GAC5B,gBAAgB,IAAI,IAAI;GACxB,WAAW,IAAI,SAAS;GACxB,MAAM,WAAW,IAAI,IAAI,SAAS,EAAE,KAAK,CAAC;GAC1C,oBAAoB,IAAI,SAAS;EACnC,EAAE,EACD,KAAK,yBAAyB;EAEjC,OAAO,KAAK;GAAE;GAAS;EAAW,CAAC;CACrC;CAEA,OAAO;AACT;AAaA,SAAgB,+BACd,QACA,SACQ;CACR,MAAM,SAAS,8BAA8B,EAAE,UAAU,QAAQ,SAAS,CAAC;CAC3E,MAAM,oBAAoB,kCAAkC,MAAM;CAClE,OAAO,6BAA6B,QAAQ,QAAQ,QAAQ,WAAW,iBAAiB;AAC1F;AAeA,SAAS,eAAe,QAAoD;CAC1E,MAAM,kBAAkB,OAAO,QAAQ,OAAO,UAAU,QAAQ,MAAM,WAAW,QAAQ,CAAC;CAC1F,IAAI,OAAO,UAAU,GACnB,OAAO,GAAG,gBAAgB;CAE5B,OAAO,GAAG,gBAAgB,uBAAuB,OAAO,OAAO;AACjE;;;;;;;;;;AAWA,SAAgB,iBACd,QACiD;CACjD,MAAM,EAAE,QAAQ,gBAAgB;CAEhC,IAAI,gBAAgB,KAAA,KAAa,CAAC,eAAe,WAAW,GAC1D,OAAO,MAAM,oBAAoB,WAAW,CAAC;CAG/C,IAAI,gBAAgB,KAAA,KAAa,CAAC,OAAO,MAAM,MAAM,EAAE,YAAY,WAAW,GAC5E,OAAO,MAAM,mBAAmB,aAAa,OAAO,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;CAGnF,MAAM,eACJ,gBAAgB,KAAA,IAAY,OAAO,QAAQ,MAAM,EAAE,YAAY,WAAW,IAAI;CAEhF,MAAM,eACJ,aAAa,WAAW,IAAI,CAAC;EAAE,SAAS;EAAc,YAAY,CAAC;CAAE,CAAC,IAAI;CAE5E,OAAO,GAAG;EACR,IAAI;EACJ,QAAQ;EACR,SAAS,eAAe,YAAY;CACtC,CAAC;AACH;;;;;;AAOA,eAAsB,4BACpB,SACA,OACA,IAC0D;CAC1D,MAAM,SAAS,MAAM,WAAW,QAAQ,MAAM;CAC9C,MAAM,EAAE,YAAY,eAAe,uBAAuB,sBACxD,QAAQ,QACR,MACF;CAEA,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb,SAAS;IACP;KAAE,OAAO;KAAU,OAAO;IAAW;IACrC;KAAE,OAAO;KAAc,OAAO;IAAmB;IACjD,GAAI,QAAQ,UAAU,KAAA,IAAY,CAAC;KAAE,OAAO;KAAS,OAAO,QAAQ;IAAM,CAAC,IAAI,CAAC;GAClF;GACA;EACF,CAAC;EACD,GAAG,OAAO,MAAM;CAClB;CAEA,MAAM,SAAS,MAAM,mBAAmB,QAAQ,EAAE,cAAc,CAAC;CACjE,IAAI,CAAC,OAAO,IACV,OAAO,MAAM,OAAO,OAAO;CAQ7B,OAAO,iBAAiB;EACtB,QAAA,MANmB,uCACnB,OAAO,MAAM,WACb,aACF;EAIE,GAAG,UAAU,eAAe,QAAQ,KAAK;CAC3C,CAAC;AACH;AAEA,SAAgB,6BAAsC;CACpD,MAAM,UAAU,IAAI,QAAQ,MAAM;CAClC,uBACE,SACA,6DACA,0gBAQF;CACA,mBAAmB,SAAS;EAC1B;EACA;EACA;EACA;CACF,CAAC;CACD,kBAAkB,SAAS;EACzB;GAAE,MAAM;GAAoB,UAAU;EAAyC;EAC/E;GAAE,MAAM;GAAiB,UAAU;EAAkC;EACrE;GAAE,MAAM;GAAmB,UAAU;EAAoC;EACzE;GAAE,MAAM;GAAkB,UAAU;EAAqC;CAC3E,CAAC;CACD,iBAAiB,OAAO,EACrB,OAAO,mBAAmB,+BAA+B,EACzD,OAAO,gBAAgB,0CAA0C,EACjE,OAAO,WAAW,uCAAuC,EACzD,OAAO,OAAO,YAAkC;EAC/C,MAAM,QAAQ,uBAAuB,OAAO;EAC5C,MAAM,KAAK,iBAAiB,KAAK;EAEjC,MAAM,WAAW,aAAa,MADT,4BAA4B,SAAS,OAAO,EAAE,GAC7B,OAAO,KAAK,eAAe;GAC/D,IAAI,MAAM,MACR,GAAG,OAAO,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,OAChB,GAAG,OACD,+BAA+B,YAAY;IACzC,WAAW,GAAG,iBAAiB,QAAQ,UAAU,IAAI;IACrD,UAAU,GAAG;GACf,CAAC,CACH;EAEJ,CAAC;EACD,QAAQ,KAAK,QAAQ;CACvB,CAAC;CACH,OAAO;AACT"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration-log.mjs","names":[],"sources":["../../src/commands/migration-log.ts"],"sourcesContent":["import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { findPath } from '@prisma-next/migration-tools/migration-graph';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { cyan, dim } from 'colorette';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n maskConnectionUrl,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n targetSupportsMigrations,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationLogOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n}\n\nexport interface MigrationLogEntry {\n readonly dirName: string;\n readonly from: string;\n readonly to: string;\n readonly migrationHash: string;\n readonly operationCount: number;\n readonly createdAt: string;\n}\n\nexport interface MigrationLogResult {\n readonly ok: true;\n readonly markerHash: string | null;\n readonly applied: readonly MigrationLogEntry[];\n readonly summary: string;\n}\n\nexport async function executeMigrationLogCommand(\n options: MigrationLogOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationLogResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, appMigrationsRelative, migrationsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for migration log (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'migration log',\n }),\n );\n }\n if (!config.driver) {\n return notOk(errorDriverRequired({ why: 'Config.driver is required for migration log' }));\n }\n if (!targetSupportsMigrations(config.target)) {\n return notOk(errorUnexpected('Target does not support migrations'));\n }\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration log',\n description: 'Show executed migration history',\n details: [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ...(typeof dbConnection === 'string'\n ? [{ label: 'database', value: maskConnectionUrl(dbConnection) }]\n : []),\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n const loaded = await buildReadAggregate(config, { migrationsDir });\n if (!loaded.ok) {\n return loaded;\n }\n const graph = loaded.value.aggregate.app.graph();\n const bundles = loaded.value.aggregate.app.packages;\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n try {\n await client.connect(dbConnection);\n const marker = await client.readMarker();\n const markerHash = marker?.storageHash ?? null;\n\n if (!markerHash) {\n return ok({\n ok: true,\n markerHash: null,\n applied: [],\n summary: 'No migrations applied (database has no marker)',\n });\n }\n\n const appliedPath = findPath(graph, EMPTY_CONTRACT_HASH, markerHash);\n if (appliedPath === null) {\n return notOk(\n errorUnexpected('Database marker is not reachable from migration history', {\n why: `Marker hash ${markerHash} is not reachable from the root of the on-disk migration graph.`,\n fix: 'The database may have been migrated outside this project. Use `migration status` to inspect the current state.',\n }),\n );\n }\n const pkgByDirName = new Map(bundles.map((p) => [p.dirName, p]));\n const entries: MigrationLogEntry[] = appliedPath.map((edge) => {\n const pkg = pkgByDirName.get(edge.dirName);\n const ops = (pkg?.ops ?? []) as readonly MigrationPlanOperation[];\n return {\n dirName: edge.dirName,\n from: edge.from,\n to: edge.to,\n migrationHash: edge.migrationHash,\n operationCount: ops.length,\n createdAt: edge.createdAt,\n };\n });\n\n return ok({\n ok: true,\n markerHash,\n applied: entries,\n summary: `${entries.length} migration(s) applied`,\n });\n } catch (error) {\n if (CliStructuredError.is(error)) return notOk(error);\n if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration log: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createMigrationLogCommand(): Command {\n const command = new Command('log');\n setCommandDescriptions(\n command,\n 'Show executed migration history',\n 'Reads the database marker and displays the applied migration chain\\n' +\n 'from the initial state to the current marker position.',\n );\n setCommandExamples(command, [\n 'prisma-next migration log --db $DATABASE_URL',\n 'prisma-next migration log --json --db $DATABASE_URL',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration status', oneLiner: 'Show migration path and pending status' },\n { verb: 'migration list', oneLiner: 'List on-disk migrations' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n { verb: 'migration show', oneLiner: 'Display migration package contents' },\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: MigrationLogOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const result = await executeMigrationLogCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (logResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(logResult, null, 2));\n } else if (!flags.quiet) {\n const c = (fn: (s: string) => string, s: string) => (flags.color !== false ? fn(s) : s);\n if (logResult.applied.length === 0) {\n ui.log(logResult.summary);\n } else {\n for (const entry of logResult.applied) {\n ui.log(\n `${c(cyan, '✓')} ${entry.dirName} ${c(dim, entry.migrationHash.slice(0, 16) + '…')} ${entry.operationCount} op(s)`,\n );\n }\n ui.log(`\\n${logResult.summary}`);\n }\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration-status.mjs","names":[],"sources":["../../src/commands/migration-status.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport {\n createControlStack,\n type MigrationPlanOperation,\n} from '@prisma-next/framework-components/control';\nimport {\n type ContractMarkerRecordLike,\n type ContractSpaceAggregate,\n graphWalkStrategy,\n loadContractSpaceAggregate,\n requireHeadRef,\n} from '@prisma-next/migration-tools/aggregate';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport {\n errorNoInvariantPath,\n errorUnknownInvariant,\n MigrationToolsError,\n} from '@prisma-next/migration-tools/errors';\nimport type { MigrationEdge, MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport {\n findPath,\n findPathWithDecision,\n findReachableLeaves,\n} from '@prisma-next/migration-tools/migration-graph';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport type { RefEntry, Refs } from '@prisma-next/migration-tools/refs';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { cyan, dim, magenta, yellow } from 'colorette';\nimport { Command } from 'commander';\n\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorRuntime,\n errorUnexpected,\n mapMigrationToolsError,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n collectDeclaredInvariants,\n maskConnectionUrl,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n toPathDecisionResult,\n toStructuralEdge,\n} from '../utils/command-helpers';\nimport {\n appContractStandInFromIdentity,\n loadContractRawSafely,\n refuseContractSpaceIntegrity,\n refusePackageCorruptionOnAggregate,\n} from '../utils/contract-space-aggregate-loader';\nimport { toDeclaredExtensionsFromRaw } from '../utils/extension-pack-inputs';\nimport {\n type EdgeStatus,\n type EdgeStatusKind,\n migrationGraphToRenderInput,\n} from '../utils/formatters/graph-migration-mapper';\nimport {\n extractRelevantSubgraph,\n graphRenderer,\n isLinearGraph,\n} from '../utils/formatters/graph-render';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport type { StatusDiagnostic, StatusRef } from '../utils/migration-types';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationStatusOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly to?: string;\n readonly from?: string;\n}\n\nexport interface MigrationStatusEntry {\n readonly dirName: string;\n readonly from: string;\n readonly to: string;\n readonly migrationHash: string;\n readonly operationCount: number;\n readonly operationSummary: string;\n readonly hasDestructive: boolean;\n readonly status: EdgeStatusKind | 'unknown';\n}\n\n/**\n * Per-space status row in the aggregate-shaped status output.\n *\n * Surfaces, for each contract space:\n *\n * - `headHash`: the on-disk head ref's hash (where the space is going).\n * - `markerHash`: the live marker hash for the space, or null if no\n * marker has been written yet (greenfield, or pre-`migrate`).\n * - `pendingCount`: number of migration edges between marker and head.\n * Computed via {@link graphWalkStrategy}; 0 means the space is\n * already at head.\n * - `status`: convenience tag the formatter uses to pick a glyph.\n * `'never-planned'` is reserved for spaces with non-empty head but\n * no on-disk migrations — which shouldn't happen if the loader's\n * integrity check passes.\n *\n * Online-only fields (`markerHash`, `status`) are absent when the\n * command runs without a database connection.\n */\nexport interface MigrationStatusSpaceEntry {\n readonly spaceId: string;\n readonly kind: 'app' | 'extension';\n readonly headHash: string;\n readonly markerHash?: string | null;\n readonly pendingCount?: number;\n readonly status?: 'up-to-date' | 'pending' | 'no-marker' | 'never-planned' | 'unreachable';\n}\n\n/**\n * Sum per-space `pendingCount` into a cross-space total, but only when\n * every loaded space reports a defined `pendingCount`. Returns\n * `undefined` if any space is on the marker-unknown / offline path\n * (where `pendingCount` is intentionally absent), so JSON consumers can\n * distinguish \"no pending\" from \"unknown\".\n */\nexport function computeTotalPendingAcrossSpaces(\n spaces: readonly MigrationStatusSpaceEntry[],\n): number | undefined {\n if (spaces.length === 0) return undefined;\n let total = 0;\n for (const s of spaces) {\n if (s.pendingCount === undefined) return undefined;\n total += s.pendingCount;\n }\n return total;\n}\n\nexport type { StatusDiagnostic, StatusRef } from '../utils/migration-types';\n\nexport interface MigrationStatusResult {\n readonly ok: true;\n readonly mode: 'online' | 'offline';\n readonly migrations: readonly MigrationStatusEntry[];\n readonly markerHash?: string;\n readonly targetHash: string;\n readonly contractHash: string;\n readonly refs?: readonly StatusRef[];\n /** Required invariants from the active ref, sorted ascending. Always present (`[]` when no `--ref` or the ref declares none) — knowable offline. */\n readonly requiredInvariants: readonly string[];\n /**\n * Invariants the marker has applied at least once, intersected with\n * `requiredInvariants` for display relevance. JSON consumers see only the\n * subset overlapping the active ref's required set — the full unfiltered\n * marker invariant list lives on `marker.invariants` (control plane) and\n * is not surfaced here. Present only in `mode === 'online'`; absent when\n * offline (the marker is unknown, not empty).\n */\n readonly appliedInvariants?: readonly string[];\n /** required − applied. Present only in `mode === 'online'`; absent when offline. */\n readonly missingInvariants?: readonly string[];\n readonly pathDecision?: {\n readonly fromHash: string;\n readonly toHash: string;\n readonly alternativeCount: number;\n readonly tieBreakReasons: readonly string[];\n readonly refName?: string;\n readonly requiredInvariants: readonly string[];\n readonly satisfiedInvariants: readonly string[];\n readonly selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly invariants: readonly string[];\n }[];\n };\n readonly summary: string;\n readonly diagnostics: readonly StatusDiagnostic[];\n /**\n * Aggregate enumeration of every on-disk contract space (app +\n * extensions), in canonical schedule order (extensions\n * alphabetically, then app). Present whenever the aggregate loader\n * succeeded; absent in early-error returns (e.g. unreadable\n * migrations directory) where the existing diagnostics already\n * surface the failure.\n *\n * The top-level fields (`migrations`, `markerHash`, `targetHash`,\n * `pathDecision`, …) describe the **app member** specifically.\n * Per-space detail for extension members lives only on this list.\n */\n readonly spaces?: readonly MigrationStatusSpaceEntry[];\n /** Cross-space pending-migration total (sum of `spaces[].pendingCount`). Present when `spaces` is. */\n readonly totalPendingAcrossSpaces?: number;\n readonly graph?: MigrationGraph;\n readonly bundles?: readonly OnDiskMigrationPackage[];\n readonly edgeStatuses?: readonly EdgeStatus[];\n readonly activeRefHash?: string;\n readonly activeRefName?: string;\n readonly diverged?: boolean;\n}\n\nfunction summarizeOps(ops: readonly MigrationPlanOperation[]): {\n summary: string;\n hasDestructive: boolean;\n} {\n if (ops.length === 0) return { summary: '0 ops', hasDestructive: false };\n\n const classes = new Map<string, number>();\n for (const op of ops) {\n classes.set(op.operationClass, (classes.get(op.operationClass) ?? 0) + 1);\n }\n\n const hasDestructive = classes.has('destructive');\n const count = ops.length;\n const noun = count === 1 ? 'op' : 'ops';\n\n if (classes.size === 1) {\n const cls = [...classes.keys()][0]!;\n return { summary: `${count} ${noun} (all ${cls})`, hasDestructive };\n }\n\n const destructiveCount = classes.get('destructive');\n if (destructiveCount) {\n return { summary: `${count} ${noun} (${destructiveCount} destructive)`, hasDestructive };\n }\n\n const parts = [...classes.entries()].map(([cls, n]) => `${n} ${cls}`);\n return { summary: `${count} ${noun} (${parts.join(', ')})`, hasDestructive };\n}\n\n/**\n * Derive per-edge status across the full graph using path analysis.\n *\n * - **applied**: edge is on the path from root to the DB marker\n * - **pending**: edge is on the path from the DB marker to the target\n * (and the marker is reachable from root, i.e. it's on the same branch)\n * - **unreachable**: edge is on the path from root to the target but the DB\n * marker is on a different branch — `apply` can't reach these edges\n * without the DB first moving to this branch\n *\n * Returns statuses only for edges that have a known status (skips offline\n * and edges not on any relevant path).\n *\n * @internal Exported for testing only.\n */\nexport function deriveEdgeStatuses(\n graph: MigrationGraph,\n targetHash: string,\n contractHash: string,\n markerHash: string | undefined,\n mode: 'online' | 'offline',\n): EdgeStatus[] {\n if (mode === 'offline') return [];\n\n const edgeKey = (e: MigrationEdge) => `${e.from}\\0${e.to}`;\n\n // No marker = empty DB — treat root as the marker (nothing applied, everything pending)\n const effectiveMarker = markerHash ?? EMPTY_CONTRACT_HASH;\n\n const appliedPath =\n markerHash !== undefined ? findPath(graph, EMPTY_CONTRACT_HASH, markerHash) : null;\n\n const pendingPath = findPath(graph, effectiveMarker, targetHash);\n const targetPath = findPath(graph, EMPTY_CONTRACT_HASH, targetHash);\n\n const statuses: EdgeStatus[] = [];\n const assignedKeys = new Set<string>();\n\n // Applied edges (root → marker)\n if (appliedPath) {\n for (const e of appliedPath) {\n assignedKeys.add(edgeKey(e));\n statuses.push({ dirName: e.dirName, status: 'applied' });\n }\n }\n\n // Pending edges (marker → target)\n if (pendingPath) {\n for (const e of pendingPath) {\n assignedKeys.add(edgeKey(e));\n statuses.push({ dirName: e.dirName, status: 'pending' });\n }\n }\n\n // Pending edges beyond the target: target → contract (when target is a ref\n // and the contract is reachable from it)\n if (\n contractHash !== EMPTY_CONTRACT_HASH &&\n contractHash !== targetHash &&\n graph.nodes.has(contractHash)\n ) {\n const beyondTarget = findPath(graph, targetHash, contractHash);\n if (beyondTarget) {\n for (const e of beyondTarget) {\n if (!assignedKeys.has(edgeKey(e))) {\n assignedKeys.add(edgeKey(e));\n statuses.push({ dirName: e.dirName, status: 'pending' });\n }\n }\n }\n }\n\n // Unreachable edges: on the path from root to the target but neither applied\n // nor pending. This covers two cases:\n // 1. Marker can't reach target at all (different branch entirely)\n // 2. Marker reaches target via a different route, leaving some root→target\n // edges orphaned (e.g. a fork where one branch was applied and apply\n // will continue through the other)\n if (targetPath) {\n for (const e of targetPath) {\n if (!assignedKeys.has(edgeKey(e))) {\n statuses.push({ dirName: e.dirName, status: 'unreachable' });\n }\n }\n }\n\n return statuses;\n}\n\n/**\n * @param mode — 'online' if we connected to the database, 'offline' otherwise\n * @param markerHash — the marker hash from the database, or undefined if no marker row / offline\n */\nfunction buildMigrationEntries(\n chain: readonly MigrationEdge[],\n packages: readonly OnDiskMigrationPackage[],\n mode: 'online' | 'offline',\n markerHash: string | undefined,\n edgeStatuses?: readonly EdgeStatus[],\n): MigrationStatusEntry[] {\n const pkgByDirName = new Map(packages.map((p) => [p.dirName, p]));\n const statusByDirName = edgeStatuses\n ? new Map(edgeStatuses.map((e) => [e.dirName, e.status]))\n : undefined;\n\n const markerInChain = markerHash === undefined || chain.some((e) => e.to === markerHash);\n\n const entries: MigrationStatusEntry[] = [];\n let reachedMarker = mode === 'online' && markerHash === undefined;\n\n for (const migration of chain) {\n const pkg = pkgByDirName.get(migration.dirName);\n const ops = (pkg?.ops ?? []) as readonly MigrationPlanOperation[];\n const { summary, hasDestructive } = summarizeOps(ops);\n\n let status: EdgeStatusKind | 'unknown';\n const edgeStatus = statusByDirName?.get(migration.dirName);\n if (edgeStatus) {\n status = edgeStatus;\n } else if (mode === 'offline' || !markerInChain) {\n status = 'unknown';\n } else if (reachedMarker) {\n status = 'pending';\n } else {\n status = 'applied';\n }\n\n entries.push({\n dirName: migration.dirName,\n from: migration.from,\n to: migration.to,\n migrationHash: migration.migrationHash,\n operationCount: ops.length,\n operationSummary: summary,\n hasDestructive,\n status,\n });\n\n if (!reachedMarker && migration.to === markerHash) {\n reachedMarker = true;\n }\n }\n\n return entries;\n}\n\n/**\n * Resolve the migration chain to display in status output.\n *\n * When offline or the marker is at EMPTY, the chain is simply the shortest\n * path from EMPTY to the target — all structural paths are equivalent per\n * the spec, so the deterministic shortest path is the canonical display.\n *\n * When online with a non-empty marker, the chain routes *through* the marker:\n * EMPTY→marker (applied history) + marker→target (pending edges). This ensures\n * the displayed chain includes the marker node so applied/pending status is\n * correct. Without this, BFS from EMPTY to target could pick a shortest path\n * that bypasses the marker entirely (e.g. in a diamond graph), causing the\n * marker to appear \"diverged\" when it isn't.\n */\nfunction resolveDisplayChain(\n graph: MigrationGraph,\n targetHash: string,\n markerHash: string | undefined,\n): readonly MigrationEdge[] | null {\n if (markerHash === undefined) {\n return findPath(graph, EMPTY_CONTRACT_HASH, targetHash);\n }\n\n const toMarker = findPath(graph, EMPTY_CONTRACT_HASH, markerHash);\n // Marker unreachable from EMPTY — show the target chain anyway.\n // The caller detects this via markerInChain and emits a divergence diagnostic.\n if (!toMarker) return findPath(graph, EMPTY_CONTRACT_HASH, targetHash);\n\n if (markerHash === targetHash) return toMarker;\n\n const fromMarker = findPath(graph, markerHash, targetHash);\n if (fromMarker) return [...toMarker, ...fromMarker];\n\n // Marker is ahead of target (or on a disconnected branch).\n // Try the inverse: target→marker. If it succeeds, the marker is ahead —\n // show the full chain from EMPTY through the target and on to the marker.\n const toTarget = findPath(graph, EMPTY_CONTRACT_HASH, targetHash);\n if (!toTarget) return null;\n\n const targetToMarker = findPath(graph, targetHash, markerHash);\n if (targetToMarker) return [...toTarget, ...targetToMarker];\n\n // Genuinely disconnected — show EMPTY→target; caller handles divergence diagnostic.\n return toTarget;\n}\n\n/**\n * Build the aggregate enumeration of contract spaces for the status\n * output. Loads the aggregate from disk (lossy on failure — extension\n * spaces are simply omitted, the app member's output keeps working),\n * reads per-space marker rows when online, and uses\n * {@link graphWalkStrategy} to compute each space's pending count.\n *\n * The aggregate-walking status reports per-space marker + pending\n * state alongside the cross-space totals.\n */\nexport async function loadAggregateStatusSpaces(args: {\n readonly aggregate: ContractSpaceAggregate;\n readonly extensionPacks: ReadonlyArray<unknown>;\n readonly markersBySpace: ReadonlyMap<string, ContractMarkerRecordLike> | null;\n}): Promise<readonly MigrationStatusSpaceEntry[]> {\n const declaredExtensions = toDeclaredExtensionsFromRaw(args.extensionPacks);\n if (\n refuseContractSpaceIntegrity(args.aggregate, {\n declaredExtensions,\n checkContracts: true,\n })\n ) {\n // Full integrity refusal (drift, layout violation, etc.) — surfacing\n // it as a status diagnostic would duplicate `migration plan`'s job.\n // The app pipeline still runs; extensions are simply not enumerated.\n return [];\n }\n const aggregate = args.aggregate;\n\n const orderedMembers = [...aggregate.extensions, aggregate.app];\n const rows: MigrationStatusSpaceEntry[] = [];\n for (const member of orderedMembers) {\n const liveMarker = args.markersBySpace?.get(member.spaceId) ?? null;\n const isApp = member.spaceId === aggregate.app.spaceId;\n // The aggregate passed the integrity gate above, so every member has\n // a resolved head ref (a missing one would have refused the load).\n const headRef = requireHeadRef(member);\n\n if (member.graph().nodes.size === 0) {\n rows.push({\n spaceId: member.spaceId,\n kind: isApp ? 'app' : 'extension',\n headHash: headRef.hash,\n ...(args.markersBySpace !== null\n ? {\n markerHash: liveMarker?.storageHash ?? null,\n status: headRef.hash === EMPTY_CONTRACT_HASH ? 'up-to-date' : 'never-planned',\n pendingCount: 0,\n }\n : {}),\n });\n continue;\n }\n\n if (args.markersBySpace === null) {\n rows.push({\n spaceId: member.spaceId,\n kind: isApp ? 'app' : 'extension',\n headHash: headRef.hash,\n });\n continue;\n }\n\n const walked = graphWalkStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n currentMarker: liveMarker,\n });\n let pendingCount = 0;\n let status: MigrationStatusSpaceEntry['status'];\n if (walked.kind === 'ok') {\n // Count pending *migrations* (graph edges), not operations: a\n // single authored migration that lowers to N ops or zero ops\n // both count as exactly one pending unit of work for the user.\n pendingCount = walked.result.migrationEdges?.length ?? 0;\n if (liveMarker === null) {\n status = pendingCount === 0 ? 'no-marker' : 'pending';\n } else {\n status = pendingCount === 0 ? 'up-to-date' : 'pending';\n }\n } else {\n status = 'unreachable';\n }\n\n rows.push({\n spaceId: member.spaceId,\n kind: isApp ? 'app' : 'extension',\n headHash: headRef.hash,\n markerHash: liveMarker?.storageHash ?? null,\n pendingCount,\n ...(status ? { status } : {}),\n });\n }\n return rows;\n}\n\n/**\n * Read the raw contract.json bytes from disk for the aggregate\n * loader. Returns `null` if the file is missing or unparseable —\n * the existing `readContractEnvelope` path will report the same\n * problem via a status diagnostic, no need to double-surface.\n */\n\nasync function validateOnlineMarkerRead(\n config: Awaited<ReturnType<typeof loadConfig>>,\n dbConnection: unknown,\n): Promise<Result<void, CliStructuredError>> {\n const driver = config.driver;\n if (!driver) {\n return ok(undefined);\n }\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n try {\n await client.connect(dbConnection);\n await client.readMarker();\n return ok(undefined);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read database marker: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nasync function executeMigrationStatusCommand(\n options: MigrationStatusOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationStatusResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, appMigrationsRelative, migrationsDir, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const dbConnection = options.db ?? config.db?.connection;\n const hasDriver = !!config.driver;\n\n let activeRefName: string | undefined;\n let activeRefHash: string | undefined;\n let activeRefEntry: RefEntry | undefined;\n let allRefs: Refs = {};\n try {\n allRefs = await readRefs(refsDir);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n const diagnostics: StatusDiagnostic[] = [];\n let contractHash: string = EMPTY_CONTRACT_HASH;\n try {\n const envelope = await readContractEnvelope(config);\n contractHash = envelope.storageHash;\n } catch (error) {\n diagnostics.push({\n code: 'CONTRACT.UNREADABLE',\n severity: 'warn',\n message: `Could not read contract: ${error instanceof Error ? error.message : 'unknown error'}`,\n hints: [\"Run 'prisma-next contract emit' to generate a valid contract\"],\n });\n }\n\n const contractRawForAggregate = await loadContractRawSafely(config);\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const deserializeContract = (json: unknown): Contract => familyInstance.deserializeContract(json);\n const appContractStandIn = appContractStandInFromIdentity({\n contractHash,\n targetId: config.target.id,\n targetFamily: config.target.familyId,\n });\n let appContractForLoad: Contract = appContractStandIn;\n if (contractRawForAggregate !== null) {\n try {\n appContractForLoad = deserializeContract(contractRawForAggregate);\n } catch (error) {\n diagnostics.push({\n code: 'CONTRACT.UNREADABLE',\n severity: 'warn',\n message: `Could not deserialize contract: ${error instanceof Error ? error.message : 'unknown error'}`,\n hints: [\"Run 'prisma-next contract emit' to generate a valid contract\"],\n });\n }\n }\n\n let aggregate: ContractSpaceAggregate;\n try {\n aggregate = await loadContractSpaceAggregate({\n migrationsDir,\n deserializeContract,\n appContract: appContractForLoad,\n });\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migrations directory: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n if (contractRawForAggregate !== null) {\n const corruptionFailure = refusePackageCorruptionOnAggregate(aggregate);\n if (corruptionFailure) {\n return notOk(corruptionFailure);\n }\n }\n\n const appGraph = aggregate.app.graph();\n\n let fromOverrideHash: string | undefined;\n\n if (options.to || options.from) {\n if (options.to) {\n const refResult = parseContractRef(options.to, { graph: appGraph, refs: allRefs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n activeRefHash = refResult.value.hash;\n if (refResult.value.provenance.kind === 'ref') {\n const resolvedRefName = refResult.value.provenance.refName;\n activeRefName = resolvedRefName;\n activeRefEntry = allRefs[resolvedRefName];\n }\n }\n\n if (options.from) {\n const fromResult = parseContractRef(options.from, { graph: appGraph, refs: allRefs });\n if (!fromResult.ok) {\n return notOk(mapRefResolutionError(fromResult.failure));\n }\n fromOverrideHash = fromResult.value.hash;\n }\n }\n\n const requiredInvariants: readonly string[] = [...(activeRefEntry?.invariants ?? [])].sort();\n\n const statusRefs: StatusRef[] = Object.entries(allRefs).map(([name, entry]) => ({\n name,\n hash: entry.hash,\n active: name === activeRefName,\n }));\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (dbConnection && hasDriver) {\n details.push({ label: 'database', value: maskConnectionUrl(String(dbConnection)) });\n }\n if (activeRefName) {\n details.push({ label: 'ref', value: activeRefName });\n }\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (activeRefEntry && activeRefEntry.invariants.length > 0) {\n details.push({\n label: 'required',\n value: formatInvariantList(activeRefEntry.invariants),\n });\n }\n const header = formatStyledHeader({\n command: 'migration status',\n description: 'Show migration history and applied status',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n const bundles = aggregate.app.packages;\n const graph = appGraph;\n\n if (bundles.length === 0) {\n if (dbConnection && hasDriver) {\n const markerProbe = await validateOnlineMarkerRead(config, dbConnection);\n if (!markerProbe.ok) {\n return markerProbe;\n }\n }\n if (contractHash !== EMPTY_CONTRACT_HASH) {\n diagnostics.push({\n code: 'CONTRACT.AHEAD',\n severity: 'warn',\n message: 'No migration exists for the current contract',\n hints: [\n \"Run 'prisma-next migration plan' to generate a migration for the current contract\",\n ],\n });\n }\n return ok({\n ok: true,\n mode: dbConnection && hasDriver ? 'online' : 'offline',\n migrations: [],\n targetHash: EMPTY_CONTRACT_HASH,\n contractHash,\n summary: 'No migrations found',\n diagnostics,\n requiredInvariants,\n });\n }\n\n let targetHash: string | undefined;\n\n if (activeRefHash) {\n targetHash = activeRefHash;\n } else if (graph.nodes.has(contractHash)) {\n targetHash = contractHash;\n } else {\n const leaves = findReachableLeaves(graph, EMPTY_CONTRACT_HASH);\n if (leaves.length === 1) {\n targetHash = leaves[0];\n } else {\n diagnostics.push({\n code: 'MIGRATION.DIVERGED',\n severity: 'warn',\n message: 'There are multiple valid migration paths — you must select a target',\n hints: [\n \"Use '--to <contract>' to select a target\",\n \"Or 'prisma-next ref set <name> <hash>' to create one\",\n ],\n });\n }\n }\n\n let markerHash: string | undefined;\n let markerInvariants: readonly string[] = [];\n let mode: 'online' | 'offline' = 'offline';\n let allMarkers: ReadonlyMap<string, ContractMarkerRecordLike> | null = null;\n\n if (dbConnection && hasDriver) {\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n try {\n await client.connect(dbConnection);\n const marker = await client.readMarker();\n markerHash = marker?.storageHash;\n markerInvariants = marker?.invariants ?? [];\n mode = 'online';\n // Read every space's marker so the aggregate enumeration can\n // surface per-space marker state. `readAllMarkers` mirrors what\n // `db init` / `db update` already use to drive the planner;\n // here it powers the aggregate status output.\n //\n // Probe for the method first so we only swallow the\n // unsupported-method case: older family instances may not\n // implement `readAllMarkers` (per-space enumeration then falls\n // back to \"marker unknown\"). Real query / runtime errors from\n // an instance that *does* expose the method must propagate up\n // — otherwise transient DB failures would silently degrade\n // status to \"markers unknown\".\n if (typeof client.readAllMarkers === 'function') {\n allMarkers = await client.readAllMarkers();\n } else {\n // Leaving `allMarkers` as `null` signals \"unknown\" to the\n // aggregate loader (an empty `Map` would instead mean \"every\n // space has no marker\", which is a different condition).\n allMarkers = null;\n }\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n if (!flags.json && !flags.quiet) {\n ui.warn('Could not connect to database — showing offline status');\n }\n } finally {\n await client.close();\n }\n }\n\n if (fromOverrideHash !== undefined) {\n markerHash = fromOverrideHash;\n mode = 'offline';\n allMarkers = null;\n }\n\n let aggregateSpaces: readonly MigrationStatusSpaceEntry[] = [];\n if (contractRawForAggregate !== null) {\n try {\n aggregateSpaces = await loadAggregateStatusSpaces({\n aggregate,\n extensionPacks: config.extensionPacks ?? [],\n markersBySpace: allMarkers,\n });\n } catch {\n aggregateSpaces = [];\n }\n }\n const totalPendingAcrossSpaces = computeTotalPendingAcrossSpaces(aggregateSpaces);\n\n // Pre-check unknown invariants. Online: union the graph's declared\n // invariants with the marker's recorded set so a retired-but-applied\n // invariant doesn't surface as MIGRATION.UNKNOWN_INVARIANT — apply would\n // route fine because marker subtraction empties `effectiveRequired`.\n // Offline: keep the check graph-strict (the marker is unknown, and a\n // missing declarer is the dominant signal we can offer).\n if (activeRefEntry && activeRefEntry.invariants.length > 0) {\n const declared = collectDeclaredInvariants(graph);\n const known = new Set<string>(declared);\n if (mode === 'online') {\n for (const id of markerInvariants) known.add(id);\n }\n const unknown = activeRefEntry.invariants.filter((id) => !known.has(id));\n if (unknown.length > 0) {\n return notOk(\n mapMigrationToolsError(\n errorUnknownInvariant({\n ...ifDefined('refName', activeRefName),\n unknown,\n declared: [...declared].sort(),\n }),\n ),\n );\n }\n }\n\n // Marker exists but is not in the migration graph and doesn't match the\n // contract hash. The DB is at an unknown state relative to the graph.\n // Bail out early with a clear diagnostic instead of rendering a confusing\n // graph with no statuses.\n //\n // When marker === contract (both off-graph), the DB matches the current\n // contract — proceed normally; the detached contract node will carry both\n // the db and contract markers.\n if (\n mode === 'online' &&\n markerHash !== undefined &&\n !graph.nodes.has(markerHash) &&\n markerHash !== contractHash\n ) {\n const hints: string[] = [];\n if (graph.nodes.has(contractHash)) {\n hints.push(\n \"Run 'prisma-next db sign' to overwrite the marker if the database already matches the contract\",\n \"Run 'prisma-next db update' to push the current contract to the database\",\n \"Run 'prisma-next contract infer' to make your contract match the database\",\n \"Run 'prisma-next db verify' to inspect the database state\",\n );\n } else {\n hints.push(\n \"Run 'prisma-next db update' to push the current contract to the database\",\n \"Run 'prisma-next contract infer' to make your contract match the database\",\n \"Run 'prisma-next db verify' to inspect the database state\",\n );\n }\n diagnostics.push({\n code: 'MIGRATION.MARKER_NOT_IN_HISTORY',\n severity: 'warn',\n message:\n 'Database was updated outside the migration system (marker does not match any migration)',\n hints,\n });\n return ok({\n ok: true,\n mode,\n migrations: [],\n targetHash: EMPTY_CONTRACT_HASH,\n contractHash,\n summary: `${bundles.length} migration(s) on disk`,\n diagnostics,\n markerHash,\n requiredInvariants,\n ...(statusRefs.length > 0 ? { refs: statusRefs } : {}),\n });\n }\n\n if (mode === 'online' && markerHash === undefined) {\n diagnostics.push({\n code: 'MIGRATION.NO_MARKER',\n severity: 'warn',\n message: 'Database has not been initialized — no migration marker found',\n hints: [\"Run 'prisma-next migrate' to apply pending migrations\"],\n });\n }\n\n // Contract diagnostic — fires when no migration produces the current contract hash.\n // Suppressed when: (a) graph is diverged (MIGRATION.DIVERGED already guides the user),\n // (b) marker === contract and both off-graph (marker-not-in-graph diagnostic covers it).\n if (\n targetHash &&\n contractHash !== EMPTY_CONTRACT_HASH &&\n !graph.nodes.has(contractHash) &&\n markerHash !== contractHash\n ) {\n diagnostics.push({\n code: 'CONTRACT.AHEAD',\n severity: 'warn',\n message: 'Contract has changed since the last migration was planned',\n hints: [\"Run 'prisma-next migration plan' to generate a migration for the current contract\"],\n });\n }\n\n if (!targetHash) {\n return ok({\n ok: true,\n mode,\n migrations: [],\n targetHash: EMPTY_CONTRACT_HASH,\n contractHash,\n summary: `${bundles.length} migration(s) on disk`,\n diagnostics,\n ...ifDefined('markerHash', markerHash),\n requiredInvariants,\n ...(statusRefs.length > 0 ? { refs: statusRefs } : {}),\n graph,\n bundles,\n diverged: true,\n });\n }\n\n const chain = resolveDisplayChain(graph, targetHash, markerHash);\n\n if (!chain) {\n return notOk(\n errorRuntime('Cannot reconstruct migration history', {\n why: `No path from ${EMPTY_CONTRACT_HASH} to target ${targetHash}`,\n fix: 'The migration history may have gaps. Check the migrations directory for missing or corrupted packages.',\n }),\n );\n }\n\n const edgeStatuses = deriveEdgeStatuses(graph, targetHash, contractHash, markerHash, mode);\n const entries = buildMigrationEntries(chain, bundles, mode, markerHash, edgeStatuses);\n\n const pendingCount = edgeStatuses.filter((e) => e.status === 'pending').length;\n const appliedCount = edgeStatuses.filter((e) => e.status === 'applied').length;\n\n let appliedInvariants: readonly string[] | undefined;\n let missingInvariants: readonly string[] | undefined;\n let effectiveRequired = new Set<string>();\n if (mode === 'online') {\n // Mirrors `migrate.ts`: compute `effectiveRequired = required −\n // marker.invariants` directly, then derive the display fields from it.\n // `appliedInvariants` is the intersection (`required ∩ marker`), which\n // is what JSON consumers see for the active ref; the unfiltered set\n // lives on `marker.invariants`.\n const markerSet = new Set(markerInvariants);\n effectiveRequired = new Set(requiredInvariants.filter((id) => !markerSet.has(id)));\n appliedInvariants = requiredInvariants.filter((id) => markerSet.has(id));\n missingInvariants = [...effectiveRequired].sort();\n }\n\n // The marker can match the structural target while still missing required\n // invariants — for example, a self-edge that provides X, applied via a ref\n // declaring X. `pendingCount` (structural) says zero in that case but\n // `effectiveRequired` is non-empty, so up-to-date messaging would mislead.\n const hasInvariantWork = effectiveRequired.size > 0;\n const missingList = [...effectiveRequired].sort().join(', ');\n\n let summary: string;\n if (mode === 'online') {\n if (markerHash !== undefined && !graph.nodes.has(markerHash) && markerHash === contractHash) {\n summary = `${bundles.length} migration(s) on disk`;\n } else if (activeRefHash && activeRefName && markerHash !== undefined) {\n const distance = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName);\n summary = hasInvariantWork ? `${distance} — missing invariant(s): ${missingList}` : distance;\n } else if (pendingCount === 0 && !hasInvariantWork) {\n summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? 's' : ''} applied)`;\n } else if (pendingCount === 0 && hasInvariantWork) {\n summary = `Missing invariant(s): ${missingList} — run 'prisma-next migrate --to ${activeRefName ?? '<ref>'}' to apply`;\n } else if (markerHash === undefined) {\n summary = `${pendingCount} pending migration(s) — database has no marker`;\n } else {\n summary = `${pendingCount} pending migration(s) — run 'prisma-next migrate' to apply`;\n }\n } else {\n summary = `${entries.length} migration(s) on disk`;\n }\n\n let pathDecision: MigrationStatusResult['pathDecision'];\n let routingUnreachable = false;\n if (mode === 'online') {\n const originHash = markerHash ?? EMPTY_CONTRACT_HASH;\n const outcome = findPathWithDecision(graph, originHash, targetHash, {\n ...ifDefined('refName', activeRefName),\n required: effectiveRequired,\n });\n if (outcome.kind === 'ok') {\n pathDecision = toPathDecisionResult(outcome.decision);\n } else if (outcome.kind === 'unsatisfiable') {\n return notOk(\n mapMigrationToolsError(\n errorNoInvariantPath({\n ...ifDefined('refName', activeRefName),\n required: [...effectiveRequired].sort(),\n missing: outcome.missing,\n structuralPath: outcome.structuralPath.map(toStructuralEdge),\n }),\n ),\n );\n } else {\n // outcome.kind === 'unreachable' — origin (marker) has no structural\n // path to the active target. `pendingCount` and `hasInvariantWork`\n // both report zero in this case, but emitting MIGRATION.UP_TO_DATE\n // would be wrong: the database simply cannot reach the requested\n // ref/contract from its current state. Suppress UP_TO_DATE below.\n routingUnreachable = true;\n }\n }\n\n if (mode === 'online') {\n if (markerHash !== undefined && !graph.nodes.has(markerHash) && markerHash === contractHash) {\n diagnostics.push({\n code: 'MIGRATION.MARKER_NOT_IN_HISTORY',\n severity: 'warn',\n message: 'Database matches the current contract but was updated directly (not via migrate)',\n hints: [\"Run 'prisma-next migration plan' to plan a migration to your current contract\"],\n });\n } else if (pendingCount > 0) {\n diagnostics.push({\n code: 'MIGRATION.DATABASE_BEHIND',\n severity: 'info',\n message: `${pendingCount} migration(s) pending`,\n hints: [\"Run 'prisma-next migrate' to apply pending migrations\"],\n });\n } else if (hasInvariantWork) {\n diagnostics.push({\n code: 'MIGRATION.INVARIANTS_PENDING',\n severity: 'info',\n message: `Missing required invariant(s): ${missingList}`,\n hints: [\n `Run 'prisma-next migrate --to ${activeRefName ?? '<ref>'}' to apply a path that covers the required invariants`,\n ],\n });\n } else if (!routingUnreachable) {\n diagnostics.push({\n code: 'MIGRATION.UP_TO_DATE',\n severity: 'info',\n message: 'Database is up to date',\n hints: [],\n });\n }\n }\n\n const result: MigrationStatusResult = {\n ok: true,\n mode,\n migrations: entries,\n targetHash,\n contractHash,\n summary,\n diagnostics,\n ...ifDefined('markerHash', markerHash),\n requiredInvariants,\n ...ifDefined('appliedInvariants', appliedInvariants),\n ...ifDefined('missingInvariants', missingInvariants),\n ...(statusRefs.length > 0 ? { refs: statusRefs } : {}),\n ...ifDefined('pathDecision', pathDecision),\n graph,\n bundles,\n edgeStatuses,\n ...ifDefined('activeRefHash', activeRefHash),\n ...ifDefined('activeRefName', activeRefName),\n spaces: aggregateSpaces,\n ...ifDefined('totalPendingAcrossSpaces', totalPendingAcrossSpaces),\n };\n return ok(result);\n}\n\nexport function createMigrationStatusCommand(): Command {\n const command = new Command('status');\n setCommandDescriptions(\n command,\n 'Show migration path and pending status',\n 'Shows which migrations are pending between the database marker and\\n' +\n 'the target contract. Requires a database connection for live status.\\n' +\n 'Use `migration graph` for topology, `migration log` for history,\\n' +\n 'and `migration list` for on-disk enumeration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration status --db $DATABASE_URL',\n 'prisma-next migration status --to production --db $DATABASE_URL',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration log', oneLiner: 'Show executed migration history' },\n { verb: 'migration list', oneLiner: 'List on-disk migrations' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n { verb: 'migration show', oneLiner: 'Display migration package contents' },\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option(\n '--to <contract>',\n 'Target contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n )\n .option(\n '--from <contract>',\n 'Origin contract reference; same grammar as --to. Supplying --from switches to offline path computation.',\n )\n .action(async (options: MigrationStatusOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n const result = await executeMigrationStatusCommand(options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (statusResult) => {\n if (flags.json) {\n const {\n graph: _graph,\n bundles: _bundles,\n edgeStatuses: _edgeStatuses,\n activeRefHash: _activeRefHash,\n activeRefName: _activeRefName,\n diverged: _diverged,\n ...jsonResult\n } = statusResult;\n ui.output(JSON.stringify(jsonResult, null, 2));\n } else if (!flags.quiet) {\n const colorize = flags.color !== false;\n\n if (statusResult.graph) {\n const renderInput = migrationGraphToRenderInput({\n graph: statusResult.graph,\n mode: statusResult.mode,\n markerHash: statusResult.markerHash,\n contractHash: statusResult.contractHash,\n refs: statusResult.refs,\n activeRefHash: statusResult.activeRefHash,\n activeRefName: statusResult.activeRefName,\n edgeStatuses: statusResult.edgeStatuses,\n });\n\n const graphToRender = statusResult.diverged\n ? renderInput.graph\n : extractRelevantSubgraph(renderInput.graph, renderInput.relevantPaths);\n const dagreOptions = isLinearGraph(graphToRender) ? { ranksep: 1 } : undefined;\n const renderOptions = {\n ...renderInput.options,\n colorize,\n ...ifDefined('dagreOptions', dagreOptions),\n };\n const graphOutput = graphRenderer.render(graphToRender, renderOptions);\n ui.log(graphOutput);\n if (statusResult.mode === 'online') {\n ui.log(formatLegend(colorize));\n }\n }\n ui.log('');\n ui.log(formatStatusSummary(statusResult, colorize));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n\nfunction formatLegend(colorize: boolean): string {\n const c = (fn: (s: string) => string, s: string) => (colorize ? fn(s) : s);\n const parts = [\n `${c(cyan, '✓')} applied`,\n `${c(yellow, '⧗')} pending`,\n `${c(magenta, '✗')} unreachable`,\n ];\n return c(dim, parts.join(' '));\n}\n\nexport function formatStatusSummary(result: MigrationStatusResult, colorize: boolean): string {\n const c = (fn: (s: string) => string, s: string) => (colorize ? fn(s) : s);\n const lines: string[] = [];\n\n const hasUnknown = result.migrations.some((e) => e.status === 'unknown');\n const pendingCount = result.migrations.filter((e) => e.status === 'pending').length;\n\n const hasWarnings = result.diagnostics?.some((d) => d.severity === 'warn') ?? false;\n // INVARIANTS_PENDING is filed at severity 'info' (per ADR 208) so the\n // warn-severity check above doesn't see it. It still represents pending\n // work, so it must promote the summary off the success icon.\n const hasInvariantPending =\n result.diagnostics?.some((d) => d.code === 'MIGRATION.INVARIANTS_PENDING') ?? false;\n\n if (result.mode === 'online') {\n if (hasUnknown || hasWarnings) {\n lines.push(`${c(yellow, '⚠')} ${result.summary}`);\n } else if (pendingCount === 0 && !hasInvariantPending) {\n lines.push(`${c(cyan, '✔')} ${result.summary}`);\n } else {\n lines.push(`${c(yellow, '⧗')} ${result.summary}`);\n }\n } else {\n lines.push(result.summary);\n }\n\n if (result.requiredInvariants.length > 0) {\n if (result.appliedInvariants !== undefined && result.missingInvariants !== undefined) {\n lines.push(`${c(dim, 'applied ')}${formatInvariantList(result.appliedInvariants)}`);\n lines.push(`${c(dim, 'missing ')}${formatInvariantList(result.missingInvariants)}`);\n } else {\n lines.push(`${c(dim, 'applied ')}(unknown — connect a database to evaluate)`);\n }\n }\n\n const warnings = result.diagnostics?.filter((d) => d.severity === 'warn') ?? [];\n for (const diag of warnings) {\n lines.push(`${c(yellow, '⚠')} ${diag.message}`);\n for (const hint of diag.hints) {\n lines.push(` ${c(dim, hint)}`);\n }\n }\n\n // Per-space section. Suppressed when there's no extension space —\n // the top-level output already covers the app member.\n // When extensions exist, render every space (including the app)\n // for consistency, plus a cross-space pending total + apply hint.\n if (result.spaces?.some((s) => s.kind === 'extension')) {\n const total = result.totalPendingAcrossSpaces ?? 0;\n lines.push('');\n lines.push(c(dim, 'spaces'));\n for (const space of result.spaces) {\n lines.push(formatSpaceLine(space, c));\n }\n if (total > 0) {\n lines.push('');\n lines.push(\n `${c(yellow, '⧗')} ${total} pending migration(s) across ${result.spaces.length} space(s) — run 'prisma-next migrate' to apply`,\n );\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatSpaceLine(\n space: MigrationStatusSpaceEntry,\n c: (fn: (s: string) => string, s: string) => string,\n): string {\n const glyph = (() => {\n if (space.status === 'up-to-date' || space.status === 'no-marker') return c(cyan, '✓');\n if (space.status === 'pending') return c(yellow, '⧗');\n if (space.status === 'unreachable' || space.status === 'never-planned') return c(magenta, '✗');\n return ' ';\n })();\n const tag = space.kind === 'app' ? '[app]' : '[ext]';\n const head = space.headHash.slice(0, 8);\n const marker =\n space.markerHash === undefined\n ? '(unknown)'\n : space.markerHash === null\n ? '(no marker)'\n : space.markerHash.slice(0, 8);\n const pending =\n space.pendingCount === undefined\n ? ''\n : space.pendingCount === 0\n ? c(dim, ' (up to date)')\n : c(yellow, ` (${space.pendingCount} pending)`);\n return ` ${glyph} ${c(dim, tag)} ${space.spaceId} → head ${c(dim, head)}, marker ${c(dim, marker)}${pending}`;\n}\n\nfunction formatInvariantList(ids: readonly string[]): string {\n return ids.length === 0 ? '(none)' : ids.join(', ');\n}\n\nfunction summarizeRefDistance(\n graph: MigrationGraph,\n markerHash: string,\n refHash: string,\n refName: string,\n): string {\n if (markerHash === refHash) return `At ref \"${refName}\" target`;\n\n const pathToRef = findPath(graph, markerHash, refHash);\n if (pathToRef) return `${pathToRef.length} migration(s) behind ref \"${refName}\"`;\n\n const pathFromRef = findPath(graph, refHash, markerHash);\n if (pathFromRef) return `${pathFromRef.length} migration(s) ahead of ref \"${refName}\"`;\n\n return `No path between database marker and ref \"${refName}\" target`;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-emit-D-4jrNve.mjs","names":["isRecord"],"sources":["../src/utils/emit-queue.ts","../src/utils/publish-contract-artifact-pair.ts","../src/utils/validate-contract-deps.ts","../src/control-api/operations/contract-emit.ts"],"sourcesContent":["/**\n * Per-output FIFO queue for `executeContractEmit`.\n *\n * Ensures that at most one emit (load → resolve source → emit bytes → publish)\n * runs per output JSON path at a time. Concurrent calls for the same path\n * line up behind the in-flight one and run in submission order; the user-visible\n * outcome is \"last submission wins on disk\" without any supersession bookkeeping.\n *\n * Long-lived hosts (Vite dev server, watch CLIs) must call `disposeEmitQueue`\n * when they stop publishing to a path, otherwise the module-global `Map`\n * accumulates one entry per unique output path for the lifetime of the process.\n */\nconst emitQueues = new Map<string, Promise<unknown>>();\n\nexport function queueEmitByOutput<T>(outputJsonPath: string, action: () => Promise<T>): Promise<T> {\n const previous = emitQueues.get(outputJsonPath) ?? Promise.resolve();\n // Continue regardless of the previous task's outcome — a failed emit must not\n // block subsequent ones. The current task's outcome propagates via `next`.\n const next = previous.then(action, action);\n emitQueues.set(outputJsonPath, next);\n return next;\n}\n\nexport function disposeEmitQueue(outputJsonPath: string): void {\n emitQueues.delete(outputJsonPath);\n}\n","import { readFile, rename, rm, writeFile } from 'node:fs/promises';\nimport { basename, dirname, join } from 'pathe';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction createTempArtifactPath(path: string, publicationToken: string, phase: string): string {\n return join(dirname(path), `.${basename(path)}.${process.pid}.${publicationToken}.${phase}.tmp`);\n}\n\ntype PreviousArtifact = { readonly content: string } | 'remove';\n\nasync function readExistingArtifact(path: string): Promise<PreviousArtifact> {\n try {\n return { content: await readFile(path, 'utf-8') };\n } catch (error) {\n if (isRecord(error) && error['code'] === 'ENOENT') {\n return 'remove';\n }\n throw error;\n }\n}\n\nasync function restoreArtifact(\n path: string,\n previous: PreviousArtifact,\n publicationToken: string,\n): Promise<void> {\n if (previous === 'remove') {\n await rm(path, { force: true });\n return;\n }\n\n const restorePath = createTempArtifactPath(path, publicationToken, 'rollback');\n await writeFile(restorePath, previous.content, 'utf-8');\n try {\n await rename(restorePath, path);\n } finally {\n await rm(restorePath, { force: true });\n }\n}\n\ninterface PublishEntry {\n readonly tempPath: string;\n readonly outputPath: string;\n readonly previous: PreviousArtifact;\n}\n\nfunction withRollbackFailureCause(error: unknown, rollbackFailures: readonly unknown[]): Error {\n const rollbackCause = new AggregateError(\n rollbackFailures,\n 'Failed to restore published artifacts',\n );\n\n if (error instanceof Error) {\n Object.defineProperty(error, 'cause', {\n value: rollbackCause,\n configurable: true,\n writable: true,\n });\n return error;\n }\n\n return new Error(String(error), { cause: rollbackCause });\n}\n\nasync function publishPairWithRollback(\n entries: readonly PublishEntry[],\n publicationToken: string,\n): Promise<void> {\n const replaced: PublishEntry[] = [];\n try {\n for (const entry of entries) {\n await rename(entry.tempPath, entry.outputPath);\n replaced.push(entry);\n }\n } catch (error) {\n const rollbackResults = await Promise.allSettled(\n replaced.map((entry) => restoreArtifact(entry.outputPath, entry.previous, publicationToken)),\n );\n const rollbackFailures = rollbackResults.flatMap((result) =>\n result.status === 'rejected' ? [result.reason] : [],\n );\n\n if (rollbackFailures.length > 0) {\n throw withRollbackFailureCause(error, rollbackFailures);\n }\n\n throw error;\n }\n}\n\nexport async function publishContractArtifactPair({\n outputJsonPath,\n outputDtsPath,\n contractJson,\n contractDts,\n publicationToken,\n beforePublish,\n}: {\n readonly outputJsonPath: string;\n readonly outputDtsPath: string;\n readonly contractJson: string;\n readonly contractDts: string;\n readonly publicationToken: string;\n readonly beforePublish?: () => Promise<boolean> | boolean;\n}): Promise<boolean> {\n const tempJsonPath = createTempArtifactPath(outputJsonPath, publicationToken, 'next');\n const tempDtsPath = createTempArtifactPath(outputDtsPath, publicationToken, 'next');\n\n try {\n await writeFile(tempJsonPath, contractJson, 'utf-8');\n await writeFile(tempDtsPath, contractDts, 'utf-8');\n\n if ((await beforePublish?.()) === false) {\n return false;\n }\n\n const previousJson = await readExistingArtifact(outputJsonPath);\n const previousDts = await readExistingArtifact(outputDtsPath);\n\n await publishPairWithRollback(\n [\n { tempPath: tempDtsPath, outputPath: outputDtsPath, previous: previousDts },\n { tempPath: tempJsonPath, outputPath: outputJsonPath, previous: previousJson },\n ],\n publicationToken,\n );\n return true;\n } finally {\n await Promise.allSettled([rm(tempJsonPath, { force: true }), rm(tempDtsPath, { force: true })]);\n }\n}\n","import { createRequire } from 'node:module';\n\nconst IMPORT_PATTERN = /import\\s+type\\s+.*?\\s+from\\s+['\"](@[^/]+\\/[^/'\"]+)/g;\n\nexport function extractPackageSpecifiers(dtsContent: string): string[] {\n const packages = new Set<string>();\n for (const match of dtsContent.matchAll(IMPORT_PATTERN)) {\n const pkg = match[1];\n if (pkg) packages.add(pkg);\n }\n return [...packages];\n}\n\nexport interface ContractDepsValidation {\n readonly missing: readonly string[];\n readonly warning?: string;\n}\n\nexport function validateContractDeps(\n dtsContent: string,\n projectRoot: string,\n): ContractDepsValidation {\n const packages = extractPackageSpecifiers(dtsContent);\n const resolve = createRequire(`${projectRoot}/package.json`);\n\n const missing: string[] = [];\n for (const pkg of packages) {\n try {\n resolve.resolve(`${pkg}/package.json`);\n } catch {\n missing.push(pkg);\n }\n }\n\n if (missing.length === 0) {\n return { missing };\n }\n\n const list = missing.map((p) => ` - ${p}`).join('\\n');\n const warning = [\n 'contract.d.ts imports types from packages that are not installed:',\n list,\n '',\n 'Install them with your package manager:',\n ...missing.map((p) => ` ${p}`),\n ].join('\\n');\n\n return { missing, warning };\n}\n","import { mkdir } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { emit, getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport { abortable } from '@prisma-next/utils/abortable';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { JsonObject } from '@prisma-next/utils/json';\nimport { dirname, join } from 'pathe';\nimport { loadConfig } from '../../config-loader';\nimport { errorContractConfigMissing, errorRuntime } from '../../utils/cli-errors';\nimport { queueEmitByOutput } from '../../utils/emit-queue';\nimport { assertFrameworkComponentsCompatible } from '../../utils/framework-components';\nimport { publishContractArtifactPair } from '../../utils/publish-contract-artifact-pair';\nimport { validateContractDeps } from '../../utils/validate-contract-deps';\nimport { enrichContract } from '../contract-enrichment';\nimport type {\n ContractEmitOptions,\n ContractEmitResult,\n ControlActionName,\n OnControlProgress,\n} from '../types';\n\nconst EMIT_ACTION: ControlActionName = 'emit';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction startSpan(onProgress: OnControlProgress | undefined, spanId: string, label: string): void {\n onProgress?.({ action: EMIT_ACTION, kind: 'spanStart', spanId, label });\n}\n\nfunction endSpan(\n onProgress: OnControlProgress | undefined,\n spanId: string,\n outcome: 'ok' | 'error',\n): void {\n onProgress?.({ action: EMIT_ACTION, kind: 'spanEnd', spanId, outcome });\n}\n\nfunction failedToResolveContractSource(why: string, fix: string, meta?: Record<string, unknown>) {\n return errorRuntime('Failed to resolve contract source', {\n why,\n fix,\n ...ifDefined('meta', meta),\n });\n}\n\ntype ValidatedProviderResult =\n | { readonly ok: true; readonly value: unknown }\n | { readonly ok: false; readonly error: ReturnType<typeof errorRuntime> };\n\nfunction diagnosticLocationSuffix(diagnostic: Record<string, unknown>): string {\n const sourceId = typeof diagnostic['sourceId'] === 'string' ? diagnostic['sourceId'] : undefined;\n const span = isRecord(diagnostic['span']) ? diagnostic['span'] : undefined;\n const start = span && isRecord(span['start']) ? span['start'] : undefined;\n const line = start && typeof start['line'] === 'number' ? start['line'] : undefined;\n const column = start && typeof start['column'] === 'number' ? start['column'] : undefined;\n if (sourceId && line !== undefined && column !== undefined) {\n return ` (${sourceId}:${line}:${column})`;\n }\n if (sourceId) {\n return ` (${sourceId})`;\n }\n return '';\n}\n\nfunction mapDiagnosticsToIssues(\n diagnostics: readonly unknown[],\n): ReadonlyArray<{ readonly kind: string; readonly message: string }> {\n const issues: { readonly kind: string; readonly message: string }[] = [];\n for (const raw of diagnostics) {\n if (!isRecord(raw)) continue;\n const code = typeof raw['code'] === 'string' ? raw['code'] : 'diagnostic';\n const message = typeof raw['message'] === 'string' ? raw['message'] : '';\n issues.push({ kind: code, message: `${message}${diagnosticLocationSuffix(raw)}` });\n }\n return issues;\n}\n\nfunction validateProviderResult(providerResult: unknown): ValidatedProviderResult {\n if (!isRecord(providerResult) || typeof providerResult['ok'] !== 'boolean') {\n return {\n ok: false,\n error: failedToResolveContractSource(\n 'Contract source provider returned malformed result shape.',\n 'Ensure contract.source.load resolves to ok(Contract) or notOk({ summary, diagnostics }).',\n ),\n };\n }\n\n if (providerResult['ok']) {\n if (!('value' in providerResult)) {\n return {\n ok: false,\n error: failedToResolveContractSource(\n 'Contract source provider returned malformed success result: missing value.',\n 'Ensure contract.source.load success payload is ok(Contract).',\n ),\n };\n }\n return { ok: true, value: providerResult['value'] };\n }\n\n const failure = providerResult['failure'];\n if (\n !isRecord(failure) ||\n typeof failure['summary'] !== 'string' ||\n !Array.isArray(failure['diagnostics'])\n ) {\n return {\n ok: false,\n error: failedToResolveContractSource(\n 'Contract source provider returned malformed failure result: expected summary and diagnostics.',\n 'Ensure contract.source.load failure payload is notOk({ summary, diagnostics, meta? }).',\n ),\n };\n }\n return {\n ok: false,\n error: failedToResolveContractSource(\n String(failure['summary']),\n 'Fix contract source diagnostics and return ok(Contract).',\n {\n diagnostics: failure['diagnostics'],\n issues: mapDiagnosticsToIssues(failure['diagnostics']),\n ...ifDefined('providerMeta', failure['meta']),\n },\n ),\n };\n}\n\n/**\n * Canonical contract emit operation.\n *\n * This is the SINGLE publication path used by both the CLI command\n * (`prisma-next contract emit`) and the Vite plugin\n * (`@prisma-next/vite-plugin-contract-emit`). New callers must go through this\n * function rather than re-implementing load → emit → publish.\n *\n * The whole flow (load config → resolve source → emit bytes → atomic publish)\n * is serialized per output JSON path via `queueEmitByOutput`. Concurrent calls\n * for the same output line up FIFO; the user-visible outcome is \"last\n * submission wins on disk\" without any supersession bookkeeping. Within a\n * single emit, `publishContractArtifactPair` stages temp files, renames\n * `contract.d.ts` before `contract.json`, and attempts to restore the previous\n * pair if either rename fails — so type-only consumers never observe a\n * mismatched pair.\n *\n * @throws {CliStructuredError} on config/source/validation problems\n * @throws {DOMException} `AbortError` if cancelled via `signal`\n */\nexport async function executeContractEmit(\n options: ContractEmitOptions,\n): Promise<ContractEmitResult> {\n const { configPath, outputPath, signal = new AbortController().signal, onProgress } = options;\n const unlessAborted = abortable(signal);\n\n const config = await unlessAborted(loadConfig(configPath));\n\n if (!config.contract) {\n throw errorContractConfigMissing({\n why: 'Config.contract is required for emit. Define it in your config: contract: { source: ..., output: ... }',\n });\n }\n\n const contractConfig = config.contract;\n\n const effectiveOutput =\n outputPath !== undefined ? join(outputPath, 'contract.json') : contractConfig.output;\n\n if (!effectiveOutput) {\n throw errorContractConfigMissing({\n why: 'Contract config must have output path. This should not happen if defineConfig() was used.',\n });\n }\n\n if (typeof contractConfig.source?.load !== 'function') {\n throw errorContractConfigMissing({\n why: 'Contract config must include a valid source provider object',\n });\n }\n\n let outputPaths: ReturnType<typeof getEmittedArtifactPaths>;\n try {\n outputPaths = getEmittedArtifactPaths(effectiveOutput);\n } catch (error) {\n throw errorContractConfigMissing({\n why: error instanceof Error ? error.message : String(error),\n });\n }\n const { jsonPath: outputJsonPath, dtsPath: outputDtsPath } = outputPaths;\n\n return queueEmitByOutput(outputJsonPath, async () => {\n const stack = createControlStack(config);\n\n const sourceContext = {\n composedExtensionPacks: stack.extensionPacks.map((p) => p.id),\n scalarTypeDescriptors: stack.scalarTypeDescriptors,\n authoringContributions: stack.authoringContributions,\n codecLookup: stack.codecLookup,\n controlMutationDefaults: stack.controlMutationDefaults,\n resolvedInputs: contractConfig.source.inputs ?? [],\n };\n\n startSpan(onProgress, 'resolveSource', 'Resolving contract source...');\n let providerResult: Awaited<ReturnType<typeof contractConfig.source.load>>;\n try {\n providerResult = await unlessAborted(contractConfig.source.load(sourceContext));\n } catch (error) {\n endSpan(onProgress, 'resolveSource', 'error');\n if (signal.aborted || (isRecord(error) && error['name'] === 'AbortError')) {\n throw error;\n }\n throw failedToResolveContractSource(\n error instanceof Error ? error.message : String(error),\n 'Ensure contract.source.load resolves to ok(Contract) or returns structured diagnostics.',\n );\n }\n\n const validatedContract = validateProviderResult(providerResult);\n if (!validatedContract.ok) {\n endSpan(onProgress, 'resolveSource', 'error');\n throw validatedContract.error;\n }\n endSpan(onProgress, 'resolveSource', 'ok');\n\n startSpan(onProgress, 'emit', 'Emitting contract...');\n let emitResult: Awaited<ReturnType<typeof emit>>;\n try {\n const familyInstance = config.family.create(stack);\n const rawComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n rawComponents,\n );\n // Blind cast: `validateProviderResult` upstream has already\n // pinned `validatedContract.value` to the provider's loose\n // `Contract` envelope, but the local `Contract` type at this\n // call site is the precise structural interface. Re-narrowing\n // the envelope into the precise type is exactly what the\n // `familyInstance.deserializeContract(enrichedIR)` call on the\n // next line does — the cast just defers the structural check\n // by one statement so `enrichContract` can decorate first.\n const enrichedIR = enrichContract(\n validatedContract.value as unknown as Contract,\n frameworkComponents,\n );\n familyInstance.deserializeContract(enrichedIR);\n // Each target's descriptor ships a `contractSerializer` SPI; the\n // framework canonicalizer threads its `serializeContract` so the\n // on-disk JSON envelope is constructed by target-owned code\n // rather than by walking the in-memory contract with\n // `Object.entries` (which would leak runtime-only class API\n // fields into the persisted shape). The optional `shouldPreserveEmpty`\n // and `sortStorage` hooks let the family contribute storage-specific\n // canonicalization rules without the framework importing family code.\n const { contractSerializer } = config.target;\n const serializeContract = (c: Contract): JsonObject =>\n contractSerializer.serializeContract(c);\n emitResult = await unlessAborted(\n emit(enrichedIR, stack, config.family.emission, {\n outputJsonPath,\n serializeContract,\n ...ifDefined('shouldPreserveEmpty', contractSerializer.shouldPreserveEmpty),\n ...ifDefined('sortStorage', contractSerializer.sortStorage),\n }),\n );\n } catch (error) {\n endSpan(onProgress, 'emit', 'error');\n throw error;\n }\n endSpan(onProgress, 'emit', 'ok');\n\n await unlessAborted(mkdir(dirname(outputJsonPath), { recursive: true }));\n await publishContractArtifactPair({\n outputJsonPath,\n outputDtsPath,\n contractJson: emitResult.contractJson,\n contractDts: emitResult.contractDts,\n publicationToken: String(process.hrtime.bigint()),\n });\n\n const validationWarning = validateContractDeps(\n emitResult.contractDts,\n dirname(outputDtsPath),\n ).warning;\n\n return {\n storageHash: emitResult.storageHash,\n ...ifDefined('executionHash', emitResult.executionHash),\n profileHash: emitResult.profileHash,\n files: {\n json: outputJsonPath,\n dts: outputDtsPath,\n },\n ...ifDefined('validationWarning', validationWarning),\n };\n });\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-infer-D8uEbJuu.mjs","names":[],"sources":["../src/commands/contract-infer-paths.ts","../src/commands/contract-infer.ts"],"sourcesContent":["import { dirname, resolve } from 'pathe';\n\ninterface ContractInferPathOptions {\n readonly output?: string;\n readonly config?: string;\n}\n\n/**\n * Resolves the output path for the inferred PSL contract.\n *\n * Priority:\n * 1. --output <path> flag (resolved relative to cwd)\n * 2. contract.prisma next to config.contract.output\n * 3. Canonical default: contract.prisma in the config directory\n */\nexport function resolveContractInferOutputPath(\n options: ContractInferPathOptions,\n contractOutput: string | undefined,\n): string {\n const configDir = options.config\n ? dirname(resolve(process.cwd(), options.config))\n : process.cwd();\n\n if (options.output) {\n return resolve(process.cwd(), options.output);\n }\n if (contractOutput) {\n const contractPath = resolve(configDir, contractOutput);\n return resolve(dirname(contractPath), 'contract.prisma');\n }\n return resolve(configDir, 'contract.prisma');\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport { printPsl } from '@prisma-next/psl-printer';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { dirname, relative } from 'pathe';\nimport type { CliStructuredError } from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\nimport { resolveContractInferOutputPath } from './contract-infer-paths';\nimport {\n type InspectLiveSchemaOptions,\n type InspectLiveSchemaResult,\n inspectLiveSchema,\n} from './inspect-live-schema';\n\ninterface ContractInferOptions extends InspectLiveSchemaOptions {\n readonly output?: string;\n}\n\ninterface ContractInferSuccessResult {\n readonly ok: true;\n readonly summary: string;\n readonly target: InspectLiveSchemaResult['target'];\n readonly psl: {\n readonly path: string;\n };\n readonly meta: InspectLiveSchemaResult['meta'];\n readonly timings: {\n readonly total: number;\n };\n}\n\nasync function executeContractInferCommand(\n options: ContractInferOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<ContractInferSuccessResult, CliStructuredError>> {\n const inspectResult = await inspectLiveSchema(options, flags, ui, startTime, {\n commandName: 'contract infer',\n description: 'Infer a PSL contract from the live database schema',\n url: 'https://pris.ly/contract-infer',\n });\n\n if (!inspectResult.ok) {\n return inspectResult;\n }\n\n const { config, target, meta, pslContractAst } = inspectResult.value;\n\n if (!pslContractAst) {\n return notOk(\n errorRuntime('contract infer is not supported for this family', {\n why: 'The configured family does not implement the PslContractInferCapable capability, so an inferred PSL contract cannot be produced from the live database schema.',\n fix: 'Use a family that supports contract inference (e.g. SQL/Postgres).',\n }),\n );\n }\n\n const outputPath = resolveContractInferOutputPath(options, config.contract?.output);\n const pslContent = printPsl(pslContractAst);\n\n if (existsSync(outputPath) && !flags.json && !flags.quiet) {\n ui.stderr(`\\u26A0 Overwriting existing file: ${relative(process.cwd(), outputPath)}`);\n }\n\n mkdirSync(dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, pslContent, 'utf-8');\n\n const pslPath = relative(process.cwd(), outputPath);\n if (!flags.json && !flags.quiet) {\n ui.stderr(`\\u2714 Contract written to ${pslPath}`);\n }\n\n return ok({\n ok: true,\n summary: 'Contract inferred successfully',\n target,\n psl: {\n path: pslPath,\n },\n meta,\n timings: {\n total: Date.now() - startTime,\n },\n });\n}\n\nexport function createContractInferCommand(): Command {\n const command = new Command('infer');\n setCommandDescriptions(\n command,\n 'Infer a PSL contract from the live database schema',\n 'Reads the live database schema and writes an inferred PSL contract to disk.\\n' +\n 'This command stops at `contract.prisma`; follow it with `contract emit` and\\n' +\n '`db sign` as separate steps.',\n );\n setCommandExamples(command, [\n 'prisma-next contract infer --db $DATABASE_URL',\n 'prisma-next contract infer --db $DATABASE_URL --output ./src/prisma/contract.prisma',\n 'prisma-next contract infer --db $DATABASE_URL --json',\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--output <path>', 'Write the inferred PSL contract to the specified path')\n .action(async (options: ContractInferOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const startTime = Date.now();\n\n const result = await executeContractInferCommand(options, flags, ui, startTime);\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value, null, 2));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAeA,SAAgB,+BACd,SACA,gBACQ;CACR,MAAM,YAAY,QAAQ,SACtB,QAAQ,QAAQ,QAAQ,IAAI,GAAG,QAAQ,MAAM,CAAC,IAC9C,QAAQ,IAAI;CAEhB,IAAI,QAAQ,QACV,OAAO,QAAQ,QAAQ,IAAI,GAAG,QAAQ,MAAM;CAE9C,IAAI,gBAEF,OAAO,QAAQ,QADM,QAAQ,WAAW,cACN,CAAC,GAAG,iBAAiB;CAEzD,OAAO,QAAQ,WAAW,iBAAiB;AAC7C;;;ACQA,eAAe,4BACb,SACA,OACA,IACA,WACiE;CACjE,MAAM,gBAAgB,MAAM,kBAAkB,SAAS,OAAO,IAAI,WAAW;EAC3E,aAAa;EACb,aAAa;EACb,KAAK;CACP,CAAC;CAED,IAAI,CAAC,cAAc,IACjB,OAAO;CAGT,MAAM,EAAE,QAAQ,QAAQ,MAAM,mBAAmB,cAAc;CAE/D,IAAI,CAAC,gBACH,OAAO,MACL,aAAa,mDAAmD;EAC9D,KAAK;EACL,KAAK;CACP,CAAC,CACH;CAGF,MAAM,aAAa,+BAA+B,SAAS,OAAO,UAAU,MAAM;CAClF,MAAM,aAAa,SAAS,cAAc;CAE1C,IAAI,WAAW,UAAU,KAAK,CAAC,MAAM,QAAQ,CAAC,MAAM,OAClD,GAAG,OAAO,qCAAqC,SAAS,QAAQ,IAAI,GAAG,UAAU,GAAG;CAGtF,UAAU,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;CAClD,cAAc,YAAY,YAAY,OAAO;CAE7C,MAAM,UAAU,SAAS,QAAQ,IAAI,GAAG,UAAU;CAClD,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB,GAAG,OAAO,8BAA8B,SAAS;CAGnD,OAAO,GAAG;EACR,IAAI;EACJ,SAAS;EACT;EACA,KAAK,EACH,MAAM,QACR;EACA;EACA,SAAS,EACP,OAAO,KAAK,IAAI,IAAI,UACtB;CACF,CAAC;AACH;AAEA,SAAgB,6BAAsC;CACpD,MAAM,UAAU,IAAI,QAAQ,OAAO;CACnC,uBACE,SACA,sDACA,wLAGF;CACA,mBAAmB,SAAS;EAC1B;EACA;EACA;CACF,CAAC;CACD,iBAAiB,OAAO,EACrB,OAAO,cAAc,4BAA4B,EACjD,OAAO,mBAAmB,+BAA+B,EACzD,OAAO,mBAAmB,uDAAuD,EACjF,OAAO,OAAO,YAAkC;EAC/C,MAAM,QAAQ,uBAAuB,OAAO;EAC5C,MAAM,KAAK,iBAAiB,KAAK;EAIjC,MAAM,WAAW,aAAa,MADT,4BAA4B,SAAS,OAAO,IAF/C,KAAK,IAEsD,CAAC,GACxC,OAAO,KAAK,UAAU;GAC1D,IAAI,MAAM,MACR,GAAG,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;EAE5C,CAAC;EAED,QAAQ,KAAK,QAAQ;CACvB,CAAC;CAEH,OAAO;AACT"}