@prisma-next/cli 0.4.1 → 0.4.2

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.
Files changed (121) hide show
  1. package/README.md +1 -6
  2. package/dist/agent-skill-mongo.md +63 -31
  3. package/dist/agent-skill-postgres.md +1 -1
  4. package/dist/cli-errors-BFYgBH3L.d.mts +4 -0
  5. package/dist/{cli-errors-CznZA5-d.mjs → cli-errors-Cd79vmTH.mjs} +2 -2
  6. package/dist/cli.mjs +126 -13
  7. package/dist/cli.mjs.map +1 -1
  8. package/dist/{client-DGKrciLM.mjs → client-CrsnY58k.mjs} +4 -4
  9. package/dist/{client-DGKrciLM.mjs.map → client-CrsnY58k.mjs.map} +1 -1
  10. package/dist/commands/contract-emit.mjs +7 -2
  11. package/dist/commands/contract-infer.mjs +8 -2
  12. package/dist/commands/db-init.mjs +8 -7
  13. package/dist/commands/db-init.mjs.map +1 -1
  14. package/dist/commands/db-schema.mjs +8 -5
  15. package/dist/commands/db-schema.mjs.map +1 -1
  16. package/dist/commands/db-sign.mjs +8 -7
  17. package/dist/commands/db-sign.mjs.map +1 -1
  18. package/dist/commands/db-update.mjs +8 -7
  19. package/dist/commands/db-update.mjs.map +1 -1
  20. package/dist/commands/db-verify.mjs +8 -7
  21. package/dist/commands/db-verify.mjs.map +1 -1
  22. package/dist/commands/migration-apply.mjs +9 -8
  23. package/dist/commands/migration-apply.mjs.map +1 -1
  24. package/dist/commands/migration-new.mjs +5 -5
  25. package/dist/commands/migration-plan.mjs +6 -6
  26. package/dist/commands/migration-ref.d.mts +6 -4
  27. package/dist/commands/migration-ref.d.mts.map +1 -1
  28. package/dist/commands/migration-ref.mjs +29 -34
  29. package/dist/commands/migration-ref.mjs.map +1 -1
  30. package/dist/commands/migration-show.d.mts +1 -1
  31. package/dist/commands/migration-show.mjs +6 -6
  32. package/dist/commands/migration-status.d.mts.map +1 -1
  33. package/dist/commands/migration-status.mjs +7 -2
  34. package/dist/{config-loader-_xQZsw0i.mjs → config-loader-C25b63rJ.mjs} +1 -1
  35. package/dist/{config-loader-_xQZsw0i.mjs.map → config-loader-C25b63rJ.mjs.map} +1 -1
  36. package/dist/config-loader.mjs +1 -1
  37. package/dist/contract-emit-DxgyXrqV.mjs +6 -0
  38. package/dist/{contract-emit-mU1_B_m9.mjs → contract-emit-NJ01hiiv.mjs} +10 -10
  39. package/dist/contract-emit-NJ01hiiv.mjs.map +1 -0
  40. package/dist/{contract-emit-DgeWdonT.mjs → contract-emit-V5SSitUT.mjs} +6 -6
  41. package/dist/{contract-emit-DgeWdonT.mjs.map → contract-emit-V5SSitUT.mjs.map} +1 -1
  42. package/dist/{contract-enrichment-BV4KpbNW.mjs → contract-enrichment-CAOELa-H.mjs} +1 -1
  43. package/dist/{contract-enrichment-BV4KpbNW.mjs.map → contract-enrichment-CAOELa-H.mjs.map} +1 -1
  44. package/dist/{contract-infer-CUbiWGX0.mjs → contract-infer-D9cC3rJm.mjs} +4 -4
  45. package/dist/{contract-infer-CUbiWGX0.mjs.map → contract-infer-D9cC3rJm.mjs.map} +1 -1
  46. package/dist/exports/control-api.mjs +6 -4
  47. package/dist/exports/index.mjs +7 -2
  48. package/dist/exports/index.mjs.map +1 -1
  49. package/dist/exports/init-output.d.mts +39 -0
  50. package/dist/exports/init-output.d.mts.map +1 -0
  51. package/dist/exports/init-output.mjs +3 -0
  52. package/dist/{extract-operation-statements-DWWFz1PK.mjs → extract-operation-statements-DsFfxXVZ.mjs} +2 -2
  53. package/dist/{extract-operation-statements-DWWFz1PK.mjs.map → extract-operation-statements-DsFfxXVZ.mjs.map} +1 -1
  54. package/dist/{extract-sql-ddl-7zn_AFS8.mjs → extract-sql-ddl-D9UbZDyz.mjs} +1 -1
  55. package/dist/{extract-sql-ddl-7zn_AFS8.mjs.map → extract-sql-ddl-D9UbZDyz.mjs.map} +1 -1
  56. package/dist/{framework-components-B__p--vT.mjs → framework-components-Cr--XBKy.mjs} +2 -2
  57. package/dist/{framework-components-B__p--vT.mjs.map → framework-components-Cr--XBKy.mjs.map} +1 -1
  58. package/dist/init-m8x0UoPY.mjs +2062 -0
  59. package/dist/init-m8x0UoPY.mjs.map +1 -0
  60. package/dist/{inspect-live-schema-wIYBTdL3.mjs → inspect-live-schema-yrHAvG71.mjs} +6 -6
  61. package/dist/{inspect-live-schema-wIYBTdL3.mjs.map → inspect-live-schema-yrHAvG71.mjs.map} +1 -1
  62. package/dist/migration-cli.d.mts +50 -0
  63. package/dist/migration-cli.d.mts.map +1 -0
  64. package/dist/migration-cli.mjs +184 -0
  65. package/dist/migration-cli.mjs.map +1 -0
  66. package/dist/{migration-command-scaffold-BC73xQSo.mjs → migration-command-scaffold-B3B09et6.mjs} +6 -6
  67. package/dist/{migration-command-scaffold-BC73xQSo.mjs.map → migration-command-scaffold-B3B09et6.mjs.map} +1 -1
  68. package/dist/{migration-status-CXBbScH5.mjs → migration-status-DUMiH8_G.mjs} +12 -14
  69. package/dist/{migration-status-CXBbScH5.mjs.map → migration-status-DUMiH8_G.mjs.map} +1 -1
  70. package/dist/{migrations-DYRAjiVh.mjs → migrations-Bo5WtTla.mjs} +2 -2
  71. package/dist/{migrations-DYRAjiVh.mjs.map → migrations-Bo5WtTla.mjs.map} +1 -1
  72. package/dist/output-BpcQrnnq.mjs +103 -0
  73. package/dist/output-BpcQrnnq.mjs.map +1 -0
  74. package/dist/{progress-adapter-Bwouy73-.mjs → progress-adapter-DvQWB1nK.mjs} +1 -1
  75. package/dist/{progress-adapter-Bwouy73-.mjs.map → progress-adapter-DvQWB1nK.mjs.map} +1 -1
  76. package/dist/quick-reference-mongo.md +34 -13
  77. package/dist/quick-reference-postgres.md +11 -9
  78. package/dist/{result-handler-CGohaH1o.mjs → result-handler-Ba3zWQsI.mjs} +5 -78
  79. package/dist/result-handler-Ba3zWQsI.mjs.map +1 -0
  80. package/dist/{terminal-ui-BuPXVRFY.mjs → terminal-ui-C3ZLwQxK.mjs} +76 -2
  81. package/dist/terminal-ui-C3ZLwQxK.mjs.map +1 -0
  82. package/dist/{validate-contract-deps-DZqv9m7H.mjs → validate-contract-deps-B_Cs29TL.mjs} +1 -1
  83. package/dist/{validate-contract-deps-DZqv9m7H.mjs.map → validate-contract-deps-B_Cs29TL.mjs.map} +1 -1
  84. package/dist/{verify-Cm2UFuZA.mjs → verify-Bkycc-Tf.mjs} +2 -2
  85. package/dist/{verify-Cm2UFuZA.mjs.map → verify-Bkycc-Tf.mjs.map} +1 -1
  86. package/package.json +25 -16
  87. package/src/commands/init/detect-pnpm-catalog.ts +141 -0
  88. package/src/commands/init/errors.ts +254 -0
  89. package/src/commands/init/exit-codes.ts +62 -0
  90. package/src/commands/init/hygiene-gitattributes.ts +97 -0
  91. package/src/commands/init/hygiene-gitignore.ts +48 -0
  92. package/src/commands/init/hygiene-package-scripts.ts +91 -0
  93. package/src/commands/init/index.ts +112 -7
  94. package/src/commands/init/init.ts +766 -144
  95. package/src/commands/init/inputs.ts +421 -0
  96. package/src/commands/init/output.ts +147 -0
  97. package/src/commands/init/probe-db.ts +308 -0
  98. package/src/commands/init/reinit-cleanup.ts +83 -0
  99. package/src/commands/init/templates/agent-skill-mongo.md +63 -31
  100. package/src/commands/init/templates/agent-skill-postgres.md +1 -1
  101. package/src/commands/init/templates/agent-skill.ts +25 -3
  102. package/src/commands/init/templates/code-templates.ts +125 -32
  103. package/src/commands/init/templates/env.ts +80 -0
  104. package/src/commands/init/templates/quick-reference-mongo.md +34 -13
  105. package/src/commands/init/templates/quick-reference-postgres.md +11 -9
  106. package/src/commands/init/templates/quick-reference.ts +42 -3
  107. package/src/commands/init/templates/tsconfig.ts +167 -5
  108. package/src/commands/migration-apply.ts +3 -3
  109. package/src/commands/migration-ref.ts +32 -47
  110. package/src/commands/migration-status.ts +16 -21
  111. package/src/exports/init-output.ts +10 -0
  112. package/src/migration-cli.ts +254 -0
  113. package/src/utils/cli-errors.ts +1 -0
  114. package/src/utils/command-helpers.ts +3 -3
  115. package/dist/cli-errors-z37sV3eR.d.mts +0 -4
  116. package/dist/contract-emit-304WZtZJ.mjs +0 -4
  117. package/dist/contract-emit-mU1_B_m9.mjs.map +0 -1
  118. package/dist/init-DRquYpPa.mjs +0 -430
  119. package/dist/init-DRquYpPa.mjs.map +0 -1
  120. package/dist/result-handler-CGohaH1o.mjs.map +0 -1
  121. package/dist/terminal-ui-BuPXVRFY.mjs.map +0 -1
@@ -0,0 +1,184 @@
1
+ import { t as loadConfig } from "./config-loader-C25b63rJ.mjs";
2
+ import { readFileSync, writeFileSync } from "node:fs";
3
+ import { CliStructuredError, errorMigrationCliInvalidConfigArg } from "@prisma-next/errors/control";
4
+ import { dirname, join } from "pathe";
5
+ import { createControlStack } from "@prisma-next/framework-components/control";
6
+ import { errorMigrationTargetMismatch } from "@prisma-next/errors/migration";
7
+ import { fileURLToPath } from "node:url";
8
+ import { buildMigrationArtifacts, isDirectEntrypoint, printMigrationHelp } from "@prisma-next/migration-tools/migration";
9
+
10
+ //#region src/migration-cli.ts
11
+ /**
12
+ * The migration-file CLI interface: the actor invoked when the author runs
13
+ * `node migration.ts` directly.
14
+ *
15
+ * Naming: this is *not* a "migration runner" in the apply-time sense. The
16
+ * apply-time runner is the thing `prisma-next migration apply` uses to
17
+ * execute migration JSON ops against a database. `MigrationCLI` is the
18
+ * tiny CLI surface owned by an authored `migration.ts` file: parse the
19
+ * file's argv, load the project's `prisma-next.config.ts`, assemble a
20
+ * `ControlStack`, instantiate the migration class, and serialize.
21
+ *
22
+ * The user authors a migration class, then calls
23
+ * `MigrationCLI.run(import.meta.url, MigrationClass)` at module scope
24
+ * after the class definition. When the file is invoked as a node
25
+ * entrypoint (`node migration.ts`), the CLI:
26
+ *
27
+ * 1. Detects whether the file is the direct entrypoint (no-op when imported).
28
+ * 2. Parses CLI args (`--help`, `--dry-run`, `--config <path>`).
29
+ * 3. Loads the project's `prisma-next.config.ts` via the same `loadConfig`
30
+ * the CLI commands use, walking up from the migration file's directory.
31
+ * 4. Probe-instantiates the migration class without a stack so it can read
32
+ * `targetId` and verify it matches `config.target.targetId`
33
+ * (`PN-MIG-2006` on mismatch) before any stack-driven adapter
34
+ * construction runs.
35
+ * 5. Assembles a `ControlStack` from the loaded config descriptors and
36
+ * constructs the migration with that stack.
37
+ * 6. Reads any previously-scaffolded `migration.json`, then calls
38
+ * `buildMigrationArtifacts` from `@prisma-next/migration-tools` to
39
+ * produce in-memory `ops.json` + `migration.json` content. Persists
40
+ * the result to disk (or prints in dry-run mode).
41
+ *
42
+ * File I/O lives here, in `@prisma-next/cli`: this is the only place
43
+ * that legitimately combines config loading, stack assembly, and
44
+ * on-disk persistence. `@prisma-next/migration-tools` owns the pure
45
+ * conversion from a `Migration` instance to artifact strings; `Migration`
46
+ * stays a pure abstract class.
47
+ */
48
+ /**
49
+ * Parse the subset of `process.argv` that `MigrationCLI.run` cares about.
50
+ * Recognised flags: `--help`, `--dry-run`, `--config <path>` /
51
+ * `--config=<path>`. Unknown flags are ignored to keep the surface
52
+ * forgiving for ad-hoc tooling that wraps a migration file.
53
+ *
54
+ * Throws `errorMigrationCliInvalidConfigArg` (`PN-CLI-4012`) when
55
+ * `--config` is missing its path argument or is followed by another flag
56
+ * (e.g. `--config --dry-run`); silently consuming the next flag would
57
+ * either drop dry-run handling or serialize against the wrong project.
58
+ *
59
+ * NOTE: this hand-rolled parser is a known wart, tracked separately by
60
+ * TML-2318 ("Migration CLI: replace handrolled arg parser with shared
61
+ * CLI library"). Until that lands the surface is intentionally tiny.
62
+ */
63
+ function parseArgs(argv) {
64
+ let help = false;
65
+ let dryRun = false;
66
+ let configPath;
67
+ for (let i = 0; i < argv.length; i++) {
68
+ const arg = argv[i];
69
+ if (arg === "--help" || arg === "-h") help = true;
70
+ else if (arg === "--dry-run") dryRun = true;
71
+ else if (arg === "--config") {
72
+ const next = argv[i + 1];
73
+ if (next === void 0) throw errorMigrationCliInvalidConfigArg();
74
+ if (next.startsWith("-")) throw errorMigrationCliInvalidConfigArg({ nextToken: next });
75
+ configPath = next;
76
+ i++;
77
+ } else if (arg.startsWith("--config=")) configPath = arg.slice(9);
78
+ }
79
+ return {
80
+ help,
81
+ dryRun,
82
+ configPath
83
+ };
84
+ }
85
+ /**
86
+ * The CLI surface invoked by an authored `migration.ts` file. Exposed as
87
+ * a class with a static `run` method (rather than a free function) to
88
+ * give the concept a stable identity in the ubiquitous language: this is
89
+ * the "migration-file CLI", distinct from the apply-time runner that
90
+ * executes migration JSON ops.
91
+ *
92
+ * Currently a single static method. Future surface (e.g. a programmatic
93
+ * `MigrationCLI.serializeOnly(...)` for tests, or extra subcommands) can
94
+ * land here without changing the import shape used by every authored
95
+ * migration.
96
+ */
97
+ var MigrationCLI = class {
98
+ /**
99
+ * Orchestrates a class-flow `migration.ts` script run. Awaitable:
100
+ * callers may `await MigrationCLI.run(...)` to surface async failures
101
+ * from config loading, but the typical usage pattern (top-level call
102
+ * after the class definition) does not require awaiting because
103
+ * node's module evaluation keeps the promise alive until completion.
104
+ *
105
+ * Any throwable inside this function must surface through the internal
106
+ * try/catch — script callers do not await, so an unhandled rejection
107
+ * would silently exit 0. Treat the try/catch as load-bearing for the
108
+ * no-await usage pattern.
109
+ */
110
+ static async run(importMetaUrl, MigrationClass) {
111
+ if (!importMetaUrl) return;
112
+ if (!isDirectEntrypoint(importMetaUrl)) return;
113
+ try {
114
+ const args = parseArgs(process.argv.slice(2));
115
+ if (args.help) {
116
+ printMigrationHelp();
117
+ return;
118
+ }
119
+ const migrationDir = dirname(fileURLToPath(importMetaUrl));
120
+ const config = await loadConfig(args.configPath);
121
+ const probe = new MigrationClass();
122
+ if (probe.targetId !== config.target.targetId) throw errorMigrationTargetMismatch({
123
+ migrationTargetId: probe.targetId,
124
+ configTargetId: config.target.targetId
125
+ });
126
+ serializeMigrationToDisk(new MigrationClass(createControlStack(config)), migrationDir, args.dryRun);
127
+ } catch (err) {
128
+ if (CliStructuredError.is(err)) process.stderr.write(`${err.message}: ${err.why}\n`);
129
+ else process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
130
+ process.exitCode = 1;
131
+ }
132
+ }
133
+ };
134
+ /**
135
+ * Read a previously-scaffolded `migration.json` from disk, returning
136
+ * `null` when the file is missing or unparseable. The CLI feeds this into
137
+ * `buildMigrationArtifacts` so the pure builder can preserve fields owned
138
+ * by `migration plan` (contract bookends, hints, labels, `createdAt`)
139
+ * across re-emits.
140
+ */
141
+ function readExistingManifest(manifestPath) {
142
+ let raw;
143
+ try {
144
+ raw = readFileSync(manifestPath, "utf-8");
145
+ } catch {
146
+ return null;
147
+ }
148
+ try {
149
+ return JSON.parse(raw);
150
+ } catch {
151
+ return null;
152
+ }
153
+ }
154
+ /**
155
+ * Persist a migration instance's artifacts to `migrationDir`. In
156
+ * `dryRun` mode the artifacts are printed to stdout (with the same
157
+ * `--- migration.json --- / --- ops.json ---` framing the legacy
158
+ * `serializeMigration` helper used) and no files are written. Otherwise
159
+ * `ops.json` and `migration.json` are written next to `migration.ts` and
160
+ * a confirmation line is printed.
161
+ *
162
+ * File I/O lives in the CLI rather than `@prisma-next/migration-tools`
163
+ * so the migration-tools package stays focused on the pure
164
+ * `Migration` → in-memory artifact conversion. The CLI is the only
165
+ * legitimate site for combining config loading, stack assembly, and
166
+ * filesystem persistence.
167
+ */
168
+ function serializeMigrationToDisk(instance, migrationDir, dryRun) {
169
+ const manifestPath = join(migrationDir, "migration.json");
170
+ const { opsJson, manifestJson } = buildMigrationArtifacts(instance, readExistingManifest(manifestPath));
171
+ if (dryRun) {
172
+ process.stdout.write(`--- migration.json ---\n${manifestJson}\n`);
173
+ process.stdout.write("--- ops.json ---\n");
174
+ process.stdout.write(`${opsJson}\n`);
175
+ return;
176
+ }
177
+ writeFileSync(join(migrationDir, "ops.json"), opsJson);
178
+ writeFileSync(manifestPath, manifestJson);
179
+ process.stdout.write(`Wrote ops.json + migration.json to ${migrationDir}\n`);
180
+ }
181
+
182
+ //#endregion
183
+ export { MigrationCLI };
184
+ //# sourceMappingURL=migration-cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-cli.mjs","names":["configPath: string | undefined","raw: string"],"sources":["../src/migration-cli.ts"],"sourcesContent":["/**\n * The migration-file CLI interface: the actor invoked when the author runs\n * `node migration.ts` directly.\n *\n * Naming: this is *not* a \"migration runner\" in the apply-time sense. The\n * apply-time runner is the thing `prisma-next migration apply` uses to\n * execute migration JSON ops against a database. `MigrationCLI` is the\n * tiny CLI surface owned by an authored `migration.ts` file: parse the\n * file's argv, load the project's `prisma-next.config.ts`, assemble a\n * `ControlStack`, instantiate the migration class, and serialize.\n *\n * The user authors a migration class, then calls\n * `MigrationCLI.run(import.meta.url, MigrationClass)` at module scope\n * after the class definition. When the file is invoked as a node\n * entrypoint (`node migration.ts`), the CLI:\n *\n * 1. Detects whether the file is the direct entrypoint (no-op when imported).\n * 2. Parses CLI args (`--help`, `--dry-run`, `--config <path>`).\n * 3. Loads the project's `prisma-next.config.ts` via the same `loadConfig`\n * the CLI commands use, walking up from the migration file's directory.\n * 4. Probe-instantiates the migration class without a stack so it can read\n * `targetId` and verify it matches `config.target.targetId`\n * (`PN-MIG-2006` on mismatch) before any stack-driven adapter\n * construction runs.\n * 5. Assembles a `ControlStack` from the loaded config descriptors and\n * constructs the migration with that stack.\n * 6. Reads any previously-scaffolded `migration.json`, then calls\n * `buildMigrationArtifacts` from `@prisma-next/migration-tools` to\n * produce in-memory `ops.json` + `migration.json` content. Persists\n * the result to disk (or prints in dry-run mode).\n *\n * File I/O lives here, in `@prisma-next/cli`: this is the only place\n * that legitimately combines config loading, stack assembly, and\n * on-disk persistence. `@prisma-next/migration-tools` owns the pure\n * conversion from a `Migration` instance to artifact strings; `Migration`\n * stays a pure abstract class.\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { CliStructuredError, errorMigrationCliInvalidConfigArg } from '@prisma-next/errors/control';\nimport { errorMigrationTargetMismatch } from '@prisma-next/errors/migration';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport {\n buildMigrationArtifacts,\n isDirectEntrypoint,\n type Migration,\n printMigrationHelp,\n} from '@prisma-next/migration-tools/migration';\nimport type { MigrationManifest } from '@prisma-next/migration-tools/types';\nimport { dirname, join } from 'pathe';\nimport { loadConfig } from './config-loader';\n\n/**\n * Constructor shape accepted by `MigrationCLI.run`. `Migration` subclasses\n * accept an optional `ControlStack` in their constructor (each subclass\n * narrows the stack to its own family/target generics); the CLI always\n * passes one assembled from the loaded config. We use a rest-args `any[]`\n * constructor signature so that subclass constructors with narrower\n * parameter types remain assignable - constructor type compatibility in\n * TS is contravariant in the parameter, and a wider `unknown` parameter\n * on the alias side would reject any narrower subclass signature.\n *\n * The CLI only ever passes one argument (`new MigrationClass(stack)`);\n * the rest-arity is purely a type-compatibility concession for subclass\n * constructors that declare narrower parameter types, not an extension\n * point for additional construction arguments.\n */\n// biome-ignore lint/suspicious/noExplicitAny: see JSDoc - rest args with any are the idiomatic TS pattern for accepting arbitrary subclass constructor signatures\nexport type MigrationConstructor = new (...args: any[]) => Migration;\n\ninterface ParsedArgs {\n readonly help: boolean;\n readonly dryRun: boolean;\n readonly configPath: string | undefined;\n}\n\n/**\n * Parse the subset of `process.argv` that `MigrationCLI.run` cares about.\n * Recognised flags: `--help`, `--dry-run`, `--config <path>` /\n * `--config=<path>`. Unknown flags are ignored to keep the surface\n * forgiving for ad-hoc tooling that wraps a migration file.\n *\n * Throws `errorMigrationCliInvalidConfigArg` (`PN-CLI-4012`) when\n * `--config` is missing its path argument or is followed by another flag\n * (e.g. `--config --dry-run`); silently consuming the next flag would\n * either drop dry-run handling or serialize against the wrong project.\n *\n * NOTE: this hand-rolled parser is a known wart, tracked separately by\n * TML-2318 (\"Migration CLI: replace handrolled arg parser with shared\n * CLI library\"). Until that lands the surface is intentionally tiny.\n */\nfunction parseArgs(argv: readonly string[]): ParsedArgs {\n let help = false;\n let dryRun = false;\n let configPath: string | undefined;\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i]!;\n if (arg === '--help' || arg === '-h') {\n help = true;\n } else if (arg === '--dry-run') {\n dryRun = true;\n } else if (arg === '--config') {\n const next = argv[i + 1];\n if (next === undefined) {\n throw errorMigrationCliInvalidConfigArg();\n }\n if (next.startsWith('-')) {\n throw errorMigrationCliInvalidConfigArg({ nextToken: next });\n }\n configPath = next;\n i++;\n } else if (arg.startsWith('--config=')) {\n configPath = arg.slice('--config='.length);\n }\n }\n\n return { help, dryRun, configPath };\n}\n\n/**\n * The CLI surface invoked by an authored `migration.ts` file. Exposed as\n * a class with a static `run` method (rather than a free function) to\n * give the concept a stable identity in the ubiquitous language: this is\n * the \"migration-file CLI\", distinct from the apply-time runner that\n * executes migration JSON ops.\n *\n * Currently a single static method. Future surface (e.g. a programmatic\n * `MigrationCLI.serializeOnly(...)` for tests, or extra subcommands) can\n * land here without changing the import shape used by every authored\n * migration.\n */\n// biome-ignore lint/complexity/noStaticOnlyClass: see JSDoc - intentional class facade for the migration-file CLI surface; future methods will share state derived from argv/config.\nexport class MigrationCLI {\n /**\n * Orchestrates a class-flow `migration.ts` script run. Awaitable:\n * callers may `await MigrationCLI.run(...)` to surface async failures\n * from config loading, but the typical usage pattern (top-level call\n * after the class definition) does not require awaiting because\n * node's module evaluation keeps the promise alive until completion.\n *\n * Any throwable inside this function must surface through the internal\n * try/catch — script callers do not await, so an unhandled rejection\n * would silently exit 0. Treat the try/catch as load-bearing for the\n * no-await usage pattern.\n */\n static async run(importMetaUrl: string, MigrationClass: MigrationConstructor): Promise<void> {\n if (!importMetaUrl) return;\n if (!isDirectEntrypoint(importMetaUrl)) return;\n\n try {\n const args = parseArgs(process.argv.slice(2));\n\n if (args.help) {\n printMigrationHelp();\n return;\n }\n\n const migrationFile = fileURLToPath(importMetaUrl);\n const migrationDir = dirname(migrationFile);\n\n const config = await loadConfig(args.configPath);\n\n // Probe-instantiate without a stack so we can read `targetId` before\n // any target-specific constructor side effects (e.g.\n // `PostgresMigration`'s `stack.adapter.create(stack)`) run. Concrete\n // subclasses are required to accept the no-arg form; the abstract\n // `Migration` constructor declares `stack?` and target subclasses\n // (Postgres, Mongo) propagate that optionality. This makes the\n // target-mismatch guard fail fast with `PN-MIG-2006` before any\n // stack-driven adapter construction begins, even if the wrong-target\n // adapter's `create` would otherwise succeed and silently misshapen\n // the stored adapter cast.\n const probe = new MigrationClass();\n\n if (probe.targetId !== config.target.targetId) {\n throw errorMigrationTargetMismatch({\n migrationTargetId: probe.targetId,\n configTargetId: config.target.targetId,\n });\n }\n\n const stack = createControlStack(config);\n const instance = new MigrationClass(stack);\n\n serializeMigrationToDisk(instance, migrationDir, args.dryRun);\n } catch (err) {\n if (CliStructuredError.is(err)) {\n process.stderr.write(`${err.message}: ${err.why}\\n`);\n } else {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`);\n }\n process.exitCode = 1;\n }\n }\n}\n\n/**\n * Read a previously-scaffolded `migration.json` from disk, returning\n * `null` when the file is missing or unparseable. The CLI feeds this into\n * `buildMigrationArtifacts` so the pure builder can preserve fields owned\n * by `migration plan` (contract bookends, hints, labels, `createdAt`)\n * across re-emits.\n */\nfunction readExistingManifest(manifestPath: string): Partial<MigrationManifest> | null {\n let raw: string;\n try {\n raw = readFileSync(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n try {\n return JSON.parse(raw) as Partial<MigrationManifest>;\n } catch {\n return null;\n }\n}\n\n/**\n * Persist a migration instance's artifacts to `migrationDir`. In\n * `dryRun` mode the artifacts are printed to stdout (with the same\n * `--- migration.json --- / --- ops.json ---` framing the legacy\n * `serializeMigration` helper used) and no files are written. Otherwise\n * `ops.json` and `migration.json` are written next to `migration.ts` and\n * a confirmation line is printed.\n *\n * File I/O lives in the CLI rather than `@prisma-next/migration-tools`\n * so the migration-tools package stays focused on the pure\n * `Migration` → in-memory artifact conversion. The CLI is the only\n * legitimate site for combining config loading, stack assembly, and\n * filesystem persistence.\n */\nfunction serializeMigrationToDisk(\n instance: Migration,\n migrationDir: string,\n dryRun: boolean,\n): void {\n const manifestPath = join(migrationDir, 'migration.json');\n const existing = readExistingManifest(manifestPath);\n const { opsJson, manifestJson } = buildMigrationArtifacts(instance, existing);\n\n if (dryRun) {\n process.stdout.write(`--- migration.json ---\\n${manifestJson}\\n`);\n process.stdout.write('--- ops.json ---\\n');\n process.stdout.write(`${opsJson}\\n`);\n return;\n }\n\n writeFileSync(join(migrationDir, 'ops.json'), opsJson);\n writeFileSync(manifestPath, manifestJson);\n\n process.stdout.write(`Wrote ops.json + migration.json to ${migrationDir}\\n`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4FA,SAAS,UAAU,MAAqC;CACtD,IAAI,OAAO;CACX,IAAI,SAAS;CACb,IAAIA;AAEJ,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,MAAM,KAAK;AACjB,MAAI,QAAQ,YAAY,QAAQ,KAC9B,QAAO;WACE,QAAQ,YACjB,UAAS;WACA,QAAQ,YAAY;GAC7B,MAAM,OAAO,KAAK,IAAI;AACtB,OAAI,SAAS,OACX,OAAM,mCAAmC;AAE3C,OAAI,KAAK,WAAW,IAAI,CACtB,OAAM,kCAAkC,EAAE,WAAW,MAAM,CAAC;AAE9D,gBAAa;AACb;aACS,IAAI,WAAW,YAAY,CACpC,cAAa,IAAI,MAAM,EAAmB;;AAI9C,QAAO;EAAE;EAAM;EAAQ;EAAY;;;;;;;;;;;;;;AAgBrC,IAAa,eAAb,MAA0B;;;;;;;;;;;;;CAaxB,aAAa,IAAI,eAAuB,gBAAqD;AAC3F,MAAI,CAAC,cAAe;AACpB,MAAI,CAAC,mBAAmB,cAAc,CAAE;AAExC,MAAI;GACF,MAAM,OAAO,UAAU,QAAQ,KAAK,MAAM,EAAE,CAAC;AAE7C,OAAI,KAAK,MAAM;AACb,wBAAoB;AACpB;;GAIF,MAAM,eAAe,QADC,cAAc,cAAc,CACP;GAE3C,MAAM,SAAS,MAAM,WAAW,KAAK,WAAW;GAYhD,MAAM,QAAQ,IAAI,gBAAgB;AAElC,OAAI,MAAM,aAAa,OAAO,OAAO,SACnC,OAAM,6BAA6B;IACjC,mBAAmB,MAAM;IACzB,gBAAgB,OAAO,OAAO;IAC/B,CAAC;AAMJ,4BAFiB,IAAI,eADP,mBAAmB,OAAO,CACE,EAEP,cAAc,KAAK,OAAO;WACtD,KAAK;AACZ,OAAI,mBAAmB,GAAG,IAAI,CAC5B,SAAQ,OAAO,MAAM,GAAG,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI;OAEpD,SAAQ,OAAO,MAAM,GAAG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC,IAAI;AAE/E,WAAQ,WAAW;;;;;;;;;;;AAYzB,SAAS,qBAAqB,cAAyD;CACrF,IAAIC;AACJ,KAAI;AACF,QAAM,aAAa,cAAc,QAAQ;SACnC;AACN,SAAO;;AAET,KAAI;AACF,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;;;;;;;;;;;;;;;;;AAkBX,SAAS,yBACP,UACA,cACA,QACM;CACN,MAAM,eAAe,KAAK,cAAc,iBAAiB;CAEzD,MAAM,EAAE,SAAS,iBAAiB,wBAAwB,UADzC,qBAAqB,aAAa,CAC0B;AAE7E,KAAI,QAAQ;AACV,UAAQ,OAAO,MAAM,2BAA2B,aAAa,IAAI;AACjE,UAAQ,OAAO,MAAM,qBAAqB;AAC1C,UAAQ,OAAO,MAAM,GAAG,QAAQ,IAAI;AACpC;;AAGF,eAAc,KAAK,cAAc,WAAW,EAAE,QAAQ;AACtD,eAAc,cAAc,aAAa;AAEzC,SAAQ,OAAO,MAAM,sCAAsC,aAAa,IAAI"}
@@ -1,8 +1,8 @@
1
- import { t as loadConfig } from "./config-loader-_xQZsw0i.mjs";
2
- import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, o as errorDatabaseConnectionRequired } from "./cli-errors-CznZA5-d.mjs";
3
- import { t as createControlClient } from "./client-DGKrciLM.mjs";
4
- import { _ as formatStyledHeader, a as maskConnectionUrl, n as addGlobalOptions, s as resolveContractPath } from "./result-handler-CGohaH1o.mjs";
5
- import { t as createProgressAdapter } from "./progress-adapter-Bwouy73-.mjs";
1
+ import { t as loadConfig } from "./config-loader-C25b63rJ.mjs";
2
+ import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, o as errorDatabaseConnectionRequired } from "./cli-errors-Cd79vmTH.mjs";
3
+ import { t as createControlClient } from "./client-CrsnY58k.mjs";
4
+ import { _ as formatStyledHeader, a as maskConnectionUrl, n as addGlobalOptions, s as resolveContractPath } from "./result-handler-Ba3zWQsI.mjs";
5
+ import { t as createProgressAdapter } from "./progress-adapter-DvQWB1nK.mjs";
6
6
  import { notOk, ok } from "@prisma-next/utils/result";
7
7
  import { hasMigrations } from "@prisma-next/framework-components/control";
8
8
  import { readFile } from "node:fs/promises";
@@ -102,4 +102,4 @@ function addMigrationCommandOptions(command) {
102
102
 
103
103
  //#endregion
104
104
  export { prepareMigrationContext as n, addMigrationCommandOptions as t };
105
- //# sourceMappingURL=migration-command-scaffold-BC73xQSo.mjs.map
105
+ //# sourceMappingURL=migration-command-scaffold-B3B09et6.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-command-scaffold-BC73xQSo.mjs","names":["details: Array<{ label: string; value: string }>","contractJsonContent: string","contractJson: Record<string, unknown>"],"sources":["../src/utils/migration-command-scaffold.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { hasMigrations } from '@prisma-next/framework-components/control';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport type { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type { ControlClient } from '../control-api/types';\nimport {\n type CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from './cli-errors';\nimport { addGlobalOptions, maskConnectionUrl, resolveContractPath } from './command-helpers';\nimport { formatStyledHeader } from './formatters/styled';\nimport type { GlobalFlags } from './global-flags';\nimport { createProgressAdapter } from './progress-adapter';\nimport type { TerminalUI } from './terminal-ui';\n\n/**\n * Resolved context for a migration command.\n * Contains everything needed to invoke a control-api operation.\n */\nexport interface MigrationContext {\n readonly client: ControlClient;\n readonly contractJson: Record<string, unknown>;\n readonly dbConnection: unknown;\n readonly onProgress: ReturnType<typeof createProgressAdapter>;\n readonly configPath: string;\n readonly contractPath: string;\n readonly contractPathAbsolute: string;\n readonly config: Awaited<ReturnType<typeof loadConfig>>;\n}\n\n/**\n * Command-specific configuration for the shared scaffold.\n */\nexport interface MigrationCommandDescriptor {\n readonly commandName: string;\n readonly description: string;\n readonly url: string;\n}\n\n/**\n * Prepares the shared context for migration commands (db init, db update).\n *\n * Handles: config loading, contract file reading, JSON parsing, connection resolution,\n * driver/migration-support validation, client creation, and header output.\n *\n * Returns a Result with either the resolved context or a structured error.\n */\nexport async function prepareMigrationContext(\n options: { readonly db?: string; readonly config?: string; readonly dryRun?: boolean },\n flags: GlobalFlags,\n ui: TerminalUI,\n descriptor: MigrationCommandDescriptor,\n): Promise<Result<MigrationContext, CliStructuredError>> {\n // Load config\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 const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header to stderr (decoration)\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n if (options.dryRun) {\n details.push({ label: 'mode', value: 'dry run' });\n }\n const header = formatStyledHeader({\n command: descriptor.commandName,\n description: descriptor.description,\n url: descriptor.url,\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Parse contract JSON\n let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for ${descriptor.commandName} (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: descriptor.commandName,\n }),\n );\n }\n\n // Check for driver\n if (!config.driver) {\n return notOk(\n errorDriverRequired({ why: `Config.driver is required for ${descriptor.commandName}` }),\n );\n }\n\n if (!hasMigrations(config.target)) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n // Create control client\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n // Create progress adapter\n const onProgress = createProgressAdapter({ ui, flags });\n\n return ok({\n client,\n contractJson,\n dbConnection,\n onProgress,\n configPath,\n contractPath,\n contractPathAbsolute,\n config,\n });\n}\n\n/**\n * Registers the shared CLI options for migration commands (db init, db update).\n */\nexport function addMigrationCommandOptions(command: Command): Command {\n addGlobalOptions(command);\n return command\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--dry-run', 'Preview planned operations without applying', false);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuDA,eAAsB,wBACpB,SACA,OACA,IACA,YACuD;CAEvD,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;CACJ,MAAM,uBAAuB,oBAAoB,OAAO;CACxD,MAAM,eAAe,SAAS,QAAQ,KAAK,EAAE,qBAAqB;AAGlE,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMA,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,EACtC;GAAE,OAAO;GAAY,OAAO;GAAc,CAC3C;AACD,MAAI,QAAQ,GACV,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,QAAQ,GAAG;GAAE,CAAC;AAE3E,MAAI,QAAQ,OACV,SAAQ,KAAK;GAAE,OAAO;GAAQ,OAAO;GAAW,CAAC;EAEnD,MAAM,SAAS,mBAAmB;GAChC,SAAS,WAAW;GACpB,aAAa,WAAW;GACxB,KAAK,WAAW;GAChB;GACA;GACD,CAAC;AACF,KAAG,OAAO,OAAO;;CAInB,IAAIC;AACJ,KAAI;AACF,wBAAsB,MAAM,SAAS,sBAAsB,QAAQ;UAC5D,OAAO;AACd,MAAI,iBAAiB,SAAU,MAA4B,SAAS,SAClE,QAAO,MACL,kBAAkB,sBAAsB;GACtC,KAAK,8BAA8B;GACnC,KAAK,iDAAiD,aAAa,4CAA4C;GAChH,CAAC,CACH;AAEH,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC7F,CAAC,CACH;;CAIH,IAAIC;AACJ,KAAI;AACF,iBAAe,KAAK,MAAM,oBAAoB;UACvC,OAAO;AACd,SAAO,MACL,8BACE,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACnF,EAAE,OAAO,EAAE,MAAM,sBAAsB,EAAE,CAC1C,CACF;;CAIH,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,uCAAuC,WAAW,YAAY,yBAAyB,WAAW;EACvG,aAAa,WAAW;EACzB,CAAC,CACH;AAIH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAAE,KAAK,iCAAiC,WAAW,eAAe,CAAC,CACxF;AAGH,KAAI,CAAC,cAAc,OAAO,OAAO,CAC/B,QAAO,MACL,iCAAiC,EAC/B,KAAK,WAAW,OAAO,OAAO,GAAG,gCAClC,CAAC,CACH;CAIH,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CAGF,MAAM,aAAa,sBAAsB;EAAE;EAAI;EAAO,CAAC;AAEvD,QAAO,GAAG;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;;;;AAMJ,SAAgB,2BAA2B,SAA2B;AACpE,kBAAiB,QAAQ;AACzB,QAAO,QACJ,OAAO,cAAc,6BAA6B,CAClD,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,aAAa,+CAA+C,MAAM"}
1
+ {"version":3,"file":"migration-command-scaffold-B3B09et6.mjs","names":["details: Array<{ label: string; value: string }>","contractJsonContent: string","contractJson: Record<string, unknown>"],"sources":["../src/utils/migration-command-scaffold.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { hasMigrations } from '@prisma-next/framework-components/control';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport type { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type { ControlClient } from '../control-api/types';\nimport {\n type CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from './cli-errors';\nimport { addGlobalOptions, maskConnectionUrl, resolveContractPath } from './command-helpers';\nimport { formatStyledHeader } from './formatters/styled';\nimport type { GlobalFlags } from './global-flags';\nimport { createProgressAdapter } from './progress-adapter';\nimport type { TerminalUI } from './terminal-ui';\n\n/**\n * Resolved context for a migration command.\n * Contains everything needed to invoke a control-api operation.\n */\nexport interface MigrationContext {\n readonly client: ControlClient;\n readonly contractJson: Record<string, unknown>;\n readonly dbConnection: unknown;\n readonly onProgress: ReturnType<typeof createProgressAdapter>;\n readonly configPath: string;\n readonly contractPath: string;\n readonly contractPathAbsolute: string;\n readonly config: Awaited<ReturnType<typeof loadConfig>>;\n}\n\n/**\n * Command-specific configuration for the shared scaffold.\n */\nexport interface MigrationCommandDescriptor {\n readonly commandName: string;\n readonly description: string;\n readonly url: string;\n}\n\n/**\n * Prepares the shared context for migration commands (db init, db update).\n *\n * Handles: config loading, contract file reading, JSON parsing, connection resolution,\n * driver/migration-support validation, client creation, and header output.\n *\n * Returns a Result with either the resolved context or a structured error.\n */\nexport async function prepareMigrationContext(\n options: { readonly db?: string; readonly config?: string; readonly dryRun?: boolean },\n flags: GlobalFlags,\n ui: TerminalUI,\n descriptor: MigrationCommandDescriptor,\n): Promise<Result<MigrationContext, CliStructuredError>> {\n // Load config\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 const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header to stderr (decoration)\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n if (options.dryRun) {\n details.push({ label: 'mode', value: 'dry run' });\n }\n const header = formatStyledHeader({\n command: descriptor.commandName,\n description: descriptor.description,\n url: descriptor.url,\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Parse contract JSON\n let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for ${descriptor.commandName} (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: descriptor.commandName,\n }),\n );\n }\n\n // Check for driver\n if (!config.driver) {\n return notOk(\n errorDriverRequired({ why: `Config.driver is required for ${descriptor.commandName}` }),\n );\n }\n\n if (!hasMigrations(config.target)) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n // Create control client\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n // Create progress adapter\n const onProgress = createProgressAdapter({ ui, flags });\n\n return ok({\n client,\n contractJson,\n dbConnection,\n onProgress,\n configPath,\n contractPath,\n contractPathAbsolute,\n config,\n });\n}\n\n/**\n * Registers the shared CLI options for migration commands (db init, db update).\n */\nexport function addMigrationCommandOptions(command: Command): Command {\n addGlobalOptions(command);\n return command\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--dry-run', 'Preview planned operations without applying', false);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuDA,eAAsB,wBACpB,SACA,OACA,IACA,YACuD;CAEvD,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;CACJ,MAAM,uBAAuB,oBAAoB,OAAO;CACxD,MAAM,eAAe,SAAS,QAAQ,KAAK,EAAE,qBAAqB;AAGlE,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMA,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,EACtC;GAAE,OAAO;GAAY,OAAO;GAAc,CAC3C;AACD,MAAI,QAAQ,GACV,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,QAAQ,GAAG;GAAE,CAAC;AAE3E,MAAI,QAAQ,OACV,SAAQ,KAAK;GAAE,OAAO;GAAQ,OAAO;GAAW,CAAC;EAEnD,MAAM,SAAS,mBAAmB;GAChC,SAAS,WAAW;GACpB,aAAa,WAAW;GACxB,KAAK,WAAW;GAChB;GACA;GACD,CAAC;AACF,KAAG,OAAO,OAAO;;CAInB,IAAIC;AACJ,KAAI;AACF,wBAAsB,MAAM,SAAS,sBAAsB,QAAQ;UAC5D,OAAO;AACd,MAAI,iBAAiB,SAAU,MAA4B,SAAS,SAClE,QAAO,MACL,kBAAkB,sBAAsB;GACtC,KAAK,8BAA8B;GACnC,KAAK,iDAAiD,aAAa,4CAA4C;GAChH,CAAC,CACH;AAEH,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC7F,CAAC,CACH;;CAIH,IAAIC;AACJ,KAAI;AACF,iBAAe,KAAK,MAAM,oBAAoB;UACvC,OAAO;AACd,SAAO,MACL,8BACE,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACnF,EAAE,OAAO,EAAE,MAAM,sBAAsB,EAAE,CAC1C,CACF;;CAIH,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,uCAAuC,WAAW,YAAY,yBAAyB,WAAW;EACvG,aAAa,WAAW;EACzB,CAAC,CACH;AAIH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAAE,KAAK,iCAAiC,WAAW,eAAe,CAAC,CACxF;AAGH,KAAI,CAAC,cAAc,OAAO,OAAO,CAC/B,QAAO,MACL,iCAAiC,EAC/B,KAAK,WAAW,OAAO,OAAO,GAAG,gCAClC,CAAC,CACH;CAIH,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CAGF,MAAM,aAAa,sBAAsB;EAAE;EAAI;EAAO,CAAC;AAEvD,QAAO,GAAG;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;;;;AAMJ,SAAgB,2BAA2B,SAA2B;AACpE,kBAAiB,QAAQ;AACzB,QAAO,QACJ,OAAO,cAAc,6BAA6B,CAClD,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,aAAa,+CAA+C,MAAM"}
@@ -1,8 +1,8 @@
1
- import { t as loadConfig } from "./config-loader-_xQZsw0i.mjs";
2
- import { _ as errorUnexpected, m as errorRuntime } from "./cli-errors-CznZA5-d.mjs";
3
- import { t as createControlClient } from "./client-DGKrciLM.mjs";
4
- import { _ as formatStyledHeader, a as maskConnectionUrl, c as resolveMigrationPaths, d as setCommandExamples, i as loadAllBundles, m as parseGlobalFlags, n as addGlobalOptions, o as readContractEnvelope, p as toPathDecisionResult, t as handleResult, u as setCommandDescriptions } from "./result-handler-CGohaH1o.mjs";
5
- import { t as TerminalUI } from "./terminal-ui-BuPXVRFY.mjs";
1
+ import { t as loadConfig } from "./config-loader-C25b63rJ.mjs";
2
+ import { _ as errorUnexpected, m as errorRuntime } from "./cli-errors-Cd79vmTH.mjs";
3
+ import { t as createControlClient } from "./client-CrsnY58k.mjs";
4
+ import { t as TerminalUI } from "./terminal-ui-C3ZLwQxK.mjs";
5
+ import { _ as formatStyledHeader, a as maskConnectionUrl, c as resolveMigrationPaths, d as setCommandExamples, i as loadAllBundles, m as parseGlobalFlags, n as addGlobalOptions, o as readContractEnvelope, p as toPathDecisionResult, t as handleResult, u as setCommandDescriptions } from "./result-handler-Ba3zWQsI.mjs";
6
6
  import { Command } from "commander";
7
7
  import { notOk, ok } from "@prisma-next/utils/result";
8
8
  import { ifDefined } from "@prisma-next/utils/defined";
@@ -1241,14 +1241,14 @@ function determineLimit(opts) {
1241
1241
  }
1242
1242
  async function executeMigrationStatusCommand(options, flags, ui) {
1243
1243
  const config = await loadConfig(options.config);
1244
- const { configPath, migrationsDir, migrationsRelative, refsPath } = resolveMigrationPaths(options.config, config);
1244
+ const { configPath, migrationsDir, migrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
1245
1245
  const dbConnection = options.db ?? config.db?.connection;
1246
1246
  const hasDriver = !!config.driver;
1247
1247
  let activeRefName;
1248
1248
  let activeRefHash;
1249
1249
  let allRefs = {};
1250
1250
  try {
1251
- allRefs = await readRefs(refsPath);
1251
+ allRefs = await readRefs(refsDir);
1252
1252
  } catch (error) {
1253
1253
  if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1254
1254
  why: error.why,
@@ -1259,10 +1259,8 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1259
1259
  }
1260
1260
  if (options.ref) {
1261
1261
  activeRefName = options.ref;
1262
- const refHash = allRefs[activeRefName];
1263
- if (refHash) activeRefHash = refHash;
1264
- else try {
1265
- activeRefHash = resolveRef(allRefs, activeRefName);
1262
+ try {
1263
+ activeRefHash = resolveRef(allRefs, activeRefName).hash;
1266
1264
  } catch (error) {
1267
1265
  if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1268
1266
  why: error.why,
@@ -1272,9 +1270,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1272
1270
  throw error;
1273
1271
  }
1274
1272
  }
1275
- const statusRefs = Object.entries(allRefs).map(([name, hash]) => ({
1273
+ const statusRefs = Object.entries(allRefs).map(([name, entry]) => ({
1276
1274
  name,
1277
- hash,
1275
+ hash: entry.hash,
1278
1276
  active: name === activeRefName
1279
1277
  }));
1280
1278
  if (!flags.json && !flags.quiet) {
@@ -1564,4 +1562,4 @@ function summarizeRefDistance(graph, markerHash, refHash, refName) {
1564
1562
 
1565
1563
  //#endregion
1566
1564
  export { deriveEdgeStatuses as n, createMigrationStatusCommand as t };
1567
- //# sourceMappingURL=migration-status-CXBbScH5.mjs.map
1565
+ //# sourceMappingURL=migration-status-DUMiH8_G.mjs.map