@prisma-next/cli 0.4.2 → 0.5.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.
Files changed (79) hide show
  1. package/README.md +17 -18
  2. package/dist/cli-errors-By1iVE3z.mjs +34 -0
  3. package/dist/cli-errors-By1iVE3z.mjs.map +1 -0
  4. package/dist/{cli-errors-BFYgBH3L.d.mts → cli-errors-D2NPMaxW.d.mts} +1 -0
  5. package/dist/cli.mjs +11 -11
  6. package/dist/{client-CrsnY58k.mjs → client-faKQqcix.mjs} +17 -2
  7. package/dist/client-faKQqcix.mjs.map +1 -0
  8. package/dist/commands/contract-emit.mjs +5 -5
  9. package/dist/commands/contract-infer.mjs +6 -6
  10. package/dist/commands/db-init.mjs +6 -6
  11. package/dist/commands/db-schema.mjs +5 -5
  12. package/dist/commands/db-sign.mjs +4 -4
  13. package/dist/commands/db-update.mjs +6 -6
  14. package/dist/commands/db-verify.mjs +4 -4
  15. package/dist/commands/migration-apply.d.mts +1 -1
  16. package/dist/commands/migration-apply.d.mts.map +1 -1
  17. package/dist/commands/migration-apply.mjs +10 -34
  18. package/dist/commands/migration-apply.mjs.map +1 -1
  19. package/dist/commands/migration-new.d.mts.map +1 -1
  20. package/dist/commands/migration-new.mjs +18 -23
  21. package/dist/commands/migration-new.mjs.map +1 -1
  22. package/dist/commands/migration-plan.d.mts +6 -3
  23. package/dist/commands/migration-plan.d.mts.map +1 -1
  24. package/dist/commands/migration-plan.mjs +27 -32
  25. package/dist/commands/migration-plan.mjs.map +1 -1
  26. package/dist/commands/migration-ref.d.mts +1 -1
  27. package/dist/commands/migration-ref.d.mts.map +1 -1
  28. package/dist/commands/migration-ref.mjs +4 -8
  29. package/dist/commands/migration-ref.mjs.map +1 -1
  30. package/dist/commands/migration-show.d.mts +4 -4
  31. package/dist/commands/migration-show.d.mts.map +1 -1
  32. package/dist/commands/migration-show.mjs +15 -22
  33. package/dist/commands/migration-show.mjs.map +1 -1
  34. package/dist/commands/migration-status.d.mts +5 -4
  35. package/dist/commands/migration-status.d.mts.map +1 -1
  36. package/dist/commands/migration-status.mjs +5 -5
  37. package/dist/{contract-emit-NJ01hiiv.mjs → contract-emit-B5wnhTuF.mjs} +4 -4
  38. package/dist/{contract-emit-NJ01hiiv.mjs.map → contract-emit-B5wnhTuF.mjs.map} +1 -1
  39. package/dist/contract-emit-B9wkchud.mjs +6 -0
  40. package/dist/{contract-emit-V5SSitUT.mjs → contract-emit-PeB96eHy.mjs} +3 -3
  41. package/dist/{contract-emit-V5SSitUT.mjs.map → contract-emit-PeB96eHy.mjs.map} +1 -1
  42. package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-DnY9fUw0.mjs} +3 -3
  43. package/dist/{contract-infer-D9cC3rJm.mjs.map → contract-infer-DnY9fUw0.mjs.map} +1 -1
  44. package/dist/exports/control-api.mjs +4 -4
  45. package/dist/exports/index.mjs +5 -5
  46. package/dist/{framework-components-Cr--XBKy.mjs → framework-components-C6el-5x_.mjs} +2 -2
  47. package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-C6el-5x_.mjs.map} +1 -1
  48. package/dist/{init-m8x0UoPY.mjs → init-jf33mNQ6.mjs} +3 -3
  49. package/dist/{init-m8x0UoPY.mjs.map → init-jf33mNQ6.mjs.map} +1 -1
  50. package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-CqoZhKC1.mjs} +4 -4
  51. package/dist/{inspect-live-schema-yrHAvG71.mjs.map → inspect-live-schema-CqoZhKC1.mjs.map} +1 -1
  52. package/dist/migration-cli.mjs +13 -6
  53. package/dist/migration-cli.mjs.map +1 -1
  54. package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-B40VaF-m.mjs} +4 -4
  55. package/dist/{migration-command-scaffold-B3B09et6.mjs.map → migration-command-scaffold-B40VaF-m.mjs.map} +1 -1
  56. package/dist/{migration-status-DUMiH8_G.mjs → migration-status-CDgFxhAo.mjs} +10 -22
  57. package/dist/migration-status-CDgFxhAo.mjs.map +1 -0
  58. package/dist/{migrations-Bo5WtTla.mjs → migrations-CKRMAKka.mjs} +2 -2
  59. package/dist/migrations-CKRMAKka.mjs.map +1 -0
  60. package/dist/{result-handler-Ba3zWQsI.mjs → result-handler-DcV0QoTr.mjs} +6 -14
  61. package/dist/{result-handler-Ba3zWQsI.mjs.map → result-handler-DcV0QoTr.mjs.map} +1 -1
  62. package/package.json +14 -14
  63. package/src/commands/migration-apply.ts +11 -46
  64. package/src/commands/migration-new.ts +19 -27
  65. package/src/commands/migration-plan.ts +52 -41
  66. package/src/commands/migration-ref.ts +8 -7
  67. package/src/commands/migration-show.ts +23 -27
  68. package/src/commands/migration-status.ts +20 -32
  69. package/src/control-api/operations/migration-apply.ts +15 -0
  70. package/src/migration-cli.ts +16 -9
  71. package/src/utils/cli-errors.ts +45 -1
  72. package/src/utils/command-helpers.ts +8 -21
  73. package/src/utils/formatters/graph-migration-mapper.ts +1 -1
  74. package/src/utils/formatters/migrations.ts +2 -2
  75. package/dist/cli-errors-Cd79vmTH.mjs +0 -5
  76. package/dist/client-CrsnY58k.mjs.map +0 -1
  77. package/dist/contract-emit-DxgyXrqV.mjs +0 -6
  78. package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
  79. package/dist/migrations-Bo5WtTla.mjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { t as loadConfig } from "./config-loader-C25b63rJ.mjs";
2
- import { _ as errorUnexpected, c as errorDriverRequired, o as errorDatabaseConnectionRequired, t as CliStructuredError } from "./cli-errors-Cd79vmTH.mjs";
3
- import { t as createControlClient } from "./client-CrsnY58k.mjs";
4
- import { _ as formatStyledHeader, a as maskConnectionUrl, l as sanitizeErrorMessage } from "./result-handler-Ba3zWQsI.mjs";
2
+ import { _ as errorUnexpected, c as errorDriverRequired, o as errorDatabaseConnectionRequired, t as CliStructuredError } from "./cli-errors-By1iVE3z.mjs";
3
+ import { t as createControlClient } from "./client-faKQqcix.mjs";
4
+ import { _ as formatStyledHeader, a as maskConnectionUrl, l as sanitizeErrorMessage } from "./result-handler-DcV0QoTr.mjs";
5
5
  import { t as createProgressAdapter } from "./progress-adapter-DvQWB1nK.mjs";
6
6
  import { notOk, ok } from "@prisma-next/utils/result";
7
7
  import { relative, resolve } from "pathe";
@@ -88,4 +88,4 @@ async function inspectLiveSchema(options, flags, ui, startTime, context) {
88
88
 
89
89
  //#endregion
90
90
  export { inspectLiveSchema as t };
91
- //# sourceMappingURL=inspect-live-schema-yrHAvG71.mjs.map
91
+ //# sourceMappingURL=inspect-live-schema-CqoZhKC1.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"inspect-live-schema-yrHAvG71.mjs","names":["config: LoadedCliConfig","details: Array<{ label: string; value: string }>"],"sources":["../src/commands/inspect-live-schema.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport { validatePrintableSqlSchemaIR } from '@prisma-next/psl-printer';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { maskConnectionUrl, sanitizeErrorMessage } from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions, GlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport type { TerminalUI } from '../utils/terminal-ui';\n\nexport interface InspectLiveSchemaOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n}\n\ninterface InspectLiveSchemaContext {\n readonly commandName: string;\n readonly description: string;\n readonly url: string;\n}\n\ntype LoadedCliConfig = Awaited<ReturnType<typeof loadConfig>>;\n\nexport interface InspectLiveSchemaResult {\n readonly config: LoadedCliConfig;\n readonly schema: unknown;\n readonly schemaView: CoreSchemaView | undefined;\n readonly target: {\n readonly familyId: string;\n readonly id: string;\n };\n readonly meta: {\n readonly configPath?: string;\n readonly dbUrl?: string;\n };\n readonly timings: {\n readonly total: number;\n };\n}\n\nexport async function inspectLiveSchema(\n options: InspectLiveSchemaOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n context: InspectLiveSchemaContext,\n): Promise<Result<InspectLiveSchemaResult, CliStructuredError>> {\n let config: LoadedCliConfig;\n try {\n config = await loadConfig(options.config);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: 'Failed to load config',\n }),\n );\n }\n\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n ];\n\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n } else if (config.db?.connection && typeof config.db.connection === 'string') {\n details.push({ label: 'database', value: maskConnectionUrl(config.db.connection) });\n }\n\n ui.stderr(\n formatStyledHeader({\n command: context.commandName,\n description: context.description,\n url: context.url,\n details,\n flags,\n }),\n );\n }\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for ${context.commandName} (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: context.commandName,\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: `Config.driver is required for ${context.commandName}`,\n }),\n );\n }\n\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 const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n const schemaIR = await client.introspect({\n connection: dbConnection,\n onProgress,\n });\n // TODO(TML-2251): Remove SQL-specific branching — SQL should use the same family-agnostic path as Mongo.\n const schema =\n config.family.familyId === 'sql' ? validatePrintableSqlSchemaIR(schemaIR) : schemaIR;\n const schemaView = client.toSchemaView(schema);\n\n const dbUrl = typeof dbConnection === 'string' ? maskConnectionUrl(dbConnection) : undefined;\n\n return ok({\n config,\n schema,\n schemaView,\n target: {\n familyId: config.family.familyId,\n id: config.target.targetId,\n },\n meta: {\n configPath,\n ...(dbUrl ? { dbUrl } : {}),\n },\n timings: {\n total: Date.now() - startTime,\n },\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during ${context.commandName}: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n"],"mappings":";;;;;;;;;;AAgDA,eAAsB,kBACpB,SACA,OACA,IACA,WACA,SAC8D;CAC9D,IAAIA;AACJ,KAAI;AACF,WAAS,MAAM,WAAW,QAAQ,OAAO;UAClC,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;AAGrB,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,yBACN,CAAC,CACH;;CAGH,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;AAEJ,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMC,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,CACvC;AAED,MAAI,QAAQ,GACV,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,QAAQ,GAAG;GAAE,CAAC;WAChE,OAAO,IAAI,cAAc,OAAO,OAAO,GAAG,eAAe,SAClE,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,OAAO,GAAG,WAAW;GAAE,CAAC;AAGrF,KAAG,OACD,mBAAmB;GACjB,SAAS,QAAQ;GACjB,aAAa,QAAQ;GACrB,KAAK,QAAQ;GACb;GACA;GACD,CAAC,CACH;;CAGH,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,uCAAuC,QAAQ,YAAY,yBAAyB,WAAW;EACpG,aAAa,QAAQ;EACtB,CAAC,CACH;AAGH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAClB,KAAK,iCAAiC,QAAQ,eAC/C,CAAC,CACH;CAGH,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CACF,MAAM,aAAa,sBAAsB;EAAE;EAAI;EAAO,CAAC;AAEvD,KAAI;EACF,MAAM,WAAW,MAAM,OAAO,WAAW;GACvC,YAAY;GACZ;GACD,CAAC;EAEF,MAAM,SACJ,OAAO,OAAO,aAAa,QAAQ,6BAA6B,SAAS,GAAG;EAC9E,MAAM,aAAa,OAAO,aAAa,OAAO;EAE9C,MAAM,QAAQ,OAAO,iBAAiB,WAAW,kBAAkB,aAAa,GAAG;AAEnF,SAAO,GAAG;GACR;GACA;GACA;GACA,QAAQ;IACN,UAAU,OAAO,OAAO;IACxB,IAAI,OAAO,OAAO;IACnB;GACD,MAAM;IACJ;IACA,GAAI,QAAQ,EAAE,OAAO,GAAG,EAAE;IAC3B;GACD,SAAS,EACP,OAAO,KAAK,KAAK,GAAG,WACrB;GACF,CAAC;UACK,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;EAIrB,MAAM,cAAc,qBADD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAGvE,OAAO,iBAAiB,WAAW,eAAe,OACnD;AACD,SAAO,MACL,gBAAgB,aAAa,EAC3B,KAAK,2BAA2B,QAAQ,YAAY,IAAI,eACzD,CAAC,CACH;WACO;AACR,QAAM,OAAO,OAAO"}
1
+ {"version":3,"file":"inspect-live-schema-CqoZhKC1.mjs","names":["config: LoadedCliConfig","details: Array<{ label: string; value: string }>"],"sources":["../src/commands/inspect-live-schema.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport { validatePrintableSqlSchemaIR } from '@prisma-next/psl-printer';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { maskConnectionUrl, sanitizeErrorMessage } from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions, GlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport type { TerminalUI } from '../utils/terminal-ui';\n\nexport interface InspectLiveSchemaOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n}\n\ninterface InspectLiveSchemaContext {\n readonly commandName: string;\n readonly description: string;\n readonly url: string;\n}\n\ntype LoadedCliConfig = Awaited<ReturnType<typeof loadConfig>>;\n\nexport interface InspectLiveSchemaResult {\n readonly config: LoadedCliConfig;\n readonly schema: unknown;\n readonly schemaView: CoreSchemaView | undefined;\n readonly target: {\n readonly familyId: string;\n readonly id: string;\n };\n readonly meta: {\n readonly configPath?: string;\n readonly dbUrl?: string;\n };\n readonly timings: {\n readonly total: number;\n };\n}\n\nexport async function inspectLiveSchema(\n options: InspectLiveSchemaOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n context: InspectLiveSchemaContext,\n): Promise<Result<InspectLiveSchemaResult, CliStructuredError>> {\n let config: LoadedCliConfig;\n try {\n config = await loadConfig(options.config);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: 'Failed to load config',\n }),\n );\n }\n\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n ];\n\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n } else if (config.db?.connection && typeof config.db.connection === 'string') {\n details.push({ label: 'database', value: maskConnectionUrl(config.db.connection) });\n }\n\n ui.stderr(\n formatStyledHeader({\n command: context.commandName,\n description: context.description,\n url: context.url,\n details,\n flags,\n }),\n );\n }\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for ${context.commandName} (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: context.commandName,\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: `Config.driver is required for ${context.commandName}`,\n }),\n );\n }\n\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 const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n const schemaIR = await client.introspect({\n connection: dbConnection,\n onProgress,\n });\n // TODO(TML-2251): Remove SQL-specific branching — SQL should use the same family-agnostic path as Mongo.\n const schema =\n config.family.familyId === 'sql' ? validatePrintableSqlSchemaIR(schemaIR) : schemaIR;\n const schemaView = client.toSchemaView(schema);\n\n const dbUrl = typeof dbConnection === 'string' ? maskConnectionUrl(dbConnection) : undefined;\n\n return ok({\n config,\n schema,\n schemaView,\n target: {\n familyId: config.family.familyId,\n id: config.target.targetId,\n },\n meta: {\n configPath,\n ...(dbUrl ? { dbUrl } : {}),\n },\n timings: {\n total: Date.now() - startTime,\n },\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during ${context.commandName}: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n"],"mappings":";;;;;;;;;;AAgDA,eAAsB,kBACpB,SACA,OACA,IACA,WACA,SAC8D;CAC9D,IAAIA;AACJ,KAAI;AACF,WAAS,MAAM,WAAW,QAAQ,OAAO;UAClC,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;AAGrB,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,yBACN,CAAC,CACH;;CAGH,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;AAEJ,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMC,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,CACvC;AAED,MAAI,QAAQ,GACV,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,QAAQ,GAAG;GAAE,CAAC;WAChE,OAAO,IAAI,cAAc,OAAO,OAAO,GAAG,eAAe,SAClE,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,OAAO,GAAG,WAAW;GAAE,CAAC;AAGrF,KAAG,OACD,mBAAmB;GACjB,SAAS,QAAQ;GACjB,aAAa,QAAQ;GACrB,KAAK,QAAQ;GACb;GACA;GACD,CAAC,CACH;;CAGH,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,uCAAuC,QAAQ,YAAY,yBAAyB,WAAW;EACpG,aAAa,QAAQ;EACtB,CAAC,CACH;AAGH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAClB,KAAK,iCAAiC,QAAQ,eAC/C,CAAC,CACH;CAGH,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CACF,MAAM,aAAa,sBAAsB;EAAE;EAAI;EAAO,CAAC;AAEvD,KAAI;EACF,MAAM,WAAW,MAAM,OAAO,WAAW;GACvC,YAAY;GACZ;GACD,CAAC;EAEF,MAAM,SACJ,OAAO,OAAO,aAAa,QAAQ,6BAA6B,SAAS,GAAG;EAC9E,MAAM,aAAa,OAAO,aAAa,OAAO;EAE9C,MAAM,QAAQ,OAAO,iBAAiB,WAAW,kBAAkB,aAAa,GAAG;AAEnF,SAAO,GAAG;GACR;GACA;GACA;GACA,QAAQ;IACN,UAAU,OAAO,OAAO;IACxB,IAAI,OAAO,OAAO;IACnB;GACD,MAAM;IACJ;IACA,GAAI,QAAQ,EAAE,OAAO,GAAG,EAAE;IAC3B;GACD,SAAS,EACP,OAAO,KAAK,KAAK,GAAG,WACrB;GACF,CAAC;UACK,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;EAIrB,MAAM,cAAc,qBADD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAGvE,OAAO,iBAAiB,WAAW,eAAe,OACnD;AACD,SAAO,MACL,gBAAgB,aAAa,EAC3B,KAAK,2BAA2B,QAAQ,YAAY,IAAI,eACzD,CAAC,CACH;WACO;AACR,QAAM,OAAO,OAAO"}
@@ -137,11 +137,18 @@ var MigrationCLI = class {
137
137
  * `buildMigrationArtifacts` so the pure builder can preserve fields owned
138
138
  * by `migration plan` (contract bookends, hints, labels, `createdAt`)
139
139
  * across re-emits.
140
+ *
141
+ * Author-time path: this loader is non-verifying by design. Hash mismatch
142
+ * is the *expected* outcome of a re-author (the developer's source
143
+ * changes invalidate the prior hash by construction), and verification
144
+ * here would block legitimate regenerations. Apply-time consumers always
145
+ * route through the verifying `readMigrationPackage` in
146
+ * `@prisma-next/migration-tools/io` instead.
140
147
  */
141
- function readExistingManifest(manifestPath) {
148
+ function readExistingMetadata(metadataPath) {
142
149
  let raw;
143
150
  try {
144
- raw = readFileSync(manifestPath, "utf-8");
151
+ raw = readFileSync(metadataPath, "utf-8");
145
152
  } catch {
146
153
  return null;
147
154
  }
@@ -166,16 +173,16 @@ function readExistingManifest(manifestPath) {
166
173
  * filesystem persistence.
167
174
  */
168
175
  function serializeMigrationToDisk(instance, migrationDir, dryRun) {
169
- const manifestPath = join(migrationDir, "migration.json");
170
- const { opsJson, manifestJson } = buildMigrationArtifacts(instance, readExistingManifest(manifestPath));
176
+ const metadataPath = join(migrationDir, "migration.json");
177
+ const { opsJson, metadataJson } = buildMigrationArtifacts(instance, readExistingMetadata(metadataPath));
171
178
  if (dryRun) {
172
- process.stdout.write(`--- migration.json ---\n${manifestJson}\n`);
179
+ process.stdout.write(`--- migration.json ---\n${metadataJson}\n`);
173
180
  process.stdout.write("--- ops.json ---\n");
174
181
  process.stdout.write(`${opsJson}\n`);
175
182
  return;
176
183
  }
177
184
  writeFileSync(join(migrationDir, "ops.json"), opsJson);
178
- writeFileSync(manifestPath, manifestJson);
185
+ writeFileSync(metadataPath, metadataJson);
179
186
  process.stdout.write(`Wrote ops.json + migration.json to ${migrationDir}\n`);
180
187
  }
181
188
 
@@ -1 +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
+ {"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 type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport {\n buildMigrationArtifacts,\n isDirectEntrypoint,\n type Migration,\n printMigrationHelp,\n} from '@prisma-next/migration-tools/migration';\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 *\n * Author-time path: this loader is non-verifying by design. Hash mismatch\n * is the *expected* outcome of a re-author (the developer's source\n * changes invalidate the prior hash by construction), and verification\n * here would block legitimate regenerations. Apply-time consumers always\n * route through the verifying `readMigrationPackage` in\n * `@prisma-next/migration-tools/io` instead.\n */\nfunction readExistingMetadata(metadataPath: string): Partial<MigrationMetadata> | null {\n let raw: string;\n try {\n raw = readFileSync(metadataPath, 'utf-8');\n } catch {\n return null;\n }\n try {\n return JSON.parse(raw) as Partial<MigrationMetadata>;\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 metadataPath = join(migrationDir, 'migration.json');\n const existing = readExistingMetadata(metadataPath);\n const { opsJson, metadataJson } = buildMigrationArtifacts(instance, existing);\n\n if (dryRun) {\n process.stdout.write(`--- migration.json ---\\n${metadataJson}\\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(metadataPath, metadataJson);\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;;;;;;;;;;;;;;;;;;AAmBzB,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,7 +1,7 @@
1
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";
2
+ import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, o as errorDatabaseConnectionRequired } from "./cli-errors-By1iVE3z.mjs";
3
+ import { t as createControlClient } from "./client-faKQqcix.mjs";
4
+ import { _ as formatStyledHeader, a as maskConnectionUrl, n as addGlobalOptions, s as resolveContractPath } from "./result-handler-DcV0QoTr.mjs";
5
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";
@@ -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-B3B09et6.mjs.map
105
+ //# sourceMappingURL=migration-command-scaffold-B40VaF-m.mjs.map
@@ -1 +1 @@
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
+ {"version":3,"file":"migration-command-scaffold-B40VaF-m.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,16 +1,16 @@
1
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";
2
+ import { _ as errorUnexpected, m as errorRuntime, v as mapMigrationToolsError } from "./cli-errors-By1iVE3z.mjs";
3
+ import { t as createControlClient } from "./client-faKQqcix.mjs";
4
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";
5
+ import { _ as formatStyledHeader, a as maskConnectionUrl, c as resolveMigrationPaths, d as setCommandExamples, i as loadMigrationPackages, m as parseGlobalFlags, n as addGlobalOptions, o as readContractEnvelope, p as toPathDecisionResult, t as handleResult, u as setCommandDescriptions } from "./result-handler-DcV0QoTr.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";
9
9
  import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
10
10
  import { findPath, findPathWithDecision, findReachableLeaves } from "@prisma-next/migration-tools/dag";
11
11
  import { bold, cyan, dim, magenta, yellow } from "colorette";
12
+ import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
12
13
  import { readRefs, resolveRef } from "@prisma-next/migration-tools/refs";
13
- import { MigrationToolsError } from "@prisma-next/migration-tools/types";
14
14
  import dagre from "@dagrejs/dagre";
15
15
 
16
16
  //#region src/utils/formatters/graph-types.ts
@@ -1194,7 +1194,7 @@ function buildMigrationEntries(chain, packages, mode, markerHash, edgeStatuses)
1194
1194
  dirName: migration.dirName,
1195
1195
  from: migration.from,
1196
1196
  to: migration.to,
1197
- migrationId: migration.migrationId,
1197
+ migrationHash: migration.migrationHash,
1198
1198
  operationCount: ops.length,
1199
1199
  operationSummary: summary,
1200
1200
  hasDestructive,
@@ -1250,11 +1250,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1250
1250
  try {
1251
1251
  allRefs = await readRefs(refsDir);
1252
1252
  } catch (error) {
1253
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1254
- why: error.why,
1255
- fix: error.fix,
1256
- meta: { code: error.code }
1257
- }));
1253
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
1258
1254
  throw error;
1259
1255
  }
1260
1256
  if (options.ref) {
@@ -1262,11 +1258,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1262
1258
  try {
1263
1259
  activeRefHash = resolveRef(allRefs, activeRefName).hash;
1264
1260
  } catch (error) {
1265
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1266
- why: error.why,
1267
- fix: error.fix,
1268
- meta: { code: error.code }
1269
- }));
1261
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
1270
1262
  throw error;
1271
1263
  }
1272
1264
  }
@@ -1314,13 +1306,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1314
1306
  let bundles;
1315
1307
  let graph;
1316
1308
  try {
1317
- ({bundles, graph} = await loadAllBundles(migrationsDir));
1309
+ ({bundles, graph} = await loadMigrationPackages(migrationsDir));
1318
1310
  } catch (error) {
1319
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
1320
- why: error.why,
1321
- fix: error.fix,
1322
- meta: { code: error.code }
1323
- }));
1311
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
1324
1312
  return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migrations directory: ${error instanceof Error ? error.message : String(error)}` }));
1325
1313
  }
1326
1314
  if (bundles.length === 0) {
@@ -1562,4 +1550,4 @@ function summarizeRefDistance(graph, markerHash, refHash, refName) {
1562
1550
 
1563
1551
  //#endregion
1564
1552
  export { deriveEdgeStatuses as n, createMigrationStatusCommand as t };
1565
- //# sourceMappingURL=migration-status-DUMiH8_G.mjs.map
1553
+ //# sourceMappingURL=migration-status-CDgFxhAo.mjs.map