prisma-next 0.11.0 → 0.12.0-dev.10
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 +259 -12
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-oXO2WCPD.mjs → client-CDr4o07S.mjs} +88 -63
- package/dist/client-CDr4o07S.mjs.map +1 -0
- package/dist/{command-helpers-BSb0tRC8.mjs → command-helpers-Bbw1GbwL.mjs} +646 -46
- package/dist/command-helpers-Bbw1GbwL.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +32 -7
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +3 -4
- 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 +12 -10
- 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 +41 -11
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +6 -2
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +75 -40
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +4 -3
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +1 -280
- package/dist/commands/migration-graph.d.mts +31 -2
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +2 -137
- package/dist/commands/migration-list.d.mts +64 -4
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +143 -56
- package/dist/commands/migration-list.mjs.map +1 -1
- package/dist/commands/migration-log.d.mts +10 -1
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +10 -15
- package/dist/commands/migration-log.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +32 -38
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +3 -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 +4 -55
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +61 -153
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +12 -49
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +86 -82
- package/dist/commands/migration-status.mjs.map +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +38 -10
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/config-loader-B6sJjXTv.mjs.map +1 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/contract-at-errors-BxP-TOMl.mjs +42 -0
- package/dist/contract-at-errors-BxP-TOMl.mjs.map +1 -0
- package/dist/{contract-emit-bcrpT-wD.mjs → contract-emit-D-4jrNve.mjs} +25 -10
- package/dist/contract-emit-D-4jrNve.mjs.map +1 -0
- package/dist/{contract-emit-r4y8Zhf1.mjs → contract-emit-DxcGl4Uq.mjs} +19 -14
- package/dist/contract-emit-DxcGl4Uq.mjs.map +1 -0
- package/dist/{contract-enrichment-Dani0mMW.mjs → contract-enrichment-a0V5Y_mL.mjs} +4 -25
- package/dist/contract-enrichment-a0V5Y_mL.mjs.map +1 -0
- package/dist/{contract-infer-BmySmqVT.mjs → contract-infer-C8J1WMvO.mjs} +4 -5
- package/dist/{contract-infer-BmySmqVT.mjs.map → contract-infer-C8J1WMvO.mjs.map} +1 -1
- package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs +247 -0
- package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs.map +1 -0
- package/dist/{db-verify-BClPs3ph.mjs → db-verify-BeRHwN8M.mjs} +5 -7
- package/dist/{db-verify-BClPs3ph.mjs.map → db-verify-BeRHwN8M.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +3 -3
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -3
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/extension-pack-inputs-IDvjRCi3.mjs +62 -0
- package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +1 -0
- package/dist/{framework-components-65gOHkHB.mjs → framework-components-fYXjz_in.mjs} +2 -2
- package/dist/{framework-components-65gOHkHB.mjs.map → framework-components-fYXjz_in.mjs.map} +1 -1
- package/dist/global-flags-DEHjV8_s.d.mts +34 -0
- package/dist/global-flags-DEHjV8_s.d.mts.map +1 -0
- package/dist/{graph-render-DJVv0_uf.mjs → graph-render-rFAqZujX.mjs} +2 -2
- package/dist/{graph-render-DJVv0_uf.mjs.map → graph-render-rFAqZujX.mjs.map} +1 -1
- package/dist/{init-BCJZPWE1.mjs → init-Cv9UzWL5.mjs} +20 -269
- package/dist/init-Cv9UzWL5.mjs.map +1 -0
- package/dist/{inspect-live-schema-DSRbFoOL.mjs → inspect-live-schema-BlKR2Zln.mjs} +4 -5
- package/dist/{inspect-live-schema-DSRbFoOL.mjs.map → inspect-live-schema-BlKR2Zln.mjs.map} +1 -1
- package/dist/migration-check-BiBJoYYW.mjs +341 -0
- package/dist/migration-check-BiBJoYYW.mjs.map +1 -0
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +4 -4
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-Bzd9La5c.mjs → migration-command-scaffold-BAGUiGOK.mjs} +4 -5
- package/dist/{migration-command-scaffold-Bzd9La5c.mjs.map → migration-command-scaffold-BAGUiGOK.mjs.map} +1 -1
- package/dist/migration-graph-C9WC-7eO.mjs +1478 -0
- package/dist/migration-graph-C9WC-7eO.mjs.map +1 -0
- package/dist/migration-list-styler-BRwF4-gy.mjs +399 -0
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +1 -0
- package/dist/{migration-plan-CFwqw3Gk.mjs → migration-plan-9DJ7q7_z.mjs} +372 -133
- package/dist/migration-plan-9DJ7q7_z.mjs.map +1 -0
- package/dist/{migration-types-BXWvz12q.d.mts → migration-types-D2FW63pr.d.mts} +1 -1
- package/dist/{migration-types-BXWvz12q.d.mts.map → migration-types-D2FW63pr.d.mts.map} +1 -1
- package/dist/{migrations-CwZMa1Ck.mjs → migrations-Cv2jxNNK.mjs} +12 -13
- package/dist/migrations-Cv2jxNNK.mjs.map +1 -0
- package/dist/{output-BlsrGMEF.mjs → output-B60Gw5fu.mjs} +1 -1
- package/dist/{output-BlsrGMEF.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
- package/dist/{progress-adapter-DFfvZcYL.mjs → progress-adapter-C644QK8l.mjs} +1 -1
- package/dist/{progress-adapter-DFfvZcYL.mjs.map → progress-adapter-C644QK8l.mjs.map} +1 -1
- package/dist/ref-advancement-DUZqsue6.mjs +50 -0
- package/dist/ref-advancement-DUZqsue6.mjs.map +1 -0
- package/dist/terminal-ui-5Y6mrg93.d.mts +133 -0
- package/dist/terminal-ui-5Y6mrg93.d.mts.map +1 -0
- package/dist/{types--CqjMdk0.d.mts → types-CeC5ec2Y.d.mts} +35 -29
- package/dist/types-CeC5ec2Y.d.mts.map +1 -0
- package/dist/{verify-Bom75OYI.mjs → verify-DCA9Sldu.mjs} +2 -2
- package/dist/{verify-Bom75OYI.mjs.map → verify-DCA9Sldu.mjs.map} +1 -1
- package/package.json +28 -17
- package/dist/cli-errors-Czmx92Zy.d.mts +0 -3
- package/dist/cli-errors-Djtz98Vm.mjs +0 -71
- package/dist/cli-errors-Djtz98Vm.mjs.map +0 -1
- package/dist/client-oXO2WCPD.mjs.map +0 -1
- package/dist/command-helpers-BSb0tRC8.mjs.map +0 -1
- package/dist/commands/migration-check.mjs.map +0 -1
- package/dist/commands/migration-graph.mjs.map +0 -1
- package/dist/contract-emit-bcrpT-wD.mjs.map +0 -1
- package/dist/contract-emit-r4y8Zhf1.mjs.map +0 -1
- package/dist/contract-enrichment-Dani0mMW.mjs.map +0 -1
- package/dist/contract-space-aggregate-loader-BmNQwlws.mjs +0 -160
- package/dist/contract-space-aggregate-loader-BmNQwlws.mjs.map +0 -1
- package/dist/global-flags-CdE7M0d9.d.mts +0 -15
- package/dist/global-flags-CdE7M0d9.d.mts.map +0 -1
- package/dist/init-BCJZPWE1.mjs.map +0 -1
- package/dist/migration-plan-CFwqw3Gk.mjs.map +0 -1
- package/dist/migrations-CwZMa1Ck.mjs.map +0 -1
- package/dist/rolldown-runtime-twds-ZHy.mjs +0 -14
- package/dist/terminal-ui-BiB_8KNo.mjs +0 -379
- package/dist/terminal-ui-BiB_8KNo.mjs.map +0 -1
- package/dist/types--CqjMdk0.d.mts.map +0 -1
|
@@ -1,18 +1,253 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { d as errorInvalidOutputFormat, m as errorOutputFormatMutex, t as CliStructuredError } from "./cli-errors-Djtz98Vm.mjs";
|
|
3
|
-
import { a as isCI, i as formatErrorOutput, o as createColorFormatter, r as formatErrorJson, s as formatDim, t as createTerminalUI } from "./terminal-ui-BiB_8KNo.mjs";
|
|
1
|
+
import { CliStructuredError as CliStructuredError$1, errorConfigValidation as errorConfigValidation$1, errorContractConfigMissing as errorContractConfigMissing$1, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDriverRequired, errorFileNotFound, errorInvalidOutputFormat, errorMigrationPlanningFailed, errorOutputFormatMutex, errorTargetMigrationNotSupported, errorUnexpected as errorUnexpected$1 } from "@prisma-next/errors/control";
|
|
4
2
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
5
3
|
import { notOk } from "@prisma-next/utils/result";
|
|
6
4
|
import { relative, resolve } from "pathe";
|
|
7
5
|
import { readFile } from "node:fs/promises";
|
|
8
6
|
import { hasMigrations } from "@prisma-next/framework-components/control";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
7
|
+
import { ERROR_CODE_DESTRUCTIVE_CHANGES, errorDestructiveChanges, errorHashMismatch, errorMarkerMissing, errorRunnerFailed, errorRuntime, errorRuntime as errorRuntime$1, errorTargetMismatch } from "@prisma-next/errors/execution";
|
|
8
|
+
import "@prisma-next/errors/migration";
|
|
11
9
|
import { APP_SPACE_ID as APP_SPACE_ID$1, spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
|
|
12
|
-
import { blue, bold, cyan, dim, green, magenta } from "colorette";
|
|
10
|
+
import { blue, bold, cyan, dim, green, magenta, red, yellow } from "colorette";
|
|
13
11
|
import wrapAnsi from "wrap-ansi";
|
|
14
12
|
import stringWidth from "string-width";
|
|
15
13
|
import stripAnsi from "strip-ansi";
|
|
14
|
+
import { isCI } from "ci-info";
|
|
15
|
+
import * as clack from "@clack/prompts";
|
|
16
|
+
//#region src/utils/cli-errors.ts
|
|
17
|
+
function errorRefSetHashNotInGraph(resolvedHash, reachableHashes, graphTipHash) {
|
|
18
|
+
const reachableList = reachableHashes.length > 0 ? reachableHashes.join(", ") : "(none — migration graph is empty)";
|
|
19
|
+
const fix = reachableHashes.length > 0 ? graphTipHash !== null ? `Set the ref to a graph-node hash such as ${graphTipHash}, or run \`prisma-next migration plan\` to extend the graph.` : "Set the ref to a hash that appears in the migration graph." : "Run `prisma-next migration plan` first.";
|
|
20
|
+
return errorRuntime(`Resolved contract hash is not in the migration graph: ${resolvedHash}`, {
|
|
21
|
+
why: reachableHashes.length > 0 ? `The migration graph reaches ${reachableList}; resolved ${resolvedHash} isn't a graph node.` : "The migration graph is empty — no hashes reachable.",
|
|
22
|
+
fix,
|
|
23
|
+
meta: {
|
|
24
|
+
code: "MIGRATION.HASH_NOT_IN_GRAPH",
|
|
25
|
+
resolvedHash,
|
|
26
|
+
reachableHashes: [...reachableHashes],
|
|
27
|
+
...graphTipHash !== null ? { graphTipHash } : {}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function errorRefSetEmptySentinel(hash) {
|
|
32
|
+
return errorRuntime(`Cannot set ref to the empty-database sentinel: ${hash}`, {
|
|
33
|
+
why: "The empty-database sentinel is a planner internal; it is not a valid ref target.",
|
|
34
|
+
fix: "Set the ref to a contract hash from the migration graph, or use another ref name.",
|
|
35
|
+
meta: {
|
|
36
|
+
code: "MIGRATION.REF_SET_EMPTY_SENTINEL",
|
|
37
|
+
hash
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `--space <id>` was given a value that doesn't satisfy the contract-space
|
|
43
|
+
* naming rule (`[a-z][a-z0-9_-]{0,63}` per `isValidSpaceId`). Fires before
|
|
44
|
+
* any fs work — the input is syntactically rejected the same way an on-disk
|
|
45
|
+
* directory with that name would be skipped by the enumerator.
|
|
46
|
+
*/
|
|
47
|
+
function errorInvalidSpaceId(spaceId) {
|
|
48
|
+
return errorRuntime(`Invalid contract space id: ${spaceId}`, {
|
|
49
|
+
why: "Contract space ids must match [a-z][a-z0-9_-]{0,63} (lowercase, starts with a letter, max 64 characters — the rule applied to every on-disk space directory).",
|
|
50
|
+
fix: "Pass a space id that matches the directory naming rule, or omit --space to list every space.",
|
|
51
|
+
meta: {
|
|
52
|
+
code: "MIGRATION.INVALID_SPACE_ID",
|
|
53
|
+
spaceId
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* `migration list --space <id>` was given a contract-space id that has no
|
|
59
|
+
* directory under `migrations/`. Distinct from "the space exists but is
|
|
60
|
+
* empty" — that path renders the empty-state line and exits 0 per the
|
|
61
|
+
* slice spec § Empty-state. This error fires only when `<projectMigrationsDir>/<spaceId>`
|
|
62
|
+
* does not exist on disk.
|
|
63
|
+
*
|
|
64
|
+
* `availableSpaces` lists the contract-space directory names actually
|
|
65
|
+
* present, sorted lex-asc, so the diagnostic can suggest a near match
|
|
66
|
+
* without making the user reach for `ls`.
|
|
67
|
+
*/
|
|
68
|
+
function errorSpaceNotFound(spaceId, availableSpaces) {
|
|
69
|
+
const availableList = availableSpaces.length > 0 ? availableSpaces.join(", ") : "(none — no contract spaces on disk yet)";
|
|
70
|
+
const fix = availableSpaces.length > 0 ? `Pick one of: ${availableList}. Run \`prisma-next migration list\` (no --space) to see every space's migrations.` : "Author a migration with `prisma-next migration new` to create the first contract-space directory.";
|
|
71
|
+
return errorRuntime(`Unknown contract space: ${spaceId}`, {
|
|
72
|
+
why: `No directory named "${spaceId}" exists under the migrations root.`,
|
|
73
|
+
fix,
|
|
74
|
+
meta: {
|
|
75
|
+
code: "MIGRATION.SPACE_NOT_FOUND",
|
|
76
|
+
spaceId,
|
|
77
|
+
availableSpaces: [...availableSpaces]
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function errorRefSetBundleNotFound(hash) {
|
|
82
|
+
return errorRuntime(`No migration bundle matches graph-node hash ${hash}`, {
|
|
83
|
+
why: `The hash is a graph node but no on-disk bundle has metadata.to = ${hash}.`,
|
|
84
|
+
fix: "Run `pnpm fixtures:check`, or re-emit the migration that produces this hash so its bundle is restored.",
|
|
85
|
+
meta: {
|
|
86
|
+
code: "MIGRATION.REF_SET_BUNDLE_NOT_FOUND",
|
|
87
|
+
hash
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function errorPlanForgotTheFlag(resolvedHash, reachableRefs, graphTipHash) {
|
|
92
|
+
const reachableList = reachableRefs.length > 0 ? reachableRefs.map((r) => `${r.name} (${r.hash})`).join(", ") : "(none)";
|
|
93
|
+
const refFix = reachableRefs.length > 0 ? `Run migration plan with ${reachableRefs.map((r) => `--from ${r.name}`).join(" or ")}.` : graphTipHash !== null ? `Run migration plan --from ${graphTipHash}.` : "Commit pending migrations first, then run migration plan.";
|
|
94
|
+
return errorRuntime(`Resolved from-hash is not in the migration graph: ${resolvedHash}`, {
|
|
95
|
+
why: `The migration graph reaches ${reachableList}; resolved ${resolvedHash} isn't a graph node.`,
|
|
96
|
+
fix: refFix,
|
|
97
|
+
meta: {
|
|
98
|
+
code: "MIGRATION.HASH_NOT_IN_GRAPH",
|
|
99
|
+
resolvedHash,
|
|
100
|
+
reachableRefs: reachableRefs.map((r) => r.name),
|
|
101
|
+
...graphTipHash !== null ? { graphTipHash } : {}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function errorSnapshotMissing(identifier, options) {
|
|
106
|
+
const viaRef = options?.viaRef !== false;
|
|
107
|
+
const fix = viaRef ? `Run "prisma-next db update --advance-ref ${identifier}" to repopulate the snapshot, or "prisma-next ref delete ${identifier}" to clear the orphan pointer.` : `No contract source exists for hash "${identifier}" on an empty migration graph. Use --from with a ref name that has a paired snapshot, or run db update first.`;
|
|
108
|
+
return errorRuntime(viaRef ? `Ref "${identifier}" has no paired contract snapshot` : `No contract source for from-hash "${identifier}"`, {
|
|
109
|
+
why: viaRef ? `Ref "${identifier}" exists but its paired snapshot files are missing.` : `Hash "${identifier}" is not a graph node and no paired ref snapshot supplies a contract.`,
|
|
110
|
+
fix,
|
|
111
|
+
meta: {
|
|
112
|
+
code: "MIGRATION.SNAPSHOT_MISSING",
|
|
113
|
+
identifier,
|
|
114
|
+
viaRef
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function errorMarkerMismatch(markerHash, reachableHashes, graphTip) {
|
|
119
|
+
const reachableList = reachableHashes.length > 0 ? reachableHashes.join(", ") : "(none — migration graph is empty)";
|
|
120
|
+
const planFromFix = graphTip !== null ? `Run \`prisma-next migration plan --from ${graphTip}\` if the live marker is canonical and the on-disk graph needs catching up.` : "Run `prisma-next migration plan` if the live marker is canonical and the on-disk graph needs catching up.";
|
|
121
|
+
return errorRuntime("Database marker is not reachable in the on-disk migration graph", {
|
|
122
|
+
why: `DB marker is ${markerHash}, but the on-disk migration graph reaches: ${reachableList}.`,
|
|
123
|
+
fix: [
|
|
124
|
+
planFromFix,
|
|
125
|
+
`Run \`prisma-next ref set db ${markerHash}\` if the on-disk graph is canonical and the local \`db\` ref drifted.`,
|
|
126
|
+
"Investigate whether the database was migrated by an out-of-band process."
|
|
127
|
+
].join("\n"),
|
|
128
|
+
meta: {
|
|
129
|
+
code: "MIGRATION.MARKER_MISMATCH",
|
|
130
|
+
markerHash,
|
|
131
|
+
reachableHashes: [...reachableHashes],
|
|
132
|
+
...graphTip !== null ? { graphTip } : {}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function errorPathUnreachable(failure) {
|
|
137
|
+
const meta = failure.meta ?? {};
|
|
138
|
+
const fromHashMeta = typeof meta["fromHash"] === "string" ? meta["fromHash"] : null;
|
|
139
|
+
const planFromHash = fromHashMeta === "<empty>" ? null : fromHashMeta;
|
|
140
|
+
const targetHash = typeof meta["targetHash"] === "string" ? meta["targetHash"] : typeof meta["target"] === "string" ? meta["target"] : null;
|
|
141
|
+
const deadEnds = meta["deadEnds"];
|
|
142
|
+
const deadEndsSuffix = Array.isArray(deadEnds) && deadEnds.length > 0 ? ` Dead-ends: ${deadEnds.map(String).join(", ")}.` : "";
|
|
143
|
+
const planCommand = (() => {
|
|
144
|
+
if (planFromHash !== null && targetHash !== null) return `prisma-next migration plan --from ${planFromHash} --to ${targetHash} --name <slug>`;
|
|
145
|
+
if (targetHash !== null) return `prisma-next migration plan --to ${targetHash} --name <slug>`;
|
|
146
|
+
if (planFromHash !== null) return `prisma-next migration plan --from ${planFromHash} --name <slug>`;
|
|
147
|
+
return "prisma-next migration plan";
|
|
148
|
+
})();
|
|
149
|
+
const applyCommand = targetHash !== null ? `prisma-next migrate --to ${targetHash}` : "prisma-next migrate";
|
|
150
|
+
return errorRuntime(failure.summary, {
|
|
151
|
+
why: failure.why ?? `Cannot reach target "${targetHash ?? "<unknown>"}" from current marker "${fromHashMeta ?? "<unknown>"}".${deadEndsSuffix}`,
|
|
152
|
+
fix: [
|
|
153
|
+
"Plan the missing edge, then apply it:",
|
|
154
|
+
` 1. ${planCommand}`,
|
|
155
|
+
` 2. ${applyCommand}`,
|
|
156
|
+
"A rollback (reverse) plan is expected to contain destructive (DROP) operations — review them before applying.",
|
|
157
|
+
"Narrower cases (rename inference, re-adding a NOT NULL column without a safe default, or a type change that needs data) may additionally need a hint in the planned migration.",
|
|
158
|
+
"Inspect the on-disk graph with `prisma-next migration list`, or `prisma-next migration show <bundle>` for any bundle in the path you expected."
|
|
159
|
+
].join("\n"),
|
|
160
|
+
meta: {
|
|
161
|
+
...meta,
|
|
162
|
+
code: "MIGRATION.PATH_UNREACHABLE"
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Maps a `MigrationToolsError` raised by the migration-tools loader/graph
|
|
168
|
+
* surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,
|
|
169
|
+
* `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.
|
|
170
|
+
*
|
|
171
|
+
* The full `error.details` payload is forwarded into `meta` so machine
|
|
172
|
+
* consumers (`--json`) see structural fields like `dir`, `storedHash`,
|
|
173
|
+
* `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable
|
|
174
|
+
* `code`. The user-visible `summary`/`why`/`fix` text is unchanged.
|
|
175
|
+
*
|
|
176
|
+
* Callers are expected to gate on `MigrationToolsError.is(error)` first
|
|
177
|
+
* (mirroring the original inline pattern); non-`MigrationToolsError`
|
|
178
|
+
* values are caller-classified (rethrow, wrap with command-specific
|
|
179
|
+
* `errorUnexpected`, etc.).
|
|
180
|
+
*/
|
|
181
|
+
function mapMigrationToolsError(error) {
|
|
182
|
+
return errorRuntime(error.message, {
|
|
183
|
+
why: error.why,
|
|
184
|
+
fix: error.fix,
|
|
185
|
+
meta: {
|
|
186
|
+
code: error.code,
|
|
187
|
+
...error.details ?? {}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Maps a `RefResolutionError` from the contract/migration reference
|
|
193
|
+
* resolver into a CLI structured error envelope.
|
|
194
|
+
*/
|
|
195
|
+
function mapRefResolutionError(error) {
|
|
196
|
+
switch (error.kind) {
|
|
197
|
+
case "not-found": return errorRuntime(`Not a known ${error.grammar} reference: "${error.input}"`, {
|
|
198
|
+
why: `No ${error.grammar} matching "${error.input}" exists in the migration graph or refs index.`,
|
|
199
|
+
fix: error.grammar === "contract" ? "Provide a valid contract hash, ref name, or migration directory name." : "Provide a valid migration directory name or migration hash.",
|
|
200
|
+
meta: {
|
|
201
|
+
input: error.input,
|
|
202
|
+
grammar: error.grammar
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
case "ambiguous": return errorRuntime(`Ambiguous ${error.grammar} reference: "${error.input}"`, {
|
|
206
|
+
why: `"${error.input}" matches multiple ${error.grammar}s: ${error.candidates.join(", ")}`,
|
|
207
|
+
fix: "Provide a longer prefix or use the full hash to disambiguate.",
|
|
208
|
+
meta: {
|
|
209
|
+
input: error.input,
|
|
210
|
+
candidates: error.candidates,
|
|
211
|
+
grammar: error.grammar
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
case "wrong-grammar": return errorRuntime(error.message, {
|
|
215
|
+
why: error.message,
|
|
216
|
+
fix: error.fix,
|
|
217
|
+
meta: {
|
|
218
|
+
input: error.input,
|
|
219
|
+
expectedGrammar: error.expectedGrammar
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
case "invalid-format": return errorRuntime(`Invalid reference format: "${error.input}"`, {
|
|
223
|
+
why: error.reason,
|
|
224
|
+
fix: "Provide a valid contract hash, ref name, or migration directory name.",
|
|
225
|
+
meta: { input: error.input }
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/utils/formatters/helpers.ts
|
|
231
|
+
/**
|
|
232
|
+
* Checks if verbose output is enabled at the specified level.
|
|
233
|
+
*/
|
|
234
|
+
function isVerbose(flags, level) {
|
|
235
|
+
return (flags.verbose ?? 0) >= level;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Creates a color-aware formatter function.
|
|
239
|
+
* Returns a function that applies the color only if colors are enabled.
|
|
240
|
+
*/
|
|
241
|
+
function createColorFormatter(useColor, colorFn) {
|
|
242
|
+
return useColor ? colorFn : (text) => text;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Formats text with dim styling if colors are enabled.
|
|
246
|
+
*/
|
|
247
|
+
function formatDim(useColor, text) {
|
|
248
|
+
return useColor ? dim(text) : text;
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
16
251
|
//#region src/utils/formatters/styled.ts
|
|
17
252
|
/**
|
|
18
253
|
* Fixed width for left column in help output.
|
|
@@ -417,6 +652,75 @@ function formatRootHelp(options) {
|
|
|
417
652
|
return `${lines.join("\n")}\n`;
|
|
418
653
|
}
|
|
419
654
|
//#endregion
|
|
655
|
+
//#region src/utils/is-ci.ts
|
|
656
|
+
/**
|
|
657
|
+
* Returns true when the process is running in any CI environment recognised
|
|
658
|
+
* by the `ci-info` package. The single source of truth for CI detection
|
|
659
|
+
* across this CLI — colour-output suppression and telemetry-skip both call
|
|
660
|
+
* this helper, so neither path drifts from the other when a new CI provider
|
|
661
|
+
* is added upstream.
|
|
662
|
+
*
|
|
663
|
+
* `ci-info` checks the standard `CI=true` marker plus dozens of
|
|
664
|
+
* provider-specific environment variables (Buildkite, Jenkins, Drone,
|
|
665
|
+
* Bitbucket Pipelines, Azure Pipelines, AWS CodeBuild, …) that the raw
|
|
666
|
+
* `process.env.CI` read misses.
|
|
667
|
+
*
|
|
668
|
+
*/
|
|
669
|
+
function isCI$1() {
|
|
670
|
+
return isCI;
|
|
671
|
+
}
|
|
672
|
+
//#endregion
|
|
673
|
+
//#region src/utils/formatters/errors.ts
|
|
674
|
+
/**
|
|
675
|
+
* Formats error output for human-readable display.
|
|
676
|
+
*/
|
|
677
|
+
function formatErrorOutput(error, flags) {
|
|
678
|
+
const lines = [];
|
|
679
|
+
const useColor = flags.color !== false;
|
|
680
|
+
const formatRed = createColorFormatter(useColor, red);
|
|
681
|
+
const formatDimText = (text) => formatDim(useColor, text);
|
|
682
|
+
lines.push(`${formatRed("✖")} ${error.summary} (${error.code})`);
|
|
683
|
+
if (error.why) lines.push(`${formatDimText(` Why: ${error.why}`)}`);
|
|
684
|
+
if (error.fix) lines.push(`${formatDimText(` Fix: ${error.fix}`)}`);
|
|
685
|
+
if (error.where?.path) {
|
|
686
|
+
const whereLine = error.where.line ? `${error.where.path}:${error.where.line}` : error.where.path;
|
|
687
|
+
lines.push(`${formatDimText(` Where: ${whereLine}`)}`);
|
|
688
|
+
}
|
|
689
|
+
if (error.meta?.["conflicts"]) {
|
|
690
|
+
const conflicts = error.meta["conflicts"];
|
|
691
|
+
if (conflicts.length > 0) {
|
|
692
|
+
const maxToShow = isVerbose(flags, 1) ? conflicts.length : Math.min(3, conflicts.length);
|
|
693
|
+
const header = isVerbose(flags, 1) ? " Conflicts:" : ` Conflicts (showing ${maxToShow} of ${conflicts.length}):`;
|
|
694
|
+
lines.push(`${formatDimText(header)}`);
|
|
695
|
+
for (const conflict of conflicts.slice(0, maxToShow)) lines.push(`${formatDimText(` - [${conflict.kind}] ${conflict.summary}`)}`);
|
|
696
|
+
if (!isVerbose(flags, 1) && conflicts.length > maxToShow) lines.push(`${formatDimText(" Re-run with -v/--verbose to see all conflicts")}`);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (error.meta?.["issues"]) {
|
|
700
|
+
const issues = error.meta["issues"];
|
|
701
|
+
if (issues.length > 0) {
|
|
702
|
+
const maxToShow = isVerbose(flags, 1) ? issues.length : Math.min(3, issues.length);
|
|
703
|
+
const header = isVerbose(flags, 1) ? " Issues:" : ` Issues (showing ${maxToShow} of ${issues.length}):`;
|
|
704
|
+
lines.push(`${formatDimText(header)}`);
|
|
705
|
+
for (const issue of issues.slice(0, maxToShow)) {
|
|
706
|
+
const kind = issue.kind ?? "issue";
|
|
707
|
+
const message = issue.message ?? "";
|
|
708
|
+
lines.push(`${formatDimText(` - [${kind}] ${message}`)}`);
|
|
709
|
+
}
|
|
710
|
+
if (!isVerbose(flags, 1) && issues.length > maxToShow) lines.push(`${formatDimText(" Re-run with -v/--verbose to see all issues")}`);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
if (error.docsUrl && isVerbose(flags, 1)) lines.push(formatDimText(error.docsUrl));
|
|
714
|
+
if (isVerbose(flags, 2) && error.meta) lines.push(`${formatDimText(` Meta: ${JSON.stringify(error.meta, null, 2)}`)}`);
|
|
715
|
+
return lines.join("\n");
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Formats error output as JSON.
|
|
719
|
+
*/
|
|
720
|
+
function formatErrorJson(error) {
|
|
721
|
+
return JSON.stringify(error, null, 2);
|
|
722
|
+
}
|
|
723
|
+
//#endregion
|
|
420
724
|
//#region src/utils/result-handler.ts
|
|
421
725
|
/**
|
|
422
726
|
* Processes a CLI command result, handling both success and error cases.
|
|
@@ -438,6 +742,333 @@ function handleResult(result, flags, ui, onSuccess) {
|
|
|
438
742
|
return result.failure.domain === "CLI" ? 2 : 1;
|
|
439
743
|
}
|
|
440
744
|
//#endregion
|
|
745
|
+
//#region src/utils/glyph-mode.ts
|
|
746
|
+
function localeString(env) {
|
|
747
|
+
return env["LC_ALL"] ?? env["LC_CTYPE"] ?? env["LANG"] ?? "";
|
|
748
|
+
}
|
|
749
|
+
function isUtf8Locale(env) {
|
|
750
|
+
const locale = localeString(env);
|
|
751
|
+
if (locale.length === 0) return false;
|
|
752
|
+
return /UTF-8|utf8/i.test(locale);
|
|
753
|
+
}
|
|
754
|
+
function detectGlyphMode(input) {
|
|
755
|
+
if (!input.isTTY) return "ascii";
|
|
756
|
+
if (!isUtf8Locale(input.env)) return "ascii";
|
|
757
|
+
return "unicode";
|
|
758
|
+
}
|
|
759
|
+
//#endregion
|
|
760
|
+
//#region src/utils/shutdown.ts
|
|
761
|
+
function createShutdownHandler(options) {
|
|
762
|
+
const exit = options?.exit ?? ((code) => process.exit(code));
|
|
763
|
+
const gracePeriodMs = options?.gracePeriodMs ?? 3e3;
|
|
764
|
+
const controller = new AbortController();
|
|
765
|
+
let shuttingDown = false;
|
|
766
|
+
let graceTimer;
|
|
767
|
+
const onSignal = () => {
|
|
768
|
+
if (shuttingDown) {
|
|
769
|
+
exit(130);
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
shuttingDown = true;
|
|
773
|
+
controller.abort();
|
|
774
|
+
graceTimer = setTimeout(() => exit(130), gracePeriodMs);
|
|
775
|
+
graceTimer.unref();
|
|
776
|
+
};
|
|
777
|
+
return {
|
|
778
|
+
signal: controller.signal,
|
|
779
|
+
isShuttingDown: () => shuttingDown,
|
|
780
|
+
onSignal,
|
|
781
|
+
clearGraceTimer: () => {
|
|
782
|
+
if (graceTimer !== void 0) {
|
|
783
|
+
clearTimeout(graceTimer);
|
|
784
|
+
graceTimer = void 0;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
const globalHandler = createShutdownHandler();
|
|
790
|
+
/**
|
|
791
|
+
* The global AbortSignal. Pass this to any async operation that should
|
|
792
|
+
* be cancellable on Ctrl+C (e.g., DB queries, long-running emit).
|
|
793
|
+
*/
|
|
794
|
+
const shutdownSignal = globalHandler.signal;
|
|
795
|
+
/**
|
|
796
|
+
* Installs SIGINT and SIGTERM handlers. Call once at CLI startup.
|
|
797
|
+
*
|
|
798
|
+
* - First signal: aborts the controller, starts a 3s grace timer.
|
|
799
|
+
* - Second signal: force-exits immediately.
|
|
800
|
+
*/
|
|
801
|
+
let installed = false;
|
|
802
|
+
function installShutdownHandlers() {
|
|
803
|
+
if (installed) return;
|
|
804
|
+
installed = true;
|
|
805
|
+
process.on("SIGINT", globalHandler.onSignal);
|
|
806
|
+
process.on("SIGTERM", globalHandler.onSignal);
|
|
807
|
+
}
|
|
808
|
+
//#endregion
|
|
809
|
+
//#region src/utils/terminal-ui.ts
|
|
810
|
+
/**
|
|
811
|
+
* Composable CLI output abstraction.
|
|
812
|
+
*
|
|
813
|
+
* Follows the Unix convention of separating data from decoration:
|
|
814
|
+
* - **stdout** — data output only (`ui.output()`). This is what scripts and pipes capture.
|
|
815
|
+
* - **stderr** — all decoration (spinners, logs, notes, intro/outro). Visible in terminal, invisible in pipes.
|
|
816
|
+
*
|
|
817
|
+
* Rules:
|
|
818
|
+
* 1. All methods except `output()` and `error()` write to stderr only in interactive mode.
|
|
819
|
+
* 2. `output(data)` always writes to stdout — if a command calls it, there is data to emit.
|
|
820
|
+
* 3. `error()` always writes to stderr — errors matter even when piped.
|
|
821
|
+
* 4. Decoration is suppressed when piped unless `--format pretty` was explicit (`forcePretty`).
|
|
822
|
+
* 5. Never write data to stderr — decoration methods are for human context only.
|
|
823
|
+
* 6. Never write decoration to stdout — it breaks pipes, `$(...)` captures, and `> file` redirects.
|
|
824
|
+
*/
|
|
825
|
+
var TerminalUI = class TerminalUI {
|
|
826
|
+
/**
|
|
827
|
+
* True when stdout is a TTY (interactive terminal).
|
|
828
|
+
* False when piped (e.g., `prisma-next db verify | jq`).
|
|
829
|
+
*/
|
|
830
|
+
isInteractive;
|
|
831
|
+
/**
|
|
832
|
+
* Whether color output is enabled.
|
|
833
|
+
*/
|
|
834
|
+
useColor;
|
|
835
|
+
/**
|
|
836
|
+
* When true, decoration methods write even on non-TTY stdout
|
|
837
|
+
* (explicit `--format pretty`).
|
|
838
|
+
*/
|
|
839
|
+
forcePretty;
|
|
840
|
+
/**
|
|
841
|
+
* Whether stdout is a TTY — used for migration-list graph glyph detection.
|
|
842
|
+
*/
|
|
843
|
+
stdoutIsTTY;
|
|
844
|
+
/**
|
|
845
|
+
* Process environment snapshot for locale-aware glyph detection.
|
|
846
|
+
*/
|
|
847
|
+
env;
|
|
848
|
+
static stderrOpts = { output: process.stderr };
|
|
849
|
+
constructor(options) {
|
|
850
|
+
this.isInteractive = options?.interactive ?? !!process.stdout.isTTY;
|
|
851
|
+
this.forcePretty = options?.forcePretty ?? false;
|
|
852
|
+
this.useColor = options?.color ?? (this.isInteractive || this.forcePretty);
|
|
853
|
+
this.stdoutIsTTY = options?.stdoutIsTTY ?? !!process.stdout.isTTY;
|
|
854
|
+
this.env = options?.env ?? process.env;
|
|
855
|
+
}
|
|
856
|
+
get isTTY() {
|
|
857
|
+
return this.stdoutIsTTY;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Resolve glyph mode for migration list/tree output. `--ascii` forces ASCII;
|
|
861
|
+
* otherwise delegates to the pure {@link detectGlyphMode} helper.
|
|
862
|
+
*/
|
|
863
|
+
resolveGlyphMode(forceAscii) {
|
|
864
|
+
if (forceAscii) return "ascii";
|
|
865
|
+
return detectGlyphMode(this.glyphModeInput());
|
|
866
|
+
}
|
|
867
|
+
glyphModeInput() {
|
|
868
|
+
return {
|
|
869
|
+
isTTY: this.stdoutIsTTY,
|
|
870
|
+
env: this.env
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
get shouldDecorate() {
|
|
874
|
+
return this.isInteractive || this.forcePretty;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Log a message line to stderr. No-op when piped unless forcePretty.
|
|
878
|
+
*/
|
|
879
|
+
log(message) {
|
|
880
|
+
if (!this.shouldDecorate) return;
|
|
881
|
+
clack.log.message(message, TerminalUI.stderrOpts);
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Log a success message to stderr. No-op when piped unless forcePretty.
|
|
885
|
+
*/
|
|
886
|
+
success(message) {
|
|
887
|
+
if (!this.shouldDecorate) return;
|
|
888
|
+
clack.log.success(message, TerminalUI.stderrOpts);
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Log a warning message to stderr. No-op when piped unless forcePretty.
|
|
892
|
+
*/
|
|
893
|
+
warn(message) {
|
|
894
|
+
if (!this.shouldDecorate) return;
|
|
895
|
+
clack.log.warn(message, TerminalUI.stderrOpts);
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Log an error message to stderr. Always writes (errors matter even in pipes).
|
|
899
|
+
*/
|
|
900
|
+
error(message) {
|
|
901
|
+
clack.log.error(message, TerminalUI.stderrOpts);
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Log an info message to stderr. No-op when piped unless forcePretty.
|
|
905
|
+
*/
|
|
906
|
+
info(message) {
|
|
907
|
+
if (!this.shouldDecorate) return;
|
|
908
|
+
clack.log.info(message, TerminalUI.stderrOpts);
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Log a step message to stderr. No-op when piped unless forcePretty.
|
|
912
|
+
*/
|
|
913
|
+
step(message) {
|
|
914
|
+
if (!this.shouldDecorate) return;
|
|
915
|
+
clack.log.step(message, TerminalUI.stderrOpts);
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Display a note box on stderr. No-op when piped unless forcePretty.
|
|
919
|
+
*/
|
|
920
|
+
note(message, title) {
|
|
921
|
+
if (!this.shouldDecorate) return;
|
|
922
|
+
clack.note(message, title, TerminalUI.stderrOpts);
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Display intro banner on stderr. No-op when piped unless forcePretty.
|
|
926
|
+
*/
|
|
927
|
+
intro(title) {
|
|
928
|
+
if (!this.shouldDecorate) return;
|
|
929
|
+
clack.intro(title, TerminalUI.stderrOpts);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Display outro banner on stderr. No-op when piped unless forcePretty.
|
|
933
|
+
*/
|
|
934
|
+
outro(message) {
|
|
935
|
+
if (!this.shouldDecorate) return;
|
|
936
|
+
clack.outro(message, TerminalUI.stderrOpts);
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Create a Clack spinner on stderr with a 100ms delay threshold.
|
|
940
|
+
* The spinner only appears if the operation takes longer than the threshold,
|
|
941
|
+
* avoiding flicker for fast operations. Returns a no-op spinner when not decorating.
|
|
942
|
+
*/
|
|
943
|
+
spinner(delayMs = 100) {
|
|
944
|
+
const noop = {
|
|
945
|
+
start: () => {},
|
|
946
|
+
stop: () => {},
|
|
947
|
+
cancel: () => {},
|
|
948
|
+
error: () => {},
|
|
949
|
+
message: () => {},
|
|
950
|
+
clear: () => {},
|
|
951
|
+
get isCancelled() {
|
|
952
|
+
return false;
|
|
953
|
+
}
|
|
954
|
+
};
|
|
955
|
+
if (!this.shouldDecorate) return noop;
|
|
956
|
+
let inner;
|
|
957
|
+
let timer;
|
|
958
|
+
let pendingMsg;
|
|
959
|
+
let settled = false;
|
|
960
|
+
const ensureCleared = () => {
|
|
961
|
+
if (timer !== void 0) {
|
|
962
|
+
clearTimeout(timer);
|
|
963
|
+
timer = void 0;
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
const onAbort = () => {
|
|
967
|
+
if (!settled) {
|
|
968
|
+
settled = true;
|
|
969
|
+
ensureCleared();
|
|
970
|
+
if (inner) inner.cancel("Interrupted");
|
|
971
|
+
}
|
|
972
|
+
};
|
|
973
|
+
if (!shutdownSignal.aborted) shutdownSignal.addEventListener("abort", onAbort, { once: true });
|
|
974
|
+
return {
|
|
975
|
+
start(msg) {
|
|
976
|
+
pendingMsg = msg;
|
|
977
|
+
timer = setTimeout(() => {
|
|
978
|
+
if (!settled) {
|
|
979
|
+
inner = clack.spinner(TerminalUI.stderrOpts);
|
|
980
|
+
inner.start(pendingMsg);
|
|
981
|
+
}
|
|
982
|
+
}, delayMs);
|
|
983
|
+
},
|
|
984
|
+
stop(msg) {
|
|
985
|
+
settled = true;
|
|
986
|
+
ensureCleared();
|
|
987
|
+
if (inner) inner.stop(msg);
|
|
988
|
+
},
|
|
989
|
+
cancel(msg) {
|
|
990
|
+
settled = true;
|
|
991
|
+
ensureCleared();
|
|
992
|
+
if (inner) inner.cancel(msg);
|
|
993
|
+
},
|
|
994
|
+
error(msg) {
|
|
995
|
+
settled = true;
|
|
996
|
+
ensureCleared();
|
|
997
|
+
if (inner) inner.error(msg);
|
|
998
|
+
},
|
|
999
|
+
message(msg) {
|
|
1000
|
+
pendingMsg = msg;
|
|
1001
|
+
if (inner) inner.message(msg);
|
|
1002
|
+
},
|
|
1003
|
+
clear() {
|
|
1004
|
+
settled = true;
|
|
1005
|
+
ensureCleared();
|
|
1006
|
+
if (inner) inner.clear();
|
|
1007
|
+
},
|
|
1008
|
+
get isCancelled() {
|
|
1009
|
+
return inner?.isCancelled ?? false;
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Prompt for yes/no confirmation on stderr. Returns true if confirmed.
|
|
1015
|
+
* In non-interactive mode or when cancelled (Ctrl-C), returns false.
|
|
1016
|
+
*/
|
|
1017
|
+
async confirm(message) {
|
|
1018
|
+
if (!this.isInteractive) return false;
|
|
1019
|
+
const result = await clack.confirm({
|
|
1020
|
+
message,
|
|
1021
|
+
...TerminalUI.stderrOpts
|
|
1022
|
+
});
|
|
1023
|
+
if (clack.isCancel(result)) return false;
|
|
1024
|
+
return result;
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* Write a raw line to stderr. No-op when piped unless forcePretty.
|
|
1028
|
+
* Use for decoration that doesn't fit Clack's log format (e.g. styled headers).
|
|
1029
|
+
*/
|
|
1030
|
+
stderr(message) {
|
|
1031
|
+
if (!this.shouldDecorate) return;
|
|
1032
|
+
process.stderr.write(`${message}\n`);
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Write machine-readable data to stdout.
|
|
1036
|
+
* Always writes — if a command calls output(), there is data to emit.
|
|
1037
|
+
*
|
|
1038
|
+
* This is what scripts and pipes capture: `prisma-next db verify --json | jq .ok`
|
|
1039
|
+
*/
|
|
1040
|
+
output(data) {
|
|
1041
|
+
process.stdout.write(`${data}\n`);
|
|
1042
|
+
}
|
|
1043
|
+
green(text) {
|
|
1044
|
+
return this.useColor ? green(text) : text;
|
|
1045
|
+
}
|
|
1046
|
+
red(text) {
|
|
1047
|
+
return this.useColor ? red(text) : text;
|
|
1048
|
+
}
|
|
1049
|
+
cyan(text) {
|
|
1050
|
+
return this.useColor ? cyan(text) : text;
|
|
1051
|
+
}
|
|
1052
|
+
dim(text) {
|
|
1053
|
+
return this.useColor ? dim(text) : text;
|
|
1054
|
+
}
|
|
1055
|
+
bold(text) {
|
|
1056
|
+
return this.useColor ? bold(text) : text;
|
|
1057
|
+
}
|
|
1058
|
+
yellow(text) {
|
|
1059
|
+
return this.useColor ? yellow(text) : text;
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
function createTerminalUI(flags, runtime) {
|
|
1063
|
+
return new TerminalUI({
|
|
1064
|
+
color: flags.color,
|
|
1065
|
+
interactive: flags.interactive,
|
|
1066
|
+
forcePretty: flags.format === "pretty" && flags.explicitFormat,
|
|
1067
|
+
stdoutIsTTY: runtime?.isTTY,
|
|
1068
|
+
env: runtime?.env
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
1071
|
+
//#endregion
|
|
441
1072
|
//#region src/utils/global-flags.ts
|
|
442
1073
|
function isJsonFlagSet(json) {
|
|
443
1074
|
return json === true;
|
|
@@ -499,7 +1130,7 @@ function parseGlobalFlagsOrExit(options) {
|
|
|
499
1130
|
try {
|
|
500
1131
|
return parseGlobalFlags(options);
|
|
501
1132
|
} catch (error) {
|
|
502
|
-
if (CliStructuredError.is(error)) emitGlobalFlagParseError(error, options);
|
|
1133
|
+
if (CliStructuredError$1.is(error)) emitGlobalFlagParseError(error, options);
|
|
503
1134
|
throw error;
|
|
504
1135
|
}
|
|
505
1136
|
}
|
|
@@ -525,7 +1156,7 @@ function parseGlobalFlags(options) {
|
|
|
525
1156
|
if (process.env["NO_COLOR"] || flags.json) flags.color = false;
|
|
526
1157
|
else if (options["no-color"]) flags.color = false;
|
|
527
1158
|
else if (options.color !== void 0) flags.color = options.color;
|
|
528
|
-
else flags.color = process.stdout.isTTY && !isCI();
|
|
1159
|
+
else flags.color = process.stdout.isTTY && !isCI$1();
|
|
529
1160
|
if (options["no-interactive"]) flags.interactive = false;
|
|
530
1161
|
else if (options.interactive !== void 0) flags.interactive = options.interactive;
|
|
531
1162
|
else flags.interactive = !!process.stdout.isTTY;
|
|
@@ -534,26 +1165,6 @@ function parseGlobalFlags(options) {
|
|
|
534
1165
|
}
|
|
535
1166
|
//#endregion
|
|
536
1167
|
//#region src/utils/command-helpers.ts
|
|
537
|
-
var command_helpers_exports = /* @__PURE__ */ __exportAll({
|
|
538
|
-
addGlobalOptions: () => addGlobalOptions,
|
|
539
|
-
collectDeclaredInvariants: () => collectDeclaredInvariants,
|
|
540
|
-
getCommandExamples: () => getCommandExamples,
|
|
541
|
-
getCommandSeeAlso: () => getCommandSeeAlso,
|
|
542
|
-
getLongDescription: () => getLongDescription,
|
|
543
|
-
getTargetMigrations: () => getTargetMigrations,
|
|
544
|
-
loadMigrationPackages: () => loadMigrationPackages,
|
|
545
|
-
maskConnectionUrl: () => maskConnectionUrl,
|
|
546
|
-
readContractEnvelope: () => readContractEnvelope,
|
|
547
|
-
resolveContractPath: () => resolveContractPath,
|
|
548
|
-
resolveMigrationPaths: () => resolveMigrationPaths,
|
|
549
|
-
sanitizeErrorMessage: () => sanitizeErrorMessage,
|
|
550
|
-
setCommandDescriptions: () => setCommandDescriptions,
|
|
551
|
-
setCommandExamples: () => setCommandExamples,
|
|
552
|
-
setCommandSeeAlso: () => setCommandSeeAlso,
|
|
553
|
-
targetSupportsMigrations: () => targetSupportsMigrations,
|
|
554
|
-
toPathDecisionResult: () => toPathDecisionResult,
|
|
555
|
-
toStructuralEdge: () => toStructuralEdge
|
|
556
|
-
});
|
|
557
1168
|
const longDescriptions = /* @__PURE__ */ new WeakMap();
|
|
558
1169
|
const commandExamples = /* @__PURE__ */ new WeakMap();
|
|
559
1170
|
const commandSeeAlso = /* @__PURE__ */ new WeakMap();
|
|
@@ -602,10 +1213,13 @@ function getCommandSeeAlso(command) {
|
|
|
602
1213
|
}
|
|
603
1214
|
/**
|
|
604
1215
|
* Resolves the absolute path to contract.json from the config.
|
|
605
|
-
* Centralises the fallback logic shared by every command that reads the contract.
|
|
606
1216
|
*/
|
|
607
1217
|
function resolveContractPath(config) {
|
|
608
|
-
|
|
1218
|
+
if (config.contract?.output === void 0) throw errorRuntime$1("config.contract.output is required to resolve the contract path", {
|
|
1219
|
+
why: "CLI commands read the emitted contract from config.contract.output; the config has no value to read.",
|
|
1220
|
+
fix: "Ensure your prisma-next.config.ts goes through `defineConfig()`, which normalises a default output when the provider supplies an input path, or set `contract.output` explicitly."
|
|
1221
|
+
});
|
|
1222
|
+
return resolve(config.contract.output);
|
|
609
1223
|
}
|
|
610
1224
|
/**
|
|
611
1225
|
* Resolves the migrations directory and config path from CLI options.
|
|
@@ -683,20 +1297,6 @@ function getTargetMigrations(target) {
|
|
|
683
1297
|
return hasMigrations(target) ? target.migrations : void 0;
|
|
684
1298
|
}
|
|
685
1299
|
/**
|
|
686
|
-
* Reads the migrations directory and builds the migration graph from all
|
|
687
|
-
* packages. Throws on I/O or graph errors — callers handle error mapping.
|
|
688
|
-
*
|
|
689
|
-
* Every on-disk package is content-addressed (`migrationHash` is always a
|
|
690
|
-
* string); there is no draft state to filter out.
|
|
691
|
-
*/
|
|
692
|
-
async function loadMigrationPackages(migrationsDir) {
|
|
693
|
-
const bundles = await readMigrationsDir(migrationsDir);
|
|
694
|
-
return {
|
|
695
|
-
bundles,
|
|
696
|
-
graph: reconstructGraph(bundles)
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
/**
|
|
700
1300
|
* Reads and parses contract.json, validating the framework-level envelope
|
|
701
1301
|
* fields (storageHash, schemaVersion, target, targetFamily).
|
|
702
1302
|
*
|
|
@@ -770,6 +1370,6 @@ function addGlobalOptions(command) {
|
|
|
770
1370
|
} }).option("--format <pretty|json>", "Output format (default: pretty, or json when stdout is not a TTY)").option("--json", "Output as JSON (alias for --format json)").option("-q, --quiet", "Quiet mode: errors only").option("-v, --verbose", "Verbose output: debug info, timings").option("--trace", "Trace output: deep internals, stack traces").option("--color", "Force color output").option("--no-color", "Disable color output").option("--interactive", "Force interactive mode").option("--no-interactive", "Disable interactive prompts").option("-y, --yes", "Auto-accept prompts");
|
|
771
1371
|
}
|
|
772
1372
|
//#endregion
|
|
773
|
-
export {
|
|
1373
|
+
export { errorTargetMigrationNotSupported as $, CliStructuredError$1 as A, errorInvalidSpaceId as B, formatCommandHelp as C, createColorFormatter as D, formatSuccessMessage as E, errorDatabaseConnectionRequired as F, errorPlanForgotTheFlag as G, errorMarkerMissing as H, errorDestructiveChanges as I, errorRefSetHashNotInGraph as J, errorRefSetBundleNotFound as K, errorDriverRequired as L, errorConfigValidation$1 as M, errorContractConfigMissing$1 as N, formatDim as O, errorContractValidationFailed as P, errorSpaceNotFound as Q, errorFileNotFound as R, isCI$1 as S, formatStyledHeader as T, errorMigrationPlanningFailed as U, errorMarkerMismatch as V, errorPathUnreachable as W, errorRuntime$1 as X, errorRunnerFailed as Y, errorSnapshotMissing as Z, createTerminalUI as _, readContractEnvelope as a, formatErrorJson as b, sanitizeErrorMessage as c, setCommandSeeAlso as d, errorTargetMismatch as et, targetSupportsMigrations as f, parseGlobalFlagsOrExit as g, parseGlobalFlags as h, maskConnectionUrl as i, ERROR_CODE_DESTRUCTIVE_CHANGES as j, isVerbose as k, setCommandDescriptions as l, toStructuralEdge as m, collectDeclaredInvariants as n, mapMigrationToolsError as nt, resolveContractPath as o, toPathDecisionResult as p, errorRefSetEmptySentinel as q, getTargetMigrations as r, mapRefResolutionError as rt, resolveMigrationPaths as s, addGlobalOptions as t, errorUnexpected$1 as tt, setCommandExamples as u, installShutdownHandlers as v, formatRootHelp as w, formatErrorOutput as x, handleResult as y, errorHashMismatch as z };
|
|
774
1374
|
|
|
775
|
-
//# sourceMappingURL=command-helpers-
|
|
1375
|
+
//# sourceMappingURL=command-helpers-Bbw1GbwL.mjs.map
|