@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,5 +1,6 @@
|
|
|
1
1
|
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
2
2
|
import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
3
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
3
4
|
import { ok, type Result } from '@prisma-next/utils/result';
|
|
4
5
|
import { Command } from 'commander';
|
|
5
6
|
import { loadConfig } from '../config-loader';
|
|
@@ -12,40 +13,80 @@ import {
|
|
|
12
13
|
setCommandSeeAlso,
|
|
13
14
|
} from '../utils/command-helpers';
|
|
14
15
|
import { buildReadAggregate } from '../utils/contract-space-aggregate-loader';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
import { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-labels';
|
|
17
|
+
import {
|
|
18
|
+
computeGlobalMaxDirNameWidth,
|
|
19
|
+
computeGlobalMaxEdgeTreePrefixWidth,
|
|
20
|
+
indentMigrationGraphTreeBlock,
|
|
21
|
+
renderMigrationGraphSpaceTree,
|
|
22
|
+
} from '../utils/formatters/migration-graph-space-render';
|
|
20
23
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
21
24
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
22
25
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
23
|
-
import
|
|
26
|
+
import { shouldShowLegend, validateLegendOptions } from '../utils/legend';
|
|
24
27
|
import { handleResult } from '../utils/result-handler';
|
|
25
28
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
29
|
+
import type { MigrationGraphJsonResult, MigrationSpaceGraphEntry } from './json/schemas';
|
|
30
|
+
import {
|
|
31
|
+
listRefsByContractHash,
|
|
32
|
+
migrationSpaceListEntriesFromAggregate,
|
|
33
|
+
runMigrationList,
|
|
34
|
+
} from './migration-list';
|
|
26
35
|
|
|
27
36
|
interface MigrationGraphOptions extends CommonCommandOptions {
|
|
28
37
|
readonly config?: string;
|
|
29
38
|
readonly dot?: boolean;
|
|
30
|
-
readonly
|
|
39
|
+
readonly space?: string;
|
|
31
40
|
readonly ascii?: boolean;
|
|
41
|
+
readonly legend?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MigrationGraphTreeSection {
|
|
45
|
+
readonly space: string;
|
|
46
|
+
readonly tree: string;
|
|
47
|
+
readonly showHeading: boolean;
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
export interface MigrationGraphResult {
|
|
35
51
|
readonly ok: true;
|
|
52
|
+
/** App-space graph for the `--dot` Graphviz output. */
|
|
36
53
|
readonly graph: MigrationGraph;
|
|
37
|
-
|
|
38
|
-
readonly
|
|
54
|
+
/** Nested per-space contracts + migrations for `--json`. */
|
|
55
|
+
readonly spaces: readonly MigrationSpaceGraphEntry[];
|
|
56
|
+
readonly treeSections: readonly MigrationGraphTreeSection[];
|
|
39
57
|
readonly summary: string;
|
|
40
58
|
}
|
|
41
59
|
|
|
60
|
+
function computeGraphSummary(spaces: readonly MigrationSpaceGraphEntry[]): string {
|
|
61
|
+
const contractCount = spaces.reduce((count, space) => count + space.contracts.length, 0);
|
|
62
|
+
const migrationCount = spaces.reduce((count, space) => count + space.migrations.length, 0);
|
|
63
|
+
return `${spaces.length} space(s), ${contractCount} contract(s), ${migrationCount} migration(s)`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function formatMigrationGraphHumanOutput(result: MigrationGraphResult): string {
|
|
67
|
+
const sections: string[] = [];
|
|
68
|
+
for (const section of result.treeSections) {
|
|
69
|
+
if (section.showHeading) {
|
|
70
|
+
sections.push(`${section.space}:`);
|
|
71
|
+
}
|
|
72
|
+
if (section.tree.length > 0) {
|
|
73
|
+
sections.push(section.tree);
|
|
74
|
+
} else {
|
|
75
|
+
sections.push('(no migrations)');
|
|
76
|
+
}
|
|
77
|
+
sections.push('');
|
|
78
|
+
}
|
|
79
|
+
sections.push(result.summary);
|
|
80
|
+
return sections.join('\n').trimEnd();
|
|
81
|
+
}
|
|
82
|
+
|
|
42
83
|
export async function executeMigrationGraphCommand(
|
|
43
84
|
options: MigrationGraphOptions,
|
|
44
85
|
flags: GlobalFlags,
|
|
45
86
|
ui: TerminalUI,
|
|
46
87
|
): Promise<Result<MigrationGraphResult, CliStructuredError>> {
|
|
47
88
|
const config = await loadConfig(options.config);
|
|
48
|
-
const { configPath,
|
|
89
|
+
const { configPath, migrationsRelative, migrationsDir } = resolveMigrationPaths(
|
|
49
90
|
options.config,
|
|
50
91
|
config,
|
|
51
92
|
);
|
|
@@ -56,11 +97,21 @@ export async function executeMigrationGraphCommand(
|
|
|
56
97
|
description: 'Show the migration graph topology',
|
|
57
98
|
details: [
|
|
58
99
|
{ label: 'config', value: configPath },
|
|
59
|
-
{ label: 'migrations', value:
|
|
100
|
+
{ label: 'migrations', value: migrationsRelative },
|
|
101
|
+
...(options.space !== undefined ? [{ label: 'space', value: options.space }] : []),
|
|
60
102
|
],
|
|
61
103
|
flags,
|
|
62
104
|
});
|
|
63
105
|
ui.stderr(header);
|
|
106
|
+
if (shouldShowLegend(options, flags)) {
|
|
107
|
+
ui.stderr(
|
|
108
|
+
renderMigrationGraphLegend({
|
|
109
|
+
colorize: flags.color !== false,
|
|
110
|
+
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
ui.stderr('');
|
|
114
|
+
}
|
|
64
115
|
}
|
|
65
116
|
|
|
66
117
|
const loaded = await buildReadAggregate(config, { migrationsDir });
|
|
@@ -68,20 +119,90 @@ export async function executeMigrationGraphCommand(
|
|
|
68
119
|
return loaded;
|
|
69
120
|
}
|
|
70
121
|
|
|
71
|
-
const { aggregate, contractHash } = loaded.value;
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
122
|
+
const { aggregate, contractHash: liveContractHash } = loaded.value;
|
|
123
|
+
const appGraph = aggregate.app.graph();
|
|
124
|
+
|
|
125
|
+
const listSpaces = await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir);
|
|
126
|
+
const listResult = runMigrationList({
|
|
127
|
+
spaces: listSpaces,
|
|
128
|
+
...ifDefined('spaceFilter', options.space),
|
|
129
|
+
});
|
|
130
|
+
if (!listResult.ok) {
|
|
131
|
+
return listResult;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const scopedSpaces = listResult.value.spaces;
|
|
135
|
+
const showSpaceHeadings = scopedSpaces.length > 1;
|
|
136
|
+
const glyphMode = ui.resolveGlyphMode(options.ascii === true);
|
|
137
|
+
const colorize = flags.color !== false;
|
|
138
|
+
|
|
139
|
+
const globalLayoutInputs = showSpaceHeadings
|
|
140
|
+
? scopedSpaces
|
|
141
|
+
.filter((spaceEntry) => spaceEntry.migrations.length > 0)
|
|
142
|
+
.map((spaceEntry) => ({
|
|
143
|
+
graph: aggregate.space(spaceEntry.space)!.graph(),
|
|
144
|
+
liveContractHash,
|
|
145
|
+
}))
|
|
146
|
+
: [];
|
|
147
|
+
const globalMaxEdgeTreePrefixWidth =
|
|
148
|
+
globalLayoutInputs.length > 0
|
|
149
|
+
? computeGlobalMaxEdgeTreePrefixWidth(globalLayoutInputs)
|
|
150
|
+
: undefined;
|
|
151
|
+
const globalMaxDirNameWidth =
|
|
152
|
+
globalLayoutInputs.length > 0 ? computeGlobalMaxDirNameWidth(globalLayoutInputs) : undefined;
|
|
153
|
+
|
|
154
|
+
const treeSections: MigrationGraphTreeSection[] = [];
|
|
155
|
+
const spaces: MigrationSpaceGraphEntry[] = [];
|
|
156
|
+
for (const spaceEntry of scopedSpaces) {
|
|
157
|
+
const member = aggregate.space(spaceEntry.space);
|
|
158
|
+
if (member === undefined) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const graph = member.graph();
|
|
162
|
+
const isAppSpace = spaceEntry.space === aggregate.app.spaceId;
|
|
163
|
+
const refsByHash = listRefsByContractHash(member);
|
|
164
|
+
const tree =
|
|
165
|
+
spaceEntry.migrations.length === 0
|
|
166
|
+
? ''
|
|
167
|
+
: renderMigrationGraphSpaceTree({
|
|
168
|
+
graph,
|
|
169
|
+
migrations: spaceEntry.migrations,
|
|
170
|
+
liveContractHash,
|
|
171
|
+
glyphMode,
|
|
172
|
+
colorize,
|
|
173
|
+
isAppSpace,
|
|
174
|
+
refsByHash,
|
|
175
|
+
...(globalMaxEdgeTreePrefixWidth !== undefined ? { globalMaxEdgeTreePrefixWidth } : {}),
|
|
176
|
+
...(globalMaxDirNameWidth !== undefined ? { globalMaxDirNameWidth } : {}),
|
|
177
|
+
});
|
|
178
|
+
const displayTree =
|
|
179
|
+
showSpaceHeadings && tree.length > 0 ? indentMigrationGraphTreeBlock(tree, ' ') : tree;
|
|
180
|
+
treeSections.push({
|
|
181
|
+
space: spaceEntry.space,
|
|
182
|
+
tree: displayTree,
|
|
183
|
+
showHeading: showSpaceHeadings,
|
|
184
|
+
});
|
|
185
|
+
spaces.push({
|
|
186
|
+
space: spaceEntry.space,
|
|
187
|
+
contracts: [...graph.nodes].map((hash) => ({
|
|
188
|
+
hash,
|
|
189
|
+
refs: [...(refsByHash.get(hash) ?? [])],
|
|
190
|
+
})),
|
|
191
|
+
migrations: [...graph.migrationByHash.values()].map((edge) => ({
|
|
192
|
+
name: edge.dirName,
|
|
193
|
+
hash: edge.migrationHash,
|
|
194
|
+
fromContract: edge.from === EMPTY_CONTRACT_HASH ? null : edge.from,
|
|
195
|
+
toContract: edge.to,
|
|
196
|
+
})),
|
|
197
|
+
});
|
|
198
|
+
}
|
|
78
199
|
|
|
79
200
|
return ok({
|
|
80
201
|
ok: true,
|
|
81
|
-
graph,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
summary:
|
|
202
|
+
graph: appGraph,
|
|
203
|
+
spaces,
|
|
204
|
+
treeSections,
|
|
205
|
+
summary: computeGraphSummary(spaces),
|
|
85
206
|
});
|
|
86
207
|
}
|
|
87
208
|
|
|
@@ -90,18 +211,19 @@ export function createMigrationGraphCommand(): Command {
|
|
|
90
211
|
setCommandDescriptions(
|
|
91
212
|
command,
|
|
92
213
|
'Show the migration graph topology',
|
|
93
|
-
'Renders the migration graph topology
|
|
94
|
-
'
|
|
95
|
-
'
|
|
96
|
-
'--json for machine-readable output, or --dot for Graphviz DOT\n' +
|
|
214
|
+
'Renders the migration graph topology.\n' +
|
|
215
|
+
'Offline — does not consult the database.\n' +
|
|
216
|
+
'--ascii swaps box-drawing for pipe-friendly ASCII glyphs.\n' +
|
|
217
|
+
'Use --json for machine-readable output, or --dot for Graphviz DOT\n' +
|
|
97
218
|
'format.',
|
|
98
219
|
);
|
|
99
220
|
setCommandExamples(command, [
|
|
100
221
|
'prisma-next migration graph',
|
|
101
222
|
'prisma-next migration graph --json',
|
|
102
223
|
'prisma-next migration graph --dot',
|
|
103
|
-
'prisma-next migration graph --
|
|
104
|
-
'prisma-next migration graph --
|
|
224
|
+
'prisma-next migration graph --ascii',
|
|
225
|
+
'prisma-next migration graph --legend',
|
|
226
|
+
'prisma-next migration graph --space app',
|
|
105
227
|
]);
|
|
106
228
|
setCommandSeeAlso(command, [
|
|
107
229
|
{ verb: 'migration status', oneLiner: 'Show migration path and pending status' },
|
|
@@ -111,19 +233,19 @@ export function createMigrationGraphCommand(): Command {
|
|
|
111
233
|
]);
|
|
112
234
|
addGlobalOptions(command)
|
|
113
235
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
236
|
+
.option('--space <id>', 'Narrow output to a single contract space')
|
|
114
237
|
.option('--dot', 'Output in Graphviz DOT format')
|
|
115
|
-
.option('--
|
|
116
|
-
.option('--
|
|
238
|
+
.option('--ascii', 'Use ASCII glyphs (pipe-friendly)')
|
|
239
|
+
.option('--legend', 'Print a key for the tree glyphs and lane colors')
|
|
117
240
|
.action(async (options: MigrationGraphOptions) => {
|
|
118
241
|
const flags = parseGlobalFlagsOrExit(options);
|
|
119
242
|
const ui = createTerminalUI(flags);
|
|
243
|
+
const legendValidation = validateLegendOptions(options, flags);
|
|
244
|
+
if (!legendValidation.ok) {
|
|
245
|
+
process.exit(handleResult(legendValidation, flags, ui));
|
|
246
|
+
}
|
|
120
247
|
const result = await executeMigrationGraphCommand(options, flags, ui);
|
|
121
248
|
const exitCode = handleResult(result, flags, ui, (graphResult) => {
|
|
122
|
-
// Explicit format flags win over the auto-JSON default. `flags.json`
|
|
123
|
-
// is auto-enabled when stdout is non-TTY (per CLI Style Guide §
|
|
124
|
-
// JSON Semantics); without this ordering, `migration graph --dot |
|
|
125
|
-
// dot -Tsvg` pipes JSON into the GraphViz binary, which then
|
|
126
|
-
// errors. `--dot` is the more specific instruction; honour it.
|
|
127
249
|
if (options.dot) {
|
|
128
250
|
const lines = ['digraph migrations {'];
|
|
129
251
|
for (const edge of graphResult.graph.migrationByHash.values()) {
|
|
@@ -134,63 +256,14 @@ export function createMigrationGraphCommand(): Command {
|
|
|
134
256
|
lines.push('}');
|
|
135
257
|
ui.output(lines.join('\n'));
|
|
136
258
|
} else if (flags.json) {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}));
|
|
144
|
-
ui.output(
|
|
145
|
-
JSON.stringify({ ok: true, nodes, edges, summary: graphResult.summary }, null, 2),
|
|
146
|
-
);
|
|
259
|
+
const jsonResult: MigrationGraphJsonResult = {
|
|
260
|
+
ok: true,
|
|
261
|
+
spaces: [...graphResult.spaces],
|
|
262
|
+
summary: graphResult.summary,
|
|
263
|
+
};
|
|
264
|
+
ui.output(JSON.stringify(jsonResult, null, 2));
|
|
147
265
|
} else if (!flags.quiet) {
|
|
148
|
-
|
|
149
|
-
const refsByHash = new Map<string, string[]>();
|
|
150
|
-
for (const ref of graphResult.refs) {
|
|
151
|
-
const existing = refsByHash.get(ref.hash);
|
|
152
|
-
refsByHash.set(ref.hash, existing ? [...existing, ref.name] : [ref.name]);
|
|
153
|
-
}
|
|
154
|
-
const rowModel = buildMigrationGraphRows(graphResult.graph, {
|
|
155
|
-
...(graphResult.contractHash !== null
|
|
156
|
-
? { contractHash: graphResult.contractHash }
|
|
157
|
-
: {}),
|
|
158
|
-
});
|
|
159
|
-
const layout = buildMigrationGraphLayout(rowModel);
|
|
160
|
-
const activeRef = graphResult.refs.find((ref) => ref.active);
|
|
161
|
-
const treeOutput = renderMigrationGraphTree(layout, {
|
|
162
|
-
refsByHash,
|
|
163
|
-
...(graphResult.contractHash !== null
|
|
164
|
-
? { contractHash: graphResult.contractHash }
|
|
165
|
-
: {}),
|
|
166
|
-
...(activeRef !== undefined ? { activeRefName: activeRef.name } : {}),
|
|
167
|
-
colorize: flags.color !== false,
|
|
168
|
-
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
169
|
-
});
|
|
170
|
-
// Emit the rendered tree to stdout (same stream as flat `migration list`),
|
|
171
|
-
// not through clack's `log.message` rail: the graph is the command's
|
|
172
|
-
// result (and its own box-drawing is the only vertical structure it
|
|
173
|
-
// should carry), not a status line that needs the prompt gutter.
|
|
174
|
-
ui.output(treeOutput);
|
|
175
|
-
ui.output(`\n${graphResult.summary}`);
|
|
176
|
-
} else {
|
|
177
|
-
const renderInput = migrationGraphToRenderInput({
|
|
178
|
-
graph: graphResult.graph,
|
|
179
|
-
mode: 'offline',
|
|
180
|
-
markerHash: undefined,
|
|
181
|
-
contractHash: graphResult.contractHash ?? EMPTY_CONTRACT_HASH,
|
|
182
|
-
refs: graphResult.refs,
|
|
183
|
-
activeRefHash: undefined,
|
|
184
|
-
activeRefName: undefined,
|
|
185
|
-
edgeStatuses: [],
|
|
186
|
-
});
|
|
187
|
-
const graphOutput = graphRenderer.render(renderInput.graph, {
|
|
188
|
-
...renderInput.options,
|
|
189
|
-
colorize: flags.color !== false,
|
|
190
|
-
});
|
|
191
|
-
ui.log(graphOutput);
|
|
192
|
-
ui.log(`\n${graphResult.summary}`);
|
|
193
|
-
}
|
|
266
|
+
ui.output(formatMigrationGraphHumanOutput(graphResult));
|
|
194
267
|
}
|
|
195
268
|
});
|
|
196
269
|
process.exit(exitCode);
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
ContractSpaceAggregate,
|
|
3
3
|
ContractSpaceMember,
|
|
4
4
|
} from '@prisma-next/migration-tools/aggregate';
|
|
5
|
+
import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
5
6
|
import { HEAD_REF_NAME, refsByContractHash } from '@prisma-next/migration-tools/refs';
|
|
6
7
|
import {
|
|
7
8
|
APP_SPACE_ID,
|
|
@@ -26,10 +27,8 @@ import {
|
|
|
26
27
|
setCommandSeeAlso,
|
|
27
28
|
} from '../utils/command-helpers';
|
|
28
29
|
import { buildReadAggregate } from '../utils/contract-space-aggregate-loader';
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
renderMigrationListWithStyle,
|
|
32
|
-
} from '../utils/formatters/migration-list-render';
|
|
30
|
+
import { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-labels';
|
|
31
|
+
import { renderMigrationListWithStyle } from '../utils/formatters/migration-list-render';
|
|
33
32
|
import { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';
|
|
34
33
|
import type {
|
|
35
34
|
MigrationListEntry,
|
|
@@ -40,6 +39,7 @@ import { formatStyledHeader } from '../utils/formatters/styled';
|
|
|
40
39
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
41
40
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
42
41
|
import type { GlyphMode } from '../utils/glyph-mode';
|
|
42
|
+
import { shouldShowLegend, validateLegendOptions } from '../utils/legend';
|
|
43
43
|
import { handleResult } from '../utils/result-handler';
|
|
44
44
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
45
45
|
|
|
@@ -52,8 +52,8 @@ function compareSpaceIds(a: string, b: string): number {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function compareDirNamesDescending(a: MigrationListEntry, b: MigrationListEntry): number {
|
|
55
|
-
if (a.
|
|
56
|
-
if (a.
|
|
55
|
+
if (a.name < b.name) return 1;
|
|
56
|
+
if (a.name > b.name) return -1;
|
|
57
57
|
return 0;
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -65,7 +65,7 @@ function compareDirNamesDescending(a: MigrationListEntry, b: MigrationListEntry)
|
|
|
65
65
|
* keep that output. The app space synthesises its head, so it carries
|
|
66
66
|
* no on-disk `head` ref to restore.
|
|
67
67
|
*/
|
|
68
|
-
function listRefsByContractHash(
|
|
68
|
+
export function listRefsByContractHash(
|
|
69
69
|
member: ContractSpaceMember,
|
|
70
70
|
): ReadonlyMap<string, readonly string[]> {
|
|
71
71
|
const byHash = new Map(refsByContractHash(member.refs));
|
|
@@ -110,18 +110,18 @@ export async function migrationSpaceListEntriesFromAggregate(
|
|
|
110
110
|
const refsByHash = listRefsByContractHash(member);
|
|
111
111
|
const migrations: MigrationListEntry[] = member.packages
|
|
112
112
|
.map((pkg) => ({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
name: pkg.dirName,
|
|
114
|
+
hash: pkg.metadata.migrationHash,
|
|
115
|
+
fromContract: pkg.metadata.from,
|
|
116
|
+
toContract: pkg.metadata.to,
|
|
117
117
|
operationCount: pkg.ops.length,
|
|
118
118
|
createdAt: pkg.metadata.createdAt,
|
|
119
|
-
refs: refsByHash.get(pkg.metadata.to) ?? [],
|
|
120
|
-
providedInvariants: pkg.metadata.providedInvariants,
|
|
119
|
+
refs: [...(refsByHash.get(pkg.metadata.to) ?? [])],
|
|
120
|
+
providedInvariants: [...pkg.metadata.providedInvariants],
|
|
121
121
|
}))
|
|
122
122
|
.sort(compareDirNamesDescending);
|
|
123
123
|
|
|
124
|
-
spaces.push({ spaceId, migrations });
|
|
124
|
+
spaces.push({ space: spaceId, migrations });
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
return spaces;
|
|
@@ -131,11 +131,21 @@ interface MigrationListOptions extends CommonCommandOptions {
|
|
|
131
131
|
readonly config?: string;
|
|
132
132
|
readonly space?: string;
|
|
133
133
|
readonly ascii?: boolean;
|
|
134
|
+
readonly legend?: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface MigrationListExecuteResult {
|
|
138
|
+
readonly list: MigrationListResult;
|
|
139
|
+
readonly liveContractHash: string;
|
|
140
|
+
readonly aggregate: ContractSpaceAggregate;
|
|
134
141
|
}
|
|
135
142
|
|
|
136
143
|
export interface MigrationListHumanRenderOptions {
|
|
137
144
|
readonly glyphMode: GlyphMode;
|
|
138
145
|
readonly useColor: boolean;
|
|
146
|
+
readonly liveContractHash: string;
|
|
147
|
+
readonly graphForSpace: (spaceId: string) => MigrationGraph | undefined;
|
|
148
|
+
readonly appSpaceId?: string;
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
export function renderMigrationListHumanOutput(
|
|
@@ -143,8 +153,12 @@ export function renderMigrationListHumanOutput(
|
|
|
143
153
|
options: MigrationListHumanRenderOptions,
|
|
144
154
|
): string {
|
|
145
155
|
const styler = createAnsiMigrationListStyler({ useColor: options.useColor });
|
|
146
|
-
|
|
147
|
-
|
|
156
|
+
return renderMigrationListWithStyle(result, styler, options.glyphMode, {
|
|
157
|
+
colorize: options.useColor,
|
|
158
|
+
liveContractHash: options.liveContractHash,
|
|
159
|
+
graphForSpace: options.graphForSpace,
|
|
160
|
+
...(options.appSpaceId !== undefined ? { appSpaceId: options.appSpaceId } : {}),
|
|
161
|
+
});
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
/**
|
|
@@ -186,19 +200,19 @@ export function runMigrationList(
|
|
|
186
200
|
return notOk(errorInvalidSpaceId(spaceFilter));
|
|
187
201
|
}
|
|
188
202
|
|
|
189
|
-
if (spaceFilter !== undefined && !spaces.some((s) => s.
|
|
190
|
-
return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.
|
|
203
|
+
if (spaceFilter !== undefined && !spaces.some((s) => s.space === spaceFilter)) {
|
|
204
|
+
return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.space).sort()));
|
|
191
205
|
}
|
|
192
206
|
|
|
193
207
|
const scopedSpaces =
|
|
194
|
-
spaceFilter !== undefined ? spaces.filter((s) => s.
|
|
208
|
+
spaceFilter !== undefined ? spaces.filter((s) => s.space === spaceFilter) : spaces;
|
|
195
209
|
|
|
196
210
|
const resultSpaces: readonly MigrationSpaceListEntry[] =
|
|
197
|
-
scopedSpaces.length === 0 ? [{
|
|
211
|
+
scopedSpaces.length === 0 ? [{ space: APP_SPACE_ID, migrations: [] }] : scopedSpaces;
|
|
198
212
|
|
|
199
213
|
return ok({
|
|
200
214
|
ok: true,
|
|
201
|
-
spaces: resultSpaces,
|
|
215
|
+
spaces: [...resultSpaces],
|
|
202
216
|
summary: computeSummary(resultSpaces),
|
|
203
217
|
});
|
|
204
218
|
}
|
|
@@ -212,7 +226,7 @@ export async function executeMigrationListCommand(
|
|
|
212
226
|
options: MigrationListOptions,
|
|
213
227
|
flags: GlobalFlags,
|
|
214
228
|
ui: TerminalUI,
|
|
215
|
-
): Promise<Result<
|
|
229
|
+
): Promise<Result<MigrationListExecuteResult, CliStructuredError>> {
|
|
216
230
|
const config = await loadConfig(options.config);
|
|
217
231
|
const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(
|
|
218
232
|
options.config,
|
|
@@ -222,7 +236,7 @@ export async function executeMigrationListCommand(
|
|
|
222
236
|
if (!flags.json && !flags.quiet) {
|
|
223
237
|
const header = formatStyledHeader({
|
|
224
238
|
command: 'migration list',
|
|
225
|
-
description: 'List on-disk migrations
|
|
239
|
+
description: 'List on-disk migrations per contract space',
|
|
226
240
|
details: [
|
|
227
241
|
{ label: 'config', value: configPath },
|
|
228
242
|
{ label: 'migrations', value: migrationsRelative },
|
|
@@ -231,6 +245,15 @@ export async function executeMigrationListCommand(
|
|
|
231
245
|
flags,
|
|
232
246
|
});
|
|
233
247
|
ui.stderr(header);
|
|
248
|
+
if (shouldShowLegend(options, flags)) {
|
|
249
|
+
ui.stderr(
|
|
250
|
+
renderMigrationGraphLegend({
|
|
251
|
+
colorize: flags.color !== false,
|
|
252
|
+
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
ui.stderr('');
|
|
256
|
+
}
|
|
234
257
|
}
|
|
235
258
|
|
|
236
259
|
const loaded = await buildReadAggregate(config, { migrationsDir });
|
|
@@ -238,35 +261,37 @@ export async function executeMigrationListCommand(
|
|
|
238
261
|
return notOk(loaded.failure);
|
|
239
262
|
}
|
|
240
263
|
|
|
241
|
-
const
|
|
242
|
-
loaded.value.aggregate,
|
|
243
|
-
migrationsDir,
|
|
244
|
-
);
|
|
264
|
+
const { aggregate, contractHash: liveContractHash } = loaded.value;
|
|
245
265
|
|
|
246
|
-
|
|
266
|
+
const spaces = await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir);
|
|
267
|
+
|
|
268
|
+
const listResult = runMigrationList({
|
|
247
269
|
spaces,
|
|
248
270
|
...ifDefined('spaceFilter', options.space),
|
|
249
271
|
});
|
|
272
|
+
if (!listResult.ok) {
|
|
273
|
+
return listResult;
|
|
274
|
+
}
|
|
275
|
+
return ok({ list: listResult.value, liveContractHash, aggregate });
|
|
250
276
|
}
|
|
251
277
|
|
|
252
278
|
export function createMigrationListCommand(): Command {
|
|
253
279
|
const command = new Command('list');
|
|
254
280
|
setCommandDescriptions(
|
|
255
281
|
command,
|
|
256
|
-
'List on-disk migrations
|
|
282
|
+
'List on-disk migrations per contract space',
|
|
257
283
|
'Enumerates every on-disk migration under migrations/<space>/ for every\n' +
|
|
258
|
-
'contract space found on disk
|
|
259
|
-
'
|
|
260
|
-
'
|
|
261
|
-
'
|
|
262
|
-
'
|
|
263
|
-
'to narrow to one contract space. --ascii forces ASCII kind glyphs\n' +
|
|
264
|
-
'(orthogonal to --no-color).',
|
|
284
|
+
'contract space found on disk. Offline — does not consult the database.\n' +
|
|
285
|
+
'Human output draws the shared migration graph tree with operation counts,\n' +
|
|
286
|
+
'invariants on each migration row, and refs on destination contract nodes.\n' +
|
|
287
|
+
'Pass --space <id> to narrow to one contract space. --ascii forces ASCII\n' +
|
|
288
|
+
'tree glyphs (orthogonal to --no-color).',
|
|
265
289
|
);
|
|
266
290
|
setCommandExamples(command, [
|
|
267
291
|
'prisma-next migration list',
|
|
268
292
|
'prisma-next migration list --space app',
|
|
269
293
|
'prisma-next migration list --ascii',
|
|
294
|
+
'prisma-next migration list --legend',
|
|
270
295
|
'prisma-next migration list --json',
|
|
271
296
|
]);
|
|
272
297
|
setCommandSeeAlso(command, [
|
|
@@ -279,18 +304,26 @@ export function createMigrationListCommand(): Command {
|
|
|
279
304
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
280
305
|
.option('--space <id>', 'Narrow output to a single contract space')
|
|
281
306
|
.option('--ascii', 'Use ASCII kind glyphs (pipe-friendly)')
|
|
307
|
+
.option('--legend', 'Print a key for the tree glyphs and lane colors')
|
|
282
308
|
.action(async (options: MigrationListOptions) => {
|
|
283
309
|
const flags = parseGlobalFlagsOrExit(options);
|
|
284
310
|
const ui = createTerminalUI(flags);
|
|
311
|
+
const legendValidation = validateLegendOptions(options, flags);
|
|
312
|
+
if (!legendValidation.ok) {
|
|
313
|
+
process.exit(handleResult(legendValidation, flags, ui));
|
|
314
|
+
}
|
|
285
315
|
const result = await executeMigrationListCommand(options, flags, ui);
|
|
286
|
-
const exitCode = handleResult(result, flags, ui, (
|
|
316
|
+
const exitCode = handleResult(result, flags, ui, ({ list, liveContractHash, aggregate }) => {
|
|
287
317
|
if (flags.json) {
|
|
288
|
-
ui.output(JSON.stringify(
|
|
318
|
+
ui.output(JSON.stringify(list, null, 2));
|
|
289
319
|
} else if (!flags.quiet) {
|
|
290
320
|
ui.output(
|
|
291
|
-
renderMigrationListHumanOutput(
|
|
321
|
+
renderMigrationListHumanOutput(list, {
|
|
292
322
|
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
293
323
|
useColor: ui.useColor,
|
|
324
|
+
liveContractHash,
|
|
325
|
+
graphForSpace: (spaceId) => aggregate.space(spaceId)?.graph(),
|
|
326
|
+
appSpaceId: aggregate.app.spaceId,
|
|
294
327
|
}),
|
|
295
328
|
);
|
|
296
329
|
}
|