@prisma-next/cli 0.4.0-dev.5 → 0.4.0-dev.7

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 (92) hide show
  1. package/README.md +8 -7
  2. package/dist/cli-errors-BUuJr6py.mjs +5 -0
  3. package/dist/{cli-errors-DStABy9d.d.mts → cli-errors-Dic2eADK.d.mts} +1 -0
  4. package/dist/cli.mjs +9 -16
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{client-tdnbk0OR.mjs → client-CJxHfhze.mjs} +4 -2
  7. package/dist/client-CJxHfhze.mjs.map +1 -0
  8. package/dist/commands/contract-emit.mjs +1 -6
  9. package/dist/commands/contract-infer.mjs +1 -7
  10. package/dist/commands/db-init.mjs +5 -6
  11. package/dist/commands/db-init.mjs.map +1 -1
  12. package/dist/commands/db-schema.mjs +3 -6
  13. package/dist/commands/db-schema.mjs.map +1 -1
  14. package/dist/commands/db-sign.mjs +4 -5
  15. package/dist/commands/db-sign.mjs.map +1 -1
  16. package/dist/commands/db-update.mjs +5 -6
  17. package/dist/commands/db-update.mjs.map +1 -1
  18. package/dist/commands/db-verify.mjs +4 -5
  19. package/dist/commands/db-verify.mjs.map +1 -1
  20. package/dist/commands/migration-apply.mjs +6 -7
  21. package/dist/commands/migration-apply.mjs.map +1 -1
  22. package/dist/commands/migration-emit.d.mts +38 -0
  23. package/dist/commands/migration-emit.d.mts.map +1 -0
  24. package/dist/commands/migration-emit.mjs +81 -0
  25. package/dist/commands/migration-emit.mjs.map +1 -0
  26. package/dist/commands/migration-new.d.mts.map +1 -1
  27. package/dist/commands/migration-new.mjs +33 -10
  28. package/dist/commands/migration-new.mjs.map +1 -1
  29. package/dist/commands/migration-plan.d.mts.map +1 -1
  30. package/dist/commands/migration-plan.mjs +93 -81
  31. package/dist/commands/migration-plan.mjs.map +1 -1
  32. package/dist/commands/migration-ref.d.mts +1 -1
  33. package/dist/commands/migration-ref.mjs +2 -2
  34. package/dist/commands/migration-show.d.mts +1 -1
  35. package/dist/commands/migration-show.mjs +4 -4
  36. package/dist/commands/migration-show.mjs.map +1 -1
  37. package/dist/commands/migration-status.mjs +1 -6
  38. package/dist/contract-emit-C2_J2U7A.mjs +4 -0
  39. package/dist/{contract-emit-CRoS1nx5.mjs → contract-emit-CKig_Lra.mjs} +4 -4
  40. package/dist/{contract-emit-CRoS1nx5.mjs.map → contract-emit-CKig_Lra.mjs.map} +1 -1
  41. package/dist/{contract-emit-Ctn6mH9H.mjs → contract-emit-gpJNLGs7.mjs} +5 -5
  42. package/dist/{contract-emit-Ctn6mH9H.mjs.map → contract-emit-gpJNLGs7.mjs.map} +1 -1
  43. package/dist/{contract-infer-Ba1SE57Q.mjs → contract-infer-BDJgg7Xb.mjs} +3 -3
  44. package/dist/{contract-infer-Ba1SE57Q.mjs.map → contract-infer-BDJgg7Xb.mjs.map} +1 -1
  45. package/dist/exports/control-api.mjs +2 -4
  46. package/dist/exports/index.mjs +1 -6
  47. package/dist/exports/index.mjs.map +1 -1
  48. package/dist/{framework-components-BAsliT4V.mjs → framework-components-Bsr1GaIj.mjs} +2 -2
  49. package/dist/{framework-components-BAsliT4V.mjs.map → framework-components-Bsr1GaIj.mjs.map} +1 -1
  50. package/dist/{init-CYWnL7gq.mjs → init-DlFLMBaU.mjs} +2 -2
  51. package/dist/{init-CYWnL7gq.mjs.map → init-DlFLMBaU.mjs.map} +1 -1
  52. package/dist/{inspect-live-schema-gYQiWfpl.mjs → inspect-live-schema-ChqrALmw.mjs} +4 -4
  53. package/dist/{inspect-live-schema-gYQiWfpl.mjs.map → inspect-live-schema-ChqrALmw.mjs.map} +1 -1
  54. package/dist/{migration-command-scaffold-x4n_ZhAh.mjs → migration-command-scaffold-B0oH_hyB.mjs} +4 -4
  55. package/dist/{migration-command-scaffold-x4n_ZhAh.mjs.map → migration-command-scaffold-B0oH_hyB.mjs.map} +1 -1
  56. package/dist/migration-emit-Du4DBMqz.mjs +125 -0
  57. package/dist/migration-emit-Du4DBMqz.mjs.map +1 -0
  58. package/dist/{migration-status-DyVDf5NI.mjs → migration-status-CPamfEPj.mjs} +5 -5
  59. package/dist/{migration-status-DyVDf5NI.mjs.map → migration-status-CPamfEPj.mjs.map} +1 -1
  60. package/dist/{migrations-DTZBYXm1.mjs → migrations-BIsjFjSV.mjs} +6 -15
  61. package/dist/migrations-BIsjFjSV.mjs.map +1 -0
  62. package/dist/{result-handler-oK_vA-Fn.mjs → result-handler-AFK4hxyX.mjs} +2 -2
  63. package/dist/result-handler-AFK4hxyX.mjs.map +1 -0
  64. package/dist/{validate-contract-deps-esa-VQ0h.mjs → validate-contract-deps-DBH6iTAD.mjs} +1 -1
  65. package/dist/{validate-contract-deps-esa-VQ0h.mjs.map → validate-contract-deps-DBH6iTAD.mjs.map} +1 -1
  66. package/dist/{verify-DlFQ2FOw.mjs → verify-C56CuQc7.mjs} +2 -2
  67. package/dist/{verify-DlFQ2FOw.mjs.map → verify-C56CuQc7.mjs.map} +1 -1
  68. package/package.json +19 -19
  69. package/src/cli.ts +4 -4
  70. package/src/commands/migration-apply.ts +2 -2
  71. package/src/commands/migration-emit.ts +134 -0
  72. package/src/commands/migration-new.ts +50 -15
  73. package/src/commands/migration-plan.ts +138 -130
  74. package/src/commands/migration-show.ts +1 -1
  75. package/src/commands/migration-status.ts +1 -1
  76. package/src/control-api/operations/db-init.ts +3 -0
  77. package/src/control-api/operations/db-update.ts +3 -0
  78. package/src/lib/migration-emit.ts +125 -0
  79. package/src/lib/migration-strategy.ts +49 -0
  80. package/src/utils/cli-errors.ts +7 -0
  81. package/src/utils/formatters/help.ts +1 -1
  82. package/src/utils/formatters/migrations.ts +6 -20
  83. package/dist/cli-errors-BDCYR5ap.mjs +0 -4
  84. package/dist/client-tdnbk0OR.mjs.map +0 -1
  85. package/dist/commands/migration-verify.d.mts +0 -16
  86. package/dist/commands/migration-verify.d.mts.map +0 -1
  87. package/dist/commands/migration-verify.mjs +0 -110
  88. package/dist/commands/migration-verify.mjs.map +0 -1
  89. package/dist/contract-emit-CVUWsFfx.mjs +0 -6
  90. package/dist/migrations-DTZBYXm1.mjs.map +0 -1
  91. package/dist/result-handler-oK_vA-Fn.mjs.map +0 -1
  92. package/src/commands/migration-verify.ts +0 -180
