@prisma-next/cli 0.12.0 → 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 (213) 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 +17 -8
  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 +164 -91
  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-D7DVUElV.mjs +0 -1232
  199. package/dist/migration-graph-D7DVUElV.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-layout.ts +0 -1119
  213. package/src/utils/formatters/migration-graph-tree-render.ts +0 -459
@@ -1,459 +0,0 @@
1
- import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
2
- import { bold } from 'colorette';
3
- import stringWidth from 'string-width';
4
- import type { GlyphMode } from '../glyph-mode';
5
- import type {
6
- MigrationGraphGridModel,
7
- MigrationGraphGridRow,
8
- StructuralCell,
9
- } from './migration-graph-layout';
10
- import type { ClassifiedEdge } from './migration-graph-rows';
11
- import {
12
- MIGRATION_LIST_HASH_WIDTH,
13
- migrationListEmptySource,
14
- migrationListForwardArrow,
15
- } from './migration-list-data-column';
16
- import type { MigrationEdgeKind } from './migration-list-graph-topology';
17
- import type { MigrationListStyler } from './migration-list-render';
18
- import { CONTRACT_MARKER_NAME, createAnsiMigrationListStyler } from './migration-list-styler';
19
-
20
- const LABEL_GAP = 2;
21
-
22
- /**
23
- * The live-database overlay marker. Just another ref as far as styling goes —
24
- * the only emphasized markers are the active ref and the `contract`
25
- * desired-state marker (see {@link CONTRACT_MARKER_NAME}).
26
- */
27
- const DB_MARKER_NAME = 'db';
28
-
29
- export interface RenderMigrationGraphTreeOptions {
30
- readonly refsByHash?: ReadonlyMap<string, readonly string[]>;
31
- readonly dbHash?: string;
32
- readonly contractHash?: string;
33
- readonly activeRefName?: string;
34
- readonly hashLength?: number;
35
- readonly colorize: boolean;
36
- readonly glyphMode?: GlyphMode;
37
- }
38
-
39
- interface MigrationGraphTreeGlyphPalette {
40
- readonly node: string;
41
- readonly arcLand: string;
42
- readonly arcTee: string;
43
- readonly verticalPass: string;
44
- readonly branchTee: string;
45
- readonly mergeTee: string;
46
- readonly branchCorner: string;
47
- readonly mergeCorner: string;
48
- readonly arcBranchCorner: string;
49
- readonly arcBranchTee: string;
50
- readonly arcLandCorner: string;
51
- readonly arcCrossing: string;
52
- readonly arcLandBridge: string;
53
- readonly horizontalPass: string;
54
- readonly connectorBranchTee: string;
55
- readonly connectorBranchTeeCo: string;
56
- readonly connectorMergeTeeCo: string;
57
- readonly edgeArrow: Readonly<Record<MigrationEdgeKind, string>>;
58
- readonly forwardArrow: string;
59
- readonly emptySource: string;
60
- }
61
-
62
- const UNICODE_PALETTE: MigrationGraphTreeGlyphPalette = {
63
- node: '○ ',
64
- arcLand: '○◂',
65
- arcTee: '○─',
66
- verticalPass: '│ ',
67
- branchTee: '├─',
68
- mergeTee: '├─',
69
- branchCorner: '╮ ',
70
- mergeCorner: '╯ ',
71
- arcBranchCorner: '╮ ',
72
- arcBranchTee: '┬─',
73
- arcLandCorner: '╯ ',
74
- arcCrossing: '┼─',
75
- arcLandBridge: '──',
76
- horizontalPass: '──',
77
- connectorBranchTee: '├─',
78
- connectorBranchTeeCo: '┬─',
79
- connectorMergeTeeCo: '┴─',
80
- edgeArrow: { forward: '↑', rollback: '↓', self: '⟲' },
81
- forwardArrow: migrationListForwardArrow('unicode'),
82
- emptySource: migrationListEmptySource('unicode'),
83
- };
84
-
85
- const ASCII_PALETTE: MigrationGraphTreeGlyphPalette = {
86
- node: '* ',
87
- arcLand: '*<',
88
- arcTee: '*-',
89
- verticalPass: '| ',
90
- branchTee: '+-',
91
- mergeTee: '+-',
92
- branchCorner: '\\ ',
93
- mergeCorner: '/ ',
94
- arcBranchCorner: '\\ ',
95
- arcBranchTee: '+-',
96
- arcLandCorner: '/ ',
97
- arcCrossing: '+-',
98
- arcLandBridge: '--',
99
- horizontalPass: '--',
100
- connectorBranchTee: '+-',
101
- connectorBranchTeeCo: '+-',
102
- connectorMergeTeeCo: '+-',
103
- edgeArrow: { forward: '^', rollback: 'v', self: '@' },
104
- forwardArrow: migrationListForwardArrow('ascii'),
105
- emptySource: migrationListEmptySource('ascii'),
106
- };
107
-
108
- function paletteFor(mode: GlyphMode): MigrationGraphTreeGlyphPalette {
109
- return mode === 'ascii' ? ASCII_PALETTE : UNICODE_PALETTE;
110
- }
111
-
112
- function arrowForEdgeKind(
113
- kind: MigrationEdgeKind,
114
- palette: MigrationGraphTreeGlyphPalette,
115
- ): string {
116
- return palette.edgeArrow[kind];
117
- }
118
-
119
- /**
120
- * A node-marker glyph pair (`○◂`, `○─`, `*<`, `*-`) is the contract node
121
- * marker (`○` / `*`) followed by an arc connector (`◂` / `─` / `<` / `-`).
122
- * The marker is the signal and stays bright (`style.kind`); the connector is
123
- * gutter and stays dim (`style.lane`) — consistent with the plain node marker,
124
- * which is never dimmed.
125
- */
126
- function renderNodeMarkerPair(pair: string, style: MigrationListStyler): string {
127
- return style.kind(pair.slice(0, 1)) + style.lane(pair.slice(1));
128
- }
129
-
130
- function renderCellPair(
131
- cell: StructuralCell,
132
- style: MigrationListStyler,
133
- palette: MigrationGraphTreeGlyphPalette,
134
- ): string {
135
- switch (cell.kind) {
136
- case 'node':
137
- if (cell.arcLand === true) return renderNodeMarkerPair(palette.arcLand, style);
138
- if (cell.arcTee === true) return renderNodeMarkerPair(palette.arcTee, style);
139
- return style.kind(palette.node);
140
- case 'vertical-pass':
141
- return style.lane(palette.verticalPass);
142
- case 'edge-lane':
143
- // The lane stays dim; the direction arrow (↑ / ↓ / ⟲) is the signal and
144
- // stays bright, like the contract-node marker.
145
- return cell.ownsLabel
146
- ? style.lane(palette.verticalPass.trimEnd()) +
147
- style.kind(arrowForEdgeKind(cell.edgeKind, palette))
148
- : style.lane(palette.verticalPass);
149
- case 'branch-tee':
150
- return style.lane(palette.branchTee);
151
- case 'merge-tee':
152
- return style.lane(palette.mergeTee);
153
- case 'branch-corner':
154
- return style.lane(palette.branchCorner);
155
- case 'merge-corner':
156
- return style.lane(palette.mergeCorner);
157
- case 'arc-branch-corner':
158
- return style.lane(palette.arcBranchCorner);
159
- case 'arc-branch-tee':
160
- return style.lane(palette.arcBranchTee);
161
- case 'arc-land-corner':
162
- return style.lane(palette.arcLandCorner);
163
- case 'arc-crossing':
164
- return style.lane(palette.arcCrossing);
165
- case 'arc-land-bridge':
166
- return style.lane(palette.arcLandBridge);
167
- case 'horizontal-pass':
168
- return style.lane(palette.horizontalPass);
169
- case 'empty':
170
- return ' ';
171
- }
172
- }
173
-
174
- function renderConnectorRow(
175
- row: MigrationGraphGridRow,
176
- gridWidth: number,
177
- style: MigrationListStyler,
178
- palette: MigrationGraphTreeGlyphPalette,
179
- ): string {
180
- const isMerge = row.kind === 'merge-connector';
181
- if (row.cells.length > 0) {
182
- let seenTee = false;
183
- let out = '';
184
- for (const cell of row.cells) {
185
- switch (cell.kind) {
186
- case 'branch-tee':
187
- out += style.lane(seenTee ? palette.connectorBranchTeeCo : palette.connectorBranchTee);
188
- seenTee = true;
189
- break;
190
- case 'merge-tee':
191
- out += style.lane(seenTee ? palette.connectorMergeTeeCo : palette.connectorBranchTee);
192
- seenTee = true;
193
- break;
194
- case 'branch-corner':
195
- out += style.lane(palette.branchCorner);
196
- break;
197
- case 'merge-corner':
198
- out += style.lane(palette.mergeCorner);
199
- break;
200
- case 'vertical-pass':
201
- out += style.lane(palette.verticalPass);
202
- break;
203
- case 'horizontal-pass':
204
- out += style.lane(palette.horizontalPass);
205
- break;
206
- default:
207
- out += ' ';
208
- }
209
- }
210
- // The cells array is sized to the grid width at emit time; a back-arc lane
211
- // allocated by a later row can push the grid wider afterwards, so pad any
212
- // trailing columns rather than dropping the lanes that pass through here.
213
- for (let column = row.cells.length; column < gridWidth; column++) {
214
- out += ' ';
215
- }
216
- return out;
217
- }
218
-
219
- const start = row.startLane ?? 0;
220
- const end = row.endLane ?? start;
221
- let out = '';
222
- for (let column = 0; column < gridWidth; column++) {
223
- if (column < start || column > end) out += ' ';
224
- else if (column === start) out += style.lane(palette.connectorBranchTee);
225
- else if (column === end)
226
- out += style.lane(isMerge ? palette.mergeCorner : palette.branchCorner);
227
- else out += style.lane(isMerge ? palette.connectorMergeTeeCo : palette.connectorBranchTeeCo);
228
- }
229
- return out;
230
- }
231
-
232
- function abbreviateHash(hash: string, hashLength: number, emptySource: string): string {
233
- if (hash === EMPTY_CONTRACT_HASH) {
234
- return emptySource;
235
- }
236
- const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;
237
- return stripped.slice(0, hashLength);
238
- }
239
-
240
- const MIN_HASH_DATA_COLUMN = 25;
241
-
242
- function overlayNamesForContract(
243
- contractHash: string,
244
- opts: RenderMigrationGraphTreeOptions,
245
- ): readonly string[] {
246
- const names: string[] = [];
247
- const userRefs = opts.refsByHash?.get(contractHash);
248
- if (userRefs) {
249
- names.push(...[...userRefs].sort((a, b) => a.localeCompare(b)));
250
- }
251
- if (opts.dbHash === contractHash) {
252
- names.push(DB_MARKER_NAME);
253
- }
254
- if (opts.contractHash === contractHash && contractHash !== EMPTY_CONTRACT_HASH) {
255
- names.push(CONTRACT_MARKER_NAME);
256
- }
257
- return names;
258
- }
259
-
260
- function createTreeStyler(opts: RenderMigrationGraphTreeOptions): MigrationListStyler {
261
- const base = createAnsiMigrationListStyler({ useColor: opts.colorize });
262
- const activeRefName = opts.activeRefName;
263
- if (!opts.colorize || activeRefName === undefined) {
264
- return base;
265
- }
266
- return {
267
- ...base,
268
- refs: (names) => {
269
- const styledNames = names.map((name) => (name === activeRefName ? bold(name) : name));
270
- return base.refs(styledNames);
271
- },
272
- };
273
- }
274
-
275
- function formatEdgeHashColumn(
276
- edge: ClassifiedEdge,
277
- style: MigrationListStyler,
278
- hashLength: number,
279
- palette: MigrationGraphTreeGlyphPalette,
280
- ): string {
281
- if (edge.kind === 'self') {
282
- const hash = abbreviateHash(edge.from, hashLength, palette.emptySource);
283
- return `${style.sourceHash(hash)} ${style.glyph(palette.forwardArrow)} ${style.destHash(hash)}`;
284
- }
285
- const source =
286
- edge.from === EMPTY_CONTRACT_HASH
287
- ? style.glyph(palette.emptySource) +
288
- ' '.repeat(Math.max(0, hashLength - palette.emptySource.length))
289
- : style.sourceHash(abbreviateHash(edge.from, hashLength, palette.emptySource));
290
- const arrow = style.glyph(palette.forwardArrow);
291
- const dest = style.destHash(abbreviateHash(edge.to, hashLength, palette.emptySource));
292
- return `${source} ${arrow} ${dest}`;
293
- }
294
-
295
- function padVisible(text: string, targetWidth: number): string {
296
- const padding = Math.max(0, targetWidth - stringWidth(text));
297
- return text + ' '.repeat(padding);
298
- }
299
-
300
- function gridWidthForModel(rows: readonly MigrationGraphGridRow[]): number {
301
- return rows.reduce(
302
- (max, row) =>
303
- row.kind === 'node' || row.kind === 'edge' ? Math.max(max, row.cells.length) : max,
304
- 1,
305
- );
306
- }
307
-
308
- function maxDirNameLength(edges: readonly ClassifiedEdge[]): number {
309
- if (edges.length === 0) return 0;
310
- return Math.max(...edges.map((edge) => edge.dirName.length));
311
- }
312
-
313
- function rowDirNameWidth(labelColumn: number, maxDirNameLen: number, dirNameGap: number): number {
314
- return Math.max(maxDirNameLen + dirNameGap, MIN_HASH_DATA_COLUMN - labelColumn);
315
- }
316
-
317
- function gridUsesSkipRollbackArcs(rows: readonly MigrationGraphGridRow[]): boolean {
318
- return rows.some((row) =>
319
- row.cells.some(
320
- (cell) => cell.kind === 'edge-lane' && cell.adjacency === 'node-skipping-rollback',
321
- ),
322
- );
323
- }
324
-
325
- function edgeLabelColumn(row: MigrationGraphGridRow, wideLabelColumn: number | undefined): number {
326
- if (wideLabelColumn !== undefined) {
327
- return wideLabelColumn;
328
- }
329
- const laneIndex = row.laneIndex ?? 0;
330
- if (row.edge?.from === EMPTY_CONTRACT_HASH && laneIndex === 0) {
331
- return (laneIndex + 1) * 2 + LABEL_GAP;
332
- }
333
- const usesFullRowGutter = row.cells.some(
334
- (cell, index) => index > laneIndex && cell.kind === 'vertical-pass',
335
- );
336
- return usesFullRowGutter ? row.cells.length * 2 + LABEL_GAP : (laneIndex + 1) * 2 + LABEL_GAP;
337
- }
338
-
339
- function nodeHasArcDecoration(row: MigrationGraphGridRow): boolean {
340
- return row.cells.some(
341
- (cell) => cell.kind === 'node' && (cell.arcTee === true || cell.arcLand === true),
342
- );
343
- }
344
-
345
- export function renderMigrationGraphTree(
346
- model: MigrationGraphGridModel,
347
- opts: RenderMigrationGraphTreeOptions,
348
- ): string {
349
- const glyphMode = opts.glyphMode ?? 'unicode';
350
- const palette = paletteFor(glyphMode);
351
- const style = createTreeStyler(opts);
352
- const hashLength = opts.hashLength ?? MIGRATION_LIST_HASH_WIDTH;
353
- const gridWidth = gridWidthForModel(model.rows);
354
- const wideLabelColumn = gridUsesSkipRollbackArcs(model.rows) ? gridWidth * 2 + 4 : undefined;
355
- const dirNameGap = wideLabelColumn !== undefined ? 3 : LABEL_GAP;
356
- const allEdges = model.rows
357
- .filter(
358
- (row): row is MigrationGraphGridRow & { edge: ClassifiedEdge } =>
359
- row.kind === 'edge' && row.edge !== undefined,
360
- )
361
- .map((row) => row.edge);
362
- const maxDirNameLen = maxDirNameLength(allEdges);
363
-
364
- const lines: string[] = [];
365
-
366
- for (let rowIndex = 0; rowIndex < model.rows.length; rowIndex++) {
367
- const row = model.rows[rowIndex];
368
- if (row === undefined) continue;
369
-
370
- if (row.kind === 'component-separator') {
371
- lines.push('');
372
- continue;
373
- }
374
-
375
- if (row.kind === 'branch-connector' || row.kind === 'merge-connector') {
376
- lines.push(renderConnectorRow(row, gridWidth, style, palette).replace(/\s+$/, ''));
377
- continue;
378
- }
379
-
380
- let gutter = row.cells.map((cell) => renderCellPair(cell, style, palette)).join('');
381
- const prevRow = model.rows[rowIndex - 1];
382
- let laneSpan = row.cells.length;
383
- if (row.kind === 'node') {
384
- const contractHash = row.contractHash ?? EMPTY_CONTRACT_HASH;
385
- if (prevRow?.kind === 'merge-connector' || contractHash === EMPTY_CONTRACT_HASH) {
386
- laneSpan = 1;
387
- } else {
388
- laneSpan = row.cells.length;
389
- }
390
- }
391
- const labelColumn =
392
- row.kind === 'edge'
393
- ? edgeLabelColumn(row, wideLabelColumn)
394
- : wideLabelColumn !== undefined &&
395
- (nodeHasArcDecoration(row) || row.contractHash !== undefined)
396
- ? wideLabelColumn
397
- : laneSpan * 2 + LABEL_GAP;
398
- if (
399
- row.kind === 'edge' &&
400
- row.edge?.from === EMPTY_CONTRACT_HASH &&
401
- (row.laneIndex ?? 0) === 0
402
- ) {
403
- gutter = row.cells
404
- .slice(0, 1)
405
- .map((cell) => renderCellPair(cell, style, palette))
406
- .join('');
407
- } else if (row.kind === 'node' && laneSpan < row.cells.length && !nodeHasArcDecoration(row)) {
408
- gutter = row.cells
409
- .slice(0, laneSpan)
410
- .map((cell) => renderCellPair(cell, style, palette))
411
- .join('');
412
- } else if (gutter.length < laneSpan * 2) {
413
- gutter = gutter.padEnd(laneSpan * 2, ' ');
414
- }
415
- const dirNameWidth = rowDirNameWidth(labelColumn, maxDirNameLen, dirNameGap);
416
- const dataColumn = labelColumn + dirNameWidth;
417
- const gutterPad = padVisible(gutter, labelColumn);
418
-
419
- if (row.kind === 'node') {
420
- const contractHash = row.contractHash ?? EMPTY_CONTRACT_HASH;
421
- if (contractHash === EMPTY_CONTRACT_HASH) {
422
- const trailingLanes = row.cells
423
- .slice(1)
424
- .map((cell) => renderCellPair(cell, style, palette))
425
- .join('');
426
- const emptyGutter = palette.emptySource.padEnd(2, ' ') + trailingLanes;
427
- const overlayNames = overlayNamesForContract(contractHash, opts);
428
- if (overlayNames.length === 0) {
429
- lines.push(emptyGutter.replace(/\s+$/, ''));
430
- continue;
431
- }
432
- const overlay = style.refs(overlayNames);
433
- lines.push(`${padVisible(emptyGutter, dataColumn)}${overlay}`.replace(/\s+$/, ''));
434
- continue;
435
- }
436
- const hashText = style.sourceHash(
437
- abbreviateHash(contractHash, hashLength, palette.emptySource),
438
- );
439
- const overlayNames = overlayNamesForContract(contractHash, opts);
440
- const overlayPad =
441
- overlayNames.length > 0
442
- ? ' '.repeat(Math.max(0, dataColumn - labelColumn - stringWidth(hashText)))
443
- : '';
444
- const overlay = overlayNames.length > 0 ? style.refs(overlayNames) : '';
445
- lines.push(`${gutterPad}${hashText}${overlayPad}${overlay}`.replace(/\s+$/, ''));
446
- continue;
447
- }
448
-
449
- const edge = row.edge;
450
- if (edge === undefined) continue;
451
-
452
- const dirNamePadding = ' '.repeat(Math.max(0, dirNameWidth - edge.dirName.length));
453
- const dirName = `${style.dirName(edge.dirName)}${dirNamePadding}`;
454
- const hashColumn = formatEdgeHashColumn(edge, style, hashLength, palette);
455
- lines.push(`${gutterPad}${dirName}${hashColumn}`.replace(/\s+$/, ''));
456
- }
457
-
458
- return lines.join('\n');
459
- }