prisma-next 0.6.0-dev.3 → 0.6.0-dev.5
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 +4 -4
- package/dist/{client-qVH-rEgd.mjs → client-BCnP7cHo.mjs} +9 -119
- package/dist/client-BCnP7cHo.mjs.map +1 -0
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +3 -3
- package/dist/commands/db-schema.mjs +1 -1
- package/dist/commands/db-sign.mjs +1 -1
- package/dist/commands/db-update.mjs +3 -3
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migration-apply.d.mts +1 -1
- package/dist/commands/migration-apply.mjs +2 -2
- 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 +55 -7
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +153 -46
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/{contract-infer-BK9YFGEG.mjs → contract-infer-ByxhPjpW.mjs} +2 -2
- package/dist/{contract-infer-BK9YFGEG.mjs.map → contract-infer-ByxhPjpW.mjs.map} +1 -1
- package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs +160 -0
- package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs.map +1 -0
- package/dist/{db-verify-C0y1PCO2.mjs → db-verify-Czm5T-J4.mjs} +2 -2
- package/dist/{db-verify-C0y1PCO2.mjs.map → db-verify-Czm5T-J4.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +1 -1
- package/dist/{inspect-live-schema-CWYxGKlb.mjs → inspect-live-schema-DxdBd4Er.mjs} +2 -2
- package/dist/{inspect-live-schema-CWYxGKlb.mjs.map → inspect-live-schema-DxdBd4Er.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-B5dORFEv.mjs → migration-command-scaffold-BdV8JYXV.mjs} +2 -2
- package/dist/{migration-command-scaffold-B5dORFEv.mjs.map → migration-command-scaffold-BdV8JYXV.mjs.map} +1 -1
- package/dist/{migration-plan-C6lVaHsO.mjs → migration-plan-mRu5K81L.mjs} +89 -149
- package/dist/migration-plan-mRu5K81L.mjs.map +1 -0
- package/dist/{migration-status-CZ-D5k7k.mjs → migration-status-By9G5p2H.mjs} +6 -8
- package/dist/{migration-status-CZ-D5k7k.mjs.map → migration-status-By9G5p2H.mjs.map} +1 -1
- package/dist/{migrations-D_UJnpuW.mjs → migrations-CTsyBXCA.mjs} +42 -29
- package/dist/migrations-CTsyBXCA.mjs.map +1 -0
- package/dist/{types-D7x-IFLO.d.mts → types-LItU7E4l.d.mts} +7 -9
- package/dist/{types-D7x-IFLO.d.mts.map → types-LItU7E4l.d.mts.map} +1 -1
- package/package.json +10 -10
- package/dist/client-qVH-rEgd.mjs.map +0 -1
- package/dist/extension-pack-inputs-C7xgE-vv.mjs +0 -74
- package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +0 -1
- package/dist/migration-plan-C6lVaHsO.mjs.map +0 -1
- package/dist/migrations-D_UJnpuW.mjs.map +0 -1
|
@@ -5,8 +5,12 @@ import { OperationPreview } from "@prisma-next/framework-components/control";
|
|
|
5
5
|
import { OnDiskMigrationPackage } from "@prisma-next/migration-tools/package";
|
|
6
6
|
|
|
7
7
|
//#region src/commands/migration-show.d.ts
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Details of one space's latest (or targeted) migration package.
|
|
10
|
+
*/
|
|
11
|
+
interface MigrationShowSpacePresent {
|
|
12
|
+
readonly kind: 'present';
|
|
13
|
+
readonly spaceId: string;
|
|
10
14
|
readonly dirName: string;
|
|
11
15
|
readonly dirPath: string;
|
|
12
16
|
readonly from: string | null;
|
|
@@ -19,16 +23,60 @@ interface MigrationShowResult {
|
|
|
19
23
|
readonly operationClass: string;
|
|
20
24
|
}[];
|
|
21
25
|
/**
|
|
22
|
-
* Family-agnostic textual preview of the migration's operations.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* `OperationPreviewCapable` capability.
|
|
26
|
+
* Family-agnostic textual preview of the migration's operations. Always
|
|
27
|
+
* defined; statements is empty for a no-op migration or a family that does
|
|
28
|
+
* not implement the `OperationPreviewCapable` capability.
|
|
26
29
|
*/
|
|
27
30
|
readonly preview: OperationPreview;
|
|
28
31
|
readonly summary: string;
|
|
29
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Placeholder for a loaded contract space that has no on-disk migration
|
|
35
|
+
* package — the extension descriptor declared the space but no migrations
|
|
36
|
+
* directory has been materialised for it yet. Surfaces the space in the
|
|
37
|
+
* response so JSON consumers see every loaded extension instead of having
|
|
38
|
+
* silently-skipped entries.
|
|
39
|
+
*/
|
|
40
|
+
interface MigrationShowSpaceMissing {
|
|
41
|
+
readonly kind: 'missing';
|
|
42
|
+
readonly spaceId: string;
|
|
43
|
+
readonly summary: string;
|
|
44
|
+
}
|
|
45
|
+
type MigrationShowSpaceResult = MigrationShowSpacePresent | MigrationShowSpaceMissing;
|
|
46
|
+
interface MigrationShowResult {
|
|
47
|
+
readonly ok: true;
|
|
48
|
+
/**
|
|
49
|
+
* Per-space results, ordered: app first, then extensions alphabetically
|
|
50
|
+
* (matching the aggregate's canonical ordering).
|
|
51
|
+
*/
|
|
52
|
+
readonly spaces: readonly MigrationShowSpaceResult[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validate that a path-like `migration show` target resolves inside the app
|
|
56
|
+
* migrations directory. The returned result is always emitted under
|
|
57
|
+
* `aggregate.app.spaceId`, so accepting an extension-space (or otherwise
|
|
58
|
+
* external) path here would silently mislabel the result. Returns the
|
|
59
|
+
* resolved absolute path on success.
|
|
60
|
+
*
|
|
61
|
+
* `pathe.relative` can return an absolute path when the target cannot be
|
|
62
|
+
* expressed relative to the base (e.g. on Windows when `target` is on a
|
|
63
|
+
* different drive than `appMigrationsDir`). That case does not start with
|
|
64
|
+
* `..`, so the absolute-check below is required to reject cross-drive
|
|
65
|
+
* targets rather than mislabeling them as app-space.
|
|
66
|
+
*/
|
|
67
|
+
declare function resolveAppTargetPath(target: string, appMigrationsDir: string, appMigrationsRelative: string): Result<string, CliStructuredError>;
|
|
30
68
|
declare function resolveByHashPrefix(packages: readonly OnDiskMigrationPackage[], prefix: string): Result<OnDiskMigrationPackage, CliStructuredError>;
|
|
69
|
+
/**
|
|
70
|
+
* Resolve the latest migration from a space directory.
|
|
71
|
+
*
|
|
72
|
+
* Returns `ok(null)` only when the directory is empty or absent (ENOENT is
|
|
73
|
+
* absorbed by `readMigrationsDir`). If `readMigrationsDir` returned packages
|
|
74
|
+
* but `findLatestMigration` cannot pick a leaf, the on-disk history is
|
|
75
|
+
* corrupt — return a runtime error rather than collapsing it to a `missing`
|
|
76
|
+
* placeholder, which would hide the corruption from the caller.
|
|
77
|
+
*/
|
|
78
|
+
declare function resolveLatestFromDir(spaceDir: string): Promise<Result<OnDiskMigrationPackage | null, CliStructuredError>>;
|
|
31
79
|
declare function createMigrationShowCommand(): Command;
|
|
32
80
|
//#endregion
|
|
33
|
-
export { MigrationShowResult, createMigrationShowCommand, resolveByHashPrefix };
|
|
81
|
+
export { MigrationShowResult, MigrationShowSpaceMissing, MigrationShowSpacePresent, MigrationShowSpaceResult, createMigrationShowCommand, resolveAppTargetPath, resolveByHashPrefix, resolveLatestFromDir };
|
|
34
82
|
//# sourceMappingURL=migration-show.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"mappings":";;;;;;;;;AAmDA;UAAiB,yBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;EAAA,SACA,EAAA;EAAA,SACA,aAAA;EAAA,SACA,SAAA;EAAA,SACA,UAAA;IAAA,SACE,EAAA;IAAA,SACA,KAAA;IAAA,SACA,cAAA;EAAA;EAAA;;;;;EAAA,SAOF,OAAA,EAAS,gBAAA;EAAA,SACT,OAAA;AAAA;;;;;;;;UAUM,yBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;AAAA;AAAA,KAGC,wBAAA,GAA2B,yBAAA,GAA4B,yBAAA;AAAA,UAElD,mBAAA;EAAA,SACN,EAAA;EAKyC;;;;EAAA,SAAzC,MAAA,WAAiB,wBAAA;AAAA;AAoB5B;;;;;;;;;;;AAuBA;;AAvBA,iBAAgB,oBAAA,CACd,MAAA,UACA,gBAAA,UACA,qBAAA,WACC,MAAA,SAAe,kBAAA;AAAA,iBAmBF,mBAAA,CACd,QAAA,WAAmB,sBAAA,IACnB,MAAA,WACC,MAAA,CAAO,sBAAA,EAAwB,kBAAA;;;;;;;;;;iBAmCZ,oBAAA,CACpB,QAAA,WACC,OAAA,CAAQ,MAAA,CAAO,sBAAA,SAA+B,kBAAA;AAAA,iBAkOjC,0BAAA,CAAA,GAA8B,OAAA"}
|
|
@@ -1,21 +1,47 @@
|
|
|
1
1
|
import { t as loadConfig } from "../config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import { _ as errorUnexpected, m as errorRuntime, v as mapMigrationToolsError } from "../cli-errors-D3_sMh2K.mjs";
|
|
3
|
-
import { d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, t as addGlobalOptions, y as formatStyledHeader } from "../command-helpers-BeZHkxV8.mjs";
|
|
2
|
+
import { _ as errorUnexpected, a as errorContractValidationFailed, l as errorFileNotFound, m as errorRuntime, v as mapMigrationToolsError } from "../cli-errors-D3_sMh2K.mjs";
|
|
3
|
+
import { c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, l as resolveMigrationPaths, t as addGlobalOptions, y as formatStyledHeader } from "../command-helpers-BeZHkxV8.mjs";
|
|
4
4
|
import { t as TerminalUI } from "../terminal-ui-C_hFNbAn.mjs";
|
|
5
5
|
import { t as handleResult } from "../result-handler-rmPVKIP2.mjs";
|
|
6
|
-
import { t as createControlClient } from "../client-
|
|
7
|
-
import {
|
|
6
|
+
import { t as createControlClient } from "../client-BCnP7cHo.mjs";
|
|
7
|
+
import { t as buildContractSpaceAggregate } from "../contract-space-aggregate-loader-BrwKK6Q6.mjs";
|
|
8
|
+
import { a as formatMigrationShowOutput } from "../migrations-CTsyBXCA.mjs";
|
|
8
9
|
import { Command } from "commander";
|
|
10
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
9
11
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
10
|
-
import { relative, resolve } from "pathe";
|
|
12
|
+
import { isAbsolute, relative, resolve } from "pathe";
|
|
13
|
+
import { readFile } from "node:fs/promises";
|
|
14
|
+
import { createControlStack } from "@prisma-next/framework-components/control";
|
|
11
15
|
import { readMigrationPackage, readMigrationsDir } from "@prisma-next/migration-tools/io";
|
|
12
16
|
import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/migration-graph";
|
|
13
|
-
import {
|
|
17
|
+
import { spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
|
|
14
18
|
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
15
19
|
//#region src/commands/migration-show.ts
|
|
16
20
|
function looksLikePath(target) {
|
|
17
21
|
return target.includes("/") || target.includes("\\");
|
|
18
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Validate that a path-like `migration show` target resolves inside the app
|
|
25
|
+
* migrations directory. The returned result is always emitted under
|
|
26
|
+
* `aggregate.app.spaceId`, so accepting an extension-space (or otherwise
|
|
27
|
+
* external) path here would silently mislabel the result. Returns the
|
|
28
|
+
* resolved absolute path on success.
|
|
29
|
+
*
|
|
30
|
+
* `pathe.relative` can return an absolute path when the target cannot be
|
|
31
|
+
* expressed relative to the base (e.g. on Windows when `target` is on a
|
|
32
|
+
* different drive than `appMigrationsDir`). That case does not start with
|
|
33
|
+
* `..`, so the absolute-check below is required to reject cross-drive
|
|
34
|
+
* targets rather than mislabeling them as app-space.
|
|
35
|
+
*/
|
|
36
|
+
function resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative) {
|
|
37
|
+
const targetPath = resolve(target);
|
|
38
|
+
const relativeToApp = relative(appMigrationsDir, targetPath);
|
|
39
|
+
if (relativeToApp === "" || relativeToApp === "." || relativeToApp.startsWith("..") || isAbsolute(relativeToApp)) return notOk(errorRuntime("Target must point to an app-space migration", {
|
|
40
|
+
why: `Expected a path under ${appMigrationsRelative}, got ${target}`,
|
|
41
|
+
fix: "Pass an app-space migration directory or use a hash prefix."
|
|
42
|
+
}));
|
|
43
|
+
return ok(targetPath);
|
|
44
|
+
}
|
|
19
45
|
function resolveByHashPrefix(packages, prefix) {
|
|
20
46
|
const normalizedPrefix = prefix.startsWith("sha256:") ? prefix : `sha256:${prefix}`;
|
|
21
47
|
const matches = packages.filter((p) => p.metadata.migrationHash.startsWith(normalizedPrefix));
|
|
@@ -29,19 +55,71 @@ function resolveByHashPrefix(packages, prefix) {
|
|
|
29
55
|
fix: "Provide a longer prefix to uniquely identify the migration."
|
|
30
56
|
}));
|
|
31
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Resolve the latest migration from a space directory.
|
|
60
|
+
*
|
|
61
|
+
* Returns `ok(null)` only when the directory is empty or absent (ENOENT is
|
|
62
|
+
* absorbed by `readMigrationsDir`). If `readMigrationsDir` returned packages
|
|
63
|
+
* but `findLatestMigration` cannot pick a leaf, the on-disk history is
|
|
64
|
+
* corrupt — return a runtime error rather than collapsing it to a `missing`
|
|
65
|
+
* placeholder, which would hide the corruption from the caller.
|
|
66
|
+
*/
|
|
67
|
+
async function resolveLatestFromDir(spaceDir) {
|
|
68
|
+
try {
|
|
69
|
+
const allPackages = await readMigrationsDir(spaceDir);
|
|
70
|
+
if (allPackages.length === 0) return ok(null);
|
|
71
|
+
const latestMigration = findLatestMigration(reconstructGraph(allPackages));
|
|
72
|
+
if (!latestMigration) return notOk(errorRuntime("Could not resolve latest migration", {
|
|
73
|
+
why: `No latest migration found in ${relative(process.cwd(), spaceDir)}`,
|
|
74
|
+
fix: "The migrations directory may be corrupted. Inspect the migration.json files."
|
|
75
|
+
}));
|
|
76
|
+
return ok(allPackages.find((p) => p.metadata.migrationHash === latestMigration.migrationHash) ?? null);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
79
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migrations: ${error instanceof Error ? error.message : String(error)}` }));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function pkgToSpaceResult(spaceId, pkg, client) {
|
|
83
|
+
const ops = pkg.ops;
|
|
84
|
+
const preview = client.toOperationPreview(ops) ?? { statements: [] };
|
|
85
|
+
return {
|
|
86
|
+
kind: "present",
|
|
87
|
+
spaceId,
|
|
88
|
+
dirName: pkg.dirName,
|
|
89
|
+
dirPath: relative(process.cwd(), pkg.dirPath),
|
|
90
|
+
from: pkg.metadata.from,
|
|
91
|
+
to: pkg.metadata.to,
|
|
92
|
+
migrationHash: pkg.metadata.migrationHash,
|
|
93
|
+
createdAt: pkg.metadata.createdAt,
|
|
94
|
+
operations: ops.map((op) => ({
|
|
95
|
+
id: op.id,
|
|
96
|
+
label: op.label,
|
|
97
|
+
operationClass: op.operationClass
|
|
98
|
+
})),
|
|
99
|
+
preview,
|
|
100
|
+
summary: `${ops.length} operation(s)`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
32
103
|
async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
33
104
|
const config = await loadConfig(options.config);
|
|
34
|
-
const configPath
|
|
35
|
-
const
|
|
36
|
-
const
|
|
105
|
+
const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } = resolveMigrationPaths(options.config, config);
|
|
106
|
+
const contractPathAbsolute = resolveContractPath(config);
|
|
107
|
+
const contractPath = relative(process.cwd(), contractPathAbsolute);
|
|
37
108
|
if (!flags.json && !flags.quiet) {
|
|
38
|
-
const details = [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
109
|
+
const details = [
|
|
110
|
+
{
|
|
111
|
+
label: "config",
|
|
112
|
+
value: configPath
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
label: "contract",
|
|
116
|
+
value: contractPath
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
label: "migrations",
|
|
120
|
+
value: appMigrationsRelative
|
|
121
|
+
}
|
|
122
|
+
];
|
|
45
123
|
if (target) details.push({
|
|
46
124
|
label: "target",
|
|
47
125
|
value: target
|
|
@@ -54,10 +132,48 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
|
54
132
|
});
|
|
55
133
|
ui.stderr(header);
|
|
56
134
|
}
|
|
57
|
-
let
|
|
135
|
+
let contractJsonContent;
|
|
58
136
|
try {
|
|
59
|
-
|
|
60
|
-
|
|
137
|
+
contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
|
|
140
|
+
why: `Contract file not found at ${contractPathAbsolute}`,
|
|
141
|
+
fix: `Run \`prisma-next contract emit\` to generate ${contractPath}`
|
|
142
|
+
}));
|
|
143
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: "Failed to read contract file" }));
|
|
144
|
+
}
|
|
145
|
+
let appContract;
|
|
146
|
+
try {
|
|
147
|
+
appContract = JSON.parse(contractJsonContent);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
return notOk(errorContractValidationFailed(`Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
|
|
150
|
+
}
|
|
151
|
+
const stack = createControlStack(config);
|
|
152
|
+
const familyInstance = config.family.create(stack);
|
|
153
|
+
const aggregateResult = await buildContractSpaceAggregate({
|
|
154
|
+
targetId: config.target.targetId,
|
|
155
|
+
migrationsDir,
|
|
156
|
+
appContract,
|
|
157
|
+
extensionPacks: config.extensionPacks ?? [],
|
|
158
|
+
validateContract: (json) => familyInstance.validateContract(json)
|
|
159
|
+
});
|
|
160
|
+
if (!aggregateResult.ok) return notOk(aggregateResult.failure);
|
|
161
|
+
const aggregate = aggregateResult.value;
|
|
162
|
+
const client = createControlClient({
|
|
163
|
+
family: config.family,
|
|
164
|
+
target: config.target,
|
|
165
|
+
adapter: config.adapter,
|
|
166
|
+
...ifDefined("driver", config.driver),
|
|
167
|
+
extensionPacks: config.extensionPacks ?? []
|
|
168
|
+
});
|
|
169
|
+
const spaces = [];
|
|
170
|
+
try {
|
|
171
|
+
let appPkg;
|
|
172
|
+
if (target && looksLikePath(target)) {
|
|
173
|
+
const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);
|
|
174
|
+
if (!resolved.ok) return resolved;
|
|
175
|
+
appPkg = await readMigrationPackage(resolved.value);
|
|
176
|
+
} else {
|
|
61
177
|
const allPackages = await readMigrationsDir(appMigrationsDir);
|
|
62
178
|
if (allPackages.length === 0) return notOk(errorRuntime("No migrations found", {
|
|
63
179
|
why: `No migration packages found in ${appMigrationsRelative}`,
|
|
@@ -66,7 +182,7 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
|
66
182
|
if (target) {
|
|
67
183
|
const resolved = resolveByHashPrefix(allPackages, target);
|
|
68
184
|
if (!resolved.ok) return resolved;
|
|
69
|
-
|
|
185
|
+
appPkg = resolved.value;
|
|
70
186
|
} else {
|
|
71
187
|
const latestMigration = findLatestMigration(reconstructGraph(allPackages));
|
|
72
188
|
if (!latestMigration) return notOk(errorRuntime("Could not resolve latest migration", {
|
|
@@ -78,43 +194,34 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
|
78
194
|
why: `Latest migration ${latestMigration.dirName} does not match any package`,
|
|
79
195
|
fix: "The migrations directory may be corrupted. Inspect the migration.json files."
|
|
80
196
|
}));
|
|
81
|
-
|
|
197
|
+
appPkg = leafPkg;
|
|
82
198
|
}
|
|
83
199
|
}
|
|
200
|
+
spaces.push(pkgToSpaceResult(aggregate.app.spaceId, appPkg, client));
|
|
84
201
|
} catch (error) {
|
|
85
202
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
86
|
-
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}` }));
|
|
203
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read app-space migration: ${error instanceof Error ? error.message : String(error)}` }));
|
|
204
|
+
}
|
|
205
|
+
for (const ext of aggregate.extensions) {
|
|
206
|
+
const extPkgResult = await resolveLatestFromDir(spaceMigrationDirectory(migrationsDir, ext.spaceId));
|
|
207
|
+
if (!extPkgResult.ok) return extPkgResult;
|
|
208
|
+
if (extPkgResult.value !== null) spaces.push(pkgToSpaceResult(ext.spaceId, extPkgResult.value, client));
|
|
209
|
+
else spaces.push({
|
|
210
|
+
kind: "missing",
|
|
211
|
+
spaceId: ext.spaceId,
|
|
212
|
+
summary: "No on-disk migration package for this space"
|
|
213
|
+
});
|
|
87
214
|
}
|
|
88
|
-
const ops = pkg.ops;
|
|
89
|
-
const preview = createControlClient({
|
|
90
|
-
family: config.family,
|
|
91
|
-
target: config.target,
|
|
92
|
-
adapter: config.adapter,
|
|
93
|
-
...config.driver ? { driver: config.driver } : {},
|
|
94
|
-
extensionPacks: config.extensionPacks ?? []
|
|
95
|
-
}).toOperationPreview(ops) ?? { statements: [] };
|
|
96
215
|
return ok({
|
|
97
216
|
ok: true,
|
|
98
|
-
|
|
99
|
-
dirPath: relative(process.cwd(), pkg.dirPath),
|
|
100
|
-
from: pkg.metadata.from,
|
|
101
|
-
to: pkg.metadata.to,
|
|
102
|
-
migrationHash: pkg.metadata.migrationHash,
|
|
103
|
-
createdAt: pkg.metadata.createdAt,
|
|
104
|
-
operations: ops.map((op) => ({
|
|
105
|
-
id: op.id,
|
|
106
|
-
label: op.label,
|
|
107
|
-
operationClass: op.operationClass
|
|
108
|
-
})),
|
|
109
|
-
preview,
|
|
110
|
-
summary: `${ops.length} operation(s)`
|
|
217
|
+
spaces
|
|
111
218
|
});
|
|
112
219
|
}
|
|
113
220
|
function createMigrationShowCommand() {
|
|
114
221
|
const command = new Command("show");
|
|
115
|
-
setCommandDescriptions(command, "Display migration package contents", "Shows the operations, statement preview, and metadata for
|
|
222
|
+
setCommandDescriptions(command, "Display migration package contents", "Shows the operations, statement preview, and metadata for every loaded contract\nspace (app + extensions). Accepts a directory path or hash prefix to target a\nspecific app-space migration; defaults to the latest per space.");
|
|
116
223
|
setCommandExamples(command, ["prisma-next migration show", "prisma-next migration show sha256:a1b2c3"]);
|
|
117
|
-
addGlobalOptions(command).argument("[target]", "
|
|
224
|
+
addGlobalOptions(command).argument("[target]", "App-space migration path or migrationHash prefix (defaults to latest)").option("--config <path>", "Path to prisma-next.config.ts").action(async (target, options) => {
|
|
118
225
|
const flags = parseGlobalFlags(options);
|
|
119
226
|
const ui = new TerminalUI({
|
|
120
227
|
color: flags.color,
|
|
@@ -129,6 +236,6 @@ function createMigrationShowCommand() {
|
|
|
129
236
|
return command;
|
|
130
237
|
}
|
|
131
238
|
//#endregion
|
|
132
|
-
export { createMigrationShowCommand, resolveByHashPrefix };
|
|
239
|
+
export { createMigrationShowCommand, resolveAppTargetPath, resolveByHashPrefix, resolveLatestFromDir };
|
|
133
240
|
|
|
134
241
|
//# sourceMappingURL=migration-show.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-show.mjs","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import type {\n MigrationPlanOperation,\n OperationPreview,\n} from '@prisma-next/framework-components/control';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport {\n findLatestMigration,\n reconstructGraph,\n} from '@prisma-next/migration-tools/migration-graph';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { APP_SPACE_ID, spaceMigrationDirectory } from '@prisma-next/migration-tools/spaces';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n type CliStructuredError,\n errorRuntime,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport interface MigrationShowResult {\n readonly ok: true;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the migration's operations. Replaces\n * the previous string-array DDL field. Always defined; statements is empty\n * for a no-op migration or a family that does not implement the\n * `OperationPreviewCapable` capability.\n */\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\nexport function resolveByHashPrefix(\n packages: readonly OnDiskMigrationPackage[],\n prefix: string,\n): Result<OnDiskMigrationPackage, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const matches = packages.filter((p) => p.metadata.migrationHash.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No migration has a migrationHash starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.metadata.migrationHash}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n const migrationsDirRoot = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const appMigrationsDir = spaceMigrationDirectory(migrationsDirRoot, APP_SPACE_ID);\n const appMigrationsRelative = relative(process.cwd(), appMigrationsDir);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let pkg: OnDiskMigrationPackage;\n\n try {\n if (target && looksLikePath(target)) {\n pkg = await readMigrationPackage(resolve(target));\n } else {\n const allPackages = await readMigrationsDir(appMigrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${appMigrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n pkg = resolved.value;\n } else {\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n pkg = leafPkg;\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n\n // `migration show` is an offline command; the control client is constructed\n // purely to dispatch the family-specific `toOperationPreview` capability and\n // is not connected to a database.\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n ...(config.driver ? { driver: config.driver } : {}),\n extensionPacks: config.extensionPacks ?? [],\n });\n const preview: OperationPreview = client.toOperationPreview(ops) ?? { statements: [] };\n\n const result: MigrationShowResult = {\n ok: true,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n createdAt: pkg.metadata.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n preview,\n summary: `${ops.length} operation(s)`,\n };\n return ok(result);\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, statement preview, and metadata for a migration package.\\n' +\n 'Accepts a directory path, a hash prefix (git-style), or defaults to the\\n' +\n 'latest migration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument('[target]', 'Migration directory path or migrationHash prefix (defaults to latest)')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"migration-show.mjs","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport {\n createControlStack,\n type MigrationPlanOperation,\n type OperationPreview,\n} from '@prisma-next/framework-components/control';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport {\n findLatestMigration,\n reconstructGraph,\n} from '@prisma-next/migration-tools/migration-graph';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { spaceMigrationDirectory } from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { isAbsolute, relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n type CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { buildContractSpaceAggregate } from '../utils/contract-space-aggregate-loader';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\n/**\n * Details of one space's latest (or targeted) migration package.\n */\nexport interface MigrationShowSpacePresent {\n readonly kind: 'present';\n readonly spaceId: string;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the migration's operations. Always\n * defined; statements is empty for a no-op migration or a family that does\n * not implement the `OperationPreviewCapable` capability.\n */\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\n/**\n * Placeholder for a loaded contract space that has no on-disk migration\n * package — the extension descriptor declared the space but no migrations\n * directory has been materialised for it yet. Surfaces the space in the\n * response so JSON consumers see every loaded extension instead of having\n * silently-skipped entries.\n */\nexport interface MigrationShowSpaceMissing {\n readonly kind: 'missing';\n readonly spaceId: string;\n readonly summary: string;\n}\n\nexport type MigrationShowSpaceResult = MigrationShowSpacePresent | MigrationShowSpaceMissing;\n\nexport interface MigrationShowResult {\n readonly ok: true;\n /**\n * Per-space results, ordered: app first, then extensions alphabetically\n * (matching the aggregate's canonical ordering).\n */\n readonly spaces: readonly MigrationShowSpaceResult[];\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\n/**\n * Validate that a path-like `migration show` target resolves inside the app\n * migrations directory. The returned result is always emitted under\n * `aggregate.app.spaceId`, so accepting an extension-space (or otherwise\n * external) path here would silently mislabel the result. Returns the\n * resolved absolute path on success.\n *\n * `pathe.relative` can return an absolute path when the target cannot be\n * expressed relative to the base (e.g. on Windows when `target` is on a\n * different drive than `appMigrationsDir`). That case does not start with\n * `..`, so the absolute-check below is required to reject cross-drive\n * targets rather than mislabeling them as app-space.\n */\nexport function resolveAppTargetPath(\n target: string,\n appMigrationsDir: string,\n appMigrationsRelative: string,\n): Result<string, CliStructuredError> {\n const targetPath = resolve(target);\n const relativeToApp = relative(appMigrationsDir, targetPath);\n const isOutsideAppDir =\n relativeToApp === '' ||\n relativeToApp === '.' ||\n relativeToApp.startsWith('..') ||\n isAbsolute(relativeToApp);\n if (isOutsideAppDir) {\n return notOk(\n errorRuntime('Target must point to an app-space migration', {\n why: `Expected a path under ${appMigrationsRelative}, got ${target}`,\n fix: 'Pass an app-space migration directory or use a hash prefix.',\n }),\n );\n }\n return ok(targetPath);\n}\n\nexport function resolveByHashPrefix(\n packages: readonly OnDiskMigrationPackage[],\n prefix: string,\n): Result<OnDiskMigrationPackage, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const matches = packages.filter((p) => p.metadata.migrationHash.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No migration has a migrationHash starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.metadata.migrationHash}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\n/**\n * Resolve the latest migration from a space directory.\n *\n * Returns `ok(null)` only when the directory is empty or absent (ENOENT is\n * absorbed by `readMigrationsDir`). If `readMigrationsDir` returned packages\n * but `findLatestMigration` cannot pick a leaf, the on-disk history is\n * corrupt — return a runtime error rather than collapsing it to a `missing`\n * placeholder, which would hide the corruption from the caller.\n */\nexport async function resolveLatestFromDir(\n spaceDir: string,\n): Promise<Result<OnDiskMigrationPackage | null, CliStructuredError>> {\n try {\n const allPackages = await readMigrationsDir(spaceDir);\n if (allPackages.length === 0) return ok(null);\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `No latest migration found in ${relative(process.cwd(), spaceDir)}`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n return ok(leafPkg ?? null);\n } catch (error) {\n if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migrations: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n}\n\nfunction pkgToSpaceResult(\n spaceId: string,\n pkg: OnDiskMigrationPackage,\n client: ReturnType<typeof createControlClient>,\n): MigrationShowSpacePresent {\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n const preview: OperationPreview = client.toOperationPreview(ops) ?? { statements: [] };\n return {\n kind: 'present',\n spaceId,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n createdAt: pkg.metadata.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n preview,\n summary: `${ops.length} operation(s)`,\n };\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } =\n resolveMigrationPaths(options.config, config);\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load the app contract so the aggregate loader can validate it.\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: 'Failed to read contract file',\n }),\n );\n }\n\n let appContract: Contract;\n try {\n appContract = JSON.parse(contractJsonContent) as Contract;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n // Build the aggregate against current disk state to enumerate all spaces.\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const aggregateResult = await buildContractSpaceAggregate({\n targetId: config.target.targetId,\n migrationsDir,\n appContract,\n extensionPacks: config.extensionPacks ?? [],\n validateContract: (json: unknown) => familyInstance.validateContract(json),\n });\n if (!aggregateResult.ok) {\n return notOk(aggregateResult.failure);\n }\n const aggregate = aggregateResult.value;\n\n // `migration show` is an offline command; the control client is constructed\n // purely to dispatch the family-specific `toOperationPreview` capability and\n // is not connected to a database.\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n ...ifDefined('driver', config.driver),\n extensionPacks: config.extensionPacks ?? [],\n });\n\n const spaces: MigrationShowSpaceResult[] = [];\n\n // App space: honour the `target` argument (path or hash prefix) when provided.\n try {\n let appPkg: OnDiskMigrationPackage;\n if (target && looksLikePath(target)) {\n const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);\n if (!resolved.ok) return resolved;\n appPkg = await readMigrationPackage(resolved.value);\n } else {\n const allPackages = await readMigrationsDir(appMigrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${appMigrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n appPkg = resolved.value;\n } else {\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n appPkg = leafPkg;\n }\n }\n spaces.push(pkgToSpaceResult(aggregate.app.spaceId, appPkg, client));\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read app-space migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Extension spaces: always emit one entry per loaded extension so the\n // response enumerates every space the aggregate knows about. Spaces\n // with no on-disk migration package yet (e.g. an extension was declared\n // but never `migrate`d) become `kind: 'missing'` placeholders instead\n // of being silently skipped.\n for (const ext of aggregate.extensions) {\n const extSpaceDir = spaceMigrationDirectory(migrationsDir, ext.spaceId);\n const extPkgResult = await resolveLatestFromDir(extSpaceDir);\n if (!extPkgResult.ok) return extPkgResult;\n if (extPkgResult.value !== null) {\n spaces.push(pkgToSpaceResult(ext.spaceId, extPkgResult.value, client));\n } else {\n spaces.push({\n kind: 'missing',\n spaceId: ext.spaceId,\n summary: 'No on-disk migration package for this space',\n });\n }\n }\n\n return ok({ ok: true, spaces });\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, statement preview, and metadata for every loaded contract\\n' +\n 'space (app + extensions). Accepts a directory path or hash prefix to target a\\n' +\n 'specific app-space migration; defaults to the latest per space.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument('[target]', 'App-space migration path or migrationHash prefix (defaults to latest)')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/contract-space-aggregate-loader.ts","../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"mappings":";;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/contract-space-aggregate-loader.ts","../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"mappings":";;;;;;;;;;;;;;;;UAqHiB,oBAAA;EAAA,SACN,QAAA,EAAU,SAAA;EAAA,SACV,aAAA;EAAA,SACA,WAAA,EAAa,QAAA;EAAA,SACb,cAAA,EAAgB,aAAA,CAAc,0BAAA,CAA2B,SAAA,EAAW,SAAA;EAAA,SACpE,gBAAA,GAAmB,YAAA,cAA0B,QAAA;EAJnC;;;;;;;;;;;;EAAA,SAiBV,oBAAA,GAAuB,aAAA,CAAc,sBAAA;AAAA;;;UCvI/B,SAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,IAAA;EAAA,SACA,QAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA;AAAA;;;KCOC,cAAA;;UAmBK,UAAA;EAAA,SACN,OAAA;EAAA,SACA,MAAA,EAAQ,cAAA;AAAA;;;UCwCF,oBAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAA;EAAA,SACA,EAAA;EAAA,SACA,aAAA;EAAA,SACA,cAAA;EAAA,SACA,gBAAA;EAAA,SACA,cAAA;EAAA,SACA,MAAA,EAAQ,cAAA;AAAA;;;;;;;;;;;;;;;;;;;;UAsBF,yBAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAA;EAAA,SACA,QAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA;EAAA,SACA,MAAA;AAAA;;;;AFlHX;;;;iBE4HgB,+BAAA,CACd,MAAA,WAAiB,yBAAA;AAAA,UAaF,qBAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA,WAAqB,oBAAA;EAAA,SACrB,UAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA;EAAA,SACA,IAAA,YAAgB,SAAA;EFzIhB;EAAA,SE2IA,kBAAA;EFzIA;;;;;;ACOX;;EDPW,SEkJA,iBAAA;ED3Ie;EAAA,SC6If,iBAAA;EAAA,SACA,YAAA;IAAA,SACE,QAAA;IAAA,SACA,MAAA;IAAA,SACA,gBAAA;IAAA,SACA,eAAA;IAAA,SACA,OAAA;IAAA,SACA,kBAAA;IAAA,SACA,mBAAA;IAAA,SACA,YAAA;MAAA,SACE,OAAA;MAAA,SACA,aAAA;MAAA,SACA,IAAA;MAAA,SACA,EAAA;MAAA,SACA,UAAA;IAAA;EAAA;EAAA,SAGJ,OAAA;EAAA,SACA,WAAA,WAAsB,gBAAA;EA/FtB;;;;;;;;;AA2BX;;;;EA3BW,SA6GA,MAAA,YAAkB,yBAAA;EAhFlB;EAAA,SAkFA,wBAAA;EAAA,SACA,KAAA,GAAQ,cAAA;EAAA,SACR,OAAA,YAAmB,sBAAA;EAAA,SACnB,YAAA,YAAwB,UAAA;EAAA,SACxB,aAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA;AAAA;;;;AA5DX;;;;;;;;;;;;iBA2GgB,kBAAA,CACd,KAAA,EAAO,cAAA,EACP,UAAA,UACA,YAAA,UACA,UAAA,sBACA,IAAA,yBACC,UAAA;;;;;;;;;;;;iBAuMmB,yBAAA,CAA0B,IAAA;EAAA,SACrC,QAAA;EAAA,SACA,aAAA;EAAA,SACA,cAAA;EAAA,SACA,cAAA,EAAgB,oBAAA;EAAA,SAChB,gBAAA,EAAkB,oBAAA;EAAA,SAClB,cAAA,EAAgB,WAAA,SAAoB,wBAAA;AAAA,IAC3C,OAAA,UAAiB,yBAAA;AAAA,iBAqlBL,4BAAA,CAAA,GAAgC,OAAA;AAAA,iBAoGhC,mBAAA,CAAoB,MAAA,EAAQ,qBAAA,EAAuB,QAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as loadAggregateStatusSpaces, i as formatStatusSummary, n as createMigrationStatusCommand, r as deriveEdgeStatuses, t as computeTotalPendingAcrossSpaces } from "../migration-status-
|
|
1
|
+
import { a as loadAggregateStatusSpaces, i as formatStatusSummary, n as createMigrationStatusCommand, r as deriveEdgeStatuses, t as computeTotalPendingAcrossSpaces } from "../migration-status-By9G5p2H.mjs";
|
|
2
2
|
export { computeTotalPendingAcrossSpaces, createMigrationStatusCommand, deriveEdgeStatuses, formatStatusSummary, loadAggregateStatusSpaces };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, t as addGlobalOptions } from "./command-helpers-BeZHkxV8.mjs";
|
|
2
2
|
import { t as TerminalUI } from "./terminal-ui-C_hFNbAn.mjs";
|
|
3
3
|
import { t as handleResult } from "./result-handler-rmPVKIP2.mjs";
|
|
4
|
-
import { t as inspectLiveSchema } from "./inspect-live-schema-
|
|
4
|
+
import { t as inspectLiveSchema } from "./inspect-live-schema-DxdBd4Er.mjs";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
7
|
import { dirname, relative, resolve } from "pathe";
|
|
@@ -78,4 +78,4 @@ function createContractInferCommand() {
|
|
|
78
78
|
//#endregion
|
|
79
79
|
export { createContractInferCommand as t };
|
|
80
80
|
|
|
81
|
-
//# sourceMappingURL=contract-infer-
|
|
81
|
+
//# sourceMappingURL=contract-infer-ByxhPjpW.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-infer-
|
|
1
|
+
{"version":3,"file":"contract-infer-ByxhPjpW.mjs","names":[],"sources":["../src/commands/contract-infer-paths.ts","../src/commands/contract-infer.ts"],"sourcesContent":["import { dirname, resolve } from 'pathe';\n\ninterface ContractInferPathOptions {\n readonly output?: string;\n readonly config?: string;\n}\n\n/**\n * Resolves the output path for the inferred PSL contract.\n *\n * Priority:\n * 1. --output <path> flag (resolved relative to cwd)\n * 2. contract.prisma next to config.contract.output\n * 3. Canonical default: contract.prisma in the config directory\n */\nexport function resolveContractInferOutputPath(\n options: ContractInferPathOptions,\n contractOutput: string | undefined,\n): string {\n const configDir = options.config\n ? dirname(resolve(process.cwd(), options.config))\n : process.cwd();\n\n if (options.output) {\n return resolve(process.cwd(), options.output);\n }\n if (contractOutput) {\n const contractPath = resolve(configDir, contractOutput);\n return resolve(dirname(contractPath), 'contract.prisma');\n }\n return resolve(configDir, 'contract.prisma');\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport { printPsl } from '@prisma-next/psl-printer';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { dirname, relative } from 'pathe';\nimport type { CliStructuredError } from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\nimport { resolveContractInferOutputPath } from './contract-infer-paths';\nimport {\n type InspectLiveSchemaOptions,\n type InspectLiveSchemaResult,\n inspectLiveSchema,\n} from './inspect-live-schema';\n\ninterface ContractInferOptions extends InspectLiveSchemaOptions {\n readonly output?: string;\n}\n\ninterface ContractInferSuccessResult {\n readonly ok: true;\n readonly summary: string;\n readonly target: InspectLiveSchemaResult['target'];\n readonly psl: {\n readonly path: string;\n };\n readonly meta: InspectLiveSchemaResult['meta'];\n readonly timings: {\n readonly total: number;\n };\n}\n\nasync function executeContractInferCommand(\n options: ContractInferOptions,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<ContractInferSuccessResult, CliStructuredError>> {\n const flags = parseGlobalFlags(options);\n const inspectResult = await inspectLiveSchema(options, flags, ui, startTime, {\n commandName: 'contract infer',\n description: 'Infer a PSL contract from the live database schema',\n url: 'https://pris.ly/contract-infer',\n });\n\n if (!inspectResult.ok) {\n return inspectResult;\n }\n\n const { config, target, meta, pslContractAst } = inspectResult.value;\n\n if (!pslContractAst) {\n return notOk(\n errorRuntime('contract infer is not supported for this family', {\n why: 'The configured family does not implement the PslContractInferCapable capability, so an inferred PSL contract cannot be produced from the live database schema.',\n fix: 'Use a family that supports contract inference (e.g. SQL/Postgres).',\n }),\n );\n }\n\n const outputPath = resolveContractInferOutputPath(options, config.contract?.output);\n const pslContent = printPsl(pslContractAst);\n\n if (existsSync(outputPath) && !flags.json && !flags.quiet) {\n ui.stderr(`\\u26A0 Overwriting existing file: ${relative(process.cwd(), outputPath)}`);\n }\n\n mkdirSync(dirname(outputPath), { recursive: true });\n writeFileSync(outputPath, pslContent, 'utf-8');\n\n const pslPath = relative(process.cwd(), outputPath);\n if (!flags.json && !flags.quiet) {\n ui.stderr(`\\u2714 Contract written to ${pslPath}`);\n }\n\n return ok({\n ok: true,\n summary: 'Contract inferred successfully',\n target,\n psl: {\n path: pslPath,\n },\n meta,\n timings: {\n total: Date.now() - startTime,\n },\n });\n}\n\nexport function createContractInferCommand(): Command {\n const command = new Command('infer');\n setCommandDescriptions(\n command,\n 'Infer a PSL contract from the live database schema',\n 'Reads the live database schema and writes an inferred PSL contract to disk.\\n' +\n 'This command stops at `contract.prisma`; follow it with `contract emit` and\\n' +\n '`db sign` as separate steps.',\n );\n setCommandExamples(command, [\n 'prisma-next contract infer --db $DATABASE_URL',\n 'prisma-next contract infer --db $DATABASE_URL --output ./prisma/contract.prisma',\n 'prisma-next contract infer --db $DATABASE_URL --json',\n ]);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--output <path>', 'Write the inferred PSL contract to the specified path')\n .action(async (options: ContractInferOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const startTime = Date.now();\n\n const result = await executeContractInferCommand(options, ui, startTime);\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value, null, 2));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAeA,SAAgB,+BACd,SACA,gBACQ;CACR,MAAM,YAAY,QAAQ,SACtB,QAAQ,QAAQ,QAAQ,KAAK,EAAE,QAAQ,OAAO,CAAC,GAC/C,QAAQ,KAAK;CAEjB,IAAI,QAAQ,QACV,OAAO,QAAQ,QAAQ,KAAK,EAAE,QAAQ,OAAO;CAE/C,IAAI,gBAEF,OAAO,QAAQ,QADM,QAAQ,WAAW,eACL,CAAC,EAAE,kBAAkB;CAE1D,OAAO,QAAQ,WAAW,kBAAkB;;;;ACS9C,eAAe,4BACb,SACA,IACA,WACiE;CACjE,MAAM,QAAQ,iBAAiB,QAAQ;CACvC,MAAM,gBAAgB,MAAM,kBAAkB,SAAS,OAAO,IAAI,WAAW;EAC3E,aAAa;EACb,aAAa;EACb,KAAK;EACN,CAAC;CAEF,IAAI,CAAC,cAAc,IACjB,OAAO;CAGT,MAAM,EAAE,QAAQ,QAAQ,MAAM,mBAAmB,cAAc;CAE/D,IAAI,CAAC,gBACH,OAAO,MACL,aAAa,mDAAmD;EAC9D,KAAK;EACL,KAAK;EACN,CAAC,CACH;CAGH,MAAM,aAAa,+BAA+B,SAAS,OAAO,UAAU,OAAO;CACnF,MAAM,aAAa,SAAS,eAAe;CAE3C,IAAI,WAAW,WAAW,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAClD,GAAG,OAAO,qCAAqC,SAAS,QAAQ,KAAK,EAAE,WAAW,GAAG;CAGvF,UAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;CACnD,cAAc,YAAY,YAAY,QAAQ;CAE9C,MAAM,UAAU,SAAS,QAAQ,KAAK,EAAE,WAAW;CACnD,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB,GAAG,OAAO,8BAA8B,UAAU;CAGpD,OAAO,GAAG;EACR,IAAI;EACJ,SAAS;EACT;EACA,KAAK,EACH,MAAM,SACP;EACD;EACA,SAAS,EACP,OAAO,KAAK,KAAK,GAAG,WACrB;EACF,CAAC;;AAGJ,SAAgB,6BAAsC;CACpD,MAAM,UAAU,IAAI,QAAQ,QAAQ;CACpC,uBACE,SACA,sDACA,yLAGD;CACD,mBAAmB,SAAS;EAC1B;EACA;EACA;EACD,CAAC;CACF,iBAAiB,QAAQ,CACtB,OAAO,cAAc,6BAA6B,CAClD,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,mBAAmB,wDAAwD,CAClF,OAAO,OAAO,YAAkC;EAC/C,MAAM,QAAQ,iBAAiB,QAAQ;EACvC,MAAM,KAAK,IAAI,WAAW;GAAE,OAAO,MAAM;GAAO,aAAa,MAAM;GAAa,CAAC;EAIjF,MAAM,WAAW,aAAa,MADT,4BAA4B,SAAS,IAFxC,KAAK,KAEgD,CAAC,EAClC,OAAO,KAAK,UAAU;GAC1D,IAAI,MAAM,MACR,GAAG,OAAO,KAAK,UAAU,OAAO,MAAM,EAAE,CAAC;IAE3C;EAEF,QAAQ,KAAK,SAAS;GACtB;CAEJ,OAAO"}
|