@prisma-next/cli 0.12.0-dev.28 → 0.12.0-dev.29
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/dist/cli.mjs +12 -12
- package/dist/{client-nygCs15r.mjs → client-xeWpMlq1.mjs} +4 -4
- package/dist/client-xeWpMlq1.mjs.map +1 -0
- package/dist/{command-helpers-D7TK5Y9e.mjs → command-helpers-DK_5ItoJ.mjs} +16 -2
- package/dist/command-helpers-DK_5ItoJ.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +3 -3
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.mjs +4 -4
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +1 -1
- package/dist/commands/migrate.mjs +4 -4
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.d.mts +12 -15
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +84 -51
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +13 -4
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +1 -187
- package/dist/commands/migration-log.d.mts +2 -2
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.d.mts +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.mjs +2 -2
- package/dist/commands/migration-status.d.mts +20 -2
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -3
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +2 -2
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-CK3qoqZf.mjs → contract-at-errors-DG3kjgoz.mjs} +2 -2
- package/dist/{contract-at-errors-CK3qoqZf.mjs.map → contract-at-errors-DG3kjgoz.mjs.map} +1 -1
- package/dist/{contract-emit-Dzf73HdD.mjs → contract-emit-BO0l6fnT.mjs} +3 -3
- package/dist/{contract-emit-Dzf73HdD.mjs.map → contract-emit-BO0l6fnT.mjs.map} +1 -1
- package/dist/{contract-emit-DwlIz5Zg.mjs → contract-emit-C0Bs0VRj.mjs} +3 -3
- package/dist/{contract-emit-DwlIz5Zg.mjs.map → contract-emit-C0Bs0VRj.mjs.map} +1 -1
- package/dist/{contract-infer-Bzh___GO.mjs → contract-infer-2wtPflGH.mjs} +3 -3
- package/dist/{contract-infer-Bzh___GO.mjs.map → contract-infer-2wtPflGH.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-5zmOENc4.mjs → contract-space-aggregate-loader-Dbr3-jHF.mjs} +2 -2
- package/dist/{contract-space-aggregate-loader-5zmOENc4.mjs.map → contract-space-aggregate-loader-Dbr3-jHF.mjs.map} +1 -1
- package/dist/{db-verify-CNz036sw.mjs → db-verify-CxHiSiTG.mjs} +4 -4
- package/dist/{db-verify-CNz036sw.mjs.map → db-verify-CxHiSiTG.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-CyM_xYCY.mjs → framework-components-CxOVKAAh.mjs} +2 -2
- package/dist/{framework-components-CyM_xYCY.mjs.map → framework-components-CxOVKAAh.mjs.map} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-DG4uY5tV.d.mts} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-DG4uY5tV.d.mts.map} +1 -1
- package/dist/{init-DJsQpr_6.mjs → init-R272pxux.mjs} +4 -4
- package/dist/{init-DJsQpr_6.mjs.map → init-R272pxux.mjs.map} +1 -1
- package/dist/{inspect-live-schema-DE76Ou4D.mjs → inspect-live-schema-RekOwfi5.mjs} +3 -3
- package/dist/{inspect-live-schema-DE76Ou4D.mjs.map → inspect-live-schema-RekOwfi5.mjs.map} +1 -1
- package/dist/{migration-check-CL2MzDRX.mjs → migration-check-Dc0cOhKH.mjs} +2 -2
- package/dist/{migration-check-CL2MzDRX.mjs.map → migration-check-Dc0cOhKH.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-194pA8F5.mjs → migration-command-scaffold-ApB3NxWY.mjs} +3 -3
- package/dist/{migration-command-scaffold-194pA8F5.mjs.map → migration-command-scaffold-ApB3NxWY.mjs.map} +1 -1
- package/dist/{migration-graph-tree-render-CVmV9sWr.mjs → migration-graph-space-render-dmLLWift.mjs} +389 -210
- package/dist/migration-graph-space-render-dmLLWift.mjs.map +1 -0
- package/dist/migration-list-C5sXrl0U.mjs +228 -0
- package/dist/migration-list-C5sXrl0U.mjs.map +1 -0
- package/dist/{migration-log-CP6skD5b.mjs → migration-log-DD_vCbYW.mjs} +4 -4
- package/dist/{migration-log-CP6skD5b.mjs.map → migration-log-DD_vCbYW.mjs.map} +1 -1
- package/dist/{migration-plan-D61N1hID.mjs → migration-plan-CeTjQOIG.mjs} +5 -5
- package/dist/{migration-plan-D61N1hID.mjs.map → migration-plan-CeTjQOIG.mjs.map} +1 -1
- package/dist/{migration-status--ejfYqWS.mjs → migration-status-qV8ctwPy.mjs} +61 -45
- package/dist/migration-status-qV8ctwPy.mjs.map +1 -0
- package/dist/{output-B60Gw5fu.mjs → output-CF_hqzI-.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-CF_hqzI-.mjs.map} +1 -1
- package/dist/{telemetry-CnfdMrpv.mjs → telemetry-S-NGi9U6.mjs} +2 -2
- package/dist/{telemetry-CnfdMrpv.mjs.map → telemetry-S-NGi9U6.mjs.map} +1 -1
- package/dist/{types-BYwWOyYJ.d.mts → types-Mh7mdPHM.d.mts} +1 -1
- package/dist/{types-BYwWOyYJ.d.mts.map → types-Mh7mdPHM.d.mts.map} +1 -1
- package/dist/{verify-By66Zu3y.mjs → verify-BdI-BgYi.mjs} +2 -2
- package/dist/{verify-By66Zu3y.mjs.map → verify-BdI-BgYi.mjs.map} +1 -1
- package/package.json +18 -18
- package/src/commands/migration-graph.ts +125 -58
- package/src/commands/migration-list.ts +43 -9
- package/src/commands/migration-status.ts +106 -74
- package/src/control-api/operations/db-apply.ts +7 -4
- package/src/utils/cli-errors.ts +17 -0
- package/src/utils/formatters/migration-graph-lane-colors.ts +164 -1
- package/src/utils/formatters/migration-graph-rows.ts +128 -15
- package/src/utils/formatters/migration-graph-space-render.ts +138 -0
- package/src/utils/formatters/migration-graph-tree-render.ts +149 -239
- package/src/utils/formatters/migration-list-data-column.ts +6 -0
- package/src/utils/formatters/migration-list-render.ts +43 -23
- package/src/utils/formatters/migration-list-styler.ts +48 -5
- package/src/utils/legend.ts +38 -0
- package/dist/client-nygCs15r.mjs.map +0 -1
- package/dist/command-helpers-D7TK5Y9e.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/migration-graph-tree-render-CVmV9sWr.mjs.map +0 -1
- package/dist/migration-status--ejfYqWS.mjs.map +0 -1
- package/dist/migration-types-D2FW63pr.d.mts +0 -15
- package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
2
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
2
3
|
import { ok, type Result } from '@prisma-next/utils/result';
|
|
3
4
|
import { Command } from 'commander';
|
|
4
5
|
import { loadConfig } from '../config-loader';
|
|
@@ -11,55 +12,75 @@ import {
|
|
|
11
12
|
setCommandSeeAlso,
|
|
12
13
|
} from '../utils/command-helpers';
|
|
13
14
|
import { buildReadAggregate } from '../utils/contract-space-aggregate-loader';
|
|
14
|
-
import { buildMigrationGraphLayout } from '../utils/formatters/migration-graph-layout';
|
|
15
|
-
import { buildMigrationGraphRows } from '../utils/formatters/migration-graph-rows';
|
|
16
15
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
computeGlobalMaxDirNameWidth,
|
|
17
|
+
computeGlobalMaxEdgeTreePrefixWidth,
|
|
18
|
+
indentMigrationGraphTreeBlock,
|
|
19
|
+
renderMigrationGraphSpaceTree,
|
|
20
|
+
} from '../utils/formatters/migration-graph-space-render';
|
|
21
|
+
import { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-tree-render';
|
|
20
22
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
21
23
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
22
24
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
23
|
-
import
|
|
25
|
+
import { shouldShowLegend, validateLegendOptions } from '../utils/legend';
|
|
24
26
|
import { handleResult } from '../utils/result-handler';
|
|
25
27
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
28
|
+
import {
|
|
29
|
+
listRefsByContractHash,
|
|
30
|
+
migrationSpaceListEntriesFromAggregate,
|
|
31
|
+
runMigrationList,
|
|
32
|
+
} from './migration-list';
|
|
26
33
|
|
|
27
34
|
interface MigrationGraphOptions extends CommonCommandOptions {
|
|
28
35
|
readonly config?: string;
|
|
29
36
|
readonly dot?: boolean;
|
|
37
|
+
readonly space?: string;
|
|
30
38
|
readonly ascii?: boolean;
|
|
31
39
|
readonly legend?: boolean;
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*/
|
|
39
|
-
export function migrationGraphShowsLegend(
|
|
40
|
-
options: { readonly legend?: boolean; readonly dot?: boolean },
|
|
41
|
-
flags: GlobalFlags,
|
|
42
|
-
): boolean {
|
|
43
|
-
return (
|
|
44
|
-
options.legend === true && options.dot !== true && flags.json !== true && flags.quiet !== true
|
|
45
|
-
);
|
|
42
|
+
export interface MigrationGraphTreeSection {
|
|
43
|
+
readonly spaceId: string;
|
|
44
|
+
readonly tree: string;
|
|
45
|
+
readonly showHeading: boolean;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export interface MigrationGraphResult {
|
|
49
49
|
readonly ok: true;
|
|
50
|
+
/** App-space graph for `--json` / `--dot` (unchanged machine output). */
|
|
50
51
|
readonly graph: MigrationGraph;
|
|
51
|
-
readonly
|
|
52
|
-
readonly refs: readonly StatusRef[];
|
|
52
|
+
readonly treeSections: readonly MigrationGraphTreeSection[];
|
|
53
53
|
readonly summary: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
function computeGraphSummary(graph: MigrationGraph): string {
|
|
57
|
+
return `${graph.nodes.size} node(s), ${graph.migrationByHash.size} edge(s)`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function formatMigrationGraphHumanOutput(result: MigrationGraphResult): string {
|
|
61
|
+
const sections: string[] = [];
|
|
62
|
+
for (const section of result.treeSections) {
|
|
63
|
+
if (section.showHeading) {
|
|
64
|
+
sections.push(`${section.spaceId}:`);
|
|
65
|
+
}
|
|
66
|
+
if (section.tree.length > 0) {
|
|
67
|
+
sections.push(section.tree);
|
|
68
|
+
} else {
|
|
69
|
+
sections.push('(no migrations)');
|
|
70
|
+
}
|
|
71
|
+
sections.push('');
|
|
72
|
+
}
|
|
73
|
+
sections.push(result.summary);
|
|
74
|
+
return sections.join('\n').trimEnd();
|
|
75
|
+
}
|
|
76
|
+
|
|
56
77
|
export async function executeMigrationGraphCommand(
|
|
57
78
|
options: MigrationGraphOptions,
|
|
58
79
|
flags: GlobalFlags,
|
|
59
80
|
ui: TerminalUI,
|
|
60
81
|
): Promise<Result<MigrationGraphResult, CliStructuredError>> {
|
|
61
82
|
const config = await loadConfig(options.config);
|
|
62
|
-
const { configPath,
|
|
83
|
+
const { configPath, migrationsRelative, migrationsDir } = resolveMigrationPaths(
|
|
63
84
|
options.config,
|
|
64
85
|
config,
|
|
65
86
|
);
|
|
@@ -70,12 +91,13 @@ export async function executeMigrationGraphCommand(
|
|
|
70
91
|
description: 'Show the migration graph topology',
|
|
71
92
|
details: [
|
|
72
93
|
{ label: 'config', value: configPath },
|
|
73
|
-
{ label: 'migrations', value:
|
|
94
|
+
{ label: 'migrations', value: migrationsRelative },
|
|
95
|
+
...(options.space !== undefined ? [{ label: 'space', value: options.space }] : []),
|
|
74
96
|
],
|
|
75
97
|
flags,
|
|
76
98
|
});
|
|
77
99
|
ui.stderr(header);
|
|
78
|
-
if (
|
|
100
|
+
if (shouldShowLegend(options, flags)) {
|
|
79
101
|
ui.stderr(
|
|
80
102
|
renderMigrationGraphLegend({
|
|
81
103
|
colorize: flags.color !== false,
|
|
@@ -91,20 +113,72 @@ export async function executeMigrationGraphCommand(
|
|
|
91
113
|
return loaded;
|
|
92
114
|
}
|
|
93
115
|
|
|
94
|
-
const { aggregate, contractHash } = loaded.value;
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
const { aggregate, contractHash: liveContractHash } = loaded.value;
|
|
117
|
+
const appGraph = aggregate.app.graph();
|
|
118
|
+
|
|
119
|
+
const listSpaces = await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir);
|
|
120
|
+
const listResult = runMigrationList({
|
|
121
|
+
spaces: listSpaces,
|
|
122
|
+
...ifDefined('spaceFilter', options.space),
|
|
123
|
+
});
|
|
124
|
+
if (!listResult.ok) {
|
|
125
|
+
return listResult;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const scopedSpaces = listResult.value.spaces;
|
|
129
|
+
const showSpaceHeadings = scopedSpaces.length > 1;
|
|
130
|
+
const glyphMode = ui.resolveGlyphMode(options.ascii === true);
|
|
131
|
+
const colorize = flags.color !== false;
|
|
132
|
+
|
|
133
|
+
const globalLayoutInputs = showSpaceHeadings
|
|
134
|
+
? scopedSpaces
|
|
135
|
+
.filter((spaceEntry) => spaceEntry.migrations.length > 0)
|
|
136
|
+
.map((spaceEntry) => ({
|
|
137
|
+
graph: aggregate.space(spaceEntry.spaceId)!.graph(),
|
|
138
|
+
liveContractHash,
|
|
139
|
+
}))
|
|
140
|
+
: [];
|
|
141
|
+
const globalMaxEdgeTreePrefixWidth =
|
|
142
|
+
globalLayoutInputs.length > 0
|
|
143
|
+
? computeGlobalMaxEdgeTreePrefixWidth(globalLayoutInputs)
|
|
144
|
+
: undefined;
|
|
145
|
+
const globalMaxDirNameWidth =
|
|
146
|
+
globalLayoutInputs.length > 0 ? computeGlobalMaxDirNameWidth(globalLayoutInputs) : undefined;
|
|
147
|
+
|
|
148
|
+
const treeSections: MigrationGraphTreeSection[] = [];
|
|
149
|
+
for (const spaceEntry of scopedSpaces) {
|
|
150
|
+
const member = aggregate.space(spaceEntry.spaceId);
|
|
151
|
+
if (member === undefined) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const graph = member.graph();
|
|
155
|
+
const tree =
|
|
156
|
+
spaceEntry.migrations.length === 0
|
|
157
|
+
? ''
|
|
158
|
+
: renderMigrationGraphSpaceTree({
|
|
159
|
+
graph,
|
|
160
|
+
migrations: spaceEntry.migrations,
|
|
161
|
+
liveContractHash,
|
|
162
|
+
glyphMode,
|
|
163
|
+
colorize,
|
|
164
|
+
refsByHash: listRefsByContractHash(member),
|
|
165
|
+
...(globalMaxEdgeTreePrefixWidth !== undefined ? { globalMaxEdgeTreePrefixWidth } : {}),
|
|
166
|
+
...(globalMaxDirNameWidth !== undefined ? { globalMaxDirNameWidth } : {}),
|
|
167
|
+
});
|
|
168
|
+
const displayTree =
|
|
169
|
+
showSpaceHeadings && tree.length > 0 ? indentMigrationGraphTreeBlock(tree, ' ') : tree;
|
|
170
|
+
treeSections.push({
|
|
171
|
+
spaceId: spaceEntry.spaceId,
|
|
172
|
+
tree: displayTree,
|
|
173
|
+
showHeading: showSpaceHeadings,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
101
176
|
|
|
102
177
|
return ok({
|
|
103
178
|
ok: true,
|
|
104
|
-
graph,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
summary: `${graph.nodes.size} node(s), ${graph.migrationByHash.size} edge(s)`,
|
|
179
|
+
graph: appGraph,
|
|
180
|
+
treeSections,
|
|
181
|
+
summary: computeGraphSummary(appGraph),
|
|
108
182
|
});
|
|
109
183
|
}
|
|
110
184
|
|
|
@@ -124,6 +198,7 @@ export function createMigrationGraphCommand(): Command {
|
|
|
124
198
|
'prisma-next migration graph --dot',
|
|
125
199
|
'prisma-next migration graph --ascii',
|
|
126
200
|
'prisma-next migration graph --legend',
|
|
201
|
+
'prisma-next migration graph --space app',
|
|
127
202
|
]);
|
|
128
203
|
setCommandSeeAlso(command, [
|
|
129
204
|
{ verb: 'migration status', oneLiner: 'Show migration path and pending status' },
|
|
@@ -133,12 +208,17 @@ export function createMigrationGraphCommand(): Command {
|
|
|
133
208
|
]);
|
|
134
209
|
addGlobalOptions(command)
|
|
135
210
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
211
|
+
.option('--space <id>', 'Narrow output to a single contract space')
|
|
136
212
|
.option('--dot', 'Output in Graphviz DOT format')
|
|
137
213
|
.option('--ascii', 'Use ASCII glyphs (pipe-friendly)')
|
|
138
214
|
.option('--legend', 'Print a key for the tree glyphs and lane colors')
|
|
139
215
|
.action(async (options: MigrationGraphOptions) => {
|
|
140
216
|
const flags = parseGlobalFlagsOrExit(options);
|
|
141
217
|
const ui = createTerminalUI(flags);
|
|
218
|
+
const legendValidation = validateLegendOptions(options, flags);
|
|
219
|
+
if (!legendValidation.ok) {
|
|
220
|
+
process.exit(handleResult(legendValidation, flags, ui));
|
|
221
|
+
}
|
|
142
222
|
const result = await executeMigrationGraphCommand(options, flags, ui);
|
|
143
223
|
const exitCode = handleResult(result, flags, ui, (graphResult) => {
|
|
144
224
|
if (options.dot) {
|
|
@@ -159,32 +239,19 @@ export function createMigrationGraphCommand(): Command {
|
|
|
159
239
|
migrationHash: e.migrationHash,
|
|
160
240
|
}));
|
|
161
241
|
ui.output(
|
|
162
|
-
JSON.stringify(
|
|
242
|
+
JSON.stringify(
|
|
243
|
+
{
|
|
244
|
+
ok: true,
|
|
245
|
+
nodes,
|
|
246
|
+
edges,
|
|
247
|
+
summary: `${graphResult.graph.nodes.size} node(s), ${graphResult.graph.migrationByHash.size} edge(s)`,
|
|
248
|
+
},
|
|
249
|
+
null,
|
|
250
|
+
2,
|
|
251
|
+
),
|
|
163
252
|
);
|
|
164
253
|
} else if (!flags.quiet) {
|
|
165
|
-
|
|
166
|
-
for (const ref of graphResult.refs) {
|
|
167
|
-
const existing = refsByHash.get(ref.hash);
|
|
168
|
-
refsByHash.set(ref.hash, existing ? [...existing, ref.name] : [ref.name]);
|
|
169
|
-
}
|
|
170
|
-
const rowModel = buildMigrationGraphRows(graphResult.graph, {
|
|
171
|
-
...(graphResult.contractHash !== null
|
|
172
|
-
? { contractHash: graphResult.contractHash }
|
|
173
|
-
: {}),
|
|
174
|
-
});
|
|
175
|
-
const layout = buildMigrationGraphLayout(rowModel);
|
|
176
|
-
const activeRef = graphResult.refs.find((ref) => ref.active);
|
|
177
|
-
const treeOutput = renderMigrationGraphTree(layout, {
|
|
178
|
-
refsByHash,
|
|
179
|
-
...(graphResult.contractHash !== null
|
|
180
|
-
? { contractHash: graphResult.contractHash }
|
|
181
|
-
: {}),
|
|
182
|
-
...(activeRef !== undefined ? { activeRefName: activeRef.name } : {}),
|
|
183
|
-
colorize: flags.color !== false,
|
|
184
|
-
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
185
|
-
});
|
|
186
|
-
ui.output(treeOutput);
|
|
187
|
-
ui.output(`\n${graphResult.summary}`);
|
|
254
|
+
ui.output(formatMigrationGraphHumanOutput(graphResult));
|
|
188
255
|
}
|
|
189
256
|
});
|
|
190
257
|
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,6 +27,7 @@ import {
|
|
|
26
27
|
setCommandSeeAlso,
|
|
27
28
|
} from '../utils/command-helpers';
|
|
28
29
|
import { buildReadAggregate } from '../utils/contract-space-aggregate-loader';
|
|
30
|
+
import { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-tree-render';
|
|
29
31
|
import { renderMigrationListWithStyle } from '../utils/formatters/migration-list-render';
|
|
30
32
|
import { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';
|
|
31
33
|
import type {
|
|
@@ -37,6 +39,7 @@ import { formatStyledHeader } from '../utils/formatters/styled';
|
|
|
37
39
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
38
40
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
39
41
|
import type { GlyphMode } from '../utils/glyph-mode';
|
|
42
|
+
import { shouldShowLegend, validateLegendOptions } from '../utils/legend';
|
|
40
43
|
import { handleResult } from '../utils/result-handler';
|
|
41
44
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
42
45
|
|
|
@@ -128,11 +131,20 @@ interface MigrationListOptions extends CommonCommandOptions {
|
|
|
128
131
|
readonly config?: string;
|
|
129
132
|
readonly space?: string;
|
|
130
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;
|
|
131
141
|
}
|
|
132
142
|
|
|
133
143
|
export interface MigrationListHumanRenderOptions {
|
|
134
144
|
readonly glyphMode: GlyphMode;
|
|
135
145
|
readonly useColor: boolean;
|
|
146
|
+
readonly liveContractHash: string;
|
|
147
|
+
readonly graphForSpace: (spaceId: string) => MigrationGraph | undefined;
|
|
136
148
|
}
|
|
137
149
|
|
|
138
150
|
export function renderMigrationListHumanOutput(
|
|
@@ -142,6 +154,8 @@ export function renderMigrationListHumanOutput(
|
|
|
142
154
|
const styler = createAnsiMigrationListStyler({ useColor: options.useColor });
|
|
143
155
|
return renderMigrationListWithStyle(result, styler, options.glyphMode, {
|
|
144
156
|
colorize: options.useColor,
|
|
157
|
+
liveContractHash: options.liveContractHash,
|
|
158
|
+
graphForSpace: options.graphForSpace,
|
|
145
159
|
});
|
|
146
160
|
}
|
|
147
161
|
|
|
@@ -210,7 +224,7 @@ export async function executeMigrationListCommand(
|
|
|
210
224
|
options: MigrationListOptions,
|
|
211
225
|
flags: GlobalFlags,
|
|
212
226
|
ui: TerminalUI,
|
|
213
|
-
): Promise<Result<
|
|
227
|
+
): Promise<Result<MigrationListExecuteResult, CliStructuredError>> {
|
|
214
228
|
const config = await loadConfig(options.config);
|
|
215
229
|
const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(
|
|
216
230
|
options.config,
|
|
@@ -229,6 +243,15 @@ export async function executeMigrationListCommand(
|
|
|
229
243
|
flags,
|
|
230
244
|
});
|
|
231
245
|
ui.stderr(header);
|
|
246
|
+
if (shouldShowLegend(options, flags)) {
|
|
247
|
+
ui.stderr(
|
|
248
|
+
renderMigrationGraphLegend({
|
|
249
|
+
colorize: flags.color !== false,
|
|
250
|
+
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
251
|
+
}),
|
|
252
|
+
);
|
|
253
|
+
ui.stderr('');
|
|
254
|
+
}
|
|
232
255
|
}
|
|
233
256
|
|
|
234
257
|
const loaded = await buildReadAggregate(config, { migrationsDir });
|
|
@@ -236,15 +259,18 @@ export async function executeMigrationListCommand(
|
|
|
236
259
|
return notOk(loaded.failure);
|
|
237
260
|
}
|
|
238
261
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
);
|
|
262
|
+
const { aggregate, contractHash: liveContractHash } = loaded.value;
|
|
263
|
+
|
|
264
|
+
const spaces = await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir);
|
|
243
265
|
|
|
244
|
-
|
|
266
|
+
const listResult = runMigrationList({
|
|
245
267
|
spaces,
|
|
246
268
|
...ifDefined('spaceFilter', options.space),
|
|
247
269
|
});
|
|
270
|
+
if (!listResult.ok) {
|
|
271
|
+
return listResult;
|
|
272
|
+
}
|
|
273
|
+
return ok({ list: listResult.value, liveContractHash, aggregate });
|
|
248
274
|
}
|
|
249
275
|
|
|
250
276
|
export function createMigrationListCommand(): Command {
|
|
@@ -263,6 +289,7 @@ export function createMigrationListCommand(): Command {
|
|
|
263
289
|
'prisma-next migration list',
|
|
264
290
|
'prisma-next migration list --space app',
|
|
265
291
|
'prisma-next migration list --ascii',
|
|
292
|
+
'prisma-next migration list --legend',
|
|
266
293
|
'prisma-next migration list --json',
|
|
267
294
|
]);
|
|
268
295
|
setCommandSeeAlso(command, [
|
|
@@ -275,18 +302,25 @@ export function createMigrationListCommand(): Command {
|
|
|
275
302
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
276
303
|
.option('--space <id>', 'Narrow output to a single contract space')
|
|
277
304
|
.option('--ascii', 'Use ASCII kind glyphs (pipe-friendly)')
|
|
305
|
+
.option('--legend', 'Print a key for the tree glyphs and lane colors')
|
|
278
306
|
.action(async (options: MigrationListOptions) => {
|
|
279
307
|
const flags = parseGlobalFlagsOrExit(options);
|
|
280
308
|
const ui = createTerminalUI(flags);
|
|
309
|
+
const legendValidation = validateLegendOptions(options, flags);
|
|
310
|
+
if (!legendValidation.ok) {
|
|
311
|
+
process.exit(handleResult(legendValidation, flags, ui));
|
|
312
|
+
}
|
|
281
313
|
const result = await executeMigrationListCommand(options, flags, ui);
|
|
282
|
-
const exitCode = handleResult(result, flags, ui, (
|
|
314
|
+
const exitCode = handleResult(result, flags, ui, ({ list, liveContractHash, aggregate }) => {
|
|
283
315
|
if (flags.json) {
|
|
284
|
-
ui.output(JSON.stringify(
|
|
316
|
+
ui.output(JSON.stringify(list, null, 2));
|
|
285
317
|
} else if (!flags.quiet) {
|
|
286
318
|
ui.output(
|
|
287
|
-
renderMigrationListHumanOutput(
|
|
319
|
+
renderMigrationListHumanOutput(list, {
|
|
288
320
|
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
289
321
|
useColor: ui.useColor,
|
|
322
|
+
liveContractHash,
|
|
323
|
+
graphForSpace: (spaceId) => aggregate.space(spaceId)?.graph(),
|
|
290
324
|
}),
|
|
291
325
|
);
|
|
292
326
|
}
|