@prisma-next/cli 0.12.0-dev.4 → 0.12.0-dev.40
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-BNdG504y.mjs} +80 -56
- package/dist/client-BNdG504y.mjs.map +1 -0
- package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-xvg9oq4T.mjs} +301 -23
- package/dist/command-helpers-xvg9oq4T.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 +4 -5
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- 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.mjs +1 -1
- package/dist/commands/migrate.d.mts +2 -2
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +6 -8
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +55 -1
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +2 -2
- package/dist/commands/migration-graph.d.mts +25 -7
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +170 -2
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +24 -26
- 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 +20 -15
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -137
- 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 -4
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +13 -25
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +41 -141
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -759
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +3 -3
- 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/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-Wj3u4Xco.mjs} +2 -2
- package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-Wj3u4Xco.mjs.map} +1 -1
- package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-COg18szA.mjs} +3 -3
- package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-COg18szA.mjs.map} +1 -1
- package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-KyJNQK5-.mjs} +3 -3
- package/dist/{contract-emit-D-4jrNve.mjs.map → contract-emit-KyJNQK5-.mjs.map} +1 -1
- package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-IEp0227u.mjs} +3 -3
- package/dist/{contract-infer-D8uEbJuu.mjs.map → contract-infer-IEp0227u.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-BdRPfM3Q.mjs} +63 -5
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-BdRPfM3Q.mjs.map} +1 -1
- package/dist/{db-verify-v_vUKXTU.mjs → db-verify-C9k5KAyI.mjs} +4 -4
- package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-C9k5KAyI.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +2 -2
- package/dist/exports/control-api.d.mts.map +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-fYXjz_in.mjs → framework-components-Be4inY3I.mjs} +2 -2
- package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-Be4inY3I.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-Cv9UzWL5.mjs → init-BIxw3l7t.mjs} +5 -58
- package/dist/init-BIxw3l7t.mjs.map +1 -0
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-DXUFGQDe.mjs} +3 -3
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs.map → inspect-live-schema-DXUFGQDe.mjs.map} +1 -1
- package/dist/{migration-check-BiBJoYYW.mjs → migration-check-CUavU7U9.mjs} +236 -88
- package/dist/migration-check-CUavU7U9.mjs.map +1 -0
- package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-omgKpt3K.mjs} +3 -3
- package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-omgKpt3K.mjs.map} +1 -1
- package/dist/migration-graph-space-render-ByJ83gxp.mjs +1966 -0
- package/dist/migration-graph-space-render-ByJ83gxp.mjs.map +1 -0
- package/dist/migration-list-jK6QeczE.mjs +228 -0
- package/dist/migration-list-jK6QeczE.mjs.map +1 -0
- package/dist/migration-list-types-DS63IdFd.d.mts +23 -0
- package/dist/migration-list-types-DS63IdFd.d.mts.map +1 -0
- package/dist/migration-log-CW0EjxSr.mjs +215 -0
- package/dist/migration-log-CW0EjxSr.mjs.map +1 -0
- package/dist/migration-path-target-DqcrbOis.mjs +24 -0
- package/dist/migration-path-target-DqcrbOis.mjs.map +1 -0
- package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-NHdlUwPG.mjs} +5 -6
- package/dist/{migration-plan-9DJ7q7_z.mjs.map → migration-plan-NHdlUwPG.mjs.map} +1 -1
- package/dist/migration-status-GZ6XfbWs.mjs +439 -0
- package/dist/migration-status-GZ6XfbWs.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/{ref-advancement-DUZqsue6.mjs → ref-advancement-CJY9zOv7.mjs} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-CJY9zOv7.mjs.map} +1 -1
- package/dist/telemetry-DQP0BvKv.mjs +122 -0
- package/dist/telemetry-DQP0BvKv.mjs.map +1 -0
- package/dist/{types-Dt_SfqFm.d.mts → types-Cculk5KV.d.mts} +44 -31
- package/dist/types-Cculk5KV.d.mts.map +1 -0
- package/dist/{verify-DCA9Sldu.mjs → verify-tvHRBBVP.mjs} +2 -2
- package/dist/{verify-DCA9Sldu.mjs.map → verify-tvHRBBVP.mjs.map} +1 -1
- package/package.json +22 -19
- package/src/cli.ts +5 -0
- 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/migrate.ts +6 -6
- package/src/commands/migration-check.ts +340 -117
- package/src/commands/migration-graph.ts +163 -90
- package/src/commands/migration-list.ts +55 -25
- package/src/commands/migration-log.ts +49 -98
- package/src/commands/migration-show.ts +10 -38
- package/src/commands/migration-status-overlay.ts +61 -0
- package/src/commands/migration-status.ts +440 -1056
- package/src/commands/telemetry/index.ts +107 -0
- package/src/commands/telemetry/status.ts +67 -0
- package/src/control-api/client.ts +17 -7
- package/src/control-api/operations/db-init.ts +3 -3
- package/src/control-api/operations/{db-apply.ts → db-run.ts} +37 -10
- package/src/control-api/operations/db-update.ts +4 -4
- package/src/control-api/operations/{migration-apply.ts → migrate.ts} +32 -24
- package/src/control-api/operations/{apply.ts → run-migration.ts} +33 -27
- package/src/control-api/types.ts +46 -29
- package/src/utils/cli-errors.ts +47 -2
- package/src/utils/formatters/errors.ts +11 -0
- package/src/utils/formatters/migration-graph-lane-colors.ts +194 -0
- package/src/utils/formatters/migration-graph-layout.ts +51 -7
- 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 +405 -77
- package/src/utils/formatters/migration-list-data-column.ts +4 -91
- package/src/utils/formatters/migration-list-graph-topology.ts +68 -90
- package/src/utils/formatters/migration-list-render.ts +122 -70
- package/src/utils/formatters/migration-list-styler.ts +48 -5
- package/src/utils/formatters/migration-log-table.ts +200 -0
- package/src/utils/formatters/migrations.ts +25 -1
- package/src/utils/global-flags.ts +35 -0
- package/src/utils/legend.ts +38 -0
- package/src/utils/migration-path-target.ts +39 -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/extension-pack-inputs-IDvjRCi3.mjs +0 -62
- package/dist/extension-pack-inputs-IDvjRCi3.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/migration-check-BiBJoYYW.mjs.map +0 -1
- package/dist/migration-graph-D7DVUElV.mjs +0 -1232
- package/dist/migration-graph-D7DVUElV.mjs.map +0 -1
- package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
- package/dist/migration-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/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
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
1
|
+
import type { LedgerEntryRecord } from '@prisma-next/contract/types';
|
|
3
2
|
import { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
4
|
-
import {
|
|
3
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
5
4
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
6
|
-
import { cyan, dim } from 'colorette';
|
|
7
5
|
import { Command } from 'commander';
|
|
8
6
|
import { loadConfig } from '../config-loader';
|
|
9
7
|
import { createControlClient } from '../control-api/client';
|
|
10
8
|
import {
|
|
11
9
|
CliStructuredError,
|
|
12
|
-
errorDatabaseConnectionRequired,
|
|
13
|
-
errorDriverRequired,
|
|
14
10
|
errorUnexpected,
|
|
15
11
|
mapMigrationToolsError,
|
|
12
|
+
requireLiveDatabase,
|
|
16
13
|
} from '../utils/cli-errors';
|
|
17
14
|
import {
|
|
18
15
|
addGlobalOptions,
|
|
@@ -23,7 +20,13 @@ import {
|
|
|
23
20
|
setCommandSeeAlso,
|
|
24
21
|
targetSupportsMigrations,
|
|
25
22
|
} from '../utils/command-helpers';
|
|
26
|
-
import {
|
|
23
|
+
import { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';
|
|
24
|
+
import {
|
|
25
|
+
MIGRATION_LOG_EMPTY_MESSAGE,
|
|
26
|
+
renderMigrationLogTable,
|
|
27
|
+
type SerializedLedgerEntryRecord,
|
|
28
|
+
serializeLedgerEntriesForJson,
|
|
29
|
+
} from '../utils/formatters/migration-log-table';
|
|
27
30
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
28
31
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
29
32
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
@@ -33,46 +36,32 @@ import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
|
33
36
|
interface MigrationLogOptions extends CommonCommandOptions {
|
|
34
37
|
readonly db?: string;
|
|
35
38
|
readonly config?: string;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
export interface MigrationLogEntry {
|
|
39
|
-
readonly dirName: string;
|
|
40
|
-
readonly from: string;
|
|
41
|
-
readonly to: string;
|
|
42
|
-
readonly migrationHash: string;
|
|
43
|
-
readonly operationCount: number;
|
|
44
|
-
readonly createdAt: string;
|
|
39
|
+
readonly utc?: boolean;
|
|
40
|
+
readonly ascii?: boolean;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
export interface MigrationLogResult {
|
|
48
44
|
readonly ok: true;
|
|
49
|
-
readonly
|
|
50
|
-
readonly applied: readonly MigrationLogEntry[];
|
|
51
|
-
readonly summary: string;
|
|
45
|
+
readonly entries: readonly SerializedLedgerEntryRecord[];
|
|
52
46
|
}
|
|
53
47
|
|
|
54
48
|
export async function executeMigrationLogCommand(
|
|
55
49
|
options: MigrationLogOptions,
|
|
56
50
|
flags: GlobalFlags,
|
|
57
51
|
ui: TerminalUI,
|
|
58
|
-
): Promise<Result<
|
|
52
|
+
): Promise<Result<readonly LedgerEntryRecord[], CliStructuredError>> {
|
|
59
53
|
const config = await loadConfig(options.config);
|
|
60
|
-
const { configPath
|
|
61
|
-
options.config,
|
|
62
|
-
config,
|
|
63
|
-
);
|
|
54
|
+
const { configPath } = resolveMigrationPaths(options.config, config);
|
|
64
55
|
|
|
65
56
|
const dbConnection = options.db ?? config.db?.connection;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (!config.driver) {
|
|
75
|
-
return notOk(errorDriverRequired({ why: 'Config.driver is required for migration log' }));
|
|
57
|
+
const missingDb = requireLiveDatabase({
|
|
58
|
+
dbConnection,
|
|
59
|
+
hasDriver: !!config.driver,
|
|
60
|
+
why: `migration log needs a database connection and driver to read the ledger (set db.connection in ${configPath}, or pass --db <url>)`,
|
|
61
|
+
commandName: 'migration log',
|
|
62
|
+
});
|
|
63
|
+
if (missingDb) {
|
|
64
|
+
return notOk(missingDb);
|
|
76
65
|
}
|
|
77
66
|
if (!targetSupportsMigrations(config.target)) {
|
|
78
67
|
return notOk(errorUnexpected('Target does not support migrations'));
|
|
@@ -81,10 +70,9 @@ export async function executeMigrationLogCommand(
|
|
|
81
70
|
if (!flags.json && !flags.quiet) {
|
|
82
71
|
const header = formatStyledHeader({
|
|
83
72
|
command: 'migration log',
|
|
84
|
-
description: 'Show executed migration history',
|
|
73
|
+
description: 'Show executed migration history from the database ledger',
|
|
85
74
|
details: [
|
|
86
75
|
{ label: 'config', value: configPath },
|
|
87
|
-
{ label: 'migrations', value: appMigrationsRelative },
|
|
88
76
|
...(typeof dbConnection === 'string'
|
|
89
77
|
? [{ label: 'database', value: maskConnectionUrl(dbConnection) }]
|
|
90
78
|
: []),
|
|
@@ -94,64 +82,18 @@ export async function executeMigrationLogCommand(
|
|
|
94
82
|
ui.stderr(header);
|
|
95
83
|
}
|
|
96
84
|
|
|
97
|
-
const loaded = await buildReadAggregate(config, { migrationsDir });
|
|
98
|
-
if (!loaded.ok) {
|
|
99
|
-
return loaded;
|
|
100
|
-
}
|
|
101
|
-
const graph = loaded.value.aggregate.app.graph();
|
|
102
|
-
const bundles = loaded.value.aggregate.app.packages;
|
|
103
|
-
|
|
104
85
|
const client = createControlClient({
|
|
105
86
|
family: config.family,
|
|
106
87
|
target: config.target,
|
|
107
88
|
adapter: config.adapter,
|
|
108
|
-
driver
|
|
89
|
+
...ifDefined('driver', config.driver),
|
|
109
90
|
extensionPacks: config.extensionPacks ?? [],
|
|
110
91
|
});
|
|
111
92
|
|
|
112
93
|
try {
|
|
113
94
|
await client.connect(dbConnection);
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (!markerHash) {
|
|
118
|
-
return ok({
|
|
119
|
-
ok: true,
|
|
120
|
-
markerHash: null,
|
|
121
|
-
applied: [],
|
|
122
|
-
summary: 'No migrations applied (database has no marker)',
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const appliedPath = findPath(graph, EMPTY_CONTRACT_HASH, markerHash);
|
|
127
|
-
if (appliedPath === null) {
|
|
128
|
-
return notOk(
|
|
129
|
-
errorUnexpected('Database marker is not reachable from migration history', {
|
|
130
|
-
why: `Marker hash ${markerHash} is not reachable from the root of the on-disk migration graph.`,
|
|
131
|
-
fix: 'The database may have been migrated outside this project. Use `migration status` to inspect the current state.',
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
const pkgByDirName = new Map(bundles.map((p) => [p.dirName, p]));
|
|
136
|
-
const entries: MigrationLogEntry[] = appliedPath.map((edge) => {
|
|
137
|
-
const pkg = pkgByDirName.get(edge.dirName);
|
|
138
|
-
const ops = (pkg?.ops ?? []) as readonly MigrationPlanOperation[];
|
|
139
|
-
return {
|
|
140
|
-
dirName: edge.dirName,
|
|
141
|
-
from: edge.from,
|
|
142
|
-
to: edge.to,
|
|
143
|
-
migrationHash: edge.migrationHash,
|
|
144
|
-
operationCount: ops.length,
|
|
145
|
-
createdAt: edge.createdAt,
|
|
146
|
-
};
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
return ok({
|
|
150
|
-
ok: true,
|
|
151
|
-
markerHash,
|
|
152
|
-
applied: entries,
|
|
153
|
-
summary: `${entries.length} migration(s) applied`,
|
|
154
|
-
});
|
|
95
|
+
const ledger = await client.readLedger();
|
|
96
|
+
return ok(ledger);
|
|
155
97
|
} catch (error) {
|
|
156
98
|
if (CliStructuredError.is(error)) return notOk(error);
|
|
157
99
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
@@ -170,11 +112,13 @@ export function createMigrationLogCommand(): Command {
|
|
|
170
112
|
setCommandDescriptions(
|
|
171
113
|
command,
|
|
172
114
|
'Show executed migration history',
|
|
173
|
-
'Reads the database
|
|
174
|
-
'
|
|
115
|
+
'Reads the database ledger and displays every applied migration edge\n' +
|
|
116
|
+
'in chronological order, including rollbacks and re-applies, merged\n' +
|
|
117
|
+
'across all contract spaces. Requires a database connection.',
|
|
175
118
|
);
|
|
176
119
|
setCommandExamples(command, [
|
|
177
120
|
'prisma-next migration log --db $DATABASE_URL',
|
|
121
|
+
'prisma-next migration log --utc --db $DATABASE_URL',
|
|
178
122
|
'prisma-next migration log --json --db $DATABASE_URL',
|
|
179
123
|
]);
|
|
180
124
|
setCommandSeeAlso(command, [
|
|
@@ -186,24 +130,31 @@ export function createMigrationLogCommand(): Command {
|
|
|
186
130
|
addGlobalOptions(command)
|
|
187
131
|
.option('--db <url>', 'Database connection string')
|
|
188
132
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
133
|
+
.option('--utc', 'Render human timestamps in UTC instead of local time')
|
|
134
|
+
.option('--ascii', 'Use ASCII glyphs (pipe-friendly)')
|
|
189
135
|
.action(async (options: MigrationLogOptions) => {
|
|
190
136
|
const flags = parseGlobalFlagsOrExit(options);
|
|
191
137
|
const ui = createTerminalUI(flags);
|
|
192
138
|
const result = await executeMigrationLogCommand(options, flags, ui);
|
|
193
|
-
const exitCode = handleResult(result, flags, ui, (
|
|
139
|
+
const exitCode = handleResult(result, flags, ui, (entries) => {
|
|
194
140
|
if (flags.json) {
|
|
195
|
-
|
|
141
|
+
const result: MigrationLogResult = {
|
|
142
|
+
ok: true,
|
|
143
|
+
entries: serializeLedgerEntriesForJson(entries),
|
|
144
|
+
};
|
|
145
|
+
ui.output(JSON.stringify(result, null, 2));
|
|
196
146
|
} else if (!flags.quiet) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
ui.log(logResult.summary);
|
|
147
|
+
if (entries.length === 0) {
|
|
148
|
+
ui.output(MIGRATION_LOG_EMPTY_MESSAGE);
|
|
200
149
|
} else {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
150
|
+
const styler = createAnsiMigrationListStyler({ useColor: ui.useColor });
|
|
151
|
+
ui.output(
|
|
152
|
+
renderMigrationLogTable(entries, {
|
|
153
|
+
utc: options.utc === true,
|
|
154
|
+
styler,
|
|
155
|
+
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
156
|
+
}),
|
|
157
|
+
);
|
|
207
158
|
}
|
|
208
159
|
}
|
|
209
160
|
});
|
|
@@ -13,7 +13,7 @@ import { castAs } from '@prisma-next/utils/casts';
|
|
|
13
13
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
14
14
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
15
15
|
import { Command } from 'commander';
|
|
16
|
-
import {
|
|
16
|
+
import { relative } from 'pathe';
|
|
17
17
|
import { loadConfig } from '../config-loader';
|
|
18
18
|
import { createControlClient } from '../control-api/client';
|
|
19
19
|
import {
|
|
@@ -36,6 +36,11 @@ import { formatMigrationShowOutput } from '../utils/formatters/migrations';
|
|
|
36
36
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
37
37
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
38
38
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
39
|
+
import {
|
|
40
|
+
findPackageByDirPath,
|
|
41
|
+
looksLikePath,
|
|
42
|
+
resolveAppTargetPath,
|
|
43
|
+
} from '../utils/migration-path-target';
|
|
39
44
|
import { handleResult } from '../utils/result-handler';
|
|
40
45
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
41
46
|
|
|
@@ -65,33 +70,6 @@ export interface MigrationShowResult {
|
|
|
65
70
|
readonly migration: MigrationShowPresent;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
function looksLikePath(target: string): boolean {
|
|
69
|
-
return target.includes('/') || target.includes('\\');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function resolveAppTargetPath(
|
|
73
|
-
target: string,
|
|
74
|
-
appMigrationsDir: string,
|
|
75
|
-
appMigrationsRelative: string,
|
|
76
|
-
): Result<string, CliStructuredError> {
|
|
77
|
-
const targetPath = resolve(target);
|
|
78
|
-
const relativeToApp = relative(appMigrationsDir, targetPath);
|
|
79
|
-
const isOutsideAppDir =
|
|
80
|
-
relativeToApp === '' ||
|
|
81
|
-
relativeToApp === '.' ||
|
|
82
|
-
relativeToApp.startsWith('..') ||
|
|
83
|
-
isAbsolute(relativeToApp);
|
|
84
|
-
if (isOutsideAppDir) {
|
|
85
|
-
return notOk(
|
|
86
|
-
errorRuntime('Target must point to an app-space migration', {
|
|
87
|
-
why: `Expected a path under ${appMigrationsRelative}, got ${target}`,
|
|
88
|
-
fix: 'Pass an app-space migration directory or use a hash prefix.',
|
|
89
|
-
}),
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
return ok(targetPath);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
73
|
function pkgToPresent(
|
|
96
74
|
spaceId: string,
|
|
97
75
|
pkg: OnDiskMigrationPackage,
|
|
@@ -117,14 +95,6 @@ function pkgToPresent(
|
|
|
117
95
|
};
|
|
118
96
|
}
|
|
119
97
|
|
|
120
|
-
function findPackageByDirPath(
|
|
121
|
-
packages: readonly OnDiskMigrationPackage[],
|
|
122
|
-
resolvedDirPath: string,
|
|
123
|
-
): OnDiskMigrationPackage | undefined {
|
|
124
|
-
const normalized = resolve(resolvedDirPath);
|
|
125
|
-
return packages.find((p) => resolve(p.dirPath) === normalized);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
98
|
async function executeMigrationShowCommand(
|
|
129
99
|
target: string,
|
|
130
100
|
options: MigrationShowOptions,
|
|
@@ -260,11 +230,13 @@ export function createMigrationShowCommand(): Command {
|
|
|
260
230
|
command,
|
|
261
231
|
'Display migration package contents',
|
|
262
232
|
'Shows the operations, statement preview, and metadata for one app-space migration.\n' +
|
|
263
|
-
'Accepts a directory path, directory name, or hash prefix
|
|
233
|
+
'Accepts a directory path, directory name, or hash prefix.\n' +
|
|
234
|
+
'Offline — does not consult the database.',
|
|
264
235
|
);
|
|
265
236
|
setCommandExamples(command, [
|
|
266
237
|
'prisma-next migration show 20260101_100000_add_user',
|
|
267
238
|
'prisma-next migration show sha256:a1b2c3',
|
|
239
|
+
'prisma-next migration show 20260101_100000_add_user --json',
|
|
268
240
|
]);
|
|
269
241
|
setCommandSeeAlso(command, [
|
|
270
242
|
{ verb: 'migration status', oneLiner: 'Show migration path and pending status' },
|
|
@@ -273,7 +245,7 @@ export function createMigrationShowCommand(): Command {
|
|
|
273
245
|
{ verb: 'migration graph', oneLiner: 'Show the migration graph topology' },
|
|
274
246
|
]);
|
|
275
247
|
addGlobalOptions(command)
|
|
276
|
-
.argument('<target>', 'Migration reference: directory name, hash/prefix, or path')
|
|
248
|
+
.argument('<target>', 'Migration reference: directory name, hash/prefix, ref, or path')
|
|
277
249
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
278
250
|
.action(async (target: string, options: MigrationShowOptions) => {
|
|
279
251
|
const flags = parseGlobalFlagsOrExit(options);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { MigrationGraph } from '@prisma-next/migration-tools/graph';
|
|
2
|
+
import { findPath } from '@prisma-next/migration-tools/migration-graph';
|
|
3
|
+
import type { MigrationEdgeAnnotation } from '../utils/formatters/migration-graph-tree-render';
|
|
4
|
+
|
|
5
|
+
export interface DeriveStatusEdgeAnnotationsInput {
|
|
6
|
+
readonly graph: MigrationGraph;
|
|
7
|
+
readonly targetHash: string;
|
|
8
|
+
readonly originHash: string;
|
|
9
|
+
readonly appliedMigrationHashes: ReadonlySet<string>;
|
|
10
|
+
readonly showAppliedOverlay: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function deriveStatusEdgeAnnotations(
|
|
14
|
+
input: DeriveStatusEdgeAnnotationsInput,
|
|
15
|
+
): ReadonlyMap<string, MigrationEdgeAnnotation> {
|
|
16
|
+
const annotations = new Map<string, MigrationEdgeAnnotation>();
|
|
17
|
+
|
|
18
|
+
if (input.showAppliedOverlay) {
|
|
19
|
+
for (const edge of input.graph.migrationByHash.values()) {
|
|
20
|
+
if (input.appliedMigrationHashes.has(edge.migrationHash)) {
|
|
21
|
+
annotations.set(edge.migrationHash, { status: 'applied' });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!input.graph.nodes.has(input.originHash)) {
|
|
27
|
+
return annotations;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const pendingPath = findPath(input.graph, input.originHash, input.targetHash);
|
|
31
|
+
if (!pendingPath) {
|
|
32
|
+
return annotations;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const edge of pendingPath) {
|
|
36
|
+
if (input.appliedMigrationHashes.has(edge.migrationHash)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const existing = annotations.get(edge.migrationHash);
|
|
40
|
+
if (existing?.status === 'applied') {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
annotations.set(edge.migrationHash, { status: 'pending' });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return annotations;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function appliedHashesFromLedger(
|
|
50
|
+
ledgerEntries: ReadonlyArray<{ readonly migrationHash: string }>,
|
|
51
|
+
): ReadonlySet<string> {
|
|
52
|
+
return new Set(ledgerEntries.map((entry) => entry.migrationHash));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function statusForMigrationHash(
|
|
56
|
+
migrationHash: string,
|
|
57
|
+
annotations: ReadonlyMap<string, MigrationEdgeAnnotation>,
|
|
58
|
+
): 'applied' | 'pending' | null {
|
|
59
|
+
const status = annotations.get(migrationHash)?.status;
|
|
60
|
+
return status ?? null;
|
|
61
|
+
}
|