@@ -1 +1 @@
1
- {"version":3,"file":"inspect-live-schema-gYQiWfpl.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-ChqrALmw.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,7 +1,7 @@
1
1
  import { t as loadConfig } from "./config-loader-C4VXKl8f.mjs";
2
- import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, o as errorDatabaseConnectionRequired } from "./cli-errors-BDCYR5ap.mjs";
3
- import { t as createControlClient } from "./client-tdnbk0OR.mjs";
4
- import { _ as formatStyledHeader, a as maskConnectionUrl, n as addGlobalOptions, s as resolveContractPath } from "./result-handler-oK_vA-Fn.mjs";
2
+ import { a as errorContractValidationFailed, c as errorDriverRequired, g as errorTargetMigrationNotSupported, l as errorFileNotFound, o as errorDatabaseConnectionRequired, v as errorUnexpected } from "./cli-errors-BUuJr6py.mjs";
3
+ import { t as createControlClient } from "./client-CJxHfhze.mjs";
4
+ import { _ as formatStyledHeader, a as maskConnectionUrl, n as addGlobalOptions, s as resolveContractPath } from "./result-handler-AFK4hxyX.mjs";
5
5
  import { t as createProgressAdapter } from "./progress-adapter-B-YvmcDu.mjs";
6
6
  import { notOk, ok } from "@prisma-next/utils/result";
7
7
  import { relative, resolve } from "node:path";
@@ -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-x4n_ZhAh.mjs.map
105
+ //# sourceMappingURL=migration-command-scaffold-B0oH_hyB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-command-scaffold-x4n_ZhAh.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-B0oH_hyB.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"}
@@ -0,0 +1,125 @@
1
+ import { f as errorMigrationFileMissing, g as errorTargetMigrationNotSupported } from "./cli-errors-BUuJr6py.mjs";
2
+ import { errorTargetHasIncompleteMigrationCapabilities } from "@prisma-next/errors/migration";
3
+ import { readMigrationPackage, writeMigrationOps } from "@prisma-next/migration-tools/io";
4
+ import assert from "node:assert/strict";
5
+ import { attestMigration } from "@prisma-next/migration-tools/attestation";
6
+ import { evaluateMigrationTs, hasMigrationTs } from "@prisma-next/migration-tools/migration-ts";
7
+
8
+ //#region src/lib/migration-strategy.ts
9
+ /**
10
+ * Migration authoring strategy selector.
11
+ *
12
+ * Targets currently use one of two strategies to author `migration.ts`:
13
+ *
14
+ * - **Descriptor flow** — the planner produces an `OperationDescriptor[]`
15
+ * and `migration.ts` is a `export default () => [...]` file that the CLI
16
+ * later replays through `resolveDescriptors` at emit time. Postgres uses
17
+ * this today.
18
+ * - **Class flow** — the planner produces a `MigrationPlanWithAuthoringSurface`
19
+ * that renders itself as a `class M extends Migration { ... }` file. The
20
+ * CLI dispatches to the target's `emit` capability at emit time. Mongo
21
+ * uses this today.
22
+ *
23
+ * The two are mutually exclusive at the target level: a migrations capability
24
+ * either implements the descriptor-flow trio (`planWithDescriptors`,
25
+ * `resolveDescriptors`, `renderDescriptorTypeScript`) or the class-flow
26
+ * `emit` hook. `migrationStrategy` discriminates between them by observing
27
+ * which hooks are present, and is consumed by `migration new`, `migration
28
+ * plan`, and `migration emit` to keep strategy-specific branching in one
29
+ * place.
30
+ */
31
+ /**
32
+ * Determine which authoring strategy a target uses, based on the shape of
33
+ * its `TargetMigrationsCapability`. Callers that need strategy-specific
34
+ * guarantees (e.g. that `resolveDescriptors` is present) should narrow on
35
+ * the returned tag and trust the capability fields directly rather than
36
+ * re-probing.
37
+ *
38
+ * Throws `errorTargetHasIncompleteMigrationCapabilities` (PN-MIG-2011) when
39
+ * the capability registers neither flow. We diagnose this here rather than
40
+ * deferring to the dispatch site so a misconfigured target gets an honest
41
+ * "incomplete capability" error instead of being silently routed to one
42
+ * flow and reported as missing the *other* flow's hook.
43
+ */
44
+ function migrationStrategy(migrations, targetId) {
45
+ if (migrations.resolveDescriptors) return "descriptor";
46
+ if (migrations.emit) return "class-based";
47
+ throw errorTargetHasIncompleteMigrationCapabilities({ targetId });
48
+ }
49
+
50
+ //#endregion
51
+ //#region src/lib/migration-emit.ts
52
+ /**
53
+ * Shared helper for emitting `ops.json` and attesting `migration.json` for a
54
+ * migration package's `migration.ts`.
55
+ *
56
+ * Two flows are dispatched here:
57
+ * - Descriptor flow (Postgres): the framework evaluates `migration.ts`
58
+ * (which re-exports the planner's descriptor list), calls the target's
59
+ * `resolveDescriptors` to produce display-oriented operations, writes
60
+ * `ops.json`, and attests `migration.json`.
61
+ * - Class flow (Mongo): the target's `emit` capability dynamic-imports
62
+ * `migration.ts`, instantiates the default-exported `Migration` subclass
63
+ * (or invokes the default-exported factory function), reads `operations`,
64
+ * and writes `ops.json`. This helper then attests `migration.json` once
65
+ * the capability returns.
66
+ *
67
+ * In both cases attestation is owned by this helper so the on-disk artifacts
68
+ * are guaranteed to be fully attested when emit returns.
69
+ *
70
+ * Note that this helper is the CLI-driven emit path. Class-flow `migration.ts`
71
+ * files are also self-emitting via `Migration.run(...)` when run directly;
72
+ * that path attests inside `Migration.run` and produces byte-identical
73
+ * artifacts. This helper exists primarily to bridge descriptor-flow targets
74
+ * and to give `migration plan` a single in-process emit dispatch.
75
+ *
76
+ * Used by `migration emit` (always) and `migration plan` (always, after
77
+ * scaffolding `migration.ts`). Both flows run in-process so that structured
78
+ * errors thrown during evaluation (notably `errorUnfilledPlaceholder` with
79
+ * code `PN-MIG-2001`) propagate as real exceptions and the CLI's error
80
+ * envelope renders them with full structured metadata.
81
+ */
82
+ /**
83
+ * Emit `ops.json` and attest `migrationId` for the migration package at `dir`.
84
+ *
85
+ * Dispatches to descriptor flow when the target implements `resolveDescriptors`,
86
+ * otherwise to the target's `emit` capability. Throws a structured error if
87
+ * `migration.ts` is missing or the target supports neither flow. Other
88
+ * structured errors thrown during evaluation propagate unchanged.
89
+ */
90
+ async function emitMigration(dir, ctx) {
91
+ if (!await hasMigrationTs(dir)) throw errorMigrationFileMissing(dir);
92
+ if (migrationStrategy(ctx.migrations, ctx.targetId) === "descriptor") return emitDescriptorFlow(dir, ctx.migrations, ctx);
93
+ if (!ctx.migrations.emit) throw errorTargetMigrationNotSupported({ why: `Target "${ctx.targetId}" does not implement the class-flow \`emit\` capability; cannot emit a migration package` });
94
+ return {
95
+ operations: await ctx.migrations.emit({
96
+ dir,
97
+ frameworkComponents: ctx.frameworkComponents
98
+ }),
99
+ migrationId: await attestMigration(dir)
100
+ };
101
+ }
102
+ /**
103
+ * Descriptor flow: evaluate `migration.ts` to obtain a list of operation
104
+ * descriptors, hand them to the target's `resolveDescriptors` along with the
105
+ * manifest's contract bookends, then persist `ops.json` and attest the package.
106
+ */
107
+ async function emitDescriptorFlow(dir, migrations, ctx) {
108
+ assert(migrations.resolveDescriptors, "emitDescriptorFlow requires resolveDescriptors; gated by caller");
109
+ const pkg = await readMigrationPackage(dir);
110
+ const descriptors = await evaluateMigrationTs(dir);
111
+ const operations = migrations.resolveDescriptors(descriptors, {
112
+ fromContract: pkg.manifest.fromContract,
113
+ toContract: pkg.manifest.toContract,
114
+ frameworkComponents: ctx.frameworkComponents
115
+ });
116
+ await writeMigrationOps(dir, operations);
117
+ return {
118
+ operations,
119
+ migrationId: await attestMigration(dir)
120
+ };
121
+ }
122
+
123
+ //#endregion
124
+ export { migrationStrategy as n, emitMigration as t };
125
+ //# sourceMappingURL=migration-emit-Du4DBMqz.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration-emit-Du4DBMqz.mjs","names":[],"sources":["../src/lib/migration-strategy.ts","../src/lib/migration-emit.ts"],"sourcesContent":["/**\n * Migration authoring strategy selector.\n *\n * Targets currently use one of two strategies to author `migration.ts`:\n *\n * - **Descriptor flow** — the planner produces an `OperationDescriptor[]`\n * and `migration.ts` is a `export default () => [...]` file that the CLI\n * later replays through `resolveDescriptors` at emit time. Postgres uses\n * this today.\n * - **Class flow** — the planner produces a `MigrationPlanWithAuthoringSurface`\n * that renders itself as a `class M extends Migration { ... }` file. The\n * CLI dispatches to the target's `emit` capability at emit time. Mongo\n * uses this today.\n *\n * The two are mutually exclusive at the target level: a migrations capability\n * either implements the descriptor-flow trio (`planWithDescriptors`,\n * `resolveDescriptors`, `renderDescriptorTypeScript`) or the class-flow\n * `emit` hook. `migrationStrategy` discriminates between them by observing\n * which hooks are present, and is consumed by `migration new`, `migration\n * plan`, and `migration emit` to keep strategy-specific branching in one\n * place.\n */\n\nimport { errorTargetHasIncompleteMigrationCapabilities } from '@prisma-next/errors/migration';\nimport type { TargetMigrationsCapability } from '@prisma-next/framework-components/control';\n\nexport type MigrationStrategy = 'descriptor' | 'class-based';\n\n/**\n * Determine which authoring strategy a target uses, based on the shape of\n * its `TargetMigrationsCapability`. Callers that need strategy-specific\n * guarantees (e.g. that `resolveDescriptors` is present) should narrow on\n * the returned tag and trust the capability fields directly rather than\n * re-probing.\n *\n * Throws `errorTargetHasIncompleteMigrationCapabilities` (PN-MIG-2011) when\n * the capability registers neither flow. We diagnose this here rather than\n * deferring to the dispatch site so a misconfigured target gets an honest\n * \"incomplete capability\" error instead of being silently routed to one\n * flow and reported as missing the *other* flow's hook.\n */\nexport function migrationStrategy(\n migrations: TargetMigrationsCapability,\n targetId: string,\n): MigrationStrategy {\n if (migrations.resolveDescriptors) return 'descriptor';\n if (migrations.emit) return 'class-based';\n throw errorTargetHasIncompleteMigrationCapabilities({ targetId });\n}\n","/**\n * Shared helper for emitting `ops.json` and attesting `migration.json` for a\n * migration package's `migration.ts`.\n *\n * Two flows are dispatched here:\n * - Descriptor flow (Postgres): the framework evaluates `migration.ts`\n * (which re-exports the planner's descriptor list), calls the target's\n * `resolveDescriptors` to produce display-oriented operations, writes\n * `ops.json`, and attests `migration.json`.\n * - Class flow (Mongo): the target's `emit` capability dynamic-imports\n * `migration.ts`, instantiates the default-exported `Migration` subclass\n * (or invokes the default-exported factory function), reads `operations`,\n * and writes `ops.json`. This helper then attests `migration.json` once\n * the capability returns.\n *\n * In both cases attestation is owned by this helper so the on-disk artifacts\n * are guaranteed to be fully attested when emit returns.\n *\n * Note that this helper is the CLI-driven emit path. Class-flow `migration.ts`\n * files are also self-emitting via `Migration.run(...)` when run directly;\n * that path attests inside `Migration.run` and produces byte-identical\n * artifacts. This helper exists primarily to bridge descriptor-flow targets\n * and to give `migration plan` a single in-process emit dispatch.\n *\n * Used by `migration emit` (always) and `migration plan` (always, after\n * scaffolding `migration.ts`). Both flows run in-process so that structured\n * errors thrown during evaluation (notably `errorUnfilledPlaceholder` with\n * code `PN-MIG-2001`) propagate as real exceptions and the CLI's error\n * envelope renders them with full structured metadata.\n */\n\nimport assert from 'node:assert/strict';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n MigrationPlanOperation,\n OperationDescriptor,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { attestMigration } from '@prisma-next/migration-tools/attestation';\nimport { readMigrationPackage, writeMigrationOps } from '@prisma-next/migration-tools/io';\nimport { evaluateMigrationTs, hasMigrationTs } from '@prisma-next/migration-tools/migration-ts';\nimport { errorMigrationFileMissing, errorTargetMigrationNotSupported } from '../utils/cli-errors';\nimport { migrationStrategy } from './migration-strategy';\n\n/**\n * Context passed to `emitMigration`. Captures everything the helper needs to\n * dispatch to the right flow without re-loading the config.\n */\nexport interface EmitMigrationContext {\n readonly targetId: string;\n readonly migrations: TargetMigrationsCapability;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;\n}\n\n/**\n * Result of a successful emit: the operations that were written to `ops.json`\n * (display-oriented shape) and the content-addressed migrationId persisted to\n * `migration.json`.\n */\nexport interface EmitMigrationResult {\n readonly operations: readonly MigrationPlanOperation[];\n readonly migrationId: string;\n}\n\n/**\n * Emit `ops.json` and attest `migrationId` for the migration package at `dir`.\n *\n * Dispatches to descriptor flow when the target implements `resolveDescriptors`,\n * otherwise to the target's `emit` capability. Throws a structured error if\n * `migration.ts` is missing or the target supports neither flow. Other\n * structured errors thrown during evaluation propagate unchanged.\n */\nexport async function emitMigration(\n dir: string,\n ctx: EmitMigrationContext,\n): Promise<EmitMigrationResult> {\n if (!(await hasMigrationTs(dir))) {\n throw errorMigrationFileMissing(dir);\n }\n\n const strategy = migrationStrategy(ctx.migrations, ctx.targetId);\n\n if (strategy === 'descriptor') {\n return emitDescriptorFlow(dir, ctx.migrations, ctx);\n }\n\n if (!ctx.migrations.emit) {\n throw errorTargetMigrationNotSupported({\n why: `Target \"${ctx.targetId}\" does not implement the class-flow \\`emit\\` capability; cannot emit a migration package`,\n });\n }\n\n const operations = await ctx.migrations.emit({\n dir,\n frameworkComponents: ctx.frameworkComponents,\n });\n const migrationId = await attestMigration(dir);\n return { operations, migrationId };\n}\n\n/**\n * Descriptor flow: evaluate `migration.ts` to obtain a list of operation\n * descriptors, hand them to the target's `resolveDescriptors` along with the\n * manifest's contract bookends, then persist `ops.json` and attest the package.\n */\nasync function emitDescriptorFlow(\n dir: string,\n migrations: TargetMigrationsCapability,\n ctx: EmitMigrationContext,\n): Promise<EmitMigrationResult> {\n assert(\n migrations.resolveDescriptors,\n 'emitDescriptorFlow requires resolveDescriptors; gated by caller',\n );\n const pkg = await readMigrationPackage(dir);\n const descriptors = await evaluateMigrationTs(dir);\n const operations = migrations.resolveDescriptors(descriptors as OperationDescriptor[], {\n fromContract: pkg.manifest.fromContract,\n toContract: pkg.manifest.toContract,\n frameworkComponents: ctx.frameworkComponents,\n });\n await writeMigrationOps(dir, operations);\n const migrationId = await attestMigration(dir);\n return { operations, migrationId };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAgB,kBACd,YACA,UACmB;AACnB,KAAI,WAAW,mBAAoB,QAAO;AAC1C,KAAI,WAAW,KAAM,QAAO;AAC5B,OAAM,8CAA8C,EAAE,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACyBnE,eAAsB,cACpB,KACA,KAC8B;AAC9B,KAAI,CAAE,MAAM,eAAe,IAAI,CAC7B,OAAM,0BAA0B,IAAI;AAKtC,KAFiB,kBAAkB,IAAI,YAAY,IAAI,SAAS,KAE/C,aACf,QAAO,mBAAmB,KAAK,IAAI,YAAY,IAAI;AAGrD,KAAI,CAAC,IAAI,WAAW,KAClB,OAAM,iCAAiC,EACrC,KAAK,WAAW,IAAI,SAAS,2FAC9B,CAAC;AAQJ,QAAO;EAAE,YALU,MAAM,IAAI,WAAW,KAAK;GAC3C;GACA,qBAAqB,IAAI;GAC1B,CAAC;EAEmB,aADD,MAAM,gBAAgB,IAAI;EACZ;;;;;;;AAQpC,eAAe,mBACb,KACA,YACA,KAC8B;AAC9B,QACE,WAAW,oBACX,kEACD;CACD,MAAM,MAAM,MAAM,qBAAqB,IAAI;CAC3C,MAAM,cAAc,MAAM,oBAAoB,IAAI;CAClD,MAAM,aAAa,WAAW,mBAAmB,aAAsC;EACrF,cAAc,IAAI,SAAS;EAC3B,YAAY,IAAI,SAAS;EACzB,qBAAqB,IAAI;EAC1B,CAAC;AACF,OAAM,kBAAkB,KAAK,WAAW;AAExC,QAAO;EAAE;EAAY,aADD,MAAM,gBAAgB,IAAI;EACZ"}
@@ -1,7 +1,7 @@
1
1
  import { t as loadConfig } from "./config-loader-C4VXKl8f.mjs";
2
- import { _ as errorUnexpected, m as errorRuntime } from "./cli-errors-BDCYR5ap.mjs";
3
- import { t as createControlClient } from "./client-tdnbk0OR.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-oK_vA-Fn.mjs";
2
+ import { h as errorRuntime, v as errorUnexpected } from "./cli-errors-BUuJr6py.mjs";
3
+ import { t as createControlClient } from "./client-CJxHfhze.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-AFK4hxyX.mjs";
5
5
  import { t as TerminalUI } from "./terminal-ui-C5k88MmW.mjs";
6
6
  import { Command } from "commander";
7
7
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -1333,7 +1333,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
1333
1333
  code: "MIGRATION.DRAFTS",
1334
1334
  severity: "warn",
1335
1335
  message: `${drafts.length} draft migration(s) found: ${drafts.map((d) => d.dirName).join(", ")}`,
1336
- hints: ["Run 'prisma-next migration verify --dir <path>' to attest draft migrations before applying"]
1336
+ hints: ["Run 'prisma-next migration emit --dir <path>' to attest draft migrations before applying"]
1337
1337
  });
1338
1338
  if (attested.length === 0) {
1339
1339
  if (contractHash !== EMPTY_CONTRACT_HASH) diagnostics.push({
@@ -1580,4 +1580,4 @@ function summarizeRefDistance(graph, markerHash, refHash, refName) {
1580
1580
 
1581
1581
  //#endregion
1582
1582
  export { deriveEdgeStatuses as n, createMigrationStatusCommand as t };
1583
- //# sourceMappingURL=migration-status-DyVDf5NI.mjs.map
1583
+ //# sourceMappingURL=migration-status-CPamfEPj.mjs.map