@prisma-next/cli 0.12.0-dev.9 → 0.13.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +16 -25
- 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-soB5uZEQ.mjs +573 -0
- package/dist/migration-check-soB5uZEQ.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-CgWSoI_g.mjs +446 -0
- package/dist/migration-status-CgWSoI_g.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 +151 -119
- 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-C9WC-7eO.mjs +0 -1478
- package/dist/migration-graph-C9WC-7eO.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-lane-colors.ts +0 -31
- package/src/utils/formatters/migration-graph-layout.ts +0 -1141
- package/src/utils/formatters/migration-graph-tree-render.ts +0 -768
|
@@ -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,69 +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 { graphRenderer } from '../utils/formatters/graph-render';
|
|
17
|
-
import { buildMigrationGraphLayout } from '../utils/formatters/migration-graph-layout';
|
|
18
|
-
import { buildMigrationGraphRows } from '../utils/formatters/migration-graph-rows';
|
|
16
|
+
import { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-labels';
|
|
19
17
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
computeGlobalMaxDirNameWidth,
|
|
19
|
+
computeGlobalMaxEdgeTreePrefixWidth,
|
|
20
|
+
indentMigrationGraphTreeBlock,
|
|
21
|
+
renderMigrationGraphSpaceTree,
|
|
22
|
+
} from '../utils/formatters/migration-graph-space-render';
|
|
23
23
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
24
24
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
25
25
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
26
|
-
import
|
|
26
|
+
import { shouldShowLegend, validateLegendOptions } from '../utils/legend';
|
|
27
27
|
import { handleResult } from '../utils/result-handler';
|
|
28
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';
|
|
29
35
|
|
|
30
36
|
interface MigrationGraphOptions extends CommonCommandOptions {
|
|
31
37
|
readonly config?: string;
|
|
32
38
|
readonly dot?: boolean;
|
|
33
|
-
readonly
|
|
39
|
+
readonly space?: string;
|
|
34
40
|
readonly ascii?: boolean;
|
|
35
41
|
readonly legend?: boolean;
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
export function migrationGraphUsesTree(options: {
|
|
43
|
-
readonly tree?: boolean;
|
|
44
|
-
readonly legend?: boolean;
|
|
45
|
-
}): boolean {
|
|
46
|
-
return options.tree === true || options.legend === true;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* The legend is decoration printed alongside the command header on stderr, so
|
|
51
|
-
* it is suppressed for the machine-readable / silent paths (`--json`, `--dot`,
|
|
52
|
-
* `--quiet`) exactly as the header is.
|
|
53
|
-
*/
|
|
54
|
-
export function migrationGraphShowsLegend(
|
|
55
|
-
options: { readonly legend?: boolean; readonly dot?: boolean },
|
|
56
|
-
flags: GlobalFlags,
|
|
57
|
-
): boolean {
|
|
58
|
-
return (
|
|
59
|
-
options.legend === true && options.dot !== true && flags.json !== true && flags.quiet !== true
|
|
60
|
-
);
|
|
44
|
+
export interface MigrationGraphTreeSection {
|
|
45
|
+
readonly space: string;
|
|
46
|
+
readonly tree: string;
|
|
47
|
+
readonly showHeading: boolean;
|
|
61
48
|
}
|
|
62
49
|
|
|
63
50
|
export interface MigrationGraphResult {
|
|
64
51
|
readonly ok: true;
|
|
52
|
+
/** App-space graph for the `--dot` Graphviz output. */
|
|
65
53
|
readonly graph: MigrationGraph;
|
|
66
|
-
|
|
67
|
-
readonly
|
|
54
|
+
/** Nested per-space contracts + migrations for `--json`. */
|
|
55
|
+
readonly spaces: readonly MigrationSpaceGraphEntry[];
|
|
56
|
+
readonly treeSections: readonly MigrationGraphTreeSection[];
|
|
68
57
|
readonly summary: string;
|
|
69
58
|
}
|
|
70
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
|
+
|
|
71
83
|
export async function executeMigrationGraphCommand(
|
|
72
84
|
options: MigrationGraphOptions,
|
|
73
85
|
flags: GlobalFlags,
|
|
74
86
|
ui: TerminalUI,
|
|
75
87
|
): Promise<Result<MigrationGraphResult, CliStructuredError>> {
|
|
76
88
|
const config = await loadConfig(options.config);
|
|
77
|
-
const { configPath,
|
|
89
|
+
const { configPath, migrationsRelative, migrationsDir } = resolveMigrationPaths(
|
|
78
90
|
options.config,
|
|
79
91
|
config,
|
|
80
92
|
);
|
|
@@ -85,19 +97,19 @@ export async function executeMigrationGraphCommand(
|
|
|
85
97
|
description: 'Show the migration graph topology',
|
|
86
98
|
details: [
|
|
87
99
|
{ label: 'config', value: configPath },
|
|
88
|
-
{ label: 'migrations', value:
|
|
100
|
+
{ label: 'migrations', value: migrationsRelative },
|
|
101
|
+
...(options.space !== undefined ? [{ label: 'space', value: options.space }] : []),
|
|
89
102
|
],
|
|
90
103
|
flags,
|
|
91
104
|
});
|
|
92
105
|
ui.stderr(header);
|
|
93
|
-
if (
|
|
106
|
+
if (shouldShowLegend(options, flags)) {
|
|
94
107
|
ui.stderr(
|
|
95
108
|
renderMigrationGraphLegend({
|
|
96
109
|
colorize: flags.color !== false,
|
|
97
110
|
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
98
111
|
}),
|
|
99
112
|
);
|
|
100
|
-
// Blank line separating the stderr key from the graph that follows on stdout.
|
|
101
113
|
ui.stderr('');
|
|
102
114
|
}
|
|
103
115
|
}
|
|
@@ -107,20 +119,90 @@ export async function executeMigrationGraphCommand(
|
|
|
107
119
|
return loaded;
|
|
108
120
|
}
|
|
109
121
|
|
|
110
|
-
const { aggregate, contractHash } = loaded.value;
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
+
}
|
|
117
199
|
|
|
118
200
|
return ok({
|
|
119
201
|
ok: true,
|
|
120
|
-
graph,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
summary:
|
|
202
|
+
graph: appGraph,
|
|
203
|
+
spaces,
|
|
204
|
+
treeSections,
|
|
205
|
+
summary: computeGraphSummary(spaces),
|
|
124
206
|
});
|
|
125
207
|
}
|
|
126
208
|
|
|
@@ -129,19 +211,19 @@ export function createMigrationGraphCommand(): Command {
|
|
|
129
211
|
setCommandDescriptions(
|
|
130
212
|
command,
|
|
131
213
|
'Show the migration graph topology',
|
|
132
|
-
'Renders the migration graph topology
|
|
133
|
-
'
|
|
134
|
-
'
|
|
135
|
-
'--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' +
|
|
136
218
|
'format.',
|
|
137
219
|
);
|
|
138
220
|
setCommandExamples(command, [
|
|
139
221
|
'prisma-next migration graph',
|
|
140
222
|
'prisma-next migration graph --json',
|
|
141
223
|
'prisma-next migration graph --dot',
|
|
142
|
-
'prisma-next migration graph --
|
|
143
|
-
'prisma-next migration graph --tree --ascii',
|
|
224
|
+
'prisma-next migration graph --ascii',
|
|
144
225
|
'prisma-next migration graph --legend',
|
|
226
|
+
'prisma-next migration graph --space app',
|
|
145
227
|
]);
|
|
146
228
|
setCommandSeeAlso(command, [
|
|
147
229
|
{ verb: 'migration status', oneLiner: 'Show migration path and pending status' },
|
|
@@ -151,20 +233,19 @@ export function createMigrationGraphCommand(): Command {
|
|
|
151
233
|
]);
|
|
152
234
|
addGlobalOptions(command)
|
|
153
235
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
236
|
+
.option('--space <id>', 'Narrow output to a single contract space')
|
|
154
237
|
.option('--dot', 'Output in Graphviz DOT format')
|
|
155
|
-
.option('--
|
|
156
|
-
.option('--
|
|
157
|
-
.option('--legend', 'Print a key for the --tree glyphs and lane colors (implies --tree)')
|
|
238
|
+
.option('--ascii', 'Use ASCII glyphs (pipe-friendly)')
|
|
239
|
+
.option('--legend', 'Print a key for the tree glyphs and lane colors')
|
|
158
240
|
.action(async (options: MigrationGraphOptions) => {
|
|
159
241
|
const flags = parseGlobalFlagsOrExit(options);
|
|
160
242
|
const ui = createTerminalUI(flags);
|
|
243
|
+
const legendValidation = validateLegendOptions(options, flags);
|
|
244
|
+
if (!legendValidation.ok) {
|
|
245
|
+
process.exit(handleResult(legendValidation, flags, ui));
|
|
246
|
+
}
|
|
161
247
|
const result = await executeMigrationGraphCommand(options, flags, ui);
|
|
162
248
|
const exitCode = handleResult(result, flags, ui, (graphResult) => {
|
|
163
|
-
// Explicit format flags win over the auto-JSON default. `flags.json`
|
|
164
|
-
// is auto-enabled when stdout is non-TTY (per CLI Style Guide §
|
|
165
|
-
// JSON Semantics); without this ordering, `migration graph --dot |
|
|
166
|
-
// dot -Tsvg` pipes JSON into the GraphViz binary, which then
|
|
167
|
-
// errors. `--dot` is the more specific instruction; honour it.
|
|
168
249
|
if (options.dot) {
|
|
169
250
|
const lines = ['digraph migrations {'];
|
|
170
251
|
for (const edge of graphResult.graph.migrationByHash.values()) {
|
|
@@ -175,63 +256,14 @@ export function createMigrationGraphCommand(): Command {
|
|
|
175
256
|
lines.push('}');
|
|
176
257
|
ui.output(lines.join('\n'));
|
|
177
258
|
} else if (flags.json) {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}));
|
|
185
|
-
ui.output(
|
|
186
|
-
JSON.stringify({ ok: true, nodes, edges, summary: graphResult.summary }, null, 2),
|
|
187
|
-
);
|
|
259
|
+
const jsonResult: MigrationGraphJsonResult = {
|
|
260
|
+
ok: true,
|
|
261
|
+
spaces: [...graphResult.spaces],
|
|
262
|
+
summary: graphResult.summary,
|
|
263
|
+
};
|
|
264
|
+
ui.output(JSON.stringify(jsonResult, null, 2));
|
|
188
265
|
} else if (!flags.quiet) {
|
|
189
|
-
|
|
190
|
-
const refsByHash = new Map<string, string[]>();
|
|
191
|
-
for (const ref of graphResult.refs) {
|
|
192
|
-
const existing = refsByHash.get(ref.hash);
|
|
193
|
-
refsByHash.set(ref.hash, existing ? [...existing, ref.name] : [ref.name]);
|
|
194
|
-
}
|
|
195
|
-
const rowModel = buildMigrationGraphRows(graphResult.graph, {
|
|
196
|
-
...(graphResult.contractHash !== null
|
|
197
|
-
? { contractHash: graphResult.contractHash }
|
|
198
|
-
: {}),
|
|
199
|
-
});
|
|
200
|
-
const layout = buildMigrationGraphLayout(rowModel);
|
|
201
|
-
const activeRef = graphResult.refs.find((ref) => ref.active);
|
|
202
|
-
const treeOutput = renderMigrationGraphTree(layout, {
|
|
203
|
-
refsByHash,
|
|
204
|
-
...(graphResult.contractHash !== null
|
|
205
|
-
? { contractHash: graphResult.contractHash }
|
|
206
|
-
: {}),
|
|
207
|
-
...(activeRef !== undefined ? { activeRefName: activeRef.name } : {}),
|
|
208
|
-
colorize: flags.color !== false,
|
|
209
|
-
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
210
|
-
});
|
|
211
|
-
// Emit the rendered tree to stdout (same stream as flat `migration list`),
|
|
212
|
-
// not through clack's `log.message` rail: the graph is the command's
|
|
213
|
-
// result (and its own box-drawing is the only vertical structure it
|
|
214
|
-
// should carry), not a status line that needs the prompt gutter.
|
|
215
|
-
ui.output(treeOutput);
|
|
216
|
-
ui.output(`\n${graphResult.summary}`);
|
|
217
|
-
} else {
|
|
218
|
-
const renderInput = migrationGraphToRenderInput({
|
|
219
|
-
graph: graphResult.graph,
|
|
220
|
-
mode: 'offline',
|
|
221
|
-
markerHash: undefined,
|
|
222
|
-
contractHash: graphResult.contractHash ?? EMPTY_CONTRACT_HASH,
|
|
223
|
-
refs: graphResult.refs,
|
|
224
|
-
activeRefHash: undefined,
|
|
225
|
-
activeRefName: undefined,
|
|
226
|
-
edgeStatuses: [],
|
|
227
|
-
});
|
|
228
|
-
const graphOutput = graphRenderer.render(renderInput.graph, {
|
|
229
|
-
...renderInput.options,
|
|
230
|
-
colorize: flags.color !== false,
|
|
231
|
-
});
|
|
232
|
-
ui.log(graphOutput);
|
|
233
|
-
ui.log(`\n${graphResult.summary}`);
|
|
234
|
-
}
|
|
266
|
+
ui.output(formatMigrationGraphHumanOutput(graphResult));
|
|
235
267
|
}
|
|
236
268
|
});
|
|
237
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
|
}
|