@prisma-next/cli 0.12.0 → 0.13.0-dev.2
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.
- package/README.md +2 -2
- package/dist/cli.mjs +180 -163
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-KgJorIvG.mjs → client-CJzuo5wX.mjs} +222 -107
- package/dist/client-CJzuo5wX.mjs.map +1 -0
- package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-DGMvGBeX.mjs} +318 -25
- package/dist/command-helpers-DGMvGBeX.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +4 -5
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +6 -6
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +10 -7
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +37 -3
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +298 -12
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +55 -13
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +3 -2
- package/dist/commands/migration-graph.d.mts +17 -8
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +185 -2
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +26 -27
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +2 -190
- package/dist/commands/migration-log.d.mts +9 -19
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -137
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +6 -5
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +1 -1
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +17 -21
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +24 -36
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +42 -144
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +3 -759
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +4 -4
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/commands/telemetry/index.d.mts +7 -0
- package/dist/commands/telemetry/index.d.mts.map +1 -0
- package/dist/commands/telemetry/index.mjs +2 -0
- package/dist/{config-loader-B6sJjXTv.mjs → config-loader-p9JMrekQ.mjs} +1 -1
- package/dist/{config-loader-B6sJjXTv.mjs.map → config-loader-p9JMrekQ.mjs.map} +1 -1
- package/dist/config-loader.mjs +1 -1
- package/dist/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-CFXsstzm.mjs} +2 -2
- package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-CFXsstzm.mjs.map} +1 -1
- package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-B_qriF8B.mjs} +5 -5
- package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-B_qriF8B.mjs.map} +1 -1
- package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-C8HmtboH.mjs} +12 -7
- package/dist/contract-emit-C8HmtboH.mjs.map +1 -0
- package/dist/{contract-enrichment-a0V5Y_mL.mjs → contract-enrichment-gn9sWbPw.mjs} +1 -1
- package/dist/{contract-enrichment-a0V5Y_mL.mjs.map → contract-enrichment-gn9sWbPw.mjs.map} +1 -1
- package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-BYT_ra_U.mjs} +5 -5
- package/dist/contract-infer-BYT_ra_U.mjs.map +1 -0
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-ClI1KN6d.mjs} +5 -5
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-ClI1KN6d.mjs.map} +1 -1
- package/dist/{db-verify-v_vUKXTU.mjs → db-verify-C24FKhb7.mjs} +6 -6
- package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-C24FKhb7.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +5 -3
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -3
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts +1 -3
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{extension-pack-inputs-IDvjRCi3.mjs → extension-pack-inputs-1ySHqxKG.mjs} +1 -1
- package/dist/{extension-pack-inputs-IDvjRCi3.mjs.map → extension-pack-inputs-1ySHqxKG.mjs.map} +1 -1
- package/dist/{framework-components-fYXjz_in.mjs → framework-components-YVQHhPH7.mjs} +2 -2
- package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-YVQHhPH7.mjs.map} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-BpoOYtNZ.d.mts} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-BpoOYtNZ.d.mts.map} +1 -1
- package/dist/{init-Cv9UzWL5.mjs → init-0HwB-Vh8.mjs} +5 -58
- package/dist/init-0HwB-Vh8.mjs.map +1 -0
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-DF6IwcDl.mjs} +7 -5
- package/dist/inspect-live-schema-DF6IwcDl.mjs.map +1 -0
- package/dist/migration-check-VwM8xCZV.mjs +574 -0
- package/dist/migration-check-VwM8xCZV.mjs.map +1 -0
- package/dist/migration-cli.mjs +1 -1
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-DA-Lhx6o.mjs} +5 -5
- package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-DA-Lhx6o.mjs.map} +1 -1
- package/dist/migration-graph-command-render-CEez7YUK.mjs +1960 -0
- package/dist/migration-graph-command-render-CEez7YUK.mjs.map +1 -0
- package/dist/migration-list-DlJJ_38Z.mjs +230 -0
- package/dist/migration-list-DlJJ_38Z.mjs.map +1 -0
- package/dist/migration-log-CG0qQAFm.mjs +222 -0
- package/dist/migration-log-CG0qQAFm.mjs.map +1 -0
- package/dist/migration-path-target-Ce6OZImp.mjs +38 -0
- package/dist/migration-path-target-Ce6OZImp.mjs.map +1 -0
- package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-z5Ing-TD.mjs} +9 -8
- package/dist/migration-plan-z5Ing-TD.mjs.map +1 -0
- package/dist/migration-status-CD-LC2Ip.mjs +447 -0
- package/dist/migration-status-CD-LC2Ip.mjs.map +1 -0
- package/dist/{output-B60Gw5fu.mjs → output-mEQ74_nd.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-mEQ74_nd.mjs.map} +1 -1
- package/dist/{progress-adapter-C644QK8l.mjs → progress-adapter-CjAeTxY_.mjs} +1 -1
- package/dist/{progress-adapter-C644QK8l.mjs.map → progress-adapter-CjAeTxY_.mjs.map} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-BkXlikCA.mjs} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-BkXlikCA.mjs.map} +1 -1
- package/dist/schemas-CeGMYFYX.d.mts +191 -0
- package/dist/schemas-CeGMYFYX.d.mts.map +1 -0
- package/dist/schemas-KhXMzNA_.mjs +112 -0
- package/dist/schemas-KhXMzNA_.mjs.map +1 -0
- package/dist/telemetry-BIM4beEO.mjs +122 -0
- package/dist/telemetry-BIM4beEO.mjs.map +1 -0
- package/dist/{terminal-ui-5Y6mrg93.d.mts → terminal-ui-DGRNFWna.d.mts} +1 -1
- package/dist/terminal-ui-DGRNFWna.d.mts.map +1 -0
- package/dist/{types-Dt_SfqFm.d.mts → types-C_tYiJYx.d.mts} +53 -31
- package/dist/types-C_tYiJYx.d.mts.map +1 -0
- package/dist/{verify-DCA9Sldu.mjs → verify-DcOYZ1tH.mjs} +2 -2
- package/dist/{verify-DCA9Sldu.mjs.map → verify-DcOYZ1tH.mjs.map} +1 -1
- package/package.json +26 -22
- package/src/cli.ts +5 -0
- package/src/commands/contract-infer.ts +2 -2
- package/src/commands/db-update.ts +7 -1
- package/src/commands/init/index.ts +6 -35
- package/src/commands/init/init.ts +1 -14
- package/src/commands/init/inputs.ts +0 -75
- package/src/commands/inspect-live-schema.ts +10 -0
- package/src/commands/json/schemas.ts +195 -0
- package/src/commands/migrate.ts +527 -8
- package/src/commands/migration-check.ts +469 -134
- package/src/commands/migration-graph.ts +164 -91
- package/src/commands/migration-list.ts +72 -39
- package/src/commands/migration-log.ts +52 -102
- package/src/commands/migration-new.ts +2 -1
- package/src/commands/migration-plan.ts +2 -1
- package/src/commands/migration-show.ts +31 -66
- package/src/commands/migration-status-overlay.ts +61 -0
- package/src/commands/migration-status.ts +458 -1066
- package/src/commands/telemetry/index.ts +107 -0
- package/src/commands/telemetry/status.ts +67 -0
- package/src/control-api/client.ts +70 -9
- package/src/control-api/operations/contract-emit.ts +22 -2
- package/src/control-api/operations/db-init.ts +6 -3
- package/src/control-api/operations/{db-apply.ts → db-run.ts} +55 -14
- package/src/control-api/operations/db-update.ts +7 -4
- package/src/control-api/operations/db-verify.ts +15 -5
- package/src/control-api/operations/{migration-apply.ts → migrate.ts} +181 -80
- package/src/control-api/operations/{apply.ts → run-migration.ts} +33 -27
- package/src/control-api/types.ts +56 -29
- package/src/utils/cli-errors.ts +70 -2
- package/src/utils/formatters/errors.ts +11 -0
- package/src/utils/formatters/migration-graph-command-render.ts +239 -0
- package/src/utils/formatters/migration-graph-grid-layout.ts +1134 -0
- package/src/utils/formatters/migration-graph-labels.ts +408 -0
- package/src/utils/formatters/migration-graph-model.ts +103 -0
- package/src/utils/formatters/migration-graph-occlusion-render.ts +258 -0
- package/src/utils/formatters/migration-graph-rows.ts +128 -15
- package/src/utils/formatters/migration-graph-space-render.ts +188 -0
- package/src/utils/formatters/migration-list-data-column.ts +4 -91
- package/src/utils/formatters/migration-list-graph-topology.ts +72 -94
- package/src/utils/formatters/migration-list-render.ts +135 -71
- package/src/utils/formatters/migration-list-styler.ts +46 -5
- package/src/utils/formatters/migration-list-types.ts +5 -21
- package/src/utils/formatters/migration-log-table.ts +205 -0
- package/src/utils/formatters/migrations.ts +33 -11
- package/src/utils/global-flags.ts +35 -0
- package/src/utils/integrity-violation-to-check-failure.ts +28 -19
- package/src/utils/legend.ts +38 -0
- package/src/utils/migration-path-target.ts +60 -0
- package/src/utils/telemetry.ts +68 -32
- package/dist/client-KgJorIvG.mjs.map +0 -1
- package/dist/command-helpers-Bbw1GbwL.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/commands/migration-log.mjs.map +0 -1
- package/dist/commands/migration-status.mjs.map +0 -1
- package/dist/contract-emit-D-4jrNve.mjs.map +0 -1
- package/dist/contract-infer-D8uEbJuu.mjs.map +0 -1
- package/dist/graph-render-rFAqZujX.mjs +0 -1081
- package/dist/graph-render-rFAqZujX.mjs.map +0 -1
- package/dist/init-Cv9UzWL5.mjs.map +0 -1
- package/dist/inspect-live-schema-C6ohV_oQ.mjs.map +0 -1
- package/dist/migration-check-BiBJoYYW.mjs +0 -341
- package/dist/migration-check-BiBJoYYW.mjs.map +0 -1
- package/dist/migration-graph-D7DVUElV.mjs +0 -1232
- package/dist/migration-graph-D7DVUElV.mjs.map +0 -1
- package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
- package/dist/migration-plan-9DJ7q7_z.mjs.map +0 -1
- package/dist/migration-types-D2FW63pr.d.mts +0 -15
- package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
- package/dist/migrations-Cv2jxNNK.mjs +0 -228
- package/dist/migrations-Cv2jxNNK.mjs.map +0 -1
- package/dist/terminal-ui-5Y6mrg93.d.mts.map +0 -1
- package/dist/types-Dt_SfqFm.d.mts.map +0 -1
- package/src/utils/formatters/graph-migration-mapper.ts +0 -235
- package/src/utils/formatters/graph-render.ts +0 -1323
- package/src/utils/formatters/graph-types.ts +0 -120
- package/src/utils/formatters/migration-graph-layout.ts +0 -1119
- package/src/utils/formatters/migration-graph-tree-render.ts +0 -459
|
@@ -1,32 +1,11 @@
|
|
|
1
|
+
import stringWidth from 'string-width';
|
|
1
2
|
import type { GlyphMode } from '../glyph-mode';
|
|
2
|
-
import type { MigrationEdgeKind } from './migration-list-graph-topology';
|
|
3
|
-
import type { MigrationListStyler } from './migration-list-render';
|
|
4
|
-
import type { MigrationListEntry } from './migration-list-types';
|
|
5
3
|
|
|
6
4
|
export const MIGRATION_LIST_HASH_WIDTH = 7;
|
|
7
5
|
export const MIGRATION_LIST_EMPTY_SOURCE = '∅';
|
|
8
6
|
export const MIGRATION_LIST_ASCII_EMPTY_SOURCE = '-';
|
|
9
7
|
export const MIGRATION_LIST_FORWARD_EDGE_GLYPH = '→';
|
|
10
8
|
export const MIGRATION_LIST_ASCII_FORWARD_EDGE_GLYPH = '->';
|
|
11
|
-
export const MIGRATION_LIST_DECORATION_PREFIX = ' ';
|
|
12
|
-
|
|
13
|
-
export const MIGRATION_LIST_UNICODE_KIND_GLYPH: Record<MigrationEdgeKind, string> = {
|
|
14
|
-
forward: '*',
|
|
15
|
-
rollback: '↩',
|
|
16
|
-
self: '⟲',
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const MIGRATION_LIST_ASCII_KIND_GLYPH: Record<MigrationEdgeKind, string> = {
|
|
20
|
-
forward: '*',
|
|
21
|
-
rollback: '<',
|
|
22
|
-
self: '~',
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export function migrationListKindGlyph(glyphMode: GlyphMode, edgeKind: MigrationEdgeKind): string {
|
|
26
|
-
return glyphMode === 'ascii'
|
|
27
|
-
? MIGRATION_LIST_ASCII_KIND_GLYPH[edgeKind]
|
|
28
|
-
: MIGRATION_LIST_UNICODE_KIND_GLYPH[edgeKind];
|
|
29
|
-
}
|
|
30
9
|
|
|
31
10
|
export function migrationListForwardArrow(glyphMode: GlyphMode): string {
|
|
32
11
|
return glyphMode === 'ascii'
|
|
@@ -43,73 +22,7 @@ export function abbreviateContractHash(hash: string): string {
|
|
|
43
22
|
return stripped.slice(0, MIGRATION_LIST_HASH_WIDTH);
|
|
44
23
|
}
|
|
45
24
|
|
|
46
|
-
export function
|
|
47
|
-
|
|
48
|
-
return
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function formatSourceColumn(
|
|
52
|
-
from: string | null,
|
|
53
|
-
style: MigrationListStyler,
|
|
54
|
-
emptySource: string,
|
|
55
|
-
): string {
|
|
56
|
-
if (from === null) {
|
|
57
|
-
return style.glyph(emptySource) + ' '.repeat(MIGRATION_LIST_HASH_WIDTH - emptySource.length);
|
|
58
|
-
}
|
|
59
|
-
return style.sourceHash(abbreviateContractHash(from));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function formatDecorations(
|
|
63
|
-
providedInvariants: readonly string[],
|
|
64
|
-
refs: readonly string[],
|
|
65
|
-
style: MigrationListStyler,
|
|
66
|
-
): string {
|
|
67
|
-
const blocks: string[] = [];
|
|
68
|
-
if (providedInvariants.length > 0) {
|
|
69
|
-
blocks.push(style.invariants(providedInvariants));
|
|
70
|
-
}
|
|
71
|
-
if (refs.length > 0) {
|
|
72
|
-
blocks.push(style.refs(refs));
|
|
73
|
-
}
|
|
74
|
-
if (blocks.length === 0) return '';
|
|
75
|
-
return `${MIGRATION_LIST_DECORATION_PREFIX}${blocks.join(' ')}`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface MigrationDataColumnOptions {
|
|
79
|
-
readonly dirNameWidth: number;
|
|
80
|
-
readonly edgeKind: MigrationEdgeKind;
|
|
81
|
-
readonly style: MigrationListStyler;
|
|
82
|
-
readonly forwardArrow?: string;
|
|
83
|
-
readonly emptySource?: string;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function formatMigrationDataColumn(
|
|
87
|
-
migration: MigrationListEntry,
|
|
88
|
-
options: MigrationDataColumnOptions,
|
|
89
|
-
): string {
|
|
90
|
-
const {
|
|
91
|
-
dirNameWidth,
|
|
92
|
-
edgeKind,
|
|
93
|
-
style,
|
|
94
|
-
forwardArrow = MIGRATION_LIST_FORWARD_EDGE_GLYPH,
|
|
95
|
-
emptySource = MIGRATION_LIST_EMPTY_SOURCE,
|
|
96
|
-
} = options;
|
|
97
|
-
const dirNamePadding = ' '.repeat(Math.max(0, dirNameWidth - migration.dirName.length));
|
|
98
|
-
const dirName = `${style.dirName(migration.dirName)}${dirNamePadding}`;
|
|
99
|
-
const decorations = formatDecorations(migration.providedInvariants, migration.refs, style);
|
|
100
|
-
|
|
101
|
-
if (edgeKind === 'self') {
|
|
102
|
-
const contractHash = migration.from ?? migration.to;
|
|
103
|
-
const hash = style.sourceHash(abbreviateContractHash(contractHash));
|
|
104
|
-
return `${dirName}${hash}${decorations}`;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const source = formatSourceColumn(migration.from, style, emptySource);
|
|
108
|
-
const arrow = style.glyph(forwardArrow);
|
|
109
|
-
const dest = style.destHash(abbreviateContractHash(migration.to));
|
|
110
|
-
return `${dirName}${source} ${arrow} ${dest}${decorations}`;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function formatNodeLineDataColumn(contractHash: string, style: MigrationListStyler): string {
|
|
114
|
-
return style.sourceHash(abbreviateContractHash(contractHash));
|
|
25
|
+
export function padFromHashColumn(text: string, width: number): string {
|
|
26
|
+
const padding = Math.max(0, width - stringWidth(text));
|
|
27
|
+
return `${' '.repeat(padding)}${text}`;
|
|
115
28
|
}
|
|
@@ -11,8 +11,7 @@ export interface MigrationListGraphTopology {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
|
-
// Shared classifier — operates on a normalized edge shape
|
|
15
|
-
// MigrationListEntry (Tier-2) and MigrationEdge / MigrationGraph (Tier-3).
|
|
14
|
+
// Shared classifier — operates on a normalized edge shape for MigrationGraph.
|
|
16
15
|
// ---------------------------------------------------------------------------
|
|
17
16
|
|
|
18
17
|
interface NormalizedEdge {
|
|
@@ -30,10 +29,30 @@ function bumpDegree(map: Map<string, number>, key: string): void {
|
|
|
30
29
|
map.set(key, (map.get(key) ?? 0) + 1);
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
function
|
|
32
|
+
function compareNodesRootFirst(a: string, b: string): number {
|
|
33
|
+
if (a === EMPTY_CONTRACT_HASH) return -1;
|
|
34
|
+
if (b === EMPTY_CONTRACT_HASH) return 1;
|
|
35
|
+
return a.localeCompare(b);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Shortest-path distance of each node from the forward roots, over the given
|
|
40
|
+
* candidate edges. Roots are the in-degree-0 nodes (baseline first, then lex);
|
|
41
|
+
* a rooted component therefore distances every node by how many forward steps
|
|
42
|
+
* it sits from a root. A component with no root (a pure cycle) is seeded from
|
|
43
|
+
* its single lexically-smallest node so the cycle still gets a stable layering.
|
|
44
|
+
*
|
|
45
|
+
* Crucially this is *shortest* path, not longest: a backward (rollback) edge
|
|
46
|
+
* `deep → shallow` never offers a shorter route to the already-shallower
|
|
47
|
+
* target, so it is inert here. Distances are thus stable whether or not the
|
|
48
|
+
* rollbacks are still in the candidate set — which is what lets the peel below
|
|
49
|
+
* tell a genuine back-edge (target strictly shallower than source) apart from a
|
|
50
|
+
* forward edge that merely happens to share the back-edge's cycle.
|
|
51
|
+
*/
|
|
52
|
+
function forwardDistances(
|
|
34
53
|
nodes: ReadonlySet<string>,
|
|
35
54
|
candidates: readonly NormalizedEdge[],
|
|
36
|
-
):
|
|
55
|
+
): Map<string, number> {
|
|
37
56
|
const inDegree = new Map<string, number>();
|
|
38
57
|
for (const node of nodes) {
|
|
39
58
|
inDegree.set(node, 0);
|
|
@@ -42,44 +61,24 @@ function forwardRootsForDepth(
|
|
|
42
61
|
bumpDegree(inDegree, edge.to);
|
|
43
62
|
}
|
|
44
63
|
|
|
45
|
-
const roots
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
roots.push(node);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
roots.sort((a, b) => {
|
|
52
|
-
if (a === EMPTY_CONTRACT_HASH) return -1;
|
|
53
|
-
if (b === EMPTY_CONTRACT_HASH) return 1;
|
|
54
|
-
return a.localeCompare(b);
|
|
55
|
-
});
|
|
56
|
-
if (roots.length > 0) return roots;
|
|
64
|
+
const roots = [...nodes].filter((node) => (inDegree.get(node) ?? 0) === 0);
|
|
65
|
+
roots.sort(compareNodesRootFirst);
|
|
66
|
+
const seeds = roots.length > 0 ? roots : [...nodes].sort(compareNodesRootFirst).slice(0, 1);
|
|
57
67
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return a.localeCompare(b);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function longestPathDepths(
|
|
66
|
-
nodes: ReadonlySet<string>,
|
|
67
|
-
candidates: readonly NormalizedEdge[],
|
|
68
|
-
): Map<string, number> {
|
|
69
|
-
const depth = new Map<string, number>();
|
|
70
|
-
for (const root of forwardRootsForDepth(nodes, candidates)) {
|
|
71
|
-
depth.set(root, 0);
|
|
68
|
+
const dist = new Map<string, number>();
|
|
69
|
+
for (const seed of seeds) {
|
|
70
|
+
dist.set(seed, 0);
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
const maxPasses = nodes.size;
|
|
75
74
|
for (let pass = 0; pass < maxPasses; pass++) {
|
|
76
75
|
let changed = false;
|
|
77
76
|
for (const edge of candidates) {
|
|
78
|
-
const base =
|
|
77
|
+
const base = dist.get(edge.from);
|
|
79
78
|
if (base === undefined) continue;
|
|
80
79
|
const next = base + 1;
|
|
81
|
-
if (next
|
|
82
|
-
|
|
80
|
+
if (next < (dist.get(edge.to) ?? Number.POSITIVE_INFINITY)) {
|
|
81
|
+
dist.set(edge.to, next);
|
|
83
82
|
changed = true;
|
|
84
83
|
}
|
|
85
84
|
}
|
|
@@ -87,12 +86,12 @@ function longestPathDepths(
|
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
for (const node of nodes) {
|
|
90
|
-
if (!
|
|
91
|
-
|
|
89
|
+
if (!dist.has(node)) {
|
|
90
|
+
dist.set(node, 0);
|
|
92
91
|
}
|
|
93
92
|
}
|
|
94
93
|
|
|
95
|
-
return
|
|
94
|
+
return dist;
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
function canReachForward(
|
|
@@ -126,45 +125,24 @@ function canReachForward(
|
|
|
126
125
|
return false;
|
|
127
126
|
}
|
|
128
127
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// recomputing — so cycles are broken deterministically regardless of edge
|
|
148
|
-
// order. `isMarginalForwardEdge` is only a fallback for the residual case and
|
|
149
|
-
// is reached only while the candidate set is still cyclic.
|
|
150
|
-
function shouldPeelForwardEdge(
|
|
151
|
-
nodes: ReadonlySet<string>,
|
|
152
|
-
candidates: readonly NormalizedEdge[],
|
|
153
|
-
edge: NormalizedEdge,
|
|
154
|
-
): boolean {
|
|
155
|
-
const without = candidates.filter((candidate) => candidate !== edge);
|
|
156
|
-
const depthWithout = longestPathDepths(nodes, without);
|
|
157
|
-
const fromDepth = depthWithout.get(edge.from) ?? 0;
|
|
158
|
-
const toWithout = depthWithout.get(edge.to) ?? 0;
|
|
159
|
-
|
|
160
|
-
if (canReachForward(edge.to, edge.from, without) && fromDepth > toWithout + 1) {
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return !isMarginalForwardEdge(nodes, candidates, edge);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function peelNonMarginalForwardEdges(
|
|
128
|
+
/**
|
|
129
|
+
* Demote node-skipping rollbacks left forward by the DFS. An edge `from → to`
|
|
130
|
+
* is a rollback exactly when both hold:
|
|
131
|
+
* 1. `to` is a forward-ancestor of `from` — `to` can still reach `from` over
|
|
132
|
+
* the other forward edges, so the edge closes a cycle; and
|
|
133
|
+
* 2. `to` is strictly shallower than `from` (smaller forward distance) — the
|
|
134
|
+
* edge points back toward the root rather than advancing history.
|
|
135
|
+
*
|
|
136
|
+
* Condition 2 is the discriminator: in a cycle created by a rollback every edge
|
|
137
|
+
* satisfies condition 1, but only the rollback itself runs deep → shallow. The
|
|
138
|
+
* forward chain edges run shallow → deep and are never peeled, however many
|
|
139
|
+
* rollbacks converge on the same target. Tight back-edges whose source and
|
|
140
|
+
* target sit at the same distance (mutual two-node cycles) are already resolved
|
|
141
|
+
* by the DFS immediate-parent rule, so they never reach this pass. One edge is
|
|
142
|
+
* peeled per iteration (dirName-descending tie-break) and distances/reachability
|
|
143
|
+
* are recomputed, making the outcome independent of edge input order.
|
|
144
|
+
*/
|
|
145
|
+
function peelNodeSkippingRollbacks(
|
|
168
146
|
nodes: ReadonlySet<string>,
|
|
169
147
|
kindByMigrationHash: Map<string, MigrationEdgeKind>,
|
|
170
148
|
nonSelf: readonly NormalizedEdge[],
|
|
@@ -172,13 +150,18 @@ function peelNonMarginalForwardEdges(
|
|
|
172
150
|
let candidates = nonSelf.filter((edge) => kindByMigrationHash.get(edge.hash) === 'forward');
|
|
173
151
|
|
|
174
152
|
while (candidates.length > 0) {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
153
|
+
const dist = forwardDistances(nodes, candidates);
|
|
154
|
+
const backEdges = candidates.filter((edge) => {
|
|
155
|
+
const toDist = dist.get(edge.to) ?? 0;
|
|
156
|
+
const fromDist = dist.get(edge.from) ?? 0;
|
|
157
|
+
if (toDist >= fromDist) return false;
|
|
158
|
+
const without = candidates.filter((candidate) => candidate !== edge);
|
|
159
|
+
return canReachForward(edge.to, edge.from, without);
|
|
160
|
+
});
|
|
161
|
+
if (backEdges.length === 0) break;
|
|
162
|
+
|
|
163
|
+
backEdges.sort(compareDirNameDesc);
|
|
164
|
+
const rollback = backEdges[0];
|
|
182
165
|
if (rollback === undefined) break;
|
|
183
166
|
|
|
184
167
|
kindByMigrationHash.set(rollback.hash, 'rollback');
|
|
@@ -189,8 +172,8 @@ function peelNonMarginalForwardEdges(
|
|
|
189
172
|
/**
|
|
190
173
|
* DFS with dirName-descending traversal. A GRAY target is a rollback only when it
|
|
191
174
|
* is the immediate DFS parent of the source — cross-links to other GRAY nodes
|
|
192
|
-
* stay forward. A follow-up peel pass
|
|
193
|
-
*
|
|
175
|
+
* stay forward. A follow-up peel pass demotes node-skipping rollbacks (target is
|
|
176
|
+
* a forward-ancestor of the source and sits strictly shallower than it).
|
|
194
177
|
*/
|
|
195
178
|
function classifyNormalizedEdges(edges: readonly NormalizedEdge[]): MigrationListGraphTopology {
|
|
196
179
|
const nodes = new Set<string>();
|
|
@@ -307,7 +290,7 @@ function classifyNormalizedEdges(edges: readonly NormalizedEdge[]): MigrationLis
|
|
|
307
290
|
runDfsFrom(root);
|
|
308
291
|
}
|
|
309
292
|
|
|
310
|
-
|
|
293
|
+
peelNodeSkippingRollbacks(nodes, kindByMigrationHash, nonSelf);
|
|
311
294
|
|
|
312
295
|
const forwardInDegree = new Map<string, number>();
|
|
313
296
|
const forwardOutDegree = new Map<string, number>();
|
|
@@ -331,26 +314,21 @@ function canonicalFrom(from: string | null): string {
|
|
|
331
314
|
|
|
332
315
|
/**
|
|
333
316
|
* Classify forward/rollback/self for a Tier-2 `MigrationListEntry[]` edge set.
|
|
334
|
-
* Returns the kind of each migration plus the forward in/out degree of each
|
|
335
|
-
* contract node. This is the established Tier-2 surface; its behaviour is
|
|
336
|
-
* unchanged — only its implementation now delegates to the shared classifier.
|
|
337
317
|
*/
|
|
338
318
|
export function classifyMigrationListGraphTopology(
|
|
339
319
|
entries: readonly MigrationListEntry[],
|
|
340
320
|
): MigrationListGraphTopology {
|
|
341
321
|
const normalized: NormalizedEdge[] = entries.map((entry) => ({
|
|
342
|
-
hash: entry.
|
|
343
|
-
from: canonicalFrom(entry.
|
|
344
|
-
to: entry.
|
|
345
|
-
dirName: entry.
|
|
322
|
+
hash: entry.hash,
|
|
323
|
+
from: canonicalFrom(entry.fromContract),
|
|
324
|
+
to: entry.toContract,
|
|
325
|
+
dirName: entry.name,
|
|
346
326
|
}));
|
|
347
327
|
return classifyNormalizedEdges(normalized);
|
|
348
328
|
}
|
|
349
329
|
|
|
350
330
|
/**
|
|
351
331
|
* Classify forward/rollback/self for a `MigrationGraph` edge set (Tier-3).
|
|
352
|
-
* Delegates to the same shared classifier as `classifyMigrationListGraphTopology`
|
|
353
|
-
* so both tiers agree on forward/rollback/self without duplicating logic.
|
|
354
332
|
*/
|
|
355
333
|
export function classifyMigrationGraphTopology(graph: MigrationGraph): MigrationListGraphTopology {
|
|
356
334
|
const normalized: NormalizedEdge[] = [];
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
+
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
2
|
+
import type { MigrationEdge, MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
1
3
|
import type { GlyphMode } from '../glyph-mode';
|
|
4
|
+
import type { MigrationEdgeAnnotation } from './migration-graph-labels';
|
|
2
5
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from './migration-list-data-column';
|
|
9
|
-
import {
|
|
10
|
-
classifyMigrationListGraphTopology,
|
|
11
|
-
type MigrationEdgeKind,
|
|
12
|
-
type MigrationListGraphTopology,
|
|
13
|
-
} from './migration-list-graph-topology';
|
|
6
|
+
computeGlobalMaxDirNameWidth,
|
|
7
|
+
computeGlobalMaxEdgeTreePrefixWidth,
|
|
8
|
+
indentMigrationGraphTreeBlock,
|
|
9
|
+
renderMigrationGraphSpaceTree,
|
|
10
|
+
} from './migration-graph-space-render';
|
|
14
11
|
import type { MigrationListEntry, MigrationListResult } from './migration-list-types';
|
|
15
12
|
|
|
16
13
|
export type { GlyphMode } from '../glyph-mode';
|
|
@@ -62,42 +59,83 @@ export const IDENTITY_MIGRATION_LIST_STYLER: MigrationListStyler = {
|
|
|
62
59
|
emptyState: (text) => text,
|
|
63
60
|
};
|
|
64
61
|
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
kindByMigrationHash: ReadonlyMap<string, MigrationEdgeKind>,
|
|
68
|
-
): MigrationEdgeKind {
|
|
69
|
-
return kindByMigrationHash.get(migrationHash) ?? 'forward';
|
|
62
|
+
function canonicalFrom(from: string | null): string {
|
|
63
|
+
return from ?? EMPTY_CONTRACT_HASH;
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
66
|
+
export function migrationGraphFromListEntries(
|
|
67
|
+
entries: readonly MigrationListEntry[],
|
|
68
|
+
): MigrationGraph {
|
|
69
|
+
const nodes = new Set<string>();
|
|
70
|
+
const forwardChain = new Map<string, MigrationEdge[]>();
|
|
71
|
+
const reverseChain = new Map<string, MigrationEdge[]>();
|
|
72
|
+
const migrationByHash = new Map<string, MigrationEdge>();
|
|
73
|
+
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
const from = canonicalFrom(entry.fromContract);
|
|
76
|
+
const edge: MigrationEdge = {
|
|
77
|
+
from,
|
|
78
|
+
to: entry.toContract,
|
|
79
|
+
migrationHash: entry.hash,
|
|
80
|
+
dirName: entry.name,
|
|
81
|
+
createdAt: entry.createdAt,
|
|
82
|
+
invariants: entry.providedInvariants,
|
|
83
|
+
};
|
|
84
|
+
nodes.add(from);
|
|
85
|
+
nodes.add(entry.toContract);
|
|
86
|
+
const forward = forwardChain.get(from);
|
|
87
|
+
if (forward) forward.push(edge);
|
|
88
|
+
else forwardChain.set(from, [edge]);
|
|
89
|
+
const reverse = reverseChain.get(entry.toContract);
|
|
90
|
+
if (reverse) reverse.push(edge);
|
|
91
|
+
else reverseChain.set(entry.toContract, [edge]);
|
|
92
|
+
migrationByHash.set(entry.hash, edge);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { nodes, forwardChain, reverseChain, migrationByHash };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function buildEdgeAnnotationsByHashFromListEntries(
|
|
99
|
+
entries: readonly MigrationListEntry[],
|
|
100
|
+
): ReadonlyMap<string, MigrationEdgeAnnotation> {
|
|
101
|
+
const annotations = new Map<string, MigrationEdgeAnnotation>();
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
annotations.set(entry.hash, {
|
|
104
|
+
operationCount: entry.operationCount,
|
|
105
|
+
invariants: entry.providedInvariants,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return annotations;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function buildRefsByHashFromListEntries(
|
|
112
|
+
entries: readonly MigrationListEntry[],
|
|
113
|
+
): ReadonlyMap<string, readonly string[]> {
|
|
114
|
+
const refsByHash = new Map<string, readonly string[]>();
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (entry.refs.length > 0) {
|
|
117
|
+
refsByHash.set(entry.toContract, entry.refs);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return refsByHash;
|
|
88
121
|
}
|
|
89
122
|
|
|
90
123
|
function formatEmptyStateLine(spaceId: string, style: MigrationListStyler): string {
|
|
91
124
|
return style.emptyState(`There are no migrations in migrations/${spaceId}/ yet`);
|
|
92
125
|
}
|
|
93
126
|
|
|
94
|
-
function
|
|
127
|
+
function renderSpaceTreeBlock(
|
|
95
128
|
spaceId: string,
|
|
96
129
|
migrations: readonly MigrationListEntry[],
|
|
97
130
|
multiSpace: boolean,
|
|
98
131
|
glyphMode: GlyphMode,
|
|
99
|
-
kindByMigrationHash: ReadonlyMap<string, MigrationEdgeKind>,
|
|
100
132
|
style: MigrationListStyler,
|
|
133
|
+
colorize: boolean,
|
|
134
|
+
liveContractHash: string,
|
|
135
|
+
graphForSpace: (spaceId: string) => MigrationGraph | undefined,
|
|
136
|
+
appSpaceId: string | undefined,
|
|
137
|
+
globalMaxEdgeTreePrefixWidth?: number,
|
|
138
|
+
globalMaxDirNameWidth?: number,
|
|
101
139
|
): readonly string[] {
|
|
102
140
|
if (migrations.length === 0) {
|
|
103
141
|
const emptyLine = formatEmptyStateLine(spaceId, style);
|
|
@@ -107,50 +145,75 @@ function renderSpaceBlock(
|
|
|
107
145
|
return [style.spaceHeading(`${spaceId}:`), ` ${emptyLine}`];
|
|
108
146
|
}
|
|
109
147
|
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
),
|
|
119
|
-
|
|
148
|
+
const graph = graphForSpace(spaceId) ?? migrationGraphFromListEntries(migrations);
|
|
149
|
+
const isAppSpace = appSpaceId === undefined ? undefined : spaceId === appSpaceId;
|
|
150
|
+
const treeOutput = renderMigrationGraphSpaceTree({
|
|
151
|
+
graph,
|
|
152
|
+
migrations,
|
|
153
|
+
liveContractHash,
|
|
154
|
+
glyphMode,
|
|
155
|
+
colorize,
|
|
156
|
+
refsByHash: buildRefsByHashFromListEntries(migrations),
|
|
157
|
+
styler: style,
|
|
158
|
+
...(isAppSpace !== undefined ? { isAppSpace } : {}),
|
|
159
|
+
...(globalMaxEdgeTreePrefixWidth !== undefined ? { globalMaxEdgeTreePrefixWidth } : {}),
|
|
160
|
+
...(globalMaxDirNameWidth !== undefined ? { globalMaxDirNameWidth } : {}),
|
|
161
|
+
});
|
|
162
|
+
|
|
120
163
|
if (!multiSpace) {
|
|
121
|
-
return
|
|
164
|
+
return treeOutput.length === 0 ? [] : [treeOutput];
|
|
122
165
|
}
|
|
123
|
-
|
|
166
|
+
|
|
167
|
+
const indented = indentMigrationGraphTreeBlock(treeOutput, ' ');
|
|
168
|
+
return [style.spaceHeading(`${spaceId}:`), indented];
|
|
124
169
|
}
|
|
125
170
|
|
|
126
|
-
export
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
171
|
+
export interface RenderMigrationListWithStyleOptions {
|
|
172
|
+
readonly colorize?: boolean;
|
|
173
|
+
readonly liveContractHash?: string;
|
|
174
|
+
readonly graphForSpace?: (spaceId: string) => MigrationGraph | undefined;
|
|
175
|
+
/**
|
|
176
|
+
* The space ID that is the app contract space. When provided, `@contract`
|
|
177
|
+
* and the floating working-contract node are shown only for this space.
|
|
178
|
+
* When absent, the renderer falls back to the default (`isAppSpace: true`
|
|
179
|
+
* for every space), which is safe for single-space callers.
|
|
180
|
+
*/
|
|
181
|
+
readonly appSpaceId?: string;
|
|
134
182
|
}
|
|
135
183
|
|
|
136
184
|
/**
|
|
137
|
-
* Compose the styled `migration list` output
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* (
|
|
185
|
+
* Compose the styled `migration list` human output via the shared tree
|
|
186
|
+
* renderer. Each on-disk migration is one edge row with package-fact
|
|
187
|
+
* annotations; refs decorate destination contract nodes.
|
|
188
|
+
*
|
|
189
|
+
* `options.colorize` must match whether `style` emits ANSI (e.g. both true for
|
|
190
|
+
* `createAnsiMigrationListStyler({ useColor: true })`).
|
|
143
191
|
*/
|
|
144
192
|
export function renderMigrationListWithStyle(
|
|
145
193
|
result: MigrationListResult,
|
|
146
194
|
style: MigrationListStyler,
|
|
147
195
|
glyphMode: GlyphMode = 'unicode',
|
|
148
|
-
|
|
149
|
-
string,
|
|
150
|
-
MigrationListGraphTopology
|
|
151
|
-
> = buildMigrationListTopologyBySpace(result),
|
|
196
|
+
options: RenderMigrationListWithStyleOptions = {},
|
|
152
197
|
): string {
|
|
153
198
|
const multiSpace = result.spaces.length > 1;
|
|
199
|
+
const colorize = options.colorize ?? false;
|
|
200
|
+
const liveContractHash = options.liveContractHash ?? EMPTY_CONTRACT_HASH;
|
|
201
|
+
const graphForSpace = options.graphForSpace ?? (() => undefined);
|
|
202
|
+
const appSpaceId = options.appSpaceId;
|
|
203
|
+
const globalLayoutInputs = multiSpace
|
|
204
|
+
? result.spaces
|
|
205
|
+
.filter((space) => space.migrations.length > 0)
|
|
206
|
+
.map((space) => ({
|
|
207
|
+
graph: graphForSpace(space.space) ?? migrationGraphFromListEntries(space.migrations),
|
|
208
|
+
liveContractHash,
|
|
209
|
+
}))
|
|
210
|
+
: [];
|
|
211
|
+
const globalMaxEdgeTreePrefixWidth =
|
|
212
|
+
globalLayoutInputs.length > 0
|
|
213
|
+
? computeGlobalMaxEdgeTreePrefixWidth(globalLayoutInputs)
|
|
214
|
+
: undefined;
|
|
215
|
+
const globalMaxDirNameWidth =
|
|
216
|
+
globalLayoutInputs.length > 0 ? computeGlobalMaxDirNameWidth(globalLayoutInputs) : undefined;
|
|
154
217
|
const lines: string[] = [];
|
|
155
218
|
|
|
156
219
|
for (let index = 0; index < result.spaces.length; index++) {
|
|
@@ -158,18 +221,19 @@ export function renderMigrationListWithStyle(
|
|
|
158
221
|
if (index > 0) {
|
|
159
222
|
lines.push('');
|
|
160
223
|
}
|
|
161
|
-
const topology = topologyBySpaceId.get(space.spaceId);
|
|
162
|
-
const kindByMigrationHash =
|
|
163
|
-
topology?.kindByMigrationHash ??
|
|
164
|
-
classifyMigrationListGraphTopology(space.migrations).kindByMigrationHash;
|
|
165
224
|
lines.push(
|
|
166
|
-
...
|
|
167
|
-
space.
|
|
225
|
+
...renderSpaceTreeBlock(
|
|
226
|
+
space.space,
|
|
168
227
|
space.migrations,
|
|
169
228
|
multiSpace,
|
|
170
229
|
glyphMode,
|
|
171
|
-
kindByMigrationHash,
|
|
172
230
|
style,
|
|
231
|
+
colorize,
|
|
232
|
+
liveContractHash,
|
|
233
|
+
graphForSpace,
|
|
234
|
+
appSpaceId,
|
|
235
|
+
globalMaxEdgeTreePrefixWidth,
|
|
236
|
+
globalMaxDirNameWidth,
|
|
173
237
|
),
|
|
174
238
|
);
|
|
175
239
|
}
|