@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,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,56 +20,45 @@ 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
|
+
serializeLedgerEntriesForJson,
|
|
28
|
+
} from '../utils/formatters/migration-log-table';
|
|
27
29
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
28
30
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
29
31
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
30
32
|
import { handleResult } from '../utils/result-handler';
|
|
31
33
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
34
|
+
import type { MigrationLogResult } from './json/schemas';
|
|
35
|
+
|
|
36
|
+
export type { MigrationLogResult };
|
|
32
37
|
|
|
33
38
|
interface MigrationLogOptions extends CommonCommandOptions {
|
|
34
39
|
readonly db?: string;
|
|
35
40
|
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;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface MigrationLogResult {
|
|
48
|
-
readonly ok: true;
|
|
49
|
-
readonly markerHash: string | null;
|
|
50
|
-
readonly applied: readonly MigrationLogEntry[];
|
|
51
|
-
readonly summary: string;
|
|
41
|
+
readonly utc?: boolean;
|
|
42
|
+
readonly ascii?: boolean;
|
|
52
43
|
}
|
|
53
44
|
|
|
54
45
|
export async function executeMigrationLogCommand(
|
|
55
46
|
options: MigrationLogOptions,
|
|
56
47
|
flags: GlobalFlags,
|
|
57
48
|
ui: TerminalUI,
|
|
58
|
-
): Promise<Result<
|
|
49
|
+
): Promise<Result<readonly LedgerEntryRecord[], CliStructuredError>> {
|
|
59
50
|
const config = await loadConfig(options.config);
|
|
60
|
-
const { configPath
|
|
61
|
-
options.config,
|
|
62
|
-
config,
|
|
63
|
-
);
|
|
51
|
+
const { configPath } = resolveMigrationPaths(options.config, config);
|
|
64
52
|
|
|
65
53
|
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' }));
|
|
54
|
+
const missingDb = requireLiveDatabase({
|
|
55
|
+
dbConnection,
|
|
56
|
+
hasDriver: !!config.driver,
|
|
57
|
+
why: `migration log needs a database connection and driver to read the ledger (set db.connection in ${configPath}, or pass --db <url>)`,
|
|
58
|
+
commandName: 'migration log',
|
|
59
|
+
});
|
|
60
|
+
if (missingDb) {
|
|
61
|
+
return notOk(missingDb);
|
|
76
62
|
}
|
|
77
63
|
if (!targetSupportsMigrations(config.target)) {
|
|
78
64
|
return notOk(errorUnexpected('Target does not support migrations'));
|
|
@@ -81,10 +67,9 @@ export async function executeMigrationLogCommand(
|
|
|
81
67
|
if (!flags.json && !flags.quiet) {
|
|
82
68
|
const header = formatStyledHeader({
|
|
83
69
|
command: 'migration log',
|
|
84
|
-
description: 'Show executed migration history',
|
|
70
|
+
description: 'Show executed migration history from the database ledger',
|
|
85
71
|
details: [
|
|
86
72
|
{ label: 'config', value: configPath },
|
|
87
|
-
{ label: 'migrations', value: appMigrationsRelative },
|
|
88
73
|
...(typeof dbConnection === 'string'
|
|
89
74
|
? [{ label: 'database', value: maskConnectionUrl(dbConnection) }]
|
|
90
75
|
: []),
|
|
@@ -94,64 +79,18 @@ export async function executeMigrationLogCommand(
|
|
|
94
79
|
ui.stderr(header);
|
|
95
80
|
}
|
|
96
81
|
|
|
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
82
|
const client = createControlClient({
|
|
105
83
|
family: config.family,
|
|
106
84
|
target: config.target,
|
|
107
85
|
adapter: config.adapter,
|
|
108
|
-
driver
|
|
86
|
+
...ifDefined('driver', config.driver),
|
|
109
87
|
extensionPacks: config.extensionPacks ?? [],
|
|
110
88
|
});
|
|
111
89
|
|
|
112
90
|
try {
|
|
113
91
|
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
|
-
});
|
|
92
|
+
const ledger = await client.readLedger();
|
|
93
|
+
return ok(ledger);
|
|
155
94
|
} catch (error) {
|
|
156
95
|
if (CliStructuredError.is(error)) return notOk(error);
|
|
157
96
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
@@ -170,11 +109,13 @@ export function createMigrationLogCommand(): Command {
|
|
|
170
109
|
setCommandDescriptions(
|
|
171
110
|
command,
|
|
172
111
|
'Show executed migration history',
|
|
173
|
-
'Reads the database
|
|
174
|
-
'
|
|
112
|
+
'Reads the database ledger and displays every applied migration edge\n' +
|
|
113
|
+
'in chronological order, including rollbacks and re-applies, merged\n' +
|
|
114
|
+
'across all contract spaces. Requires a database connection.',
|
|
175
115
|
);
|
|
176
116
|
setCommandExamples(command, [
|
|
177
117
|
'prisma-next migration log --db $DATABASE_URL',
|
|
118
|
+
'prisma-next migration log --utc --db $DATABASE_URL',
|
|
178
119
|
'prisma-next migration log --json --db $DATABASE_URL',
|
|
179
120
|
]);
|
|
180
121
|
setCommandSeeAlso(command, [
|
|
@@ -186,24 +127,33 @@ export function createMigrationLogCommand(): Command {
|
|
|
186
127
|
addGlobalOptions(command)
|
|
187
128
|
.option('--db <url>', 'Database connection string')
|
|
188
129
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
130
|
+
.option('--utc', 'Render human timestamps in UTC instead of local time')
|
|
131
|
+
.option('--ascii', 'Use ASCII glyphs (pipe-friendly)')
|
|
189
132
|
.action(async (options: MigrationLogOptions) => {
|
|
190
133
|
const flags = parseGlobalFlagsOrExit(options);
|
|
191
134
|
const ui = createTerminalUI(flags);
|
|
192
135
|
const result = await executeMigrationLogCommand(options, flags, ui);
|
|
193
|
-
const exitCode = handleResult(result, flags, ui, (
|
|
136
|
+
const exitCode = handleResult(result, flags, ui, (entries) => {
|
|
194
137
|
if (flags.json) {
|
|
195
|
-
|
|
138
|
+
const records = serializeLedgerEntriesForJson(entries);
|
|
139
|
+
const result: MigrationLogResult = {
|
|
140
|
+
ok: true,
|
|
141
|
+
records,
|
|
142
|
+
summary: `${records.length} migration(s) applied`,
|
|
143
|
+
};
|
|
144
|
+
ui.output(JSON.stringify(result, null, 2));
|
|
196
145
|
} else if (!flags.quiet) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
ui.log(logResult.summary);
|
|
146
|
+
if (entries.length === 0) {
|
|
147
|
+
ui.output(MIGRATION_LOG_EMPTY_MESSAGE);
|
|
200
148
|
} else {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
149
|
+
const styler = createAnsiMigrationListStyler({ useColor: ui.useColor });
|
|
150
|
+
ui.output(
|
|
151
|
+
renderMigrationLogTable(entries, {
|
|
152
|
+
utc: options.utc === true,
|
|
153
|
+
styler,
|
|
154
|
+
glyphMode: ui.resolveGlyphMode(options.ascii === true),
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
207
157
|
}
|
|
208
158
|
}
|
|
209
159
|
});
|
|
@@ -77,6 +77,7 @@ async function executeMigrationNewCommand(
|
|
|
77
77
|
// at the read site, not somewhere downstream. See TML-2536.
|
|
78
78
|
const stack = createControlStack(config);
|
|
79
79
|
const familyInstance = config.family.create(stack);
|
|
80
|
+
const controlAdapter = config.adapter.create(stack);
|
|
80
81
|
|
|
81
82
|
const contractPathAbsolute = resolveContractPath(config);
|
|
82
83
|
|
|
@@ -234,7 +235,7 @@ async function executeMigrationNewCommand(
|
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
237
|
|
|
237
|
-
const planner = migrations.createPlanner(
|
|
238
|
+
const planner = migrations.createPlanner(controlAdapter);
|
|
238
239
|
const emptyPlan = planner.emptyMigration(
|
|
239
240
|
{
|
|
240
241
|
packageDir,
|
|
@@ -276,6 +276,7 @@ async function executeMigrationPlanCommand(
|
|
|
276
276
|
// started dispatching on raw shapes. See TML-2536.
|
|
277
277
|
const stack = createControlStack(config);
|
|
278
278
|
const familyInstance = config.family.create(stack);
|
|
279
|
+
const controlAdapter = config.adapter.create(stack);
|
|
279
280
|
|
|
280
281
|
let toContract: Contract;
|
|
281
282
|
try {
|
|
@@ -475,7 +476,7 @@ async function executeMigrationPlanCommand(
|
|
|
475
476
|
}
|
|
476
477
|
|
|
477
478
|
try {
|
|
478
|
-
const planner = migrations.createPlanner(
|
|
479
|
+
const planner = migrations.createPlanner(controlAdapter);
|
|
479
480
|
|
|
480
481
|
if (
|
|
481
482
|
isAutoBaseline &&
|
|
@@ -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';
|
|
@@ -13,7 +12,7 @@ import { castAs } from '@prisma-next/utils/casts';
|
|
|
13
12
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
14
13
|
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
15
14
|
import { Command } from 'commander';
|
|
16
|
-
import {
|
|
15
|
+
import { relative } from 'pathe';
|
|
17
16
|
import { loadConfig } from '../config-loader';
|
|
18
17
|
import { createControlClient } from '../control-api/client';
|
|
19
18
|
import {
|
|
@@ -36,61 +35,33 @@ import { formatMigrationShowOutput } from '../utils/formatters/migrations';
|
|
|
36
35
|
import { formatStyledHeader } from '../utils/formatters/styled';
|
|
37
36
|
import type { CommonCommandOptions } from '../utils/global-flags';
|
|
38
37
|
import { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';
|
|
38
|
+
import {
|
|
39
|
+
findPackageByDirPath,
|
|
40
|
+
looksLikePath,
|
|
41
|
+
resolveAppTargetPath,
|
|
42
|
+
} from '../utils/migration-path-target';
|
|
39
43
|
import { handleResult } from '../utils/result-handler';
|
|
40
44
|
import { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';
|
|
45
|
+
import type { MigrationShowResult } from './json/schemas';
|
|
41
46
|
|
|
42
47
|
interface MigrationShowOptions extends CommonCommandOptions {
|
|
43
48
|
readonly config?: string;
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
export interface MigrationShowPresent {
|
|
47
|
-
readonly
|
|
48
|
-
readonly
|
|
49
|
-
readonly
|
|
50
|
-
readonly
|
|
51
|
-
readonly
|
|
52
|
-
readonly migrationHash: string;
|
|
52
|
+
readonly space: string;
|
|
53
|
+
readonly name: string;
|
|
54
|
+
readonly fromContract: string | null;
|
|
55
|
+
readonly toContract: string;
|
|
56
|
+
readonly hash: string;
|
|
53
57
|
readonly createdAt: string;
|
|
54
|
-
readonly operations:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}[];
|
|
59
|
-
readonly preview: OperationPreview;
|
|
60
|
-
readonly summary: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export interface MigrationShowResult {
|
|
64
|
-
readonly ok: true;
|
|
65
|
-
readonly migration: MigrationShowPresent;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function looksLikePath(target: string): boolean {
|
|
69
|
-
return target.includes('/') || target.includes('\\');
|
|
58
|
+
readonly operations: { id: string; label: string; operationClass: string }[];
|
|
59
|
+
readonly preview: {
|
|
60
|
+
statements: { text: string; language: string }[];
|
|
61
|
+
};
|
|
70
62
|
}
|
|
71
63
|
|
|
72
|
-
export
|
|
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
|
-
}
|
|
64
|
+
export type { MigrationShowResult };
|
|
94
65
|
|
|
95
66
|
function pkgToPresent(
|
|
96
67
|
spaceId: string,
|
|
@@ -98,33 +69,23 @@ function pkgToPresent(
|
|
|
98
69
|
client: ReturnType<typeof createControlClient>,
|
|
99
70
|
): MigrationShowPresent {
|
|
100
71
|
const ops = castAs<readonly MigrationPlanOperation[]>(pkg.ops);
|
|
101
|
-
const
|
|
72
|
+
const rawPreview = client.toOperationPreview(ops) ?? { statements: [] };
|
|
102
73
|
return {
|
|
103
|
-
spaceId,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
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,
|
|
109
79
|
createdAt: pkg.metadata.createdAt,
|
|
110
80
|
operations: ops.map((op) => ({
|
|
111
81
|
id: op.id,
|
|
112
82
|
label: op.label,
|
|
113
83
|
operationClass: op.operationClass,
|
|
114
84
|
})),
|
|
115
|
-
preview,
|
|
116
|
-
summary: `${ops.length} operation(s)`,
|
|
85
|
+
preview: { statements: [...rawPreview.statements] },
|
|
117
86
|
};
|
|
118
87
|
}
|
|
119
88
|
|
|
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
89
|
async function executeMigrationShowCommand(
|
|
129
90
|
target: string,
|
|
130
91
|
options: MigrationShowOptions,
|
|
@@ -248,9 +209,11 @@ async function executeMigrationShowCommand(
|
|
|
248
209
|
appPkg = matchedPkg;
|
|
249
210
|
}
|
|
250
211
|
|
|
212
|
+
const migration = pkgToPresent(APP_SPACE_ID, appPkg, client);
|
|
251
213
|
return ok({
|
|
252
214
|
ok: true,
|
|
253
|
-
migration:
|
|
215
|
+
summary: `Migration ${migration.name} in ${migration.space}: ${migration.operations.length} operation(s)`,
|
|
216
|
+
migration,
|
|
254
217
|
});
|
|
255
218
|
}
|
|
256
219
|
|
|
@@ -260,11 +223,13 @@ export function createMigrationShowCommand(): Command {
|
|
|
260
223
|
command,
|
|
261
224
|
'Display migration package contents',
|
|
262
225
|
'Shows the operations, statement preview, and metadata for one app-space migration.\n' +
|
|
263
|
-
'Accepts a directory path, directory name, or hash prefix
|
|
226
|
+
'Accepts a directory path, directory name, or hash prefix.\n' +
|
|
227
|
+
'Offline — does not consult the database.',
|
|
264
228
|
);
|
|
265
229
|
setCommandExamples(command, [
|
|
266
230
|
'prisma-next migration show 20260101_100000_add_user',
|
|
267
231
|
'prisma-next migration show sha256:a1b2c3',
|
|
232
|
+
'prisma-next migration show 20260101_100000_add_user --json',
|
|
268
233
|
]);
|
|
269
234
|
setCommandSeeAlso(command, [
|
|
270
235
|
{ verb: 'migration status', oneLiner: 'Show migration path and pending status' },
|
|
@@ -273,7 +238,7 @@ export function createMigrationShowCommand(): Command {
|
|
|
273
238
|
{ verb: 'migration graph', oneLiner: 'Show the migration graph topology' },
|
|
274
239
|
]);
|
|
275
240
|
addGlobalOptions(command)
|
|
276
|
-
.argument('<target>', 'Migration reference: directory name, hash/prefix, or path')
|
|
241
|
+
.argument('<target>', 'Migration reference: directory name, hash/prefix, ref, or path')
|
|
277
242
|
.option('--config <path>', 'Path to prisma-next.config.ts')
|
|
278
243
|
.action(async (target: string, options: MigrationShowOptions) => {
|
|
279
244
|
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-labels';
|
|
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
|
+
}
|