@prisma-next/cli 0.12.0-dev.47 → 0.12.0-dev.49
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-CJWPvdKj.mjs → client-DC-UlBLy.mjs} +4 -4
- package/dist/{client-CJWPvdKj.mjs.map → client-DC-UlBLy.mjs.map} +1 -1
- package/dist/{command-helpers-C6lqKJG1.mjs → command-helpers-esJGBD4W.mjs} +5 -5
- package/dist/command-helpers-esJGBD4W.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.d.mts +3 -15
- 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 +9 -18
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +33 -20
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +4 -4
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-log.d.mts +5 -20
- package/dist/commands/migration-log.d.mts.map +1 -1
- 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 +17 -18
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +13 -13
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +24 -26
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +3 -2
- 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-CVQsgp3V.mjs → contract-at-errors-COZAemUl.mjs} +2 -2
- package/dist/{contract-at-errors-CVQsgp3V.mjs.map → contract-at-errors-COZAemUl.mjs.map} +1 -1
- package/dist/{contract-emit-DnUkRd-7.mjs → contract-emit-Bv46RAIO.mjs} +3 -3
- package/dist/{contract-emit-DnUkRd-7.mjs.map → contract-emit-Bv46RAIO.mjs.map} +1 -1
- package/dist/{contract-emit-Iyq5V7OU.mjs → contract-emit-DIWImLqS.mjs} +3 -3
- package/dist/{contract-emit-Iyq5V7OU.mjs.map → contract-emit-DIWImLqS.mjs.map} +1 -1
- package/dist/{contract-infer-MmQMIms7.mjs → contract-infer-DpGN9SAj.mjs} +3 -3
- package/dist/{contract-infer-MmQMIms7.mjs.map → contract-infer-DpGN9SAj.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-BSWfMkFY.mjs → contract-space-aggregate-loader-CpNVrBqW.mjs} +2 -2
- package/dist/{contract-space-aggregate-loader-BSWfMkFY.mjs.map → contract-space-aggregate-loader-CpNVrBqW.mjs.map} +1 -1
- package/dist/{db-verify-B-YOEESk.mjs → db-verify-Cq16Obsw.mjs} +4 -4
- package/dist/{db-verify-B-YOEESk.mjs.map → db-verify-Cq16Obsw.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-D6VMhw2T.mjs → framework-components-BO9VO43s.mjs} +2 -2
- package/dist/{framework-components-D6VMhw2T.mjs.map → framework-components-BO9VO43s.mjs.map} +1 -1
- package/dist/{global-flags-DG4uY5tV.d.mts → global-flags-CV5LhrFg.d.mts} +1 -1
- package/dist/{global-flags-DG4uY5tV.d.mts.map → global-flags-CV5LhrFg.d.mts.map} +1 -1
- package/dist/{init-Ceib8PNc.mjs → init-C0rjiQ9I.mjs} +4 -4
- package/dist/{init-Ceib8PNc.mjs.map → init-C0rjiQ9I.mjs.map} +1 -1
- package/dist/{inspect-live-schema-CjMZ0RkS.mjs → inspect-live-schema-CRDKTNcf.mjs} +3 -3
- package/dist/{inspect-live-schema-CjMZ0RkS.mjs.map → inspect-live-schema-CRDKTNcf.mjs.map} +1 -1
- package/dist/{migration-check-DkNcCXZC.mjs → migration-check-CCXNXMXJ.mjs} +49 -30
- package/dist/migration-check-CCXNXMXJ.mjs.map +1 -0
- package/dist/{migration-command-scaffold-CrRysYxV.mjs → migration-command-scaffold-BDd9abqW.mjs} +3 -3
- package/dist/{migration-command-scaffold-CrRysYxV.mjs.map → migration-command-scaffold-BDd9abqW.mjs.map} +1 -1
- package/dist/{migration-graph-space-render-ByJ83gxp.mjs → migration-graph-space-render-CeNXh_Wy.mjs} +13 -13
- package/dist/migration-graph-space-render-CeNXh_Wy.mjs.map +1 -0
- package/dist/{migration-list-ip7fKesI.mjs → migration-list-vJWFuXca.mjs} +17 -17
- package/dist/migration-list-vJWFuXca.mjs.map +1 -0
- package/dist/{migration-log-BX9vu5c9.mjs → migration-log-6rcHQSI4.mjs} +15 -8
- package/dist/migration-log-6rcHQSI4.mjs.map +1 -0
- package/dist/{migration-path-target-ByduK0eI.mjs → migration-path-target-UkxkgXnv.mjs} +2 -2
- package/dist/{migration-path-target-ByduK0eI.mjs.map → migration-path-target-UkxkgXnv.mjs.map} +1 -1
- package/dist/{migration-plan-DLbbc_7z.mjs → migration-plan-CHu_erQ5.mjs} +5 -5
- package/dist/{migration-plan-DLbbc_7z.mjs.map → migration-plan-CHu_erQ5.mjs.map} +1 -1
- package/dist/{migration-status-BtdaOuQJ.mjs → migration-status-DzdlZQJ3.mjs} +39 -35
- package/dist/migration-status-DzdlZQJ3.mjs.map +1 -0
- package/dist/{output-CF_hqzI-.mjs → output-BD61elic.mjs} +1 -1
- package/dist/{output-CF_hqzI-.mjs.map → output-BD61elic.mjs.map} +1 -1
- package/dist/schemas-BL33A3i-.d.mts +193 -0
- package/dist/schemas-BL33A3i-.d.mts.map +1 -0
- package/dist/schemas-DJY2O09F.mjs +112 -0
- package/dist/schemas-DJY2O09F.mjs.map +1 -0
- package/dist/{telemetry-CxbY4NKn.mjs → telemetry-CZkgkR_O.mjs} +2 -2
- package/dist/{telemetry-CxbY4NKn.mjs.map → telemetry-CZkgkR_O.mjs.map} +1 -1
- package/dist/{terminal-ui-5Y6mrg93.d.mts → terminal-ui-BgLiAOYi.d.mts} +1 -1
- package/dist/{terminal-ui-5Y6mrg93.d.mts.map → terminal-ui-BgLiAOYi.d.mts.map} +1 -1
- package/dist/{types-Cculk5KV.d.mts → types-qV41eEXH.d.mts} +1 -1
- package/dist/{types-Cculk5KV.d.mts.map → types-qV41eEXH.d.mts.map} +1 -1
- package/dist/{verify-Df-8Kwat.mjs → verify-IilvIk_E.mjs} +2 -2
- package/dist/{verify-Df-8Kwat.mjs.map → verify-IilvIk_E.mjs.map} +1 -1
- package/package.json +18 -18
- package/src/commands/json/schemas.ts +195 -0
- package/src/commands/migration-check.ts +33 -24
- package/src/commands/migration-graph.ts +34 -36
- package/src/commands/migration-list.ts +14 -14
- package/src/commands/migration-log.ts +6 -7
- package/src/commands/migration-show.ts +21 -28
- package/src/commands/migration-status.ts +69 -67
- package/src/utils/formatters/migration-list-graph-topology.ts +4 -4
- package/src/utils/formatters/migration-list-render.ts +12 -12
- package/src/utils/formatters/migration-list-types.ts +5 -21
- package/src/utils/formatters/migration-log-table.ts +12 -7
- package/src/utils/formatters/migrations.ts +8 -10
- package/src/utils/integrity-violation-to-check-failure.ts +28 -19
- package/dist/command-helpers-C6lqKJG1.mjs.map +0 -1
- package/dist/migration-check-DkNcCXZC.mjs.map +0 -1
- package/dist/migration-graph-space-render-ByJ83gxp.mjs.map +0 -1
- package/dist/migration-list-ip7fKesI.mjs.map +0 -1
- package/dist/migration-list-types-DS63IdFd.d.mts +0 -23
- package/dist/migration-list-types-DS63IdFd.d.mts.map +0 -1
- package/dist/migration-log-BX9vu5c9.mjs.map +0 -1
- package/dist/migration-status-BtdaOuQJ.mjs.map +0 -1
|
@@ -47,10 +47,7 @@ import { formatErrorJson, formatErrorOutput } from '../utils/formatters/errors';
|
|
|
47
47
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
48
48
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
49
49
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
50
|
-
import {
|
|
51
|
-
type CheckFailure,
|
|
52
|
-
integrityViolationToCheckFailure,
|
|
53
|
-
} from '../utils/integrity-violation-to-check-failure';
|
|
50
|
+
import { integrityViolationToCheckFailure } from '../utils/integrity-violation-to-check-failure';
|
|
54
51
|
import {
|
|
55
52
|
findPackageByDirPath,
|
|
56
53
|
looksLikePath,
|
|
@@ -58,6 +55,7 @@ import {
|
|
|
58
55
|
resolveTargetPathAcrossSpaces,
|
|
59
56
|
} from '../utils/migration-path-target';
|
|
60
57
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
58
|
+
import type { CheckFailure, MigrationCheckResult } from './json/schemas';
|
|
61
59
|
import { INTEGRITY_FAILED, OK, PRECONDITION } from './migration-check/exit-codes';
|
|
62
60
|
|
|
63
61
|
interface MigrationCheckOptions extends CommonCommandOptions {
|
|
@@ -65,13 +63,8 @@ interface MigrationCheckOptions extends CommonCommandOptions {
|
|
|
65
63
|
readonly space?: string;
|
|
66
64
|
}
|
|
67
65
|
|
|
68
|
-
export type { CheckFailure } from '
|
|
69
|
-
|
|
70
|
-
export interface MigrationCheckResult {
|
|
71
|
-
readonly ok: boolean;
|
|
72
|
-
readonly failures: readonly CheckFailure[];
|
|
73
|
-
readonly summary: string;
|
|
74
|
-
}
|
|
66
|
+
export type { CheckFailure, MigrationCheckResult } from './json/schemas';
|
|
67
|
+
export { migrationCheckResultSchema } from './json/schemas';
|
|
75
68
|
|
|
76
69
|
function migrationPathRelative(dirPath: string): string {
|
|
77
70
|
return relative(process.cwd(), dirPath);
|
|
@@ -81,10 +74,16 @@ function migrationFileRelative(dirPath: string, fileName: string): string {
|
|
|
81
74
|
return join(migrationPathRelative(dirPath), fileName);
|
|
82
75
|
}
|
|
83
76
|
|
|
84
|
-
function checkFileExists(
|
|
77
|
+
function checkFileExists(
|
|
78
|
+
spaceId: string,
|
|
79
|
+
dirPath: string,
|
|
80
|
+
dirName: string,
|
|
81
|
+
fileName: string,
|
|
82
|
+
): CheckFailure | null {
|
|
85
83
|
if (!existsSync(join(dirPath, fileName))) {
|
|
86
84
|
return {
|
|
87
|
-
|
|
85
|
+
space: spaceId,
|
|
86
|
+
code: 'PN-MIG-CHECK-002',
|
|
88
87
|
where: migrationFileRelative(dirPath, fileName),
|
|
89
88
|
why: `${fileName} is missing from ${dirName}`,
|
|
90
89
|
fix: 'Re-emit the migration package or restore from version control.',
|
|
@@ -93,7 +92,10 @@ function checkFileExists(dirPath: string, dirName: string, fileName: string): Ch
|
|
|
93
92
|
return null;
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
function checkSnapshotConsistency(
|
|
95
|
+
function checkSnapshotConsistency(
|
|
96
|
+
spaceId: string,
|
|
97
|
+
pkg: OnDiskMigrationPackage,
|
|
98
|
+
): CheckFailure | null {
|
|
97
99
|
const endContractPath = join(pkg.dirPath, 'end-contract.json');
|
|
98
100
|
if (!existsSync(endContractPath)) return null;
|
|
99
101
|
try {
|
|
@@ -102,7 +104,8 @@ function checkSnapshotConsistency(pkg: OnDiskMigrationPackage): CheckFailure | n
|
|
|
102
104
|
const snapshotHash = storage?.['storageHash'];
|
|
103
105
|
if (typeof snapshotHash === 'string' && snapshotHash !== pkg.metadata.to) {
|
|
104
106
|
return {
|
|
105
|
-
|
|
107
|
+
space: spaceId,
|
|
108
|
+
code: 'PN-MIG-CHECK-005',
|
|
106
109
|
where: migrationPathRelative(pkg.dirPath),
|
|
107
110
|
why: `Migration "${pkg.dirName}" declares to=${pkg.metadata.to} but end-contract.json has storageHash=${snapshotHash}`,
|
|
108
111
|
fix: 'Re-emit the migration package so migration.json and end-contract.json agree.',
|
|
@@ -110,7 +113,8 @@ function checkSnapshotConsistency(pkg: OnDiskMigrationPackage): CheckFailure | n
|
|
|
110
113
|
}
|
|
111
114
|
} catch {
|
|
112
115
|
return {
|
|
113
|
-
|
|
116
|
+
space: spaceId,
|
|
117
|
+
code: 'PN-MIG-CHECK-006',
|
|
114
118
|
where: migrationPathRelative(pkg.dirPath),
|
|
115
119
|
why: `Migration "${pkg.dirName}" has an unparseable end-contract.json.`,
|
|
116
120
|
fix: 'Re-emit the migration package to repair the snapshot file.',
|
|
@@ -189,7 +193,7 @@ function checkManifestFilesPresent(space: CheckSpace): readonly CheckFailure[] {
|
|
|
189
193
|
}
|
|
190
194
|
if (!loadedDirNames.has(entry)) {
|
|
191
195
|
for (const f of ['migration.json', 'ops.json']) {
|
|
192
|
-
const fail = checkFileExists(entryPath, entry, f);
|
|
196
|
+
const fail = checkFileExists(space.spaceId, entryPath, entry, f);
|
|
193
197
|
if (fail) failures.push(fail);
|
|
194
198
|
}
|
|
195
199
|
}
|
|
@@ -207,7 +211,8 @@ function checkReachability(space: CheckSpace): readonly CheckFailure[] {
|
|
|
207
211
|
pkg.metadata.from === 'sha256:empty';
|
|
208
212
|
if (!isReachable) {
|
|
209
213
|
failures.push({
|
|
210
|
-
|
|
214
|
+
space: space.spaceId,
|
|
215
|
+
code: 'PN-MIG-CHECK-003',
|
|
211
216
|
where: migrationPathRelative(pkg.dirPath),
|
|
212
217
|
why: `Migration "${pkg.dirName}" starts from ${pkg.metadata.from} which no other migration produces`,
|
|
213
218
|
fix: 'This migration is unreachable in the graph. Delete it or re-emit a connecting migration.',
|
|
@@ -222,7 +227,8 @@ function checkDanglingRefs(space: CheckSpace): readonly CheckFailure[] {
|
|
|
222
227
|
for (const [name, entry] of Object.entries(space.refs)) {
|
|
223
228
|
if (!space.graph.nodes.has(entry.hash)) {
|
|
224
229
|
failures.push({
|
|
225
|
-
|
|
230
|
+
space: space.spaceId,
|
|
231
|
+
code: 'PN-MIG-CHECK-004',
|
|
226
232
|
where: relative(process.cwd(), join(space.refsDir, `${name}.json`)),
|
|
227
233
|
why: `Ref "${name}" points at ${entry.hash} which does not exist in the migration graph`,
|
|
228
234
|
fix: `Update the ref with \`prisma-next ref set ${name} <valid-hash>\` or delete it.`,
|
|
@@ -235,7 +241,9 @@ function checkDanglingRefs(space: CheckSpace): readonly CheckFailure[] {
|
|
|
235
241
|
function checkSpace(space: CheckSpace): readonly CheckFailure[] {
|
|
236
242
|
return [
|
|
237
243
|
...checkManifestFilesPresent(space),
|
|
238
|
-
...space.packages
|
|
244
|
+
...space.packages
|
|
245
|
+
.map((pkg) => checkSnapshotConsistency(space.spaceId, pkg))
|
|
246
|
+
.filter((f): f is CheckFailure => f !== null),
|
|
239
247
|
...checkReachability(space),
|
|
240
248
|
...checkDanglingRefs(space),
|
|
241
249
|
];
|
|
@@ -535,21 +543,22 @@ async function checkSingleTarget(
|
|
|
535
543
|
const failures: CheckFailure[] = [...checkManifestFilesPresent(matchedSpace)];
|
|
536
544
|
|
|
537
545
|
for (const f of ['migration.json', 'ops.json']) {
|
|
538
|
-
const fail = checkFileExists(matchedPkg.dirPath, matchedPkg.dirName, f);
|
|
546
|
+
const fail = checkFileExists(matchedSpace.spaceId, matchedPkg.dirPath, matchedPkg.dirName, f);
|
|
539
547
|
if (fail) failures.push(fail);
|
|
540
548
|
}
|
|
541
549
|
|
|
542
550
|
const verification = verifyMigrationHash(matchedPkg);
|
|
543
551
|
if (!verification.ok) {
|
|
544
552
|
failures.push({
|
|
545
|
-
|
|
553
|
+
space: matchedSpace.spaceId,
|
|
554
|
+
code: 'PN-MIG-CHECK-001',
|
|
546
555
|
where: migrationFileRelative(matchedPkg.dirPath, 'migration.json'),
|
|
547
556
|
why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,
|
|
548
557
|
fix: 'Re-emit the migration package or restore from version control.',
|
|
549
558
|
});
|
|
550
559
|
}
|
|
551
560
|
|
|
552
|
-
const snapshotFailure = checkSnapshotConsistency(matchedPkg);
|
|
561
|
+
const snapshotFailure = checkSnapshotConsistency(matchedSpace.spaceId, matchedPkg);
|
|
553
562
|
if (snapshotFailure) failures.push(snapshotFailure);
|
|
554
563
|
|
|
555
564
|
const resolvedSpaceId = matchedSpace.spaceId !== 'app' ? matchedSpace.spaceId : undefined;
|
|
@@ -641,7 +650,7 @@ export function createMigrationCheckCommand(): Command {
|
|
|
641
650
|
ui.log(`✔ ${result.summary}${spaceSuffix}`);
|
|
642
651
|
} else {
|
|
643
652
|
for (const f of result.failures) {
|
|
644
|
-
ui.log(`✗ [${f.
|
|
653
|
+
ui.log(`✗ [${f.code}] ${f.where}: ${f.why}`);
|
|
645
654
|
ui.log(` fix: ${f.fix}`);
|
|
646
655
|
}
|
|
647
656
|
ui.log(`\n${result.summary}`);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
1
2
|
import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
2
3
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
3
4
|
import { ok, type Result } from '@prisma-next/utils/result';
|
|
@@ -25,6 +26,7 @@ import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags'
|
|
|
25
26
|
import { shouldShowLegend, validateLegendOptions } from '../utils/legend';
|
|
26
27
|
import { handleResult } from '../utils/result-handler';
|
|
27
28
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
29
|
+
import type { MigrationGraphJsonResult, MigrationSpaceGraphEntry } from './json/schemas';
|
|
28
30
|
import {
|
|
29
31
|
listRefsByContractHash,
|
|
30
32
|
migrationSpaceListEntriesFromAggregate,
|
|
@@ -40,42 +42,32 @@ interface MigrationGraphOptions extends CommonCommandOptions {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
export interface MigrationGraphTreeSection {
|
|
43
|
-
readonly
|
|
45
|
+
readonly space: string;
|
|
44
46
|
readonly tree: string;
|
|
45
47
|
readonly showHeading: boolean;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
export interface MigrationGraphResult {
|
|
49
51
|
readonly ok: true;
|
|
50
|
-
/** App-space graph for
|
|
52
|
+
/** App-space graph for the `--dot` Graphviz output. */
|
|
51
53
|
readonly graph: MigrationGraph;
|
|
54
|
+
/** Nested per-space contracts + migrations for `--json`. */
|
|
55
|
+
readonly spaces: readonly MigrationSpaceGraphEntry[];
|
|
52
56
|
readonly treeSections: readonly MigrationGraphTreeSection[];
|
|
53
57
|
readonly summary: string;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
readonly migrationHash: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface MigrationGraphJsonResult {
|
|
64
|
-
readonly ok: true;
|
|
65
|
-
readonly nodes: readonly string[];
|
|
66
|
-
readonly edges: readonly MigrationGraphJsonEdge[];
|
|
67
|
-
readonly summary: string;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function computeGraphSummary(graph: MigrationGraph): string {
|
|
71
|
-
return `${graph.nodes.size} node(s), ${graph.migrationByHash.size} edge(s)`;
|
|
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)`;
|
|
72
64
|
}
|
|
73
65
|
|
|
74
66
|
export function formatMigrationGraphHumanOutput(result: MigrationGraphResult): string {
|
|
75
67
|
const sections: string[] = [];
|
|
76
68
|
for (const section of result.treeSections) {
|
|
77
69
|
if (section.showHeading) {
|
|
78
|
-
sections.push(`${section.
|
|
70
|
+
sections.push(`${section.space}:`);
|
|
79
71
|
}
|
|
80
72
|
if (section.tree.length > 0) {
|
|
81
73
|
sections.push(section.tree);
|
|
@@ -148,7 +140,7 @@ export async function executeMigrationGraphCommand(
|
|
|
148
140
|
? scopedSpaces
|
|
149
141
|
.filter((spaceEntry) => spaceEntry.migrations.length > 0)
|
|
150
142
|
.map((spaceEntry) => ({
|
|
151
|
-
graph: aggregate.space(spaceEntry.
|
|
143
|
+
graph: aggregate.space(spaceEntry.space)!.graph(),
|
|
152
144
|
liveContractHash,
|
|
153
145
|
}))
|
|
154
146
|
: [];
|
|
@@ -160,12 +152,14 @@ export async function executeMigrationGraphCommand(
|
|
|
160
152
|
globalLayoutInputs.length > 0 ? computeGlobalMaxDirNameWidth(globalLayoutInputs) : undefined;
|
|
161
153
|
|
|
162
154
|
const treeSections: MigrationGraphTreeSection[] = [];
|
|
155
|
+
const spaces: MigrationSpaceGraphEntry[] = [];
|
|
163
156
|
for (const spaceEntry of scopedSpaces) {
|
|
164
|
-
const member = aggregate.space(spaceEntry.
|
|
157
|
+
const member = aggregate.space(spaceEntry.space);
|
|
165
158
|
if (member === undefined) {
|
|
166
159
|
continue;
|
|
167
160
|
}
|
|
168
161
|
const graph = member.graph();
|
|
162
|
+
const refsByHash = listRefsByContractHash(member);
|
|
169
163
|
const tree =
|
|
170
164
|
spaceEntry.migrations.length === 0
|
|
171
165
|
? ''
|
|
@@ -175,24 +169,38 @@ export async function executeMigrationGraphCommand(
|
|
|
175
169
|
liveContractHash,
|
|
176
170
|
glyphMode,
|
|
177
171
|
colorize,
|
|
178
|
-
refsByHash
|
|
172
|
+
refsByHash,
|
|
179
173
|
...(globalMaxEdgeTreePrefixWidth !== undefined ? { globalMaxEdgeTreePrefixWidth } : {}),
|
|
180
174
|
...(globalMaxDirNameWidth !== undefined ? { globalMaxDirNameWidth } : {}),
|
|
181
175
|
});
|
|
182
176
|
const displayTree =
|
|
183
177
|
showSpaceHeadings && tree.length > 0 ? indentMigrationGraphTreeBlock(tree, ' ') : tree;
|
|
184
178
|
treeSections.push({
|
|
185
|
-
|
|
179
|
+
space: spaceEntry.space,
|
|
186
180
|
tree: displayTree,
|
|
187
181
|
showHeading: showSpaceHeadings,
|
|
188
182
|
});
|
|
183
|
+
spaces.push({
|
|
184
|
+
space: spaceEntry.space,
|
|
185
|
+
contracts: [...graph.nodes].map((hash) => ({
|
|
186
|
+
hash,
|
|
187
|
+
refs: [...(refsByHash.get(hash) ?? [])],
|
|
188
|
+
})),
|
|
189
|
+
migrations: [...graph.migrationByHash.values()].map((edge) => ({
|
|
190
|
+
name: edge.dirName,
|
|
191
|
+
hash: edge.migrationHash,
|
|
192
|
+
fromContract: edge.from === EMPTY_CONTRACT_HASH ? null : edge.from,
|
|
193
|
+
toContract: edge.to,
|
|
194
|
+
})),
|
|
195
|
+
});
|
|
189
196
|
}
|
|
190
197
|
|
|
191
198
|
return ok({
|
|
192
199
|
ok: true,
|
|
193
200
|
graph: appGraph,
|
|
201
|
+
spaces,
|
|
194
202
|
treeSections,
|
|
195
|
-
summary: computeGraphSummary(
|
|
203
|
+
summary: computeGraphSummary(spaces),
|
|
196
204
|
});
|
|
197
205
|
}
|
|
198
206
|
|
|
@@ -246,20 +254,10 @@ export function createMigrationGraphCommand(): Command {
|
|
|
246
254
|
lines.push('}');
|
|
247
255
|
ui.output(lines.join('\n'));
|
|
248
256
|
} else if (flags.json) {
|
|
249
|
-
const nodes = [...graphResult.graph.nodes];
|
|
250
|
-
const edges = [...graphResult.graph.migrationByHash.values()].map(
|
|
251
|
-
(e): MigrationGraphJsonEdge => ({
|
|
252
|
-
dirName: e.dirName,
|
|
253
|
-
from: e.from,
|
|
254
|
-
to: e.to,
|
|
255
|
-
migrationHash: e.migrationHash,
|
|
256
|
-
}),
|
|
257
|
-
);
|
|
258
257
|
const jsonResult: MigrationGraphJsonResult = {
|
|
259
258
|
ok: true,
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
summary: `${graphResult.graph.nodes.size} node(s), ${graphResult.graph.migrationByHash.size} edge(s)`,
|
|
259
|
+
spaces: [...graphResult.spaces],
|
|
260
|
+
summary: graphResult.summary,
|
|
263
261
|
};
|
|
264
262
|
ui.output(JSON.stringify(jsonResult, null, 2));
|
|
265
263
|
} else if (!flags.quiet) {
|
|
@@ -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
|
|
|
@@ -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;
|
|
@@ -198,19 +198,19 @@ export function runMigrationList(
|
|
|
198
198
|
return notOk(errorInvalidSpaceId(spaceFilter));
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
if (spaceFilter !== undefined && !spaces.some((s) => s.
|
|
202
|
-
return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.
|
|
201
|
+
if (spaceFilter !== undefined && !spaces.some((s) => s.space === spaceFilter)) {
|
|
202
|
+
return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.space).sort()));
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
const scopedSpaces =
|
|
206
|
-
spaceFilter !== undefined ? spaces.filter((s) => s.
|
|
206
|
+
spaceFilter !== undefined ? spaces.filter((s) => s.space === spaceFilter) : spaces;
|
|
207
207
|
|
|
208
208
|
const resultSpaces: readonly MigrationSpaceListEntry[] =
|
|
209
|
-
scopedSpaces.length === 0 ? [{
|
|
209
|
+
scopedSpaces.length === 0 ? [{ space: APP_SPACE_ID, migrations: [] }] : scopedSpaces;
|
|
210
210
|
|
|
211
211
|
return ok({
|
|
212
212
|
ok: true,
|
|
213
|
-
spaces: resultSpaces,
|
|
213
|
+
spaces: [...resultSpaces],
|
|
214
214
|
summary: computeSummary(resultSpaces),
|
|
215
215
|
});
|
|
216
216
|
}
|
|
@@ -24,7 +24,6 @@ import { createAnsiMigrationListStyler } from '../utils/formatters/migration-lis
|
|
|
24
24
|
import {
|
|
25
25
|
MIGRATION_LOG_EMPTY_MESSAGE,
|
|
26
26
|
renderMigrationLogTable,
|
|
27
|
-
type SerializedLedgerEntryRecord,
|
|
28
27
|
serializeLedgerEntriesForJson,
|
|
29
28
|
} from '../utils/formatters/migration-log-table';
|
|
30
29
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
@@ -32,6 +31,9 @@ import type { CommonCommandOptions } from '../utils/global-flags';
|
|
|
32
31
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
33
32
|
import { handleResult } from '../utils/result-handler';
|
|
34
33
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
34
|
+
import type { MigrationLogResult } from './json/schemas';
|
|
35
|
+
|
|
36
|
+
export type { MigrationLogResult };
|
|
35
37
|
|
|
36
38
|
interface MigrationLogOptions extends CommonCommandOptions {
|
|
37
39
|
readonly db?: string;
|
|
@@ -40,11 +42,6 @@ interface MigrationLogOptions extends CommonCommandOptions {
|
|
|
40
42
|
readonly ascii?: boolean;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
export interface MigrationLogResult {
|
|
44
|
-
readonly ok: true;
|
|
45
|
-
readonly entries: readonly SerializedLedgerEntryRecord[];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
45
|
export async function executeMigrationLogCommand(
|
|
49
46
|
options: MigrationLogOptions,
|
|
50
47
|
flags: GlobalFlags,
|
|
@@ -138,9 +135,11 @@ export function createMigrationLogCommand(): Command {
|
|
|
138
135
|
const result = await executeMigrationLogCommand(options, flags, ui);
|
|
139
136
|
const exitCode = handleResult(result, flags, ui, (entries) => {
|
|
140
137
|
if (flags.json) {
|
|
138
|
+
const records = serializeLedgerEntriesForJson(entries);
|
|
141
139
|
const result: MigrationLogResult = {
|
|
142
140
|
ok: true,
|
|
143
|
-
|
|
141
|
+
records,
|
|
142
|
+
summary: `${records.length} migration(s) applied`,
|
|
144
143
|
};
|
|
145
144
|
ui.output(JSON.stringify(result, null, 2));
|
|
146
145
|
} else if (!flags.quiet) {
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
APP_SPACE_ID,
|
|
5
5
|
createControlStack,
|
|
6
6
|
type MigrationPlanOperation,
|
|
7
|
-
type OperationPreview,
|
|
8
7
|
} from '@prisma-next/framework-components/control';
|
|
9
8
|
import { loadContractSpaceAggregate } from '@prisma-next/migration-tools/aggregate';
|
|
10
9
|
import type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';
|
|
@@ -43,32 +42,26 @@ import {
|
|
|
43
42
|
} from '../utils/migration-path-target';
|
|
44
43
|
import { handleResult } from '../utils/result-handler';
|
|
45
44
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
45
|
+
import type { MigrationShowResult } from './json/schemas';
|
|
46
46
|
|
|
47
47
|
interface MigrationShowOptions extends CommonCommandOptions {
|
|
48
48
|
readonly config?: string;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export interface MigrationShowPresent {
|
|
52
|
-
readonly
|
|
53
|
-
readonly
|
|
54
|
-
readonly
|
|
55
|
-
readonly
|
|
56
|
-
readonly
|
|
57
|
-
readonly migrationHash: string;
|
|
52
|
+
readonly space: string;
|
|
53
|
+
readonly name: string;
|
|
54
|
+
readonly fromContract: string | null;
|
|
55
|
+
readonly toContract: string;
|
|
56
|
+
readonly hash: string;
|
|
58
57
|
readonly createdAt: string;
|
|
59
|
-
readonly operations:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}[];
|
|
64
|
-
readonly preview: OperationPreview;
|
|
65
|
-
readonly summary: string;
|
|
58
|
+
readonly operations: { id: string; label: string; operationClass: string }[];
|
|
59
|
+
readonly preview: {
|
|
60
|
+
statements: { text: string; language: string }[];
|
|
61
|
+
};
|
|
66
62
|
}
|
|
67
63
|
|
|
68
|
-
export
|
|
69
|
-
readonly ok: true;
|
|
70
|
-
readonly migration: MigrationShowPresent;
|
|
71
|
-
}
|
|
64
|
+
export type { MigrationShowResult };
|
|
72
65
|
|
|
73
66
|
function pkgToPresent(
|
|
74
67
|
spaceId: string,
|
|
@@ -76,22 +69,20 @@ function pkgToPresent(
|
|
|
76
69
|
client: ReturnType<typeof createControlClient>,
|
|
77
70
|
): MigrationShowPresent {
|
|
78
71
|
const ops = castAs<readonly MigrationPlanOperation[]>(pkg.ops);
|
|
79
|
-
const
|
|
72
|
+
const rawPreview = client.toOperationPreview(ops) ?? { statements: [] };
|
|
80
73
|
return {
|
|
81
|
-
spaceId,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
migrationHash: pkg.metadata.migrationHash,
|
|
74
|
+
space: spaceId,
|
|
75
|
+
name: pkg.dirName,
|
|
76
|
+
fromContract: pkg.metadata.from,
|
|
77
|
+
toContract: pkg.metadata.to,
|
|
78
|
+
hash: pkg.metadata.migrationHash,
|
|
87
79
|
createdAt: pkg.metadata.createdAt,
|
|
88
80
|
operations: ops.map((op) => ({
|
|
89
81
|
id: op.id,
|
|
90
82
|
label: op.label,
|
|
91
83
|
operationClass: op.operationClass,
|
|
92
84
|
})),
|
|
93
|
-
preview,
|
|
94
|
-
summary: `${ops.length} operation(s)`,
|
|
85
|
+
preview: { statements: [...rawPreview.statements] },
|
|
95
86
|
};
|
|
96
87
|
}
|
|
97
88
|
|
|
@@ -218,9 +209,11 @@ async function executeMigrationShowCommand(
|
|
|
218
209
|
appPkg = matchedPkg;
|
|
219
210
|
}
|
|
220
211
|
|
|
212
|
+
const migration = pkgToPresent(APP_SPACE_ID, appPkg, client);
|
|
221
213
|
return ok({
|
|
222
214
|
ok: true,
|
|
223
|
-
migration:
|
|
215
|
+
summary: `Migration ${migration.name} in ${migration.space}: ${migration.operations.length} operation(s)`,
|
|
216
|
+
migration,
|
|
224
217
|
});
|
|
225
218
|
}
|
|
226
219
|
|