@prisma-next/cli 0.12.0-dev.67 → 0.12.0-dev.69

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 (41) hide show
  1. package/dist/cli.mjs +5 -5
  2. package/dist/commands/migrate.d.mts.map +1 -1
  3. package/dist/commands/migrate.mjs +17 -11
  4. package/dist/commands/migrate.mjs.map +1 -1
  5. package/dist/commands/migration-check.mjs +1 -1
  6. package/dist/commands/migration-graph.mjs +2 -2
  7. package/dist/commands/migration-graph.mjs.map +1 -1
  8. package/dist/commands/migration-list.mjs +1 -1
  9. package/dist/commands/migration-log.mjs +1 -1
  10. package/dist/commands/migration-status.d.mts.map +1 -1
  11. package/dist/commands/migration-status.mjs +1 -1
  12. package/dist/{migration-check-soB5uZEQ.mjs → migration-check-VwM8xCZV.mjs} +2 -1
  13. package/dist/{migration-check-soB5uZEQ.mjs.map → migration-check-VwM8xCZV.mjs.map} +1 -1
  14. package/dist/migration-graph-command-render-BAOzyYF6.mjs +1822 -0
  15. package/dist/migration-graph-command-render-BAOzyYF6.mjs.map +1 -0
  16. package/dist/{migration-list-CyLslAtv.mjs → migration-list-CihF6w5z.mjs} +2 -2
  17. package/dist/migration-list-CihF6w5z.mjs.map +1 -0
  18. package/dist/{migration-log-BYt18y2H.mjs → migration-log-B75IArji.mjs} +2 -2
  19. package/dist/{migration-log-BYt18y2H.mjs.map → migration-log-B75IArji.mjs.map} +1 -1
  20. package/dist/{migration-status-ciYpjhtu.mjs → migration-status-CSVe6ZlD.mjs} +4 -3
  21. package/dist/migration-status-CSVe6ZlD.mjs.map +1 -0
  22. package/package.json +19 -18
  23. package/src/commands/migrate.ts +35 -26
  24. package/src/commands/migration-graph.ts +1 -1
  25. package/src/commands/migration-list.ts +1 -1
  26. package/src/commands/migration-status-overlay.ts +1 -1
  27. package/src/commands/migration-status.ts +4 -2
  28. package/src/utils/formatters/migration-graph-command-render.ts +239 -0
  29. package/src/utils/formatters/migration-graph-grid-layout.ts +857 -0
  30. package/src/utils/formatters/migration-graph-labels.ts +406 -0
  31. package/src/utils/formatters/migration-graph-model.ts +94 -0
  32. package/src/utils/formatters/migration-graph-occlusion-render.ts +245 -0
  33. package/src/utils/formatters/migration-graph-space-render.ts +73 -33
  34. package/src/utils/formatters/migration-list-render.ts +1 -1
  35. package/dist/migration-graph-space-render-Cpg0ql8v.mjs +0 -2370
  36. package/dist/migration-graph-space-render-Cpg0ql8v.mjs.map +0 -1
  37. package/dist/migration-list-CyLslAtv.mjs.map +0 -1
  38. package/dist/migration-status-ciYpjhtu.mjs.map +0 -1
  39. package/src/utils/formatters/migration-graph-lane-colors.ts +0 -194
  40. package/src/utils/formatters/migration-graph-layout.ts +0 -1308
  41. package/src/utils/formatters/migration-graph-tree-render.ts +0 -1337
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Occlusion renderer for the line/plane/occlusion migration-graph.
3
+ *
4
+ * Per cell: pick the topmost-plane line (lowest plane number = drawn on top),
5
+ * look up its glyph, apply colour from the line's lane or role. Lower-plane
6
+ * lines are occluded (not drawn).
7
+ *
8
+ * Colour is forced via createColors({ useColor: true }) regardless of NO_COLOR.
9
+ */
10
+
11
+ import { createColors } from 'colorette';
12
+ import type { Cell, CellLine, Direction, Grid, PathRole } from './migration-graph-model';
13
+
14
+ // ---------------------------------------------------------------------------
15
+ // Force-colour seam — always emits ANSI regardless of NO_COLOR.
16
+ // Same technique as gallery-cells.ts.
17
+ // ---------------------------------------------------------------------------
18
+ const palette = createColors({ useColor: true });
19
+
20
+ // Lane colour palette: lane N → colour N+1 (lane0=white, lane1=cyan, …).
21
+ // No red (reads as an error). The on-path highlight uses greenBright (SGR 92),
22
+ // distinct from flat-lane green (SGR 32).
23
+ type Colorizer = (text: string) => string;
24
+
25
+ const LANE_COLORIZERS: Colorizer[] = [
26
+ palette.white,
27
+ palette.cyan,
28
+ palette.yellow,
29
+ palette.blueBright,
30
+ palette.magenta,
31
+ palette.green,
32
+ ];
33
+
34
+ function laneColor(lane: number): Colorizer {
35
+ return LANE_COLORIZERS[lane % LANE_COLORIZERS.length] ?? ((t) => t);
36
+ }
37
+
38
+ /**
39
+ * The colourizer for a lane's hue (lane0 = white, lane1 = cyan, …). Exported
40
+ * so the per-row LABEL renderer can tint a migration name in its lane's colour,
41
+ * matching the node `○`, the edges, and the arrows drawn in the gutter — one
42
+ * colour per lane across glyph and text.
43
+ */
44
+ export function laneColorizer(lane: number): (text: string) => string {
45
+ return laneColor(lane);
46
+ }
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Focus colour: on-path → green, off-path → dim. Read straight off the line's
50
+ // role; a defined role always overrides the lane rotation.
51
+ // ---------------------------------------------------------------------------
52
+ function roleColor(role: PathRole): Colorizer {
53
+ return role === 'on-path' ? palette.greenBright : palette.dim;
54
+ }
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Glyph alphabet — unicode and ASCII variants.
58
+ // ---------------------------------------------------------------------------
59
+ export type GraphGlyphMode = 'unicode' | 'ascii';
60
+
61
+ interface GraphGlyphAlphabet {
62
+ readonly vertical: string;
63
+ readonly horizontal: string;
64
+ readonly cornerUpRight: string;
65
+ readonly cornerDownRight: string;
66
+ readonly cornerUpLeft: string;
67
+ readonly cornerDownLeft: string;
68
+ readonly arrowUp: string;
69
+ readonly arrowDown: string;
70
+ readonly node: string;
71
+ readonly selfLoop: string;
72
+ readonly landingArrow: string;
73
+ readonly fallback: string;
74
+ }
75
+
76
+ const UNICODE_ALPHABET: GraphGlyphAlphabet = {
77
+ vertical: '│',
78
+ horizontal: '─',
79
+ cornerUpRight: '╰',
80
+ cornerDownRight: '╭',
81
+ cornerUpLeft: '╯',
82
+ cornerDownLeft: '╮',
83
+ arrowUp: '↑',
84
+ arrowDown: '↓',
85
+ node: '○',
86
+ selfLoop: '⟲',
87
+ landingArrow: '◂',
88
+ fallback: '?',
89
+ };
90
+
91
+ const ASCII_ALPHABET: GraphGlyphAlphabet = {
92
+ vertical: '|',
93
+ horizontal: '-',
94
+ cornerUpRight: '\\',
95
+ cornerDownRight: '/',
96
+ cornerUpLeft: '/',
97
+ cornerDownLeft: '\\',
98
+ arrowUp: '^',
99
+ arrowDown: 'v',
100
+ node: '*',
101
+ selfLoop: '@',
102
+ landingArrow: '<',
103
+ fallback: '?',
104
+ };
105
+
106
+ function alphabetFor(mode: GraphGlyphMode): GraphGlyphAlphabet {
107
+ return mode === 'ascii' ? ASCII_ALPHABET : UNICODE_ALPHABET;
108
+ }
109
+
110
+ function glyphFor(dirs: ReadonlySet<Direction>, alphabet: GraphGlyphAlphabet): string {
111
+ const has = (d: Direction) => dirs.has(d);
112
+
113
+ if (has('up') && has('down') && !has('left') && !has('right')) return alphabet.vertical;
114
+ if (has('left') && has('right') && !has('up') && !has('down')) return alphabet.horizontal;
115
+ if (has('up') && has('right') && !has('down') && !has('left')) return alphabet.cornerUpRight;
116
+ if (has('down') && has('right') && !has('up') && !has('left')) return alphabet.cornerDownRight;
117
+ if (has('up') && has('left') && !has('down') && !has('right')) return alphabet.cornerUpLeft;
118
+ if (has('down') && has('left') && !has('up') && !has('right')) return alphabet.cornerDownLeft;
119
+ if (has('up') && !has('down') && !has('left') && !has('right')) return alphabet.arrowUp;
120
+ if (has('down') && !has('up') && !has('left') && !has('right')) return alphabet.arrowDown;
121
+
122
+ // Fallback: shouldn't happen in well-formed grids
123
+ return alphabet.fallback;
124
+ }
125
+
126
+ // ---------------------------------------------------------------------------
127
+ // renderCell — project one cell to a coloured string fragment.
128
+ // ---------------------------------------------------------------------------
129
+
130
+ const NO_COLOR: Colorizer = (t) => t;
131
+
132
+ function renderCell(cell: Cell, colorEnabled: boolean, alphabet: GraphGlyphAlphabet): string {
133
+ // Node marker overrides everything
134
+ if (cell.node !== undefined) {
135
+ // Every node uses ○ — the ∅ identifier is only used as the label, not as a
136
+ // glyph, per the golden colour model. Colour by role (focus) or lane (flat).
137
+ const colorize = !colorEnabled
138
+ ? NO_COLOR
139
+ : cell.node.role !== undefined
140
+ ? roleColor(cell.node.role)
141
+ : laneColor(cell.node.lane);
142
+ return colorize(alphabet.node);
143
+ }
144
+
145
+ if (cell.lines.length === 0) {
146
+ return ' ';
147
+ }
148
+
149
+ // Pick the drawn line by occlusion: lowest plane number wins (drawn on top).
150
+ // At an equal plane, on-path beats off-path explicitly — never rely on array
151
+ // order to break the tie (the single-owner invariant should already prevent
152
+ // a same-plane on/off-path collision, but the priority is made explicit here).
153
+ const topLine = cell.lines.reduce<CellLine>((best, current) => {
154
+ if (current.plane < best.plane) return current;
155
+ if (current.plane > best.plane) return best;
156
+ if (current.line.role === 'on-path' && best.line.role !== 'on-path') return current;
157
+ return best;
158
+ }, cell.lines[0]!);
159
+
160
+ const glyph =
161
+ topLine.selfLoop === true
162
+ ? alphabet.selfLoop
163
+ : topLine.landingArrow === true
164
+ ? alphabet.landingArrow
165
+ : glyphFor(topLine.directions, alphabet);
166
+ const colorize = !colorEnabled
167
+ ? NO_COLOR
168
+ : topLine.line.role !== undefined
169
+ ? roleColor(topLine.line.role)
170
+ : laneColor(topLine.line.lane);
171
+ return colorize(glyph);
172
+ }
173
+
174
+ // ---------------------------------------------------------------------------
175
+ // RenderGridOptions
176
+ // ---------------------------------------------------------------------------
177
+
178
+ export interface RenderGridOptions {
179
+ readonly colorize?: boolean;
180
+ readonly colsPerLane?: number;
181
+ readonly glyphMode?: GraphGlyphMode;
182
+ }
183
+
184
+ // ---------------------------------------------------------------------------
185
+ // renderGrid — the main render function.
186
+ //
187
+ // Produces the final string: one line per grid row, each cell rendered to
188
+ // a coloured character. Trailing empty cells are trimmed, but we always
189
+ // include up to the last non-empty cell's connector column
190
+ // (the full 2-col-per-lane width for the active lane count).
191
+ // ---------------------------------------------------------------------------
192
+
193
+ /**
194
+ * Render a single grid row to a coloured string. A completely empty row returns
195
+ * the empty string (the row is NOT dropped) so callers that pair grid rows with
196
+ * an external per-row label list keep a 1:1 index correspondence. `renderGrid`
197
+ * itself drops empty rows for its standalone output.
198
+ */
199
+ export function renderGridRow(
200
+ row: readonly (Cell | undefined)[],
201
+ opts: RenderGridOptions = {},
202
+ ): string {
203
+ // Find the last non-empty cell index
204
+ let lastNonEmpty = -1;
205
+ for (let i = row.length - 1; i >= 0; i--) {
206
+ const cell = row[i];
207
+ if (cell !== undefined && (cell.lines.length > 0 || cell.node !== undefined)) {
208
+ lastNonEmpty = i;
209
+ break;
210
+ }
211
+ }
212
+
213
+ if (lastNonEmpty < 0) {
214
+ return '';
215
+ }
216
+
217
+ // Extend to the next even column boundary (connector col of the current lane)
218
+ // so that connector columns are always present for active lane ranges.
219
+ const colsPerLane = opts.colsPerLane ?? 2;
220
+ const colorEnabled = opts.colorize ?? true;
221
+ const alphabet = alphabetFor(opts.glyphMode ?? 'unicode');
222
+ const lastLane = Math.floor(lastNonEmpty / colsPerLane);
223
+ const lastConnectorCol = lastLane * colsPerLane + (colsPerLane - 1);
224
+ const renderThrough = Math.max(lastNonEmpty, lastConnectorCol);
225
+
226
+ let line = '';
227
+ for (let col = 0; col <= Math.min(renderThrough, row.length - 1); col++) {
228
+ const cell = row[col];
229
+ line += cell === undefined ? ' ' : renderCell(cell, colorEnabled, alphabet);
230
+ }
231
+ return line;
232
+ }
233
+
234
+ export function renderGrid(grid: Grid, opts: RenderGridOptions = {}): string {
235
+ const lines: string[] = [];
236
+ for (const row of grid) {
237
+ const rendered = renderGridRow(row, opts);
238
+ if (rendered === '') {
239
+ // Completely empty row — skip in standalone output.
240
+ continue;
241
+ }
242
+ lines.push(rendered);
243
+ }
244
+ return lines.join('\n');
245
+ }
@@ -1,13 +1,14 @@
1
1
  import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
2
2
  import type { GlyphMode } from '../glyph-mode';
3
- import { buildMigrationGraphLayout } from './migration-graph-layout';
4
- import { buildMigrationGraphRows } from './migration-graph-rows';
5
3
  import {
6
- computeMaxDirNameLengthForLayout,
7
- computeMaxEdgeTreePrefixWidthForLayout,
8
- type MigrationEdgeAnnotation,
9
- renderMigrationGraphTree,
10
- } from './migration-graph-tree-render';
4
+ computeLabelColumn,
5
+ computeMaxDirNameWidth,
6
+ renderMigrationGraphCommand,
7
+ } from './migration-graph-command-render';
8
+ import { buildGrid } from './migration-graph-grid-layout';
9
+ import type { MigrationEdgeAnnotation } from './migration-graph-labels';
10
+ import type { Highlight } from './migration-graph-model';
11
+ import { buildMigrationGraphRows } from './migration-graph-rows';
11
12
  import {
12
13
  buildEdgeAnnotationsByHashFromListEntries,
13
14
  buildRefsByHashFromListEntries,
@@ -32,6 +33,24 @@ export function mergeMigrationEdgeAnnotations(
32
33
  return merged;
33
34
  }
34
35
 
36
+ /**
37
+ * Translate `migrate --show` per-edge path-highlight annotations into a
38
+ * {@link Highlight}. With any `pathHighlight` present the result is focus mode
39
+ * (on-path lifted green, off-path dim); otherwise flat (lane-rotation colour).
40
+ */
41
+ export function highlightFromEdgeAnnotations(
42
+ edgeAnnotationsByHash: ReadonlyMap<string, MigrationEdgeAnnotation>,
43
+ ): Highlight {
44
+ const onPath = new Set<string>();
45
+ let anyPathHighlight = false;
46
+ for (const [migrationHash, annotation] of edgeAnnotationsByHash) {
47
+ if (annotation.pathHighlight === undefined) continue;
48
+ anyPathHighlight = true;
49
+ if (annotation.pathHighlight === 'on-path') onPath.add(migrationHash);
50
+ }
51
+ return anyPathHighlight ? { mode: 'focus', onPath } : { mode: 'flat', onPath: new Set() };
52
+ }
53
+
35
54
  export interface RenderMigrationGraphSpaceTreeInput {
36
55
  readonly graph: MigrationGraph;
37
56
  readonly migrations: readonly MigrationListEntry[];
@@ -42,14 +61,17 @@ export interface RenderMigrationGraphSpaceTreeInput {
42
61
  readonly statusOverlayByHash?: ReadonlyMap<string, MigrationEdgeAnnotation>;
43
62
  readonly dbHash?: string;
44
63
  readonly styler?: MigrationListStyler;
64
+ /**
65
+ * Cross-space override for the gutter→label column (the widest gutter across
66
+ * sibling space sections, plus the label gap). Named for historical
67
+ * continuity with the previous renderer's prefix-width input.
68
+ */
45
69
  readonly globalMaxEdgeTreePrefixWidth?: number;
46
70
  readonly globalMaxDirNameWidth?: number;
47
71
  /**
48
- * Whether this render is for the app space. When false, `contractHash` is
49
- * not forwarded to `buildMigrationGraphRows` (suppressing the floating
50
- * working-contract node) and `isAppSpace: false` is passed to
51
- * `renderMigrationGraphTree` (suppressing the `@contract` marker).
52
- * Defaults to `true` so single-space callers are unaffected.
72
+ * Whether this render is for the app space. When false, `contractHash` is not
73
+ * forwarded to `buildMigrationGraphRows` (suppressing the floating working-
74
+ * contract node) and the `@contract` marker is suppressed. Defaults to `true`.
53
75
  */
54
76
  readonly isAppSpace?: boolean;
55
77
  }
@@ -59,16 +81,27 @@ export interface ComputeGlobalMaxEdgeTreePrefixWidthInput {
59
81
  readonly liveContractHash: string;
60
82
  }
61
83
 
84
+ function buildGridForInput(input: ComputeGlobalMaxEdgeTreePrefixWidthInput): {
85
+ readonly grid: ReturnType<typeof buildGrid>;
86
+ readonly rowModel: ReturnType<typeof buildMigrationGraphRows>;
87
+ } {
88
+ const rowModel = buildMigrationGraphRows(input.graph, { contractHash: input.liveContractHash });
89
+ const grid = buildGrid(rowModel, {}, { mode: 'flat', onPath: new Set() });
90
+ return { grid, rowModel };
91
+ }
92
+
93
+ /**
94
+ * The widest gutter→label column across the given space layouts. Cross-space
95
+ * callers pass this back in so every section's labels share one column.
96
+ */
62
97
  export function computeGlobalMaxEdgeTreePrefixWidth(
63
98
  inputs: readonly ComputeGlobalMaxEdgeTreePrefixWidthInput[],
99
+ glyphMode: GlyphMode = 'unicode',
64
100
  ): number {
65
101
  let globalMax = 0;
66
102
  for (const input of inputs) {
67
- const rowModel = buildMigrationGraphRows(input.graph, {
68
- contractHash: input.liveContractHash,
69
- });
70
- const layout = buildMigrationGraphLayout(rowModel);
71
- globalMax = Math.max(globalMax, computeMaxEdgeTreePrefixWidthForLayout(layout));
103
+ const { grid } = buildGridForInput(input);
104
+ globalMax = Math.max(globalMax, computeLabelColumn(grid, glyphMode));
72
105
  }
73
106
  return globalMax;
74
107
  }
@@ -78,11 +111,8 @@ export function computeGlobalMaxDirNameWidth(
78
111
  ): number {
79
112
  let globalMax = 0;
80
113
  for (const input of inputs) {
81
- const rowModel = buildMigrationGraphRows(input.graph, {
82
- contractHash: input.liveContractHash,
83
- });
84
- const layout = buildMigrationGraphLayout(rowModel);
85
- globalMax = Math.max(globalMax, computeMaxDirNameLengthForLayout(layout));
114
+ const { rowModel } = buildGridForInput(input);
115
+ globalMax = Math.max(globalMax, computeMaxDirNameWidth(rowModel));
86
116
  }
87
117
  return globalMax;
88
118
  }
@@ -92,23 +122,27 @@ function renderMigrationGraphSpaceTreeInternal(input: RenderMigrationGraphSpaceT
92
122
  const rowModel = buildMigrationGraphRows(input.graph, {
93
123
  ...(appSpace ? { contractHash: input.liveContractHash } : {}),
94
124
  });
95
- const layout = buildMigrationGraphLayout(rowModel);
96
125
  const listOverlay = buildEdgeAnnotationsByHashFromListEntries(input.migrations);
97
126
  const edgeAnnotationsByHash =
98
127
  input.statusOverlayByHash === undefined
99
128
  ? listOverlay
100
129
  : mergeMigrationEdgeAnnotations(listOverlay, input.statusOverlayByHash);
101
- return renderMigrationGraphTree(layout, {
102
- refsByHash: input.refsByHash ?? buildRefsByHashFromListEntries(input.migrations),
130
+ const highlight = highlightFromEdgeAnnotations(edgeAnnotationsByHash);
131
+ const grid = buildGrid(rowModel, {}, highlight);
132
+
133
+ return renderMigrationGraphCommand({
134
+ grid,
135
+ rowModel,
136
+ colorize: input.colorize,
137
+ glyphMode: input.glyphMode,
103
138
  contractHash: input.liveContractHash,
104
139
  isAppSpace: appSpace,
105
140
  edgeAnnotationsByHash,
106
- colorize: input.colorize,
107
- glyphMode: input.glyphMode,
141
+ refsByHash: input.refsByHash ?? buildRefsByHashFromListEntries(input.migrations),
108
142
  ...(input.dbHash !== undefined ? { dbHash: input.dbHash } : {}),
109
143
  ...(input.styler !== undefined ? { styler: input.styler } : {}),
110
144
  ...(input.globalMaxEdgeTreePrefixWidth !== undefined
111
- ? { globalMaxEdgeTreePrefixWidth: input.globalMaxEdgeTreePrefixWidth }
145
+ ? { globalLabelColumn: input.globalMaxEdgeTreePrefixWidth }
112
146
  : {}),
113
147
  ...(input.globalMaxDirNameWidth !== undefined
114
148
  ? { globalMaxDirNameWidth: input.globalMaxDirNameWidth }
@@ -123,14 +157,20 @@ export function renderMigrationGraphSpaceTree(input: RenderMigrationGraphSpaceTr
123
157
  export function renderMigrationGraphSpaceTrees(
124
158
  inputs: readonly RenderMigrationGraphSpaceTreeInput[],
125
159
  ): readonly string[] {
126
- const globalMaxTreePrefix =
127
- inputs.length > 1 ? computeGlobalMaxEdgeTreePrefixWidth(inputs) : undefined;
128
- const globalMaxDirName = inputs.length > 1 ? computeGlobalMaxDirNameWidth(inputs) : undefined;
160
+ const globalInputs: ComputeGlobalMaxEdgeTreePrefixWidthInput[] = inputs.map((input) => ({
161
+ graph: input.graph,
162
+ liveContractHash: input.liveContractHash,
163
+ }));
164
+ const glyphMode = inputs[0]?.glyphMode ?? 'unicode';
165
+ const globalLabelColumn =
166
+ inputs.length > 1 ? computeGlobalMaxEdgeTreePrefixWidth(globalInputs, glyphMode) : undefined;
167
+ const globalMaxDirName =
168
+ inputs.length > 1 ? computeGlobalMaxDirNameWidth(globalInputs) : undefined;
129
169
  return inputs.map((input) =>
130
170
  renderMigrationGraphSpaceTreeInternal({
131
171
  ...input,
132
- ...(globalMaxTreePrefix !== undefined
133
- ? { globalMaxEdgeTreePrefixWidth: globalMaxTreePrefix }
172
+ ...(globalLabelColumn !== undefined
173
+ ? { globalMaxEdgeTreePrefixWidth: globalLabelColumn }
134
174
  : {}),
135
175
  ...(globalMaxDirName !== undefined ? { globalMaxDirNameWidth: globalMaxDirName } : {}),
136
176
  }),
@@ -1,13 +1,13 @@
1
1
  import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
2
2
  import type { MigrationEdge, MigrationGraph } from '@prisma-next/migration-tools/graph';
3
3
  import type { GlyphMode } from '../glyph-mode';
4
+ import type { MigrationEdgeAnnotation } from './migration-graph-labels';
4
5
  import {
5
6
  computeGlobalMaxDirNameWidth,
6
7
  computeGlobalMaxEdgeTreePrefixWidth,
7
8
  indentMigrationGraphTreeBlock,
8
9
  renderMigrationGraphSpaceTree,
9
10
  } from './migration-graph-space-render';
10
- import type { MigrationEdgeAnnotation } from './migration-graph-tree-render';
11
11
  import type { MigrationListEntry, MigrationListResult } from './migration-list-types';
12
12
 
13
13
  export type { GlyphMode } from '../glyph-mode';