prisma-next 0.5.0-dev.8 → 0.5.0-dev.80
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-errors-B9OBbled.d.mts +3 -0
- package/dist/cli-errors-D3_sMh2K.mjs +33 -0
- package/dist/cli-errors-D3_sMh2K.mjs.map +1 -0
- package/dist/cli.mjs +16 -78
- package/dist/cli.mjs.map +1 -1
- package/dist/client-qVH-rEgd.mjs +1595 -0
- package/dist/client-qVH-rEgd.mjs.map +1 -0
- package/dist/{result-handler-Ba3zWQsI.mjs → command-helpers-BeZHkxV8.mjs} +70 -47
- package/dist/command-helpers-BeZHkxV8.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +2 -4
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +2 -4
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +16 -13
- 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 +6 -7
- 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 +9 -9
- 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 +15 -13
- 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 -321
- package/dist/commands/migration-apply.d.mts +28 -13
- package/dist/commands/migration-apply.d.mts.map +1 -1
- package/dist/commands/migration-apply.mjs +55 -151
- package/dist/commands/migration-apply.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts +0 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +34 -40
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +33 -6
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +2 -348
- package/dist/commands/migration-ref.d.mts +1 -1
- package/dist/commands/migration-ref.d.mts.map +1 -1
- package/dist/commands/migration-ref.mjs +8 -12
- package/dist/commands/migration-ref.mjs.map +1 -1
- package/dist/commands/migration-show.d.mts +13 -7
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +35 -36
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +126 -5
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -4
- package/dist/{config-loader-C25b63rJ.mjs → config-loader-B6sJjXTv.mjs} +3 -5
- package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
- package/dist/config-loader.d.mts +0 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/config-loader.mjs +2 -3
- package/dist/contract-emit-9DBda5Ou.mjs +150 -0
- package/dist/contract-emit-9DBda5Ou.mjs.map +1 -0
- package/dist/contract-emit-B77TsJqf.mjs +327 -0
- package/dist/contract-emit-B77TsJqf.mjs.map +1 -0
- package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-Dani0mMW.mjs} +4 -6
- package/dist/contract-enrichment-Dani0mMW.mjs.map +1 -0
- package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-BK9YFGEG.mjs} +13 -22
- package/dist/contract-infer-BK9YFGEG.mjs.map +1 -0
- package/dist/db-verify-C0y1PCO2.mjs +404 -0
- package/dist/db-verify-C0y1PCO2.mjs.map +1 -0
- package/dist/exports/config-types.mjs +1 -2
- package/dist/exports/control-api.d.mts +101 -586
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +4 -6
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +28 -30
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts +2 -4
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +2 -3
- package/dist/extension-pack-inputs-C7xgE-vv.mjs +74 -0
- package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +1 -0
- package/dist/{framework-components-Cr--XBKy.mjs → framework-components-ChqVUxR-.mjs} +3 -4
- package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-ChqVUxR-.mjs.map} +1 -1
- package/dist/global-flags-Icqpxk23.d.mts +12 -0
- package/dist/global-flags-Icqpxk23.d.mts.map +1 -0
- package/dist/helpers-eqdN8tH6.mjs +25 -0
- package/dist/helpers-eqdN8tH6.mjs.map +1 -0
- package/dist/{init-C5220SY9.mjs → init-CoDVPvQ4.mjs} +26 -35
- package/dist/init-CoDVPvQ4.mjs.map +1 -0
- package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-CWYxGKlb.mjs} +10 -11
- package/dist/inspect-live-schema-CWYxGKlb.mjs.map +1 -0
- package/dist/migration-cli.d.mts +41 -12
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +309 -86
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-B5dORFEv.mjs} +8 -9
- package/dist/migration-command-scaffold-B5dORFEv.mjs.map +1 -0
- package/dist/migration-plan-C6lVaHsO.mjs +554 -0
- package/dist/migration-plan-C6lVaHsO.mjs.map +1 -0
- package/dist/{migration-status-DUMiH8_G.mjs → migration-status-CZ-D5k7k.mjs} +272 -65
- package/dist/migration-status-CZ-D5k7k.mjs.map +1 -0
- package/dist/migrations-D_UJnpuW.mjs +216 -0
- package/dist/migrations-D_UJnpuW.mjs.map +1 -0
- package/dist/{output-BpcQrnnq.mjs → output-B16Kefzx.mjs} +9 -3
- package/dist/output-B16Kefzx.mjs.map +1 -0
- package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-DFfvZcYL.mjs} +2 -2
- package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-DFfvZcYL.mjs.map} +1 -1
- package/dist/result-handler-rmPVKIP2.mjs +25 -0
- package/dist/result-handler-rmPVKIP2.mjs.map +1 -0
- package/dist/rolldown-runtime-twds-ZHy.mjs +14 -0
- package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-C_hFNbAn.mjs} +4 -28
- package/dist/terminal-ui-C_hFNbAn.mjs.map +1 -0
- package/dist/types-D7x-IFLO.d.mts +858 -0
- package/dist/types-D7x-IFLO.d.mts.map +1 -0
- package/dist/{verify-Bkycc-Tf.mjs → verify-CiwNWM9N.mjs} +3 -4
- package/dist/verify-CiwNWM9N.mjs.map +1 -0
- package/package.json +19 -17
- package/dist/cli-errors-BFYgBH3L.d.mts +0 -4
- package/dist/cli-errors-Cd79vmTH.mjs +0 -5
- package/dist/client-CrsnY58k.mjs +0 -997
- package/dist/client-CrsnY58k.mjs.map +0 -1
- package/dist/commands/db-verify.mjs.map +0 -1
- package/dist/commands/migration-plan.mjs.map +0 -1
- package/dist/config-loader-C25b63rJ.mjs.map +0 -1
- package/dist/contract-emit--feXyNd7.mjs +0 -4
- package/dist/contract-emit-NJ01hiiv.mjs +0 -195
- package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
- package/dist/contract-emit-V5SSitUT.mjs +0 -122
- package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
- package/dist/contract-enrichment-CAOELa-H.mjs.map +0 -1
- package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
- package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
- package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
- package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
- package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
- package/dist/init-C5220SY9.mjs.map +0 -1
- package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
- package/dist/migration-command-scaffold-B3B09et6.mjs.map +0 -1
- package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
- package/dist/migrations-Bo5WtTla.mjs +0 -153
- package/dist/migrations-Bo5WtTla.mjs.map +0 -1
- package/dist/output-BpcQrnnq.mjs.map +0 -1
- package/dist/result-handler-Ba3zWQsI.mjs.map +0 -1
- package/dist/terminal-ui-C3ZLwQxK.mjs.map +0 -1
- package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
- package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
- package/dist/verify-Bkycc-Tf.mjs.map +0 -1
|
@@ -1,45 +1,46 @@
|
|
|
1
|
-
import { t as loadConfig } from "../config-loader-
|
|
2
|
-
import { _ as errorUnexpected, m as errorRuntime } from "../cli-errors-
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as TerminalUI } from "../terminal-ui-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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";
|
|
4
|
+
import { t as TerminalUI } from "../terminal-ui-C_hFNbAn.mjs";
|
|
5
|
+
import { t as handleResult } from "../result-handler-rmPVKIP2.mjs";
|
|
6
|
+
import { t as createControlClient } from "../client-qVH-rEgd.mjs";
|
|
7
|
+
import { a as formatMigrationShowOutput } from "../migrations-D_UJnpuW.mjs";
|
|
7
8
|
import { Command } from "commander";
|
|
8
9
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
9
10
|
import { relative, resolve } from "pathe";
|
|
10
|
-
import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/dag";
|
|
11
11
|
import { readMigrationPackage, readMigrationsDir } from "@prisma-next/migration-tools/io";
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/migration-graph";
|
|
13
|
+
import { APP_SPACE_ID, spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
|
|
14
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
14
15
|
//#region src/commands/migration-show.ts
|
|
15
16
|
function looksLikePath(target) {
|
|
16
17
|
return target.includes("/") || target.includes("\\");
|
|
17
18
|
}
|
|
18
19
|
function resolveByHashPrefix(packages, prefix) {
|
|
19
20
|
const normalizedPrefix = prefix.startsWith("sha256:") ? prefix : `sha256:${prefix}`;
|
|
20
|
-
const matches = packages.filter((p) => p.
|
|
21
|
+
const matches = packages.filter((p) => p.metadata.migrationHash.startsWith(normalizedPrefix));
|
|
21
22
|
if (matches.length === 1) return ok(matches[0]);
|
|
22
23
|
if (matches.length === 0) return notOk(errorRuntime("No migration found matching prefix", {
|
|
23
|
-
why: `No migration has a
|
|
24
|
+
why: `No migration has a migrationHash starting with "${normalizedPrefix}"`,
|
|
24
25
|
fix: "Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages."
|
|
25
26
|
}));
|
|
26
27
|
return notOk(errorRuntime("Ambiguous hash prefix", {
|
|
27
|
-
why: `Multiple migrations match prefix "${normalizedPrefix}":\n${matches.map((p) => ` ${p.dirName} ${p.
|
|
28
|
+
why: `Multiple migrations match prefix "${normalizedPrefix}":\n${matches.map((p) => ` ${p.dirName} ${p.metadata.migrationHash}`).join("\n")}`,
|
|
28
29
|
fix: "Provide a longer prefix to uniquely identify the migration."
|
|
29
30
|
}));
|
|
30
31
|
}
|
|
31
32
|
async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
32
33
|
const config = await loadConfig(options.config);
|
|
33
34
|
const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
|
|
34
|
-
const
|
|
35
|
-
const
|
|
35
|
+
const appMigrationsDir = spaceMigrationDirectory(resolve(options.config ? resolve(options.config, "..") : process.cwd(), config.migrations?.dir ?? "migrations"), APP_SPACE_ID);
|
|
36
|
+
const appMigrationsRelative = relative(process.cwd(), appMigrationsDir);
|
|
36
37
|
if (!flags.json && !flags.quiet) {
|
|
37
38
|
const details = [{
|
|
38
39
|
label: "config",
|
|
39
40
|
value: configPath
|
|
40
41
|
}, {
|
|
41
42
|
label: "migrations",
|
|
42
|
-
value:
|
|
43
|
+
value: appMigrationsRelative
|
|
43
44
|
}];
|
|
44
45
|
if (target) details.push({
|
|
45
46
|
label: "target",
|
|
@@ -57,9 +58,9 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
|
57
58
|
try {
|
|
58
59
|
if (target && looksLikePath(target)) pkg = await readMigrationPackage(resolve(target));
|
|
59
60
|
else {
|
|
60
|
-
const allPackages = await readMigrationsDir(
|
|
61
|
+
const allPackages = await readMigrationsDir(appMigrationsDir);
|
|
61
62
|
if (allPackages.length === 0) return notOk(errorRuntime("No migrations found", {
|
|
62
|
-
why: `No migration packages found in ${
|
|
63
|
+
why: `No migration packages found in ${appMigrationsRelative}`,
|
|
63
64
|
fix: "Run `prisma-next migration plan` to create a migration first."
|
|
64
65
|
}));
|
|
65
66
|
if (target) {
|
|
@@ -72,7 +73,7 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
|
72
73
|
why: "No latest migration found in the migration history",
|
|
73
74
|
fix: "The migrations directory may be corrupted. Inspect the migration.json files."
|
|
74
75
|
}));
|
|
75
|
-
const leafPkg = allPackages.find((p) => p.
|
|
76
|
+
const leafPkg = allPackages.find((p) => p.metadata.migrationHash === latestMigration.migrationHash);
|
|
76
77
|
if (!leafPkg) return notOk(errorRuntime("Could not resolve latest migration", {
|
|
77
78
|
why: `Latest migration ${latestMigration.dirName} does not match any package`,
|
|
78
79
|
fix: "The migrations directory may be corrupted. Inspect the migration.json files."
|
|
@@ -81,41 +82,39 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
} catch (error) {
|
|
84
|
-
if (MigrationToolsError.is(error)) return notOk(
|
|
85
|
-
why: error.why,
|
|
86
|
-
fix: error.fix,
|
|
87
|
-
meta: {
|
|
88
|
-
code: error.code,
|
|
89
|
-
...error.details ?? {}
|
|
90
|
-
}
|
|
91
|
-
}));
|
|
85
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
92
86
|
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}` }));
|
|
93
87
|
}
|
|
94
88
|
const ops = pkg.ops;
|
|
95
|
-
const
|
|
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
96
|
return ok({
|
|
97
97
|
ok: true,
|
|
98
98
|
dirName: pkg.dirName,
|
|
99
99
|
dirPath: relative(process.cwd(), pkg.dirPath),
|
|
100
|
-
from: pkg.
|
|
101
|
-
to: pkg.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
createdAt: pkg.manifest.createdAt,
|
|
100
|
+
from: pkg.metadata.from,
|
|
101
|
+
to: pkg.metadata.to,
|
|
102
|
+
migrationHash: pkg.metadata.migrationHash,
|
|
103
|
+
createdAt: pkg.metadata.createdAt,
|
|
105
104
|
operations: ops.map((op) => ({
|
|
106
105
|
id: op.id,
|
|
107
106
|
label: op.label,
|
|
108
107
|
operationClass: op.operationClass
|
|
109
108
|
})),
|
|
110
|
-
|
|
109
|
+
preview,
|
|
111
110
|
summary: `${ops.length} operation(s)`
|
|
112
111
|
});
|
|
113
112
|
}
|
|
114
113
|
function createMigrationShowCommand() {
|
|
115
114
|
const command = new Command("show");
|
|
116
|
-
setCommandDescriptions(command, "Display migration package contents", "Shows the operations,
|
|
115
|
+
setCommandDescriptions(command, "Display migration package contents", "Shows the operations, statement preview, and metadata for a migration package.\nAccepts a directory path, a hash prefix (git-style), or defaults to the\nlatest migration.");
|
|
117
116
|
setCommandExamples(command, ["prisma-next migration show", "prisma-next migration show sha256:a1b2c3"]);
|
|
118
|
-
addGlobalOptions(command).argument("[target]", "Migration directory path or
|
|
117
|
+
addGlobalOptions(command).argument("[target]", "Migration directory path or migrationHash prefix (defaults to latest)").option("--config <path>", "Path to prisma-next.config.ts").action(async (target, options) => {
|
|
119
118
|
const flags = parseGlobalFlags(options);
|
|
120
119
|
const ui = new TerminalUI({
|
|
121
120
|
color: flags.color,
|
|
@@ -129,7 +128,7 @@ function createMigrationShowCommand() {
|
|
|
129
128
|
});
|
|
130
129
|
return command;
|
|
131
130
|
}
|
|
132
|
-
|
|
133
131
|
//#endregion
|
|
134
132
|
export { createMigrationShowCommand, resolveByHashPrefix };
|
|
133
|
+
|
|
135
134
|
//# sourceMappingURL=migration-show.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-show.mjs","names":["details: Array<{ label: string; value: string }>","pkg: MigrationBundle"],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\nimport { findLatestMigration, reconstructGraph } from '@prisma-next/migration-tools/dag';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport type { MigrationBundle } from '@prisma-next/migration-tools/types';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\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 { extractOperationStatements } from '../control-api/operations/extract-operation-statements';\nimport { type CliStructuredError, errorRuntime, errorUnexpected } 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;\n readonly to: string;\n readonly migrationId: string;\n readonly kind: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql: readonly string[];\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 MigrationBundle[],\n prefix: string,\n): Result<MigrationBundle, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const matches = packages.filter((p) => p.manifest.migrationId.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 migrationId 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.manifest.migrationId}`).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 migrationsDir = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\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: MigrationBundle;\n\n try {\n if (target && looksLikePath(target)) {\n pkg = await readMigrationPackage(resolve(target));\n } else {\n const allPackages = await readMigrationsDir(migrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${migrationsRelative}`,\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.manifest.migrationId === latestMigration.migrationId,\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(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\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 const sql = extractOperationStatements(config.family.familyId, ops) ?? [];\n\n const result: MigrationShowResult = {\n ok: true,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.manifest.from,\n to: pkg.manifest.to,\n migrationId: pkg.manifest.migrationId,\n kind: pkg.manifest.kind,\n createdAt: pkg.manifest.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\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, DDL 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(\n '[target]',\n 'Migration directory path or migrationId hash prefix (defaults to latest)',\n )\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 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,6 +1,40 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import {
|
|
2
|
+
import { Result } from "@prisma-next/utils/result";
|
|
3
|
+
import { ControlExtensionDescriptor } from "@prisma-next/framework-components/control";
|
|
4
|
+
import { ContractMarkerRecordLike } from "@prisma-next/migration-tools/aggregate";
|
|
5
|
+
import { Contract } from "@prisma-next/contract/types";
|
|
6
|
+
import { OnDiskMigrationPackage } from "@prisma-next/migration-tools/package";
|
|
7
|
+
import { MigrationGraph } from "@prisma-next/migration-tools/graph";
|
|
3
8
|
|
|
9
|
+
//#region src/utils/contract-space-aggregate-loader.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* Inputs needed to compose the aggregate loader at the CLI surface.
|
|
12
|
+
*
|
|
13
|
+
* Keeps the loader framework-neutral (no `Config` import) by accepting
|
|
14
|
+
* already-resolved structural inputs: validated app contract, target
|
|
15
|
+
* id, migrations root directory, and the set of extension descriptors.
|
|
16
|
+
*/
|
|
17
|
+
interface BuildAggregateInputs<TFamilyId extends string, TTargetId extends string> {
|
|
18
|
+
readonly targetId: TTargetId;
|
|
19
|
+
readonly migrationsDir: string;
|
|
20
|
+
readonly appContract: Contract;
|
|
21
|
+
readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
|
|
22
|
+
readonly validateContract: (contractJson: unknown) => Contract;
|
|
23
|
+
/**
|
|
24
|
+
* App-space migration packages to hydrate the app member's
|
|
25
|
+
* migration graph with. Defaults to `[]` (matches the `db init` /
|
|
26
|
+
* `db update` daily-driver behaviour, where the app's authored
|
|
27
|
+
* `migrations/` graph is not walked — the planner uses the synth
|
|
28
|
+
* strategy for the app member instead).
|
|
29
|
+
*
|
|
30
|
+
* `migration apply` callers thread the user's authored app-space
|
|
31
|
+
* packages (loaded via `loadMigrationPackages(appMigrationsDir)`)
|
|
32
|
+
* through here so the graph-walk strategy can plot a path through
|
|
33
|
+
* them — the prod-time replay path explicitly forbids synth.
|
|
34
|
+
*/
|
|
35
|
+
readonly appMigrationPackages?: ReadonlyArray<OnDiskMigrationPackage>;
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
4
38
|
//#region src/utils/migration-types.d.ts
|
|
5
39
|
interface StatusRef {
|
|
6
40
|
readonly name: string;
|
|
@@ -27,12 +61,47 @@ interface MigrationStatusEntry {
|
|
|
27
61
|
readonly dirName: string;
|
|
28
62
|
readonly from: string;
|
|
29
63
|
readonly to: string;
|
|
30
|
-
readonly
|
|
64
|
+
readonly migrationHash: string;
|
|
31
65
|
readonly operationCount: number;
|
|
32
66
|
readonly operationSummary: string;
|
|
33
67
|
readonly hasDestructive: boolean;
|
|
34
68
|
readonly status: EdgeStatusKind | 'unknown';
|
|
35
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Per-space status row in the aggregate-shaped status output.
|
|
72
|
+
*
|
|
73
|
+
* Surfaces, for each contract space:
|
|
74
|
+
*
|
|
75
|
+
* - `headHash`: the on-disk head ref's hash (where the space is going).
|
|
76
|
+
* - `markerHash`: the live marker hash for the space, or null if no
|
|
77
|
+
* marker has been written yet (greenfield, or pre-`migration apply`).
|
|
78
|
+
* - `pendingCount`: number of migration edges between marker and head.
|
|
79
|
+
* Computed via {@link graphWalkStrategy}; 0 means the space is
|
|
80
|
+
* already at head.
|
|
81
|
+
* - `status`: convenience tag the formatter uses to pick a glyph.
|
|
82
|
+
* `'never-planned'` is reserved for spaces with non-empty head but
|
|
83
|
+
* no on-disk migrations — which shouldn't happen if the loader's
|
|
84
|
+
* integrity check passes.
|
|
85
|
+
*
|
|
86
|
+
* Online-only fields (`markerHash`, `status`) are absent when the
|
|
87
|
+
* command runs without a database connection.
|
|
88
|
+
*/
|
|
89
|
+
interface MigrationStatusSpaceEntry {
|
|
90
|
+
readonly spaceId: string;
|
|
91
|
+
readonly kind: 'app' | 'extension';
|
|
92
|
+
readonly headHash: string;
|
|
93
|
+
readonly markerHash?: string | null;
|
|
94
|
+
readonly pendingCount?: number;
|
|
95
|
+
readonly status?: 'up-to-date' | 'pending' | 'no-marker' | 'never-planned' | 'unreachable';
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Sum per-space `pendingCount` into a cross-space total, but only when
|
|
99
|
+
* every loaded space reports a defined `pendingCount`. Returns
|
|
100
|
+
* `undefined` if any space is on the marker-unknown / offline path
|
|
101
|
+
* (where `pendingCount` is intentionally absent), so JSON consumers can
|
|
102
|
+
* distinguish "no pending" from "unknown".
|
|
103
|
+
*/
|
|
104
|
+
declare function computeTotalPendingAcrossSpaces(spaces: readonly MigrationStatusSpaceEntry[]): number | undefined;
|
|
36
105
|
interface MigrationStatusResult {
|
|
37
106
|
readonly ok: true;
|
|
38
107
|
readonly mode: 'online' | 'offline';
|
|
@@ -41,23 +110,55 @@ interface MigrationStatusResult {
|
|
|
41
110
|
readonly targetHash: string;
|
|
42
111
|
readonly contractHash: string;
|
|
43
112
|
readonly refs?: readonly StatusRef[];
|
|
113
|
+
/** Required invariants from the active ref, sorted ascending. Always present (`[]` when no `--ref` or the ref declares none) — knowable offline. */
|
|
114
|
+
readonly requiredInvariants: readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* Invariants the marker has applied at least once, intersected with
|
|
117
|
+
* `requiredInvariants` for display relevance. JSON consumers see only the
|
|
118
|
+
* subset overlapping the active ref's required set — the full unfiltered
|
|
119
|
+
* marker invariant list lives on `marker.invariants` (control plane) and
|
|
120
|
+
* is not surfaced here. Present only in `mode === 'online'`; absent when
|
|
121
|
+
* offline (the marker is unknown, not empty).
|
|
122
|
+
*/
|
|
123
|
+
readonly appliedInvariants?: readonly string[];
|
|
124
|
+
/** required − applied. Present only in `mode === 'online'`; absent when offline. */
|
|
125
|
+
readonly missingInvariants?: readonly string[];
|
|
44
126
|
readonly pathDecision?: {
|
|
45
127
|
readonly fromHash: string;
|
|
46
128
|
readonly toHash: string;
|
|
47
129
|
readonly alternativeCount: number;
|
|
48
130
|
readonly tieBreakReasons: readonly string[];
|
|
49
131
|
readonly refName?: string;
|
|
132
|
+
readonly requiredInvariants: readonly string[];
|
|
133
|
+
readonly satisfiedInvariants: readonly string[];
|
|
50
134
|
readonly selectedPath: readonly {
|
|
51
135
|
readonly dirName: string;
|
|
52
|
-
readonly
|
|
136
|
+
readonly migrationHash: string;
|
|
53
137
|
readonly from: string;
|
|
54
138
|
readonly to: string;
|
|
139
|
+
readonly invariants: readonly string[];
|
|
55
140
|
}[];
|
|
56
141
|
};
|
|
57
142
|
readonly summary: string;
|
|
58
143
|
readonly diagnostics: readonly StatusDiagnostic[];
|
|
144
|
+
/**
|
|
145
|
+
* Aggregate enumeration of every on-disk contract space (app +
|
|
146
|
+
* extensions), in canonical schedule order (extensions
|
|
147
|
+
* alphabetically, then app). Present whenever the aggregate loader
|
|
148
|
+
* succeeded; absent in early-error returns (e.g. unreadable
|
|
149
|
+
* migrations directory) where the existing diagnostics already
|
|
150
|
+
* surface the failure.
|
|
151
|
+
*
|
|
152
|
+
* The legacy top-level fields (`migrations`, `markerHash`,
|
|
153
|
+
* `targetHash`, `pathDecision`, …) describe the **app member**
|
|
154
|
+
* specifically — back-compat with single-space callers. Per-space
|
|
155
|
+
* detail for extension members lives only on this list.
|
|
156
|
+
*/
|
|
157
|
+
readonly spaces?: readonly MigrationStatusSpaceEntry[];
|
|
158
|
+
/** Cross-space pending-migration total (sum of `spaces[].pendingCount`). Present when `spaces` is. */
|
|
159
|
+
readonly totalPendingAcrossSpaces?: number;
|
|
59
160
|
readonly graph?: MigrationGraph;
|
|
60
|
-
readonly bundles?: readonly
|
|
161
|
+
readonly bundles?: readonly OnDiskMigrationPackage[];
|
|
61
162
|
readonly edgeStatuses?: readonly EdgeStatus[];
|
|
62
163
|
readonly activeRefHash?: string;
|
|
63
164
|
readonly activeRefName?: string;
|
|
@@ -79,7 +180,27 @@ interface MigrationStatusResult {
|
|
|
79
180
|
* @internal Exported for testing only.
|
|
80
181
|
*/
|
|
81
182
|
declare function deriveEdgeStatuses(graph: MigrationGraph, targetHash: string, contractHash: string, markerHash: string | undefined, mode: 'online' | 'offline'): EdgeStatus[];
|
|
183
|
+
/**
|
|
184
|
+
* Build the aggregate enumeration of contract spaces for the status
|
|
185
|
+
* output. Loads the aggregate from disk (lossy on failure — extension
|
|
186
|
+
* spaces are simply omitted, the existing single-space app behaviour
|
|
187
|
+
* keeps working), reads per-space marker rows when online, and uses
|
|
188
|
+
* {@link graphWalkStrategy} to compute each space's pending count.
|
|
189
|
+
*
|
|
190
|
+
* Sub-spec § `migration status` semantics — the aggregate-walking
|
|
191
|
+
* version reports per-space marker + pending state alongside the
|
|
192
|
+
* cross-space totals.
|
|
193
|
+
*/
|
|
194
|
+
declare function loadAggregateStatusSpaces(args: {
|
|
195
|
+
readonly targetId: string;
|
|
196
|
+
readonly migrationsDir: string;
|
|
197
|
+
readonly appContractRaw: unknown;
|
|
198
|
+
readonly extensionPacks: BuildAggregateInputs<string, string>['extensionPacks'];
|
|
199
|
+
readonly validateContract: BuildAggregateInputs<string, string>['validateContract'];
|
|
200
|
+
readonly markersBySpace: ReadonlyMap<string, ContractMarkerRecordLike> | null;
|
|
201
|
+
}): Promise<readonly MigrationStatusSpaceEntry[]>;
|
|
82
202
|
declare function createMigrationStatusCommand(): Command;
|
|
203
|
+
declare function formatStatusSummary(result: MigrationStatusResult, colorize: boolean): string;
|
|
83
204
|
//#endregion
|
|
84
|
-
export { MigrationStatusEntry, MigrationStatusResult, type StatusDiagnostic, type StatusRef, createMigrationStatusCommand, deriveEdgeStatuses };
|
|
205
|
+
export { MigrationStatusEntry, MigrationStatusResult, MigrationStatusSpaceEntry, type StatusDiagnostic, type StatusRef, computeTotalPendingAcrossSpaces, createMigrationStatusCommand, deriveEdgeStatuses, formatStatusSummary, loadAggregateStatusSpaces };
|
|
85
206
|
//# sourceMappingURL=migration-status.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"
|
|
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":";;;;;;;;;;;;;;;;UAuIiB,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;;;UCzJ/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,iBA6kBL,4BAAA,CAAA,GAAgC,OAAA;AAAA,iBAoGhC,mBAAA,CAAoB,MAAA,EAAQ,qBAAA,EAAuB,QAAA"}
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export { createMigrationStatusCommand, deriveEdgeStatuses };
|
|
1
|
+
import { a as loadAggregateStatusSpaces, i as formatStatusSummary, n as createMigrationStatusCommand, r as deriveEdgeStatuses, t as computeTotalPendingAcrossSpaces } from "../migration-status-CZ-D5k7k.mjs";
|
|
2
|
+
export { computeTotalPendingAcrossSpaces, createMigrationStatusCommand, deriveEdgeStatuses, formatStatusSummary, loadAggregateStatusSpaces };
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { getEmittedArtifactPaths } from "@prisma-next/emitter";
|
|
2
2
|
import { errorConfigFileNotFound, errorConfigValidation, errorUnexpected } from "@prisma-next/errors/control";
|
|
3
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
3
4
|
import { dirname, resolve } from "pathe";
|
|
4
5
|
import { ConfigValidationError, validateConfig } from "@prisma-next/config/config-validation";
|
|
5
|
-
import { ifDefined } from "@prisma-next/utils/defined";
|
|
6
6
|
import { loadConfig } from "c12";
|
|
7
7
|
import { normalizeContractConfig } from "@prisma-next/config/config-types";
|
|
8
|
-
|
|
9
8
|
//#region src/config-path-validation.ts
|
|
10
9
|
function throwValidation(field, why) {
|
|
11
10
|
throw new ConfigValidationError(field, why);
|
|
@@ -44,7 +43,6 @@ function finalizeConfig(config, configDir) {
|
|
|
44
43
|
}
|
|
45
44
|
};
|
|
46
45
|
}
|
|
47
|
-
|
|
48
46
|
//#endregion
|
|
49
47
|
//#region src/config-loader.ts
|
|
50
48
|
async function loadValidatedConfig(configPath) {
|
|
@@ -84,7 +82,7 @@ async function loadConfig$1(configPath) {
|
|
|
84
82
|
throw errorUnexpected(String(error));
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
|
-
|
|
88
85
|
//#endregion
|
|
89
86
|
export { loadConfig$1 as t };
|
|
90
|
-
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=config-loader-B6sJjXTv.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader-B6sJjXTv.mjs","names":["loadConfigC12","loadConfig"],"sources":["../src/config-path-validation.ts","../src/config-loader.ts"],"sourcesContent":["import {\n type ContractSourceProvider,\n normalizeContractConfig,\n type PrismaNextConfig,\n} from '@prisma-next/config/config-types';\nimport { ConfigValidationError } from '@prisma-next/config/config-validation';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { resolve } from 'pathe';\n\nfunction throwValidation(field: string, why: string): never {\n throw new ConfigValidationError(field, why);\n}\n\nfunction finalizeContractSource(\n source: ContractSourceProvider,\n configDir: string,\n): ContractSourceProvider {\n const resolvedInputs = source.inputs?.map((input) => resolve(configDir, input));\n if (resolvedInputs === undefined) {\n return source;\n }\n\n return {\n ...source,\n inputs: resolvedInputs,\n };\n}\n\nfunction validateNoOutputsAreInputs(\n inputs: readonly string[] | undefined,\n output: string | undefined,\n): void {\n if (inputs === undefined || output === undefined) {\n return;\n }\n\n let emittedArtifactPaths: ReturnType<typeof getEmittedArtifactPaths>;\n try {\n emittedArtifactPaths = getEmittedArtifactPaths(output);\n } catch (error) {\n throwValidation('contract.output', error instanceof Error ? error.message : String(error));\n }\n\n const emittedPaths = new Set([emittedArtifactPaths.jsonPath, emittedArtifactPaths.dtsPath]);\n\n for (const input of inputs) {\n if (emittedPaths.has(input)) {\n throwValidation(\n 'contract.source.inputs[]',\n 'Config.contract.source.inputs must not include emitted artifact paths derived from contract.output',\n );\n }\n }\n}\n\nexport function finalizeConfig(config: PrismaNextConfig, configDir: string): PrismaNextConfig {\n if (!config.contract) {\n return config;\n }\n const contract = normalizeContractConfig(config.contract);\n const source = finalizeContractSource(contract.source, configDir);\n const output = resolve(configDir, contract.output);\n\n validateNoOutputsAreInputs(source.inputs, output);\n\n return {\n ...config,\n contract: {\n ...contract,\n source,\n output,\n },\n };\n}\n","import type { PrismaNextConfig } from '@prisma-next/config/config-types';\nimport { ConfigValidationError, validateConfig } from '@prisma-next/config/config-validation';\nimport {\n errorConfigFileNotFound,\n errorConfigValidation,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { loadConfig as loadConfigC12 } from 'c12';\nimport { dirname, resolve } from 'pathe';\nimport { finalizeConfig } from './config-path-validation';\n\nasync function loadValidatedConfig(configPath?: string): Promise<PrismaNextConfig> {\n const cwd = process.cwd();\n const resolvedConfigPath = configPath ? resolve(cwd, configPath) : undefined;\n const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;\n\n const result = await loadConfigC12<PrismaNextConfig>({\n name: 'prisma-next',\n ...ifDefined('configFile', resolvedConfigPath),\n cwd: configCwd,\n });\n\n // When a specific config file was requested, verify it was actually loaded\n // (c12 falls back to searching by name if the specified file doesn't exist)\n if (resolvedConfigPath && result.configFile !== resolvedConfigPath) {\n throw errorConfigFileNotFound(resolvedConfigPath);\n }\n\n // Check if config is missing or empty (c12 may return empty object when file doesn't exist)\n if (!result.config || Object.keys(result.config).length === 0) {\n // Use c12's configFile if available, otherwise use explicit configPath, otherwise omit path\n const displayPath = result.configFile || resolvedConfigPath || configPath;\n throw errorConfigFileNotFound(displayPath);\n }\n\n // Validate config structure\n validateConfig(result.config);\n\n const loadedConfigDir = result.configFile ? dirname(result.configFile) : configCwd;\n return finalizeConfig(result.config, loadedConfigDir);\n}\n\n/**\n * Loads the Prisma Next config from a TypeScript file.\n * Supports both default export and named export.\n * Uses c12 to automatically handle TypeScript compilation and config file discovery.\n *\n * @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.\n * @returns The loaded config object.\n * @throws Error if config file doesn't exist or is invalid.\n */\nexport async function loadConfig(configPath?: string): Promise<PrismaNextConfig> {\n try {\n return await loadValidatedConfig(configPath);\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw errorConfigValidation(error.field, {\n why: error.why,\n });\n }\n\n // Re-throw structured errors as-is\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code: string }).code === 'string'\n ) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Check for file not found errors\n if (\n error.message.includes('not found') ||\n error.message.includes('Cannot find') ||\n error.message.includes('ENOENT')\n ) {\n // Use resolved path if available, otherwise use original configPath\n const displayPath = configPath ? resolve(process.cwd(), configPath) : undefined;\n throw errorConfigFileNotFound(displayPath, {\n why: error.message,\n });\n }\n // For other errors, wrap in unexpected error\n throw errorUnexpected(error.message, {\n why: `Failed to load config: ${error.message}`,\n });\n }\n throw errorUnexpected(String(error));\n }\n}\n"],"mappings":";;;;;;;;AASA,SAAS,gBAAgB,OAAe,KAAoB;CAC1D,MAAM,IAAI,sBAAsB,OAAO,IAAI;;AAG7C,SAAS,uBACP,QACA,WACwB;CACxB,MAAM,iBAAiB,OAAO,QAAQ,KAAK,UAAU,QAAQ,WAAW,MAAM,CAAC;CAC/E,IAAI,mBAAmB,KAAA,GACrB,OAAO;CAGT,OAAO;EACL,GAAG;EACH,QAAQ;EACT;;AAGH,SAAS,2BACP,QACA,QACM;CACN,IAAI,WAAW,KAAA,KAAa,WAAW,KAAA,GACrC;CAGF,IAAI;CACJ,IAAI;EACF,uBAAuB,wBAAwB,OAAO;UAC/C,OAAO;EACd,gBAAgB,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;;CAG5F,MAAM,eAAe,IAAI,IAAI,CAAC,qBAAqB,UAAU,qBAAqB,QAAQ,CAAC;CAE3F,KAAK,MAAM,SAAS,QAClB,IAAI,aAAa,IAAI,MAAM,EACzB,gBACE,4BACA,qGACD;;AAKP,SAAgB,eAAe,QAA0B,WAAqC;CAC5F,IAAI,CAAC,OAAO,UACV,OAAO;CAET,MAAM,WAAW,wBAAwB,OAAO,SAAS;CACzD,MAAM,SAAS,uBAAuB,SAAS,QAAQ,UAAU;CACjE,MAAM,SAAS,QAAQ,WAAW,SAAS,OAAO;CAElD,2BAA2B,OAAO,QAAQ,OAAO;CAEjD,OAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG;GACH;GACA;GACD;EACF;;;;AC5DH,eAAe,oBAAoB,YAAgD;CACjF,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,qBAAqB,aAAa,QAAQ,KAAK,WAAW,GAAG,KAAA;CACnE,MAAM,YAAY,qBAAqB,QAAQ,mBAAmB,GAAG;CAErE,MAAM,SAAS,MAAMA,WAAgC;EACnD,MAAM;EACN,GAAG,UAAU,cAAc,mBAAmB;EAC9C,KAAK;EACN,CAAC;CAIF,IAAI,sBAAsB,OAAO,eAAe,oBAC9C,MAAM,wBAAwB,mBAAmB;CAInD,IAAI,CAAC,OAAO,UAAU,OAAO,KAAK,OAAO,OAAO,CAAC,WAAW,GAG1D,MAAM,wBADc,OAAO,cAAc,sBAAsB,WACrB;CAI5C,eAAe,OAAO,OAAO;CAE7B,MAAM,kBAAkB,OAAO,aAAa,QAAQ,OAAO,WAAW,GAAG;CACzE,OAAO,eAAe,OAAO,QAAQ,gBAAgB;;;;;;;;;;;AAYvD,eAAsBC,aAAW,YAAgD;CAC/E,IAAI;EACF,OAAO,MAAM,oBAAoB,WAAW;UACrC,OAAO;EACd,IAAI,iBAAiB,uBACnB,MAAM,sBAAsB,MAAM,OAAO,EACvC,KAAK,MAAM,KACZ,CAAC;EAIJ,IACE,iBAAiB,SACjB,UAAU,SACV,OAAQ,MAA2B,SAAS,UAE5C,MAAM;EAGR,IAAI,iBAAiB,OAAO;GAE1B,IACE,MAAM,QAAQ,SAAS,YAAY,IACnC,MAAM,QAAQ,SAAS,cAAc,IACrC,MAAM,QAAQ,SAAS,SAAS,EAIhC,MAAM,wBADc,aAAa,QAAQ,QAAQ,KAAK,EAAE,WAAW,GAAG,KAAA,GAC3B,EACzC,KAAK,MAAM,SACZ,CAAC;GAGJ,MAAM,gBAAgB,MAAM,SAAS,EACnC,KAAK,0BAA0B,MAAM,WACtC,CAAC;;EAEJ,MAAM,gBAAgB,OAAO,MAAM,CAAC"}
|
package/dist/config-loader.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.mts","names":[],"sources":["../src/config-loader.ts"],"
|
|
1
|
+
{"version":3,"file":"config-loader.d.mts","names":[],"sources":["../src/config-loader.ts"],"mappings":";;;;;AAoDA;;;;;;;iBAAsB,UAAA,CAAW,UAAA,YAAsB,OAAA,CAAQ,gBAAA"}
|
package/dist/config-loader.mjs
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import { t as loadConfig } from "./config-loader-
|
|
2
|
-
|
|
3
|
-
export { loadConfig };
|
|
1
|
+
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
+
export { loadConfig };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
+
import { _ as errorUnexpected$1, t as CliStructuredError$1 } from "./cli-errors-D3_sMh2K.mjs";
|
|
3
|
+
import { n as executeContractEmit } from "./contract-emit-B77TsJqf.mjs";
|
|
4
|
+
import { r as isVerbose } from "./helpers-eqdN8tH6.mjs";
|
|
5
|
+
import { b as formatSuccessMessage, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, t as addGlobalOptions, y as formatStyledHeader } from "./command-helpers-BeZHkxV8.mjs";
|
|
6
|
+
import { t as createProgressAdapter } from "./progress-adapter-DFfvZcYL.mjs";
|
|
7
|
+
import { t as TerminalUI } from "./terminal-ui-C_hFNbAn.mjs";
|
|
8
|
+
import { t as handleResult } from "./result-handler-rmPVKIP2.mjs";
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
import { getEmittedArtifactPaths } from "@prisma-next/emitter";
|
|
11
|
+
import { errorContractConfigMissing } from "@prisma-next/errors/control";
|
|
12
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
13
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
14
|
+
import { dirname, relative, resolve } from "pathe";
|
|
15
|
+
//#region src/utils/formatters/emit.ts
|
|
16
|
+
/**
|
|
17
|
+
* Formats human-readable output for contract emit.
|
|
18
|
+
*/
|
|
19
|
+
function formatEmitOutput(result, flags) {
|
|
20
|
+
if (flags.quiet) return "";
|
|
21
|
+
const lines = [];
|
|
22
|
+
const jsonPath = relative(process.cwd(), result.files.json);
|
|
23
|
+
const dtsPath = relative(process.cwd(), result.files.dts);
|
|
24
|
+
lines.push(`✔ Emitted contract.json → ${jsonPath}`);
|
|
25
|
+
lines.push(`✔ Emitted contract.d.ts → ${dtsPath}`);
|
|
26
|
+
lines.push(` storageHash: ${result.storageHash}`);
|
|
27
|
+
if (result.executionHash) lines.push(` executionHash: ${result.executionHash}`);
|
|
28
|
+
if (result.profileHash) lines.push(` profileHash: ${result.profileHash}`);
|
|
29
|
+
if (isVerbose(flags, 1)) lines.push(` Total time: ${result.timings.total}ms`);
|
|
30
|
+
return lines.join("\n");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Formats JSON output for contract emit.
|
|
34
|
+
*/
|
|
35
|
+
function formatEmitJson(result) {
|
|
36
|
+
const output = {
|
|
37
|
+
ok: true,
|
|
38
|
+
storageHash: result.storageHash,
|
|
39
|
+
...ifDefined("executionHash", result.executionHash),
|
|
40
|
+
...result.profileHash ? { profileHash: result.profileHash } : {},
|
|
41
|
+
outDir: result.outDir,
|
|
42
|
+
files: result.files,
|
|
43
|
+
timings: result.timings
|
|
44
|
+
};
|
|
45
|
+
return JSON.stringify(output, null, 2);
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/commands/contract-emit.ts
|
|
49
|
+
/**
|
|
50
|
+
* Pre-load the config just to compute display paths for the styled header. The
|
|
51
|
+
* actual emit work goes through `executeContractEmit`, which loads the config
|
|
52
|
+
* itself; the redundant load here is bounded and lets the header render before
|
|
53
|
+
* the emit spans start.
|
|
54
|
+
*/
|
|
55
|
+
async function resolveHeaderPaths(configOption) {
|
|
56
|
+
const displayConfigPath = configOption ? relative(process.cwd(), resolve(configOption)) : "prisma-next.config.ts";
|
|
57
|
+
let config;
|
|
58
|
+
try {
|
|
59
|
+
config = await loadConfig(configOption);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (error instanceof CliStructuredError$1) return notOk(error);
|
|
62
|
+
return notOk(errorUnexpected$1(error instanceof Error ? error.message : String(error), { why: "Failed to load config" }));
|
|
63
|
+
}
|
|
64
|
+
if (!config.contract?.output) return notOk(errorContractConfigMissing({ why: "Config.contract.output is required for emit. Define it in your config: contract: { source: ..., output: ... }" }));
|
|
65
|
+
try {
|
|
66
|
+
const { jsonPath: outputJsonPath, dtsPath: outputDtsPath } = getEmittedArtifactPaths(config.contract.output);
|
|
67
|
+
return ok({
|
|
68
|
+
displayConfigPath,
|
|
69
|
+
outputJsonPath,
|
|
70
|
+
outputDtsPath
|
|
71
|
+
});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
return notOk(errorContractConfigMissing({ why: error instanceof Error ? error.message : String(error) }));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function executeContractEmitCommand(options, flags, ui, startTime) {
|
|
77
|
+
const headerPathsResult = await resolveHeaderPaths(options.config);
|
|
78
|
+
if (!headerPathsResult.ok) return headerPathsResult;
|
|
79
|
+
const { displayConfigPath, outputJsonPath, outputDtsPath } = headerPathsResult.value;
|
|
80
|
+
if (!flags.json && !flags.quiet) ui.stderr(formatStyledHeader({
|
|
81
|
+
command: "contract emit",
|
|
82
|
+
description: "Emit your contract artifacts",
|
|
83
|
+
url: "https://pris.ly/contract-emit",
|
|
84
|
+
details: [
|
|
85
|
+
{
|
|
86
|
+
label: "config",
|
|
87
|
+
value: displayConfigPath
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: "contract",
|
|
91
|
+
value: relative(process.cwd(), outputJsonPath)
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
label: "types",
|
|
95
|
+
value: relative(process.cwd(), outputDtsPath)
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
flags
|
|
99
|
+
}));
|
|
100
|
+
const onProgress = createProgressAdapter({
|
|
101
|
+
ui,
|
|
102
|
+
flags
|
|
103
|
+
});
|
|
104
|
+
const configPath = options.config ? resolve(options.config) : "prisma-next.config.ts";
|
|
105
|
+
let result;
|
|
106
|
+
try {
|
|
107
|
+
result = await executeContractEmit({
|
|
108
|
+
configPath,
|
|
109
|
+
onProgress
|
|
110
|
+
});
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (CliStructuredError$1.is(error)) return notOk(error);
|
|
113
|
+
return notOk(errorUnexpected$1("Unexpected error during contract emit", { why: error instanceof Error ? error.message : String(error) }));
|
|
114
|
+
}
|
|
115
|
+
if (result.validationWarning) ui.warn(result.validationWarning);
|
|
116
|
+
return ok({
|
|
117
|
+
storageHash: result.storageHash,
|
|
118
|
+
...ifDefined("executionHash", result.executionHash),
|
|
119
|
+
profileHash: result.profileHash,
|
|
120
|
+
outDir: dirname(result.files.json),
|
|
121
|
+
files: result.files,
|
|
122
|
+
timings: { total: Date.now() - startTime }
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function createContractEmitCommand() {
|
|
126
|
+
const command = new Command("emit");
|
|
127
|
+
setCommandDescriptions(command, "Emit your contract artifacts", "Reads your contract source (TypeScript or Prisma schema) and emits contract.json and\ncontract.d.ts. The contract.json contains the canonical contract structure, and\ncontract.d.ts provides TypeScript types for type-safe query building.");
|
|
128
|
+
setCommandExamples(command, ["prisma-next contract emit", "prisma-next contract emit --config ./custom-config.ts"]);
|
|
129
|
+
addGlobalOptions(command).option("--config <path>", "Path to prisma-next.config.ts").action(async (options) => {
|
|
130
|
+
const flags = parseGlobalFlags(options);
|
|
131
|
+
const ui = new TerminalUI({
|
|
132
|
+
color: flags.color,
|
|
133
|
+
interactive: flags.interactive
|
|
134
|
+
});
|
|
135
|
+
const exitCode = handleResult(await executeContractEmitCommand(options, flags, ui, Date.now()), flags, ui, (emitResult) => {
|
|
136
|
+
if (flags.json) ui.output(formatEmitJson(emitResult));
|
|
137
|
+
else {
|
|
138
|
+
const output = formatEmitOutput(emitResult, flags);
|
|
139
|
+
if (output) ui.log(output);
|
|
140
|
+
if (!flags.quiet) ui.success(formatSuccessMessage(flags));
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
process.exit(exitCode);
|
|
144
|
+
});
|
|
145
|
+
return command;
|
|
146
|
+
}
|
|
147
|
+
//#endregion
|
|
148
|
+
export { createContractEmitCommand as t };
|
|
149
|
+
|
|
150
|
+
//# sourceMappingURL=contract-emit-9DBda5Ou.mjs.map
|