@prisma-next/cli 0.4.0-dev.9 → 0.5.0-dev.1

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 (116) hide show
  1. package/README.md +26 -18
  2. package/dist/cli-errors-C0JhVj0c.d.mts +4 -0
  3. package/dist/cli-errors-DHq6GQGu.mjs +5 -0
  4. package/dist/cli.mjs +7 -18
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{client-CJxHfhze.mjs → client-TG7rbCWT.mjs} +7 -6
  7. package/dist/{client-CJxHfhze.mjs.map → client-TG7rbCWT.mjs.map} +1 -1
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +2 -7
  10. package/dist/commands/contract-infer.mjs +2 -8
  11. package/dist/commands/db-init.mjs +6 -7
  12. package/dist/commands/db-init.mjs.map +1 -1
  13. package/dist/commands/db-schema.mjs +4 -7
  14. package/dist/commands/db-schema.mjs.map +1 -1
  15. package/dist/commands/db-sign.mjs +5 -6
  16. package/dist/commands/db-sign.mjs.map +1 -1
  17. package/dist/commands/db-update.mjs +6 -7
  18. package/dist/commands/db-update.mjs.map +1 -1
  19. package/dist/commands/db-verify.mjs +6 -7
  20. package/dist/commands/db-verify.mjs.map +1 -1
  21. package/dist/commands/migration-apply.d.mts +1 -1
  22. package/dist/commands/migration-apply.d.mts.map +1 -1
  23. package/dist/commands/migration-apply.mjs +33 -25
  24. package/dist/commands/migration-apply.mjs.map +1 -1
  25. package/dist/commands/migration-new.d.mts.map +1 -1
  26. package/dist/commands/migration-new.mjs +47 -22
  27. package/dist/commands/migration-new.mjs.map +1 -1
  28. package/dist/commands/migration-plan.d.mts +6 -1
  29. package/dist/commands/migration-plan.d.mts.map +1 -1
  30. package/dist/commands/migration-plan.mjs +92 -69
  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 +4 -4
  34. package/dist/commands/migration-show.d.mts +2 -2
  35. package/dist/commands/migration-show.d.mts.map +1 -1
  36. package/dist/commands/migration-show.mjs +9 -14
  37. package/dist/commands/migration-show.mjs.map +1 -1
  38. package/dist/commands/migration-status.d.mts +4 -5
  39. package/dist/commands/migration-status.d.mts.map +1 -1
  40. package/dist/commands/migration-status.mjs +2 -7
  41. package/dist/config-loader-_W4T21X1.mjs +90 -0
  42. package/dist/config-loader-_W4T21X1.mjs.map +1 -0
  43. package/dist/config-loader.d.mts.map +1 -1
  44. package/dist/config-loader.mjs +1 -1
  45. package/dist/{contract-emit-gpJNLGs7.mjs → contract-emit-CNYyzJwF.mjs} +18 -14
  46. package/dist/contract-emit-CNYyzJwF.mjs.map +1 -0
  47. package/dist/{contract-emit-CKig_Lra.mjs → contract-emit-CQfj7xJn.mjs} +24 -20
  48. package/dist/contract-emit-CQfj7xJn.mjs.map +1 -0
  49. package/dist/contract-emit-fhNwwhkQ.mjs +4 -0
  50. package/dist/{contract-infer-BDJgg7Xb.mjs → contract-infer-BP3DrGgz.mjs} +3 -3
  51. package/dist/{contract-infer-BDJgg7Xb.mjs.map → contract-infer-BP3DrGgz.mjs.map} +1 -1
  52. package/dist/exports/control-api.d.mts +2 -2
  53. package/dist/exports/control-api.d.mts.map +1 -1
  54. package/dist/exports/control-api.mjs +3 -5
  55. package/dist/exports/index.mjs +2 -7
  56. package/dist/exports/index.mjs.map +1 -1
  57. package/dist/{framework-components-Bsr1GaIj.mjs → framework-components-DfZKQBQ2.mjs} +2 -2
  58. package/dist/{framework-components-Bsr1GaIj.mjs.map → framework-components-DfZKQBQ2.mjs.map} +1 -1
  59. package/dist/{init-DZWvhEP0.mjs → init-CQfo_4Ro.mjs} +2 -2
  60. package/dist/{init-DZWvhEP0.mjs.map → init-CQfo_4Ro.mjs.map} +1 -1
  61. package/dist/{inspect-live-schema-ChqrALmw.mjs → inspect-live-schema-DWzf4Q_m.mjs} +5 -5
  62. package/dist/{inspect-live-schema-ChqrALmw.mjs.map → inspect-live-schema-DWzf4Q_m.mjs.map} +1 -1
  63. package/dist/migration-cli.d.mts +50 -0
  64. package/dist/migration-cli.d.mts.map +1 -0
  65. package/dist/migration-cli.mjs +184 -0
  66. package/dist/migration-cli.mjs.map +1 -0
  67. package/dist/{migration-command-scaffold-B0oH_hyB.mjs → migration-command-scaffold-CLMD302g.mjs} +6 -6
  68. package/dist/{migration-command-scaffold-B0oH_hyB.mjs.map → migration-command-scaffold-CLMD302g.mjs.map} +1 -1
  69. package/dist/{migration-status-CPamfEPj.mjs → migration-status-B0HLF7So.mjs} +18 -34
  70. package/dist/migration-status-B0HLF7So.mjs.map +1 -0
  71. package/dist/{migrations-BIsjFjSV.mjs → migrations-B0dOQlk0.mjs} +4 -15
  72. package/dist/migrations-B0dOQlk0.mjs.map +1 -0
  73. package/dist/{result-handler-AFK4hxyX.mjs → result-handler-CIyu0Pdt.mjs} +22 -11
  74. package/dist/result-handler-CIyu0Pdt.mjs.map +1 -0
  75. package/dist/{validate-contract-deps-DBH6iTAD.mjs → validate-contract-deps-esa-VQ0h.mjs} +1 -1
  76. package/dist/{validate-contract-deps-DBH6iTAD.mjs.map → validate-contract-deps-esa-VQ0h.mjs.map} +1 -1
  77. package/dist/{verify-C56CuQc7.mjs → verify-BxiVp50b.mjs} +2 -2
  78. package/dist/{verify-C56CuQc7.mjs.map → verify-BxiVp50b.mjs.map} +1 -1
  79. package/package.json +19 -19
  80. package/src/cli.ts +1 -5
  81. package/src/commands/contract-emit.ts +9 -10
  82. package/src/commands/migration-apply.ts +34 -23
  83. package/src/commands/migration-new.ts +39 -17
  84. package/src/commands/migration-plan.ts +119 -104
  85. package/src/commands/migration-show.ts +6 -16
  86. package/src/commands/migration-status.ts +14 -34
  87. package/src/config-loader.ts +35 -29
  88. package/src/config-path-validation.ts +75 -0
  89. package/src/control-api/client.ts +2 -1
  90. package/src/control-api/operations/contract-emit.ts +24 -23
  91. package/src/control-api/types.ts +1 -1
  92. package/src/migration-cli.ts +254 -0
  93. package/src/utils/cli-errors.ts +1 -0
  94. package/src/utils/command-helpers.ts +15 -19
  95. package/src/utils/formatters/graph-migration-mapper.ts +5 -14
  96. package/src/utils/formatters/help.ts +0 -1
  97. package/src/utils/formatters/migrations.ts +2 -29
  98. package/dist/cli-errors-BUuJr6py.mjs +0 -5
  99. package/dist/cli-errors-Dic2eADK.d.mts +0 -4
  100. package/dist/commands/migration-emit.d.mts +0 -38
  101. package/dist/commands/migration-emit.d.mts.map +0 -1
  102. package/dist/commands/migration-emit.mjs +0 -81
  103. package/dist/commands/migration-emit.mjs.map +0 -1
  104. package/dist/config-loader-C4VXKl8f.mjs +0 -43
  105. package/dist/config-loader-C4VXKl8f.mjs.map +0 -1
  106. package/dist/contract-emit-CKig_Lra.mjs.map +0 -1
  107. package/dist/contract-emit-CU-SYNe4.mjs +0 -6
  108. package/dist/contract-emit-gpJNLGs7.mjs.map +0 -1
  109. package/dist/migration-emit-Du4DBMqz.mjs +0 -125
  110. package/dist/migration-emit-Du4DBMqz.mjs.map +0 -1
  111. package/dist/migration-status-CPamfEPj.mjs.map +0 -1
  112. package/dist/migrations-BIsjFjSV.mjs.map +0 -1
  113. package/dist/result-handler-AFK4hxyX.mjs.map +0 -1
  114. package/src/commands/migration-emit.ts +0 -134
  115. package/src/lib/migration-emit.ts +0 -125
  116. package/src/lib/migration-strategy.ts +0 -49
@@ -1 +1 @@
1
- {"version":3,"file":"migration-plan.mjs","names":["details: Array<{ label: string; value: string }>","contractJsonContent: string","toContractJson: Contract","fromContract: Contract | null","fromHash: string","manifest: MigrationManifest","migrationTsContent: string","lines: string[]"],"sources":["../../src/commands/migration-plan.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { findLatestMigration } from '@prisma-next/migration-tools/dag';\nimport {\n copyContractToMigrationDir,\n formatMigrationDirName,\n writeMigrationPackage,\n} from '@prisma-next/migration-tools/io';\nimport { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';\nimport { type MigrationManifest, MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractSqlDdl } from '../control-api/operations/extract-sql-ddl';\nimport { emitMigration } from '../lib/migration-emit';\nimport { migrationStrategy } from '../lib/migration-strategy';\nimport {\n type CliErrorConflict,\n CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorMigrationPlanningFailed,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\n loadAllBundles,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationPlanOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly name?: string;\n readonly from?: string;\n}\n\nexport interface MigrationPlanResult {\n readonly ok: boolean;\n readonly noOp: boolean;\n readonly from: string;\n readonly to: string;\n readonly migrationId?: string;\n readonly dir?: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql?: readonly string[];\n readonly summary: string;\n readonly timings: {\n readonly total: number;\n };\n}\n\nfunction mapMigrationToolsError(error: unknown): CliStructuredError {\n if (CliStructuredError.is(error)) {\n return error;\n }\n if (MigrationToolsError.is(error)) {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n }\n return errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during migration plan: ${error instanceof Error ? error.message : String(error)}`,\n });\n}\n\nasync function executeMigrationPlanCommand(\n options: MigrationPlanOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationPlanResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\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 { label: 'migrations', value: migrationsRelative },\n ];\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (options.name) {\n details.push({ label: 'name', value: options.name });\n }\n const header = formatStyledHeader({\n command: 'migration plan',\n description: 'Plan a migration from contract changes',\n url: 'https://pris.ly/migration-plan',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file (the \"to\" contract)\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 let toContractJson: Contract;\n try {\n toContractJson = JSON.parse(contractJsonContent) as Contract;\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 const rawStorageHash = toContractJson.storage?.storageHash;\n if (typeof rawStorageHash !== 'string') {\n return notOk(\n errorContractValidationFailed('Contract is missing storageHash', {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n const toStorageHash = rawStorageHash;\n\n // Read existing migrations and determine \"from\" contract\n let fromContract: Contract | null = null;\n let fromHash: string = EMPTY_CONTRACT_HASH;\n\n try {\n const { attested: bundles, drafts, graph } = await loadAllBundles(migrationsDir);\n\n // Check if a draft migration already targets this contract\n const existingDraft = drafts.find((d) => d.manifest.to === toStorageHash);\n if (existingDraft) {\n return notOk(\n errorRuntime('A draft migration to this contract already exists', {\n why: `Draft migration at \"${existingDraft.dirName}\" already targets ${toStorageHash}`,\n fix: `Run 'prisma-next migration emit --dir ${migrationsRelative}/${existingDraft.dirName}' to attest it, or delete it and re-plan.`,\n }),\n );\n }\n\n if (options.from) {\n const resolved = resolveBundleByPrefix(bundles, options.from);\n if (!resolved.ok) {\n const f = resolved.failure;\n return notOk(\n f.reason === 'ambiguous'\n ? errorRuntime('Multiple matching migrations found', {\n why: `Prefix \"${options.from}\" matches ${f.count} migrations in ${migrationsRelative}`,\n fix: 'Provide a longer prefix to disambiguate, or omit --from to use the latest migration target.',\n })\n : errorRuntime('Starting contract not found', {\n why: `No migration with to hash matching \"${options.from}\" exists in ${migrationsRelative}`,\n fix: 'Check that the --from hash matches a known migration target hash, or omit --from to use the latest migration target.',\n }),\n );\n }\n fromHash = resolved.value.manifest.to;\n fromContract = resolved.value.manifest.toContract;\n } else {\n const latestMigration = findLatestMigration(graph);\n if (latestMigration) {\n fromHash = latestMigration.to;\n const leafPkg = bundles.find((p) => p.manifest.migrationId === latestMigration.migrationId);\n if (leafPkg) {\n fromContract = leafPkg.manifest.toContract;\n }\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n // Check for no-op (same hash means no changes)\n if (fromHash === toStorageHash) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: true,\n from: fromHash,\n to: toStorageHash,\n operations: [],\n summary: 'No changes detected between contracts',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n // Check target supports migrations\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n [config.target, config.adapter, ...(config.extensionPacks ?? [])],\n );\n\n const strategy = migrationStrategy(migrations, config.target.targetId);\n\n // Build manifest and write migration package\n const timestamp = new Date();\n const slug = options.name ?? 'migration';\n const dirName = formatMigrationDirName(timestamp, slug);\n const packageDir = join(migrationsDir, dirName);\n\n const manifest: MigrationManifest = {\n from: fromHash,\n to: toStorageHash,\n migrationId: null,\n kind: 'regular',\n fromContract,\n toContract: toContractJson,\n hints: {\n used: [],\n applied: [],\n plannerVersion: '2.0.0',\n planningStrategy: strategy === 'descriptor' ? 'descriptors' : 'class-based',\n },\n labels: [],\n createdAt: timestamp.toISOString(),\n };\n\n const scaffoldContext = {\n packageDir,\n contractJsonPath: contractPathAbsolute,\n fromHash,\n toHash: toStorageHash,\n };\n\n try {\n let migrationTsContent: string;\n\n if (strategy === 'descriptor') {\n if (!migrations.planWithDescriptors || !migrations.renderDescriptorTypeScript) {\n throw errorTargetMigrationNotSupported({\n why: `Target \"${config.target.targetId}\" advertises descriptor flow but is missing required hooks`,\n });\n }\n const descriptorResult = migrations.planWithDescriptors({\n fromContract,\n toContract: toContractJson,\n frameworkComponents,\n });\n if (!descriptorResult.ok) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: descriptorResult.conflicts as readonly CliErrorConflict[],\n }),\n );\n }\n if (descriptorResult.descriptors.length === 0) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: [\n {\n kind: 'unsupportedChange',\n summary:\n 'Contract changed but planner produced no operations. ' +\n 'This indicates unsupported or ignored changes.',\n },\n ],\n }),\n );\n }\n migrationTsContent = migrations.renderDescriptorTypeScript(\n descriptorResult.descriptors,\n scaffoldContext,\n );\n } else {\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const planner = migrations.createPlanner(familyInstance);\n const fromSchema = migrations.contractToSchema(fromContract, frameworkComponents);\n const plannerResult = planner.plan({\n contract: toContractJson,\n schema: fromSchema,\n policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },\n fromHash,\n frameworkComponents,\n });\n if (plannerResult.kind === 'failure') {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: plannerResult.conflicts as readonly CliErrorConflict[],\n }),\n );\n }\n if (plannerResult.plan.operations.length === 0) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: [\n {\n kind: 'unsupportedChange',\n summary:\n 'Contract changed but planner produced no operations. ' +\n 'This indicates unsupported or ignored changes.',\n },\n ],\n }),\n );\n }\n migrationTsContent = plannerResult.plan.renderTypeScript();\n }\n\n await writeMigrationPackage(packageDir, manifest, []);\n await copyContractToMigrationDir(packageDir, contractPathAbsolute);\n await writeMigrationTs(packageDir, migrationTsContent);\n\n // Always run emit inline. If migration.ts contains unfilled\n // placeholders (e.g. user must hand-author a dataTransform body),\n // emitMigration throws errorUnfilledPlaceholder (PN-MIG-2001) and\n // we propagate that structured error to the user.\n const { operations, migrationId } = await emitMigration(packageDir, {\n targetId: config.target.targetId,\n migrations,\n frameworkComponents,\n });\n\n const sql = extractSqlDdl(operations);\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n migrationId,\n dir: relative(process.cwd(), packageDir),\n operations: operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `Planned ${operations.length} operation(s)`,\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n } catch (error) {\n return notOk(mapMigrationToolsError(error));\n }\n}\n\nexport function createMigrationPlanCommand(): Command {\n const command = new Command('plan');\n setCommandDescriptions(\n command,\n 'Plan a migration from contract changes',\n 'Compares the emitted contract against the latest on-disk migration state and\\n' +\n 'produces a new migration package with the required operations. No database\\n' +\n 'connection is needed — this is a fully offline operation.',\n );\n setCommandExamples(command, [\n 'prisma-next migration plan',\n 'prisma-next migration plan --name add-users-table',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--name <slug>', 'Name slug for the migration directory', 'migration')\n .option('--from <hash>', 'Explicit starting contract hash (overrides latest migration target)')\n .action(async (options: MigrationPlanOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeMigrationPlanCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (planResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(planResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationPlanOutput(planResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n\nfunction formatMigrationPlanOutput(result: MigrationPlanResult, flags: GlobalFlags): string {\n const lines: string[] = [];\n const useColor = flags.color !== false;\n\n const green_ = useColor ? (s: string) => `\\x1b[32m${s}\\x1b[0m` : (s: string) => s;\n const yellow_ = useColor ? (s: string) => `\\x1b[33m${s}\\x1b[0m` : (s: string) => s;\n const dim_ = useColor ? (s: string) => `\\x1b[2m${s}\\x1b[0m` : (s: string) => s;\n\n if (result.noOp) {\n lines.push(`${green_('✔')} No changes detected`);\n lines.push(dim_(` from: ${result.from}`));\n lines.push(dim_(` to: ${result.to}`));\n return lines.join('\\n');\n }\n\n lines.push(`${green_('✔')} ${result.summary}`);\n lines.push('');\n\n if (result.operations.length > 0) {\n lines.push(dim_('│'));\n for (let i = 0; i < result.operations.length; i++) {\n const op = result.operations[i]!;\n const isLast = i === result.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const opClassLabel =\n op.operationClass === 'destructive'\n ? yellow_(`[${op.operationClass}]`)\n : dim_(`[${op.operationClass}]`);\n lines.push(`${dim_(treeChar)}─ ${op.label} ${opClassLabel}`);\n }\n\n const hasDestructive = result.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${yellow_('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n lines.push('');\n }\n\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.migrationId) {\n lines.push(dim_(`migrationId: ${result.migrationId}`));\n }\n if (result.dir) {\n lines.push(dim_(`dir: ${result.dir}`));\n }\n\n if (result.sql && result.sql.length > 0) {\n lines.push('');\n lines.push(dim_('DDL preview'));\n lines.push('');\n for (const statement of result.sql) {\n const trimmed = statement.trim();\n if (!trimmed) continue;\n const line = trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n lines.push(line);\n }\n }\n\n if (flags.verbose && result.timings) {\n lines.push('');\n lines.push(dim_(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\nexport type PrefixResolutionFailure =\n | { reason: 'ambiguous'; count: number }\n | { reason: 'not-found' };\n\n/**\n * Resolve a migration bundle by exact hash or prefix match.\n *\n * Tries exact match first, then prefix match (auto-prepending `sha256:` when\n * the needle omits the scheme). Returns the matched bundle on success, or a\n * discriminated failure indicating whether the prefix was ambiguous or simply\n * not found.\n *\n * @internal Exported for testing only.\n */\nexport function resolveBundleByPrefix<T extends { manifest: { to: string } }>(\n bundles: readonly T[],\n needle: string,\n): Result<T, PrefixResolutionFailure> {\n const exact = bundles.find((p) => p.manifest.to === needle);\n if (exact) return ok(exact);\n\n const prefixWithScheme = needle.startsWith('sha256:') ? needle : `sha256:${needle}`;\n const candidates = bundles.filter((p) => p.manifest.to.startsWith(prefixWithScheme));\n\n if (candidates.length === 1) return ok(candidates[0]!);\n if (candidates.length > 1) return notOk({ reason: 'ambiguous', count: candidates.length });\n return notOk({ reason: 'not-found' });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"migration-plan.mjs","names":["details: Array<{ label: string; value: string }>","contractJsonContent: string","toContractJson: Contract","fromContract: Contract | null","fromHash: string","fromContractSourceDir: string | null","baseManifest: Omit<MigrationManifest, 'migrationId'>","plannedOps: readonly MigrationPlanOperation[]","lines: string[]"],"sources":["../../src/commands/migration-plan.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport {\n createControlStack,\n type MigrationPlanOperation,\n} from '@prisma-next/framework-components/control';\nimport { computeMigrationId } from '@prisma-next/migration-tools/attestation';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { findLatestMigration } from '@prisma-next/migration-tools/dag';\nimport {\n copyFilesWithRename,\n formatMigrationDirName,\n writeMigrationPackage,\n} from '@prisma-next/migration-tools/io';\nimport { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';\nimport { type MigrationManifest, MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractSqlDdl } from '../control-api/operations/extract-sql-ddl';\nimport {\n type CliErrorConflict,\n CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorMigrationPlanningFailed,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\n loadAllBundles,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationPlanOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly name?: string;\n readonly from?: string;\n}\n\nexport interface MigrationPlanResult {\n readonly ok: boolean;\n readonly noOp: boolean;\n readonly from: string;\n readonly to: string;\n readonly dir?: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql?: readonly string[];\n readonly summary: string;\n /**\n * When true, `migration.ts` was written but contains unfilled\n * `placeholder(...)` calls. The user must edit the file and then run\n * `node migration.ts` to self-emit `ops.json` / `migration.json`.\n */\n readonly pendingPlaceholders?: boolean;\n readonly timings: {\n readonly total: number;\n };\n}\n\nfunction mapMigrationToolsError(error: unknown): CliStructuredError {\n if (CliStructuredError.is(error)) {\n return error;\n }\n if (MigrationToolsError.is(error)) {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n }\n return errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during migration plan: ${error instanceof Error ? error.message : String(error)}`,\n });\n}\n\nasync function executeMigrationPlanCommand(\n options: MigrationPlanOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationPlanResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\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 { label: 'migrations', value: migrationsRelative },\n ];\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (options.name) {\n details.push({ label: 'name', value: options.name });\n }\n const header = formatStyledHeader({\n command: 'migration plan',\n description: 'Plan a migration from contract changes',\n url: 'https://pris.ly/migration-plan',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file (the \"to\" contract)\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 let toContractJson: Contract;\n try {\n toContractJson = JSON.parse(contractJsonContent) as Contract;\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 const rawStorageHash = toContractJson.storage?.storageHash;\n if (typeof rawStorageHash !== 'string') {\n return notOk(\n errorContractValidationFailed('Contract is missing storageHash', {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n const toStorageHash = rawStorageHash;\n\n // Read existing migrations and determine \"from\" contract\n let fromContract: Contract | null = null;\n let fromHash: string = EMPTY_CONTRACT_HASH;\n let fromContractSourceDir: string | null = null;\n\n try {\n const { bundles, graph } = await loadAllBundles(migrationsDir);\n\n if (options.from) {\n const resolved = resolveBundleByPrefix(bundles, options.from);\n if (!resolved.ok) {\n const f = resolved.failure;\n return notOk(\n f.reason === 'ambiguous'\n ? errorRuntime('Multiple matching migrations found', {\n why: `Prefix \"${options.from}\" matches ${f.count} migrations in ${migrationsRelative}`,\n fix: 'Provide a longer prefix to disambiguate, or omit --from to use the latest migration target.',\n })\n : errorRuntime('Starting contract not found', {\n why: `No migration with to hash matching \"${options.from}\" exists in ${migrationsRelative}`,\n fix: 'Check that the --from hash matches a known migration target hash, or omit --from to use the latest migration target.',\n }),\n );\n }\n fromHash = resolved.value.manifest.to;\n fromContract = resolved.value.manifest.toContract;\n fromContractSourceDir = resolved.value.dirPath;\n } else {\n const latestMigration = findLatestMigration(graph);\n if (latestMigration) {\n fromHash = latestMigration.to;\n const leafPkg = bundles.find((p) => p.manifest.migrationId === latestMigration.migrationId);\n if (leafPkg) {\n fromContract = leafPkg.manifest.toContract;\n fromContractSourceDir = leafPkg.dirPath;\n }\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n // Check for no-op (same hash means no changes)\n if (fromHash === toStorageHash) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: true,\n from: fromHash,\n to: toStorageHash,\n operations: [],\n summary: 'No changes detected between contracts',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n // Check target supports migrations\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n [config.target, config.adapter, ...(config.extensionPacks ?? [])],\n );\n\n // Build manifest and write migration package\n const timestamp = new Date();\n const slug = options.name ?? 'migration';\n const dirName = formatMigrationDirName(timestamp, slug);\n const packageDir = join(migrationsDir, dirName);\n\n const baseManifest: Omit<MigrationManifest, 'migrationId'> = {\n from: fromHash,\n to: toStorageHash,\n kind: 'regular',\n fromContract,\n toContract: toContractJson,\n hints: {\n used: [],\n applied: [],\n plannerVersion: '2.0.0',\n },\n labels: [],\n createdAt: timestamp.toISOString(),\n };\n\n try {\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const planner = migrations.createPlanner(familyInstance);\n const fromSchema = migrations.contractToSchema(fromContract, frameworkComponents);\n const plannerResult = planner.plan({\n contract: toContractJson,\n schema: fromSchema,\n policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },\n fromHash,\n fromContract,\n frameworkComponents,\n });\n if (plannerResult.kind === 'failure') {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: plannerResult.conflicts as readonly CliErrorConflict[],\n }),\n );\n }\n\n // Accessing .operations triggers toOp() on each call. If any call\n // is a DataTransformCall with an unfilled placeholder stub, toOp()\n // throws PN-MIG-2001. We catch that here so the migration can still\n // be scaffolded with `ops: []`; the user fills the placeholder, then\n // re-runs `node migration.ts` to attest with the real ops.\n let plannedOps: readonly MigrationPlanOperation[] = [];\n let hasPlaceholders = false;\n try {\n plannedOps = plannerResult.plan.operations;\n if (plannedOps.length === 0) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: [\n {\n kind: 'unsupportedChange',\n summary:\n 'Contract changed but planner produced no operations. ' +\n 'This indicates unsupported or ignored changes.',\n },\n ],\n }),\n );\n }\n } catch (e) {\n if (CliStructuredError.is(e) && e.domain === 'MIG' && e.code === '2001') {\n hasPlaceholders = true;\n } else {\n throw e;\n }\n }\n\n const migrationTsContent = plannerResult.plan.renderTypeScript();\n\n // Always-attest: compute migrationId over (manifest, ops). When\n // placeholders blocked lowering, ops is `[]` and the id hashes over\n // the empty list — re-emitting after the user fills the placeholder\n // produces a different id (over the real ops). This is intentional;\n // there is no on-disk \"draft\" state.\n const opsForWrite = hasPlaceholders ? [] : plannedOps;\n const manifest: MigrationManifest = {\n ...baseManifest,\n migrationId: computeMigrationId(baseManifest, opsForWrite),\n };\n\n await writeMigrationPackage(packageDir, manifest, opsForWrite);\n const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);\n await copyFilesWithRename(packageDir, [\n { sourcePath: destinationArtifacts.jsonPath, destName: 'end-contract.json' },\n { sourcePath: destinationArtifacts.dtsPath, destName: 'end-contract.d.ts' },\n ]);\n if (fromContractSourceDir !== null) {\n const sourceArtifacts = getEmittedArtifactPaths(\n join(fromContractSourceDir, 'end-contract.json'),\n );\n await copyFilesWithRename(packageDir, [\n { sourcePath: sourceArtifacts.jsonPath, destName: 'start-contract.json' },\n { sourcePath: sourceArtifacts.dtsPath, destName: 'start-contract.d.ts' },\n ]);\n }\n await writeMigrationTs(packageDir, migrationTsContent);\n\n if (hasPlaceholders) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), packageDir),\n operations: [],\n pendingPlaceholders: true,\n summary:\n 'Planned migration with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const sql = extractSqlDdl(plannedOps);\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), packageDir),\n operations: plannedOps.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `Planned ${plannedOps.length} operation(s)`,\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n } catch (error) {\n return notOk(mapMigrationToolsError(error));\n }\n}\n\nexport function createMigrationPlanCommand(): Command {\n const command = new Command('plan');\n setCommandDescriptions(\n command,\n 'Plan a migration from contract changes',\n 'Compares the emitted contract against the latest on-disk migration state and\\n' +\n 'produces a new migration package with the required operations. No database\\n' +\n 'connection is needed — this is a fully offline operation.',\n );\n setCommandExamples(command, [\n 'prisma-next migration plan',\n 'prisma-next migration plan --name add-users-table',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--name <slug>', 'Name slug for the migration directory', 'migration')\n .option('--from <hash>', 'Explicit starting contract hash (overrides latest migration target)')\n .action(async (options: MigrationPlanOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeMigrationPlanCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (planResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(planResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationPlanOutput(planResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n\nfunction formatMigrationPlanOutput(result: MigrationPlanResult, flags: GlobalFlags): string {\n const lines: string[] = [];\n const useColor = flags.color !== false;\n\n const green_ = useColor ? (s: string) => `\\x1b[32m${s}\\x1b[0m` : (s: string) => s;\n const yellow_ = useColor ? (s: string) => `\\x1b[33m${s}\\x1b[0m` : (s: string) => s;\n const dim_ = useColor ? (s: string) => `\\x1b[2m${s}\\x1b[0m` : (s: string) => s;\n\n if (result.noOp) {\n lines.push(`${green_('✔')} No changes detected`);\n lines.push(dim_(` from: ${result.from}`));\n lines.push(dim_(` to: ${result.to}`));\n return lines.join('\\n');\n }\n\n if (result.pendingPlaceholders) {\n lines.push(`${yellow_('⚠')} ${result.summary}`);\n lines.push('');\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.dir) {\n lines.push(dim_(`dir: ${result.dir}`));\n }\n lines.push('');\n lines.push(\n 'Open migration.ts and replace each `placeholder(...)` call with your actual query.',\n );\n lines.push(`Then run: ${green_(`node ${result.dir ?? '<dir>'}/migration.ts`)}`);\n return lines.join('\\n');\n }\n\n lines.push(`${green_('✔')} ${result.summary}`);\n lines.push('');\n\n if (result.operations.length > 0) {\n lines.push(dim_('│'));\n for (let i = 0; i < result.operations.length; i++) {\n const op = result.operations[i]!;\n const isLast = i === result.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const opClassLabel =\n op.operationClass === 'destructive'\n ? yellow_(`[${op.operationClass}]`)\n : dim_(`[${op.operationClass}]`);\n lines.push(`${dim_(treeChar)}─ ${op.label} ${opClassLabel}`);\n }\n\n const hasDestructive = result.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${yellow_('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n lines.push('');\n }\n\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.dir) {\n lines.push(dim_(`dir: ${result.dir}`));\n }\n\n lines.push('');\n lines.push(\n `Next: ${green_(`node ${result.dir ?? '<dir>'}/migration.ts`)} to emit ops.json and attest migrationId before running ${green_('prisma-next migration apply')}.`,\n );\n\n if (result.sql && result.sql.length > 0) {\n lines.push('');\n lines.push(dim_('DDL preview'));\n lines.push('');\n for (const statement of result.sql) {\n const trimmed = statement.trim();\n if (!trimmed) continue;\n const line = trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n lines.push(line);\n }\n }\n\n if (flags.verbose && result.timings) {\n lines.push('');\n lines.push(dim_(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\nexport type PrefixResolutionFailure =\n | { reason: 'ambiguous'; count: number }\n | { reason: 'not-found' };\n\n/**\n * Resolve a migration bundle by exact hash or prefix match.\n *\n * Tries exact match first, then prefix match (auto-prepending `sha256:` when\n * the needle omits the scheme). Returns the matched bundle on success, or a\n * discriminated failure indicating whether the prefix was ambiguous or simply\n * not found.\n *\n * @internal Exported for testing only.\n */\nexport function resolveBundleByPrefix<T extends { manifest: { to: string } }>(\n bundles: readonly T[],\n needle: string,\n): Result<T, PrefixResolutionFailure> {\n const exact = bundles.find((p) => p.manifest.to === needle);\n if (exact) return ok(exact);\n\n const prefixWithScheme = needle.startsWith('sha256:') ? needle : `sha256:${needle}`;\n const candidates = bundles.filter((p) => p.manifest.to.startsWith(prefixWithScheme));\n\n if (candidates.length === 1) return ok(candidates[0]!);\n if (candidates.length > 1) return notOk({ reason: 'ambiguous', count: candidates.length });\n return notOk({ reason: 'not-found' });\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as CliStructuredError } from "../cli-errors-Dic2eADK.mjs";
1
+ import { t as CliStructuredError } from "../cli-errors-C0JhVj0c.mjs";
2
2
  import { Command } from "commander";
3
3
  import { Result } from "@prisma-next/utils/result";
4
4
 
@@ -1,12 +1,12 @@
1
- import { t as loadConfig } from "../config-loader-C4VXKl8f.mjs";
2
- import { h as errorRuntime, t as CliStructuredError, v as errorUnexpected } from "../cli-errors-BUuJr6py.mjs";
3
- import { h as formatCommandHelp, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions } from "../result-handler-AFK4hxyX.mjs";
1
+ import { t as loadConfig } from "../config-loader-_W4T21X1.mjs";
2
+ import { _ as errorUnexpected, m as errorRuntime, t as CliStructuredError } from "../cli-errors-DHq6GQGu.mjs";
3
+ import { h as formatCommandHelp, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions } from "../result-handler-CIyu0Pdt.mjs";
4
4
  import { t as TerminalUI } from "../terminal-ui-C5k88MmW.mjs";
5
5
  import { Command } from "commander";
6
6
  import { notOk, ok } from "@prisma-next/utils/result";
7
7
  import { resolve } from "pathe";
8
- import { MigrationToolsError } from "@prisma-next/migration-tools/types";
9
8
  import { readRefs, resolveRef, validateRefName, validateRefValue, writeRefs } from "@prisma-next/migration-tools/refs";
9
+ import { MigrationToolsError } from "@prisma-next/migration-tools/types";
10
10
 
11
11
  //#region src/commands/migration-ref.ts
12
12
  function resolveRefsPath(configPath, config) {
@@ -1,4 +1,4 @@
1
- import { t as CliStructuredError } from "../cli-errors-Dic2eADK.mjs";
1
+ import { t as CliStructuredError } from "../cli-errors-C0JhVj0c.mjs";
2
2
  import { Command } from "commander";
3
3
  import { Result } from "@prisma-next/utils/result";
4
4
  import { MigrationBundle } from "@prisma-next/migration-tools/types";
@@ -10,7 +10,7 @@ interface MigrationShowResult {
10
10
  readonly dirPath: string;
11
11
  readonly from: string;
12
12
  readonly to: string;
13
- readonly migrationId: string | null;
13
+ readonly migrationId: string;
14
14
  readonly kind: string;
15
15
  readonly createdAt: string;
16
16
  readonly operations: readonly {
@@ -1 +1 @@
1
- {"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":[],"mappings":";;;;;;UA2BiB,mBAAA;;EAAA,SAAA,OAAA,EAAA,MAAmB;EAsBpB,SAAA,OAAA,EAAA,MAAmB;EACd,SAAA,IAAA,EAAA,MAAA;EAEX,SAAA,EAAA,EAAA,MAAA;EAAiB,SAAA,WAAA,EAAA,MAAA,GAAA,IAAA;EAAxB,SAAA,IAAA,EAAA,MAAA;EAAM,SAAA,SAAA,EAAA,MAAA;EA2JO,SAAA,UAAA,EAAA,SAA0B;;;;;;;;iBA9J1B,mBAAA,oBACK,oCAElB,OAAO,iBAAiB;iBA2JX,0BAAA,CAAA,GAA8B"}
1
+ {"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":[],"mappings":";;;;;;UA2BiB,mBAAA;;EAAA,SAAA,OAAA,EAAA,MAAmB;EAsBpB,SAAA,OAAA,EAAA,MAAmB;EACd,SAAA,IAAA,EAAA,MAAA;EAEX,SAAA,EAAA,EAAA,MAAA;EAAiB,SAAA,WAAA,EAAA,MAAA;EAAxB,SAAA,IAAA,EAAA,MAAA;EAAM,SAAA,SAAA,EAAA,MAAA;EAiJO,SAAA,UAAA,EAAA,SAA0B;;;;;;;;iBApJ1B,mBAAA,oBACK,oCAElB,OAAO,iBAAiB;iBAiJX,0BAAA,CAAA,GAA8B"}
@@ -1,15 +1,15 @@
1
- import { t as loadConfig } from "../config-loader-C4VXKl8f.mjs";
2
- import { h as errorRuntime, v as errorUnexpected } from "../cli-errors-BUuJr6py.mjs";
1
+ import { t as loadConfig } from "../config-loader-_W4T21X1.mjs";
2
+ import { _ as errorUnexpected, m as errorRuntime } from "../cli-errors-DHq6GQGu.mjs";
3
3
  import { t as extractOperationStatements } from "../extract-operation-statements-DZUJNmL3.mjs";
4
- import { _ as formatStyledHeader, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions } from "../result-handler-AFK4hxyX.mjs";
4
+ import { _ as formatStyledHeader, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions } from "../result-handler-CIyu0Pdt.mjs";
5
5
  import { t as TerminalUI } from "../terminal-ui-C5k88MmW.mjs";
6
- import { o as formatMigrationShowOutput } from "../migrations-BIsjFjSV.mjs";
6
+ import { a as formatMigrationShowOutput } from "../migrations-B0dOQlk0.mjs";
7
7
  import { Command } from "commander";
8
8
  import { notOk, ok } from "@prisma-next/utils/result";
9
9
  import { relative, resolve } from "pathe";
10
10
  import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/dag";
11
11
  import { readMigrationPackage, readMigrationsDir } from "@prisma-next/migration-tools/io";
12
- import { MigrationToolsError, isAttested } from "@prisma-next/migration-tools/types";
12
+ import { MigrationToolsError } from "@prisma-next/migration-tools/types";
13
13
 
14
14
  //#region src/commands/migration-show.ts
15
15
  function looksLikePath(target) {
@@ -17,10 +17,10 @@ function looksLikePath(target) {
17
17
  }
18
18
  function resolveByHashPrefix(packages, prefix) {
19
19
  const normalizedPrefix = prefix.startsWith("sha256:") ? prefix : `sha256:${prefix}`;
20
- const matches = packages.filter((p) => typeof p.manifest.migrationId === "string").filter((p) => p.manifest.migrationId.startsWith(normalizedPrefix));
20
+ const matches = packages.filter((p) => p.manifest.migrationId.startsWith(normalizedPrefix));
21
21
  if (matches.length === 1) return ok(matches[0]);
22
22
  if (matches.length === 0) return notOk(errorRuntime("No migration found matching prefix", {
23
- why: `No attested migration has a migrationId starting with "${normalizedPrefix}"`,
23
+ why: `No migration has a migrationId starting with "${normalizedPrefix}"`,
24
24
  fix: "Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages."
25
25
  }));
26
26
  return notOk(errorRuntime("Ambiguous hash prefix", {
@@ -67,17 +67,12 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
67
67
  if (!resolved.ok) return resolved;
68
68
  pkg = resolved.value;
69
69
  } else {
70
- const attested = allPackages.filter(isAttested);
71
- if (attested.length === 0) return notOk(errorRuntime("No attested migrations found", {
72
- why: `All migrations in ${migrationsRelative} are drafts (migrationId: null)`,
73
- fix: "Run `prisma-next migration emit --dir <path>` to attest a draft migration."
74
- }));
75
- const latestMigration = findLatestMigration(reconstructGraph(attested));
70
+ const latestMigration = findLatestMigration(reconstructGraph(allPackages));
76
71
  if (!latestMigration) return notOk(errorRuntime("Could not resolve latest migration", {
77
72
  why: "No latest migration found in the migration history",
78
73
  fix: "The migrations directory may be corrupted. Inspect the migration.json files."
79
74
  }));
80
- const leafPkg = attested.find((p) => p.manifest.migrationId === latestMigration.migrationId);
75
+ const leafPkg = allPackages.find((p) => p.manifest.migrationId === latestMigration.migrationId);
81
76
  if (!leafPkg) return notOk(errorRuntime("Could not resolve latest migration", {
82
77
  why: `Latest migration ${latestMigration.dirName} does not match any package`,
83
78
  fix: "The migrations directory may be corrupted. Inspect the migration.json files."
@@ -1 +1 @@
1
- {"version":3,"file":"migration-show.mjs","names":["details: Array<{ label: string; value: string }>","pkg: MigrationBundle"],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\nimport { findLatestMigration, reconstructGraph } from '@prisma-next/migration-tools/dag';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport type { MigrationBundle } from '@prisma-next/migration-tools/types';\nimport { isAttested, MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractOperationStatements } from '../control-api/operations/extract-operation-statements';\nimport { type CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport interface MigrationShowResult {\n readonly ok: true;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string;\n readonly to: string;\n readonly migrationId: string | null;\n readonly kind: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql: readonly string[];\n readonly summary: string;\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\nexport function resolveByHashPrefix(\n packages: readonly MigrationBundle[],\n prefix: string,\n): Result<MigrationBundle, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const attested = packages.filter((p) => typeof p.manifest.migrationId === 'string');\n const matches = attested.filter((p) => p.manifest.migrationId!.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No attested migration has a migrationId starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.manifest.migrationId}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n const migrationsDir = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let pkg: MigrationBundle;\n\n try {\n if (target && looksLikePath(target)) {\n pkg = await readMigrationPackage(resolve(target));\n } else {\n const allPackages = await readMigrationsDir(migrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${migrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n pkg = resolved.value;\n } else {\n const attested = allPackages.filter(isAttested);\n if (attested.length === 0) {\n return notOk(\n errorRuntime('No attested migrations found', {\n why: `All migrations in ${migrationsRelative} are drafts (migrationId: null)`,\n fix: 'Run `prisma-next migration emit --dir <path>` to attest a draft migration.',\n }),\n );\n }\n const graph = reconstructGraph(attested);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = attested.find(\n (p) => p.manifest.migrationId === latestMigration.migrationId,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n pkg = leafPkg;\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n const sql = extractOperationStatements(config.family.familyId, ops) ?? [];\n\n const result: MigrationShowResult = {\n ok: true,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.manifest.from,\n to: pkg.manifest.to,\n migrationId: pkg.manifest.migrationId,\n kind: pkg.manifest.kind,\n createdAt: pkg.manifest.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `${ops.length} operation(s)`,\n };\n return ok(result);\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, DDL preview, and metadata for a migration package.\\n' +\n 'Accepts a directory path, a hash prefix (git-style), or defaults to the\\n' +\n 'latest migration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument(\n '[target]',\n 'Migration directory path or migrationId hash prefix (defaults to latest)',\n )\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"migration-show.mjs","names":["details: Array<{ label: string; value: string }>","pkg: MigrationBundle"],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\nimport { findLatestMigration, reconstructGraph } from '@prisma-next/migration-tools/dag';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport type { MigrationBundle } from '@prisma-next/migration-tools/types';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractOperationStatements } from '../control-api/operations/extract-operation-statements';\nimport { type CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport interface MigrationShowResult {\n readonly ok: true;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string;\n readonly to: string;\n readonly migrationId: string;\n readonly kind: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql: readonly string[];\n readonly summary: string;\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\nexport function resolveByHashPrefix(\n packages: readonly MigrationBundle[],\n prefix: string,\n): Result<MigrationBundle, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const matches = packages.filter((p) => p.manifest.migrationId.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No migration has a migrationId starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.manifest.migrationId}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n const migrationsDir = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let pkg: MigrationBundle;\n\n try {\n if (target && looksLikePath(target)) {\n pkg = await readMigrationPackage(resolve(target));\n } else {\n const allPackages = await readMigrationsDir(migrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${migrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n pkg = resolved.value;\n } else {\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.manifest.migrationId === latestMigration.migrationId,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n pkg = leafPkg;\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n const sql = extractOperationStatements(config.family.familyId, ops) ?? [];\n\n const result: MigrationShowResult = {\n ok: true,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.manifest.from,\n to: pkg.manifest.to,\n migrationId: pkg.manifest.migrationId,\n kind: pkg.manifest.kind,\n createdAt: pkg.manifest.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `${ops.length} operation(s)`,\n };\n return ok(result);\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, DDL preview, and metadata for a migration package.\\n' +\n 'Accepts a directory path, a hash prefix (git-style), or defaults to the\\n' +\n 'latest migration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument(\n '[target]',\n 'Migration directory path or migrationId hash prefix (defaults to latest)',\n )\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { Command } from "commander";
2
- import { AttestedMigrationBundle, DraftMigrationBundle, MigrationGraph } from "@prisma-next/migration-tools/types";
2
+ import { MigrationBundle, MigrationGraph } from "@prisma-next/migration-tools/types";
3
3
 
4
4
  //#region src/utils/migration-types.d.ts
5
5
  interface StatusRef {
@@ -27,7 +27,7 @@ interface MigrationStatusEntry {
27
27
  readonly dirName: string;
28
28
  readonly from: string;
29
29
  readonly to: string;
30
- readonly migrationId: string | null;
30
+ readonly migrationId: string;
31
31
  readonly operationCount: number;
32
32
  readonly operationSummary: string;
33
33
  readonly hasDestructive: boolean;
@@ -49,7 +49,7 @@ interface MigrationStatusResult {
49
49
  readonly refName?: string;
50
50
  readonly selectedPath: readonly {
51
51
  readonly dirName: string;
52
- readonly migrationId: string | null;
52
+ readonly migrationId: string;
53
53
  readonly from: string;
54
54
  readonly to: string;
55
55
  }[];
@@ -57,8 +57,7 @@ interface MigrationStatusResult {
57
57
  readonly summary: string;
58
58
  readonly diagnostics: readonly StatusDiagnostic[];
59
59
  readonly graph?: MigrationGraph;
60
- readonly bundles?: readonly AttestedMigrationBundle[];
61
- readonly drafts?: readonly DraftMigrationBundle[];
60
+ readonly bundles?: readonly MigrationBundle[];
62
61
  readonly edgeStatuses?: readonly EdgeStatus[];
63
62
  readonly activeRefHash?: string;
64
63
  readonly activeRefName?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"sourcesContent":[],"mappings":";;;;UAAiB,SAAA;;;;AAAjB;AAMiB,UAAA,gBAAA,CAAgB;;;;ECWrB,SAAA,KAAA,EAAA,SAAc,MAAA,EAAA;AAmB1B;;;KAnBY,cAAA;ADjBZ;AAMiB,UC8BA,UAAA,CD9BgB;;mBCgCd;;;;ADtCF,UE4DA,oBAAA,CF5DS;EAMT,SAAA,OAAA,EAAA,MAAgB;;;;ECWrB,SAAA,cAAc,EAAA,MAAA;EAmBT,SAAA,gBAEE,EAAA,MAAA;;mBC8BA;;AAKF,UAAA,qBAAA,CAAqB;EAGN,SAAA,EAAA,EAAA,IAAA;EAIL,SAAA,IAAA,EAAA,QAAA,GAAA,SAAA;EAeM,SAAA,UAAA,EAAA,SAnBD,oBAmBC,EAAA;EACd,SAAA,UAAA,CAAA,EAAA,MAAA;EACW,SAAA,UAAA,EAAA,MAAA;EACD,SAAA,YAAA,EAAA,MAAA;EACM,SAAA,IAAA,CAAA,EAAA,SAnBR,SAmBQ,EAAA;EAAU,SAAA,YAAA,CAAA,EAAA;IAkD7B,SAAA,QAAkB,EAAA,MAAA;IAwjBlB,SAAA,MAAA,EAAA,MAAA;;;;;;;;;;;;iCA9mBiB;mBACd;8BACW;6BACD;mCACM;;;;;;;;;;;;;;;;;;;;iBAkDnB,kBAAA,QACP,uHAKN;iBAkjBa,4BAAA,CAAA,GAAgC"}
1
+ {"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"sourcesContent":[],"mappings":";;;;UAAiB,SAAA;;;;AAAjB;AAMiB,UAAA,gBAAA,CAAgB;;;;ECWrB,SAAA,KAAA,EAAA,SAAc,MAAA,EAAA;AAmB1B;;;KAnBY,cAAA;ADjBZ;AAMiB,UC8BA,UAAA,CD9BgB;;mBCgCd;;;;ADtCF,UE2DA,oBAAA,CF3DS;EAMT,SAAA,OAAA,EAAA,MAAgB;;;;ECWrB,SAAA,cAAc,EAAA,MAAA;EAmBT,SAAA,gBAEE,EAAA,MAAA;;mBC6BA;;AAKF,UAAA,qBAAA,CAAqB;EAGN,SAAA,EAAA,EAAA,IAAA;EAIL,SAAA,IAAA,EAAA,QAAA,GAAA,SAAA;EAeM,SAAA,UAAA,EAAA,SAnBD,oBAmBC,EAAA;EACd,SAAA,UAAA,CAAA,EAAA,MAAA;EACW,SAAA,UAAA,EAAA,MAAA;EACK,SAAA,YAAA,EAAA,MAAA;EAAU,SAAA,IAAA,CAAA,EAAA,SAlBlB,SAkBkB,EAAA;EAkD7B,SAAA,YAAkB,CAAA,EAAA;IA2iBlB,SAAA,QAAA,EAAA,MAAA;;;;;;;;;;;;;iCAhmBiB;mBACd;8BACW;mCACK;;;;;;;;;;;;;;;;;;;;iBAkDnB,kBAAA,QACP,uHAKN;iBAqiBa,4BAAA,CAAA,GAAgC"}
@@ -1,9 +1,4 @@
1
- import "../config-loader-C4VXKl8f.mjs";
2
- import "../cli-errors-BUuJr6py.mjs";
3
- import "../framework-components-Bsr1GaIj.mjs";
4
- import "../client-CJxHfhze.mjs";
5
- import "../result-handler-AFK4hxyX.mjs";
6
- import "../terminal-ui-C5k88MmW.mjs";
7
- import { n as deriveEdgeStatuses, t as createMigrationStatusCommand } from "../migration-status-CPamfEPj.mjs";
1
+ import "../config-loader-_W4T21X1.mjs";
2
+ import { n as deriveEdgeStatuses, t as createMigrationStatusCommand } from "../migration-status-B0HLF7So.mjs";
8
3
 
9
4
  export { createMigrationStatusCommand, deriveEdgeStatuses };
@@ -0,0 +1,90 @@
1
+ import { getEmittedArtifactPaths } from "@prisma-next/emitter";
2
+ import { errorConfigFileNotFound, errorConfigValidation, errorUnexpected } from "@prisma-next/errors/control";
3
+ import { dirname, resolve } from "pathe";
4
+ import { ConfigValidationError, validateConfig } from "@prisma-next/config/config-validation";
5
+ import { ifDefined } from "@prisma-next/utils/defined";
6
+ import { loadConfig } from "c12";
7
+ import { normalizeContractConfig } from "@prisma-next/config/config-types";
8
+
9
+ //#region src/config-path-validation.ts
10
+ function throwValidation(field, why) {
11
+ throw new ConfigValidationError(field, why);
12
+ }
13
+ function finalizeContractSource(source, configDir) {
14
+ const resolvedInputs = source.inputs?.map((input) => resolve(configDir, input));
15
+ if (resolvedInputs === void 0) return source;
16
+ return {
17
+ ...source,
18
+ inputs: resolvedInputs
19
+ };
20
+ }
21
+ function validateNoOutputsAreInputs(inputs, output) {
22
+ if (inputs === void 0 || output === void 0) return;
23
+ let emittedArtifactPaths;
24
+ try {
25
+ emittedArtifactPaths = getEmittedArtifactPaths(output);
26
+ } catch (error) {
27
+ throwValidation("contract.output", error instanceof Error ? error.message : String(error));
28
+ }
29
+ const emittedPaths = new Set([emittedArtifactPaths.jsonPath, emittedArtifactPaths.dtsPath]);
30
+ for (const input of inputs) if (emittedPaths.has(input)) throwValidation("contract.source.inputs[]", "Config.contract.source.inputs must not include emitted artifact paths derived from contract.output");
31
+ }
32
+ function finalizeConfig(config, configDir) {
33
+ if (!config.contract) return config;
34
+ const contract = normalizeContractConfig(config.contract);
35
+ const source = finalizeContractSource(contract.source, configDir);
36
+ const output = resolve(configDir, contract.output);
37
+ validateNoOutputsAreInputs(source.inputs, output);
38
+ return {
39
+ ...config,
40
+ contract: {
41
+ ...contract,
42
+ source,
43
+ output
44
+ }
45
+ };
46
+ }
47
+
48
+ //#endregion
49
+ //#region src/config-loader.ts
50
+ async function loadValidatedConfig(configPath) {
51
+ const cwd = process.cwd();
52
+ const resolvedConfigPath = configPath ? resolve(cwd, configPath) : void 0;
53
+ const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;
54
+ const result = await loadConfig({
55
+ name: "prisma-next",
56
+ ...ifDefined("configFile", resolvedConfigPath),
57
+ cwd: configCwd
58
+ });
59
+ if (resolvedConfigPath && result.configFile !== resolvedConfigPath) throw errorConfigFileNotFound(resolvedConfigPath);
60
+ if (!result.config || Object.keys(result.config).length === 0) throw errorConfigFileNotFound(result.configFile || resolvedConfigPath || configPath);
61
+ validateConfig(result.config);
62
+ const loadedConfigDir = result.configFile ? dirname(result.configFile) : configCwd;
63
+ return finalizeConfig(result.config, loadedConfigDir);
64
+ }
65
+ /**
66
+ * Loads the Prisma Next config from a TypeScript file.
67
+ * Supports both default export and named export.
68
+ * Uses c12 to automatically handle TypeScript compilation and config file discovery.
69
+ *
70
+ * @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.
71
+ * @returns The loaded config object.
72
+ * @throws Error if config file doesn't exist or is invalid.
73
+ */
74
+ async function loadConfig$1(configPath) {
75
+ try {
76
+ return await loadValidatedConfig(configPath);
77
+ } catch (error) {
78
+ if (error instanceof ConfigValidationError) throw errorConfigValidation(error.field, { why: error.why });
79
+ if (error instanceof Error && "code" in error && typeof error.code === "string") throw error;
80
+ if (error instanceof Error) {
81
+ if (error.message.includes("not found") || error.message.includes("Cannot find") || error.message.includes("ENOENT")) throw errorConfigFileNotFound(configPath ? resolve(process.cwd(), configPath) : void 0, { why: error.message });
82
+ throw errorUnexpected(error.message, { why: `Failed to load config: ${error.message}` });
83
+ }
84
+ throw errorUnexpected(String(error));
85
+ }
86
+ }
87
+
88
+ //#endregion
89
+ export { loadConfig$1 as t };
90
+ //# sourceMappingURL=config-loader-_W4T21X1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader-_W4T21X1.mjs","names":["emittedArtifactPaths: ReturnType<typeof getEmittedArtifactPaths>","loadConfigC12","loadConfig"],"sources":["../src/config-path-validation.ts","../src/config-loader.ts"],"sourcesContent":["import {\n type ContractSourceProvider,\n normalizeContractConfig,\n type PrismaNextConfig,\n} from '@prisma-next/config/config-types';\nimport { ConfigValidationError } from '@prisma-next/config/config-validation';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { resolve } from 'pathe';\n\nfunction throwValidation(field: string, why: string): never {\n throw new ConfigValidationError(field, why);\n}\n\nfunction finalizeContractSource(\n source: ContractSourceProvider,\n configDir: string,\n): ContractSourceProvider {\n const resolvedInputs = source.inputs?.map((input) => resolve(configDir, input));\n if (resolvedInputs === undefined) {\n return source;\n }\n\n return {\n ...source,\n inputs: resolvedInputs,\n };\n}\n\nfunction validateNoOutputsAreInputs(\n inputs: readonly string[] | undefined,\n output: string | undefined,\n): void {\n if (inputs === undefined || output === undefined) {\n return;\n }\n\n let emittedArtifactPaths: ReturnType<typeof getEmittedArtifactPaths>;\n try {\n emittedArtifactPaths = getEmittedArtifactPaths(output);\n } catch (error) {\n throwValidation('contract.output', error instanceof Error ? error.message : String(error));\n }\n\n const emittedPaths = new Set([emittedArtifactPaths.jsonPath, emittedArtifactPaths.dtsPath]);\n\n for (const input of inputs) {\n if (emittedPaths.has(input)) {\n throwValidation(\n 'contract.source.inputs[]',\n 'Config.contract.source.inputs must not include emitted artifact paths derived from contract.output',\n );\n }\n }\n}\n\nexport function finalizeConfig(config: PrismaNextConfig, configDir: string): PrismaNextConfig {\n if (!config.contract) {\n return config;\n }\n\n const contract = normalizeContractConfig(config.contract);\n const source = finalizeContractSource(contract.source, configDir);\n const output = resolve(configDir, contract.output);\n\n validateNoOutputsAreInputs(source.inputs, output);\n\n return {\n ...config,\n contract: {\n ...contract,\n source,\n output,\n },\n };\n}\n","import type { PrismaNextConfig } from '@prisma-next/config/config-types';\nimport { ConfigValidationError, validateConfig } from '@prisma-next/config/config-validation';\nimport {\n errorConfigFileNotFound,\n errorConfigValidation,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { loadConfig as loadConfigC12 } from 'c12';\nimport { dirname, resolve } from 'pathe';\nimport { finalizeConfig } from './config-path-validation';\n\nasync function loadValidatedConfig(configPath?: string): Promise<PrismaNextConfig> {\n const cwd = process.cwd();\n const resolvedConfigPath = configPath ? resolve(cwd, configPath) : undefined;\n const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;\n\n const result = await loadConfigC12<PrismaNextConfig>({\n name: 'prisma-next',\n ...ifDefined('configFile', resolvedConfigPath),\n cwd: configCwd,\n });\n\n // When a specific config file was requested, verify it was actually loaded\n // (c12 falls back to searching by name if the specified file doesn't exist)\n if (resolvedConfigPath && result.configFile !== resolvedConfigPath) {\n throw errorConfigFileNotFound(resolvedConfigPath);\n }\n\n // Check if config is missing or empty (c12 may return empty object when file doesn't exist)\n if (!result.config || Object.keys(result.config).length === 0) {\n // Use c12's configFile if available, otherwise use explicit configPath, otherwise omit path\n const displayPath = result.configFile || resolvedConfigPath || configPath;\n throw errorConfigFileNotFound(displayPath);\n }\n\n // Validate config structure\n validateConfig(result.config);\n\n const loadedConfigDir = result.configFile ? dirname(result.configFile) : configCwd;\n return finalizeConfig(result.config, loadedConfigDir);\n}\n\n/**\n * Loads the Prisma Next config from a TypeScript file.\n * Supports both default export and named export.\n * Uses c12 to automatically handle TypeScript compilation and config file discovery.\n *\n * @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.\n * @returns The loaded config object.\n * @throws Error if config file doesn't exist or is invalid.\n */\nexport async function loadConfig(configPath?: string): Promise<PrismaNextConfig> {\n try {\n return await loadValidatedConfig(configPath);\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw errorConfigValidation(error.field, {\n why: error.why,\n });\n }\n\n // Re-throw structured errors as-is\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code: string }).code === 'string'\n ) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Check for file not found errors\n if (\n error.message.includes('not found') ||\n error.message.includes('Cannot find') ||\n error.message.includes('ENOENT')\n ) {\n // Use resolved path if available, otherwise use original configPath\n const displayPath = configPath ? resolve(process.cwd(), configPath) : undefined;\n throw errorConfigFileNotFound(displayPath, {\n why: error.message,\n });\n }\n // For other errors, wrap in unexpected error\n throw errorUnexpected(error.message, {\n why: `Failed to load config: ${error.message}`,\n });\n }\n throw errorUnexpected(String(error));\n }\n}\n"],"mappings":";;;;;;;;;AASA,SAAS,gBAAgB,OAAe,KAAoB;AAC1D,OAAM,IAAI,sBAAsB,OAAO,IAAI;;AAG7C,SAAS,uBACP,QACA,WACwB;CACxB,MAAM,iBAAiB,OAAO,QAAQ,KAAK,UAAU,QAAQ,WAAW,MAAM,CAAC;AAC/E,KAAI,mBAAmB,OACrB,QAAO;AAGT,QAAO;EACL,GAAG;EACH,QAAQ;EACT;;AAGH,SAAS,2BACP,QACA,QACM;AACN,KAAI,WAAW,UAAa,WAAW,OACrC;CAGF,IAAIA;AACJ,KAAI;AACF,yBAAuB,wBAAwB,OAAO;UAC/C,OAAO;AACd,kBAAgB,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;;CAG5F,MAAM,eAAe,IAAI,IAAI,CAAC,qBAAqB,UAAU,qBAAqB,QAAQ,CAAC;AAE3F,MAAK,MAAM,SAAS,OAClB,KAAI,aAAa,IAAI,MAAM,CACzB,iBACE,4BACA,qGACD;;AAKP,SAAgB,eAAe,QAA0B,WAAqC;AAC5F,KAAI,CAAC,OAAO,SACV,QAAO;CAGT,MAAM,WAAW,wBAAwB,OAAO,SAAS;CACzD,MAAM,SAAS,uBAAuB,SAAS,QAAQ,UAAU;CACjE,MAAM,SAAS,QAAQ,WAAW,SAAS,OAAO;AAElD,4BAA2B,OAAO,QAAQ,OAAO;AAEjD,QAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG;GACH;GACA;GACD;EACF;;;;;AC7DH,eAAe,oBAAoB,YAAgD;CACjF,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,qBAAqB,aAAa,QAAQ,KAAK,WAAW,GAAG;CACnE,MAAM,YAAY,qBAAqB,QAAQ,mBAAmB,GAAG;CAErE,MAAM,SAAS,MAAMC,WAAgC;EACnD,MAAM;EACN,GAAG,UAAU,cAAc,mBAAmB;EAC9C,KAAK;EACN,CAAC;AAIF,KAAI,sBAAsB,OAAO,eAAe,mBAC9C,OAAM,wBAAwB,mBAAmB;AAInD,KAAI,CAAC,OAAO,UAAU,OAAO,KAAK,OAAO,OAAO,CAAC,WAAW,EAG1D,OAAM,wBADc,OAAO,cAAc,sBAAsB,WACrB;AAI5C,gBAAe,OAAO,OAAO;CAE7B,MAAM,kBAAkB,OAAO,aAAa,QAAQ,OAAO,WAAW,GAAG;AACzE,QAAO,eAAe,OAAO,QAAQ,gBAAgB;;;;;;;;;;;AAYvD,eAAsBC,aAAW,YAAgD;AAC/E,KAAI;AACF,SAAO,MAAM,oBAAoB,WAAW;UACrC,OAAO;AACd,MAAI,iBAAiB,sBACnB,OAAM,sBAAsB,MAAM,OAAO,EACvC,KAAK,MAAM,KACZ,CAAC;AAIJ,MACE,iBAAiB,SACjB,UAAU,SACV,OAAQ,MAA2B,SAAS,SAE5C,OAAM;AAGR,MAAI,iBAAiB,OAAO;AAE1B,OACE,MAAM,QAAQ,SAAS,YAAY,IACnC,MAAM,QAAQ,SAAS,cAAc,IACrC,MAAM,QAAQ,SAAS,SAAS,CAIhC,OAAM,wBADc,aAAa,QAAQ,QAAQ,KAAK,EAAE,WAAW,GAAG,QAC3B,EACzC,KAAK,MAAM,SACZ,CAAC;AAGJ,SAAM,gBAAgB,MAAM,SAAS,EACnC,KAAK,0BAA0B,MAAM,WACtC,CAAC;;AAEJ,QAAM,gBAAgB,OAAO,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.mts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;AAmBA;;;;;;;iBAAsB,UAAA,uBAAiC,QAAQ"}
1
+ {"version":3,"file":"config-loader.d.mts","names":[],"sources":["../src/config-loader.ts"],"sourcesContent":[],"mappings":";;;;;;AAoDA;;;;;;;iBAAsB,UAAA,uBAAiC,QAAQ"}
@@ -1,3 +1,3 @@
1
- import { t as loadConfig } from "./config-loader-C4VXKl8f.mjs";
1
+ import { t as loadConfig } from "./config-loader-_W4T21X1.mjs";
2
2
 
3
3
  export { loadConfig };
@@ -1,14 +1,15 @@
1
- import { t as loadConfig } from "./config-loader-C4VXKl8f.mjs";
2
- import { a as errorContractValidationFailed, h as errorRuntime, t as CliStructuredError, v as errorUnexpected$1 } from "./cli-errors-BUuJr6py.mjs";
3
- import { t as createControlClient } from "./client-CJxHfhze.mjs";
4
- import { _ as formatStyledHeader, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions, v as formatSuccessMessage, x as isVerbose } from "./result-handler-AFK4hxyX.mjs";
1
+ import { t as loadConfig } from "./config-loader-_W4T21X1.mjs";
2
+ import { _ as errorUnexpected$1, a as errorContractValidationFailed, m as errorRuntime, t as CliStructuredError$1 } from "./cli-errors-DHq6GQGu.mjs";
3
+ import { t as createControlClient } from "./client-TG7rbCWT.mjs";
4
+ import { _ as formatStyledHeader, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions, v as formatSuccessMessage, x as isVerbose } from "./result-handler-CIyu0Pdt.mjs";
5
5
  import { t as createProgressAdapter } from "./progress-adapter-B-YvmcDu.mjs";
6
6
  import { t as TerminalUI } from "./terminal-ui-C5k88MmW.mjs";
7
7
  import { Command } from "commander";
8
8
  import { mkdirSync, writeFileSync } from "node:fs";
9
+ import { getEmittedArtifactPaths } from "@prisma-next/emitter";
9
10
  import { errorContractConfigMissing } from "@prisma-next/errors/control";
10
11
  import { notOk, ok } from "@prisma-next/utils/result";
11
- import { dirname, isAbsolute, join, relative, resolve } from "pathe";
12
+ import { dirname, relative, resolve } from "pathe";
12
13
  import { ifDefined } from "@prisma-next/utils/defined";
13
14
 
14
15
  //#region src/utils/formatters/emit.ts
@@ -83,17 +84,20 @@ async function executeContractEmitCommand(options, flags, ui, startTime) {
83
84
  try {
84
85
  config = await loadConfig(options.config);
85
86
  } catch (error) {
86
- if (error instanceof CliStructuredError) return notOk(error);
87
+ if (error instanceof CliStructuredError$1) return notOk(error);
87
88
  return notOk(errorUnexpected$1(error instanceof Error ? error.message : String(error), { why: "Failed to load config" }));
88
89
  }
89
90
  const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
90
91
  if (!config.contract) return notOk(errorContractConfigMissing({ why: "Config.contract is required for emit. Define it in your config: contract: { source: ..., output: ... }" }));
91
92
  const contractConfig = config.contract;
92
93
  if (!contractConfig.output) return notOk(errorContractConfigMissing({ why: "Contract config must have output path. This should not happen if defineConfig() was used." }));
93
- if (!contractConfig.output.endsWith(".json")) return notOk(errorContractConfigMissing({ why: "Contract config output path must end with .json (e.g., \"src/prisma/contract.json\")" }));
94
- const configDir = options.config ? dirname(resolve(options.config)) : process.cwd();
95
- const outputJsonPath = isAbsolute(contractConfig.output) ? contractConfig.output : join(configDir, contractConfig.output);
96
- const outputDtsPath = `${outputJsonPath.slice(0, -5)}.d.ts`;
94
+ let outputPaths;
95
+ try {
96
+ outputPaths = getEmittedArtifactPaths(contractConfig.output);
97
+ } catch (error) {
98
+ return notOk(errorContractConfigMissing({ why: error instanceof Error ? error.message : String(error) }));
99
+ }
100
+ const { jsonPath: outputJsonPath, dtsPath: outputDtsPath } = outputPaths;
97
101
  if (!flags.json && !flags.quiet) {
98
102
  const contractPath = relative(process.cwd(), outputJsonPath);
99
103
  const typesPath = relative(process.cwd(), outputDtsPath);
@@ -132,7 +136,7 @@ async function executeContractEmitCommand(options, flags, ui, startTime) {
132
136
  try {
133
137
  const result = await client.emit({
134
138
  contractConfig: {
135
- sourceProvider: contractConfig.source,
139
+ source: contractConfig.source,
136
140
  output: outputJsonPath
137
141
  },
138
142
  onProgress
@@ -142,7 +146,7 @@ async function executeContractEmitCommand(options, flags, ui, startTime) {
142
146
  mkdirSync(dirname(outputDtsPath), { recursive: true });
143
147
  writeFileSync(outputJsonPath, result.value.contractJson, "utf-8");
144
148
  writeFileSync(outputDtsPath, result.value.contractDts, "utf-8");
145
- const { validateContractDeps } = await import("./validate-contract-deps-DBH6iTAD.mjs");
149
+ const { validateContractDeps } = await import("./validate-contract-deps-esa-VQ0h.mjs");
146
150
  const depsValidation = validateContractDeps(result.value.contractDts, dirname(outputDtsPath));
147
151
  if (depsValidation.warning) ui.warn(depsValidation.warning);
148
152
  return ok({
@@ -157,7 +161,7 @@ async function executeContractEmitCommand(options, flags, ui, startTime) {
157
161
  timings: { total: Date.now() - startTime }
158
162
  });
159
163
  } catch (error) {
160
- if (CliStructuredError.is(error)) return notOk(error);
164
+ if (CliStructuredError$1.is(error)) return notOk(error);
161
165
  return notOk(errorUnexpected$1("Unexpected error during contract emit", { why: error instanceof Error ? error.message : String(error) }));
162
166
  } finally {
163
167
  await client.close();
@@ -188,4 +192,4 @@ function createContractEmitCommand() {
188
192
 
189
193
  //#endregion
190
194
  export { createContractEmitCommand as t };
191
- //# sourceMappingURL=contract-emit-gpJNLGs7.mjs.map
195
+ //# sourceMappingURL=contract-emit-CNYyzJwF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-emit-CNYyzJwF.mjs","names":["lines: string[]","exhaustive: never","config: Awaited<ReturnType<typeof loadConfig>>","CliStructuredError","errorUnexpected","outputPaths: ReturnType<typeof getEmittedArtifactPaths>"],"sources":["../src/utils/formatters/emit.ts","../src/commands/contract-emit.ts"],"sourcesContent":["import { ifDefined } from '@prisma-next/utils/defined';\nimport { relative } from 'pathe';\n\nimport type { GlobalFlags } from '../global-flags';\nimport { isVerbose } from './helpers';\n\n// EmitContractResult type for CLI output formatting (includes file paths)\nexport interface EmitContractResult {\n readonly storageHash: string;\n readonly executionHash?: string;\n readonly profileHash: string;\n readonly outDir: string;\n readonly files: {\n readonly json: string;\n readonly dts: string;\n };\n readonly timings: {\n readonly total: number;\n };\n}\n\n/**\n * Formats human-readable output for contract emit.\n */\nexport function formatEmitOutput(result: EmitContractResult, flags: GlobalFlags): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n // Convert absolute paths to relative paths from cwd\n const jsonPath = relative(process.cwd(), result.files.json);\n const dtsPath = relative(process.cwd(), result.files.dts);\n\n lines.push(`✔ Emitted contract.json → ${jsonPath}`);\n lines.push(`✔ Emitted contract.d.ts → ${dtsPath}`);\n lines.push(` storageHash: ${result.storageHash}`);\n if (result.executionHash) {\n lines.push(` executionHash: ${result.executionHash}`);\n }\n if (result.profileHash) {\n lines.push(` profileHash: ${result.profileHash}`);\n }\n if (isVerbose(flags, 1)) {\n lines.push(` Total time: ${result.timings.total}ms`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats JSON output for contract emit.\n */\nexport function formatEmitJson(result: EmitContractResult): string {\n const output = {\n ok: true,\n storageHash: result.storageHash,\n ...ifDefined('executionHash', result.executionHash),\n ...(result.profileHash ? { profileHash: result.profileHash } : {}),\n outDir: result.outDir,\n files: result.files,\n timings: result.timings,\n };\n\n return JSON.stringify(output, null, 2);\n}\n","import { mkdirSync, writeFileSync } from 'node:fs';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { errorContractConfigMissing } from '@prisma-next/errors/control';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { dirname, relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type { EmitFailure } from '../control-api/types';\nimport {\n CliStructuredError,\n errorContractValidationFailed,\n errorRuntime,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport {\n type EmitContractResult,\n formatEmitJson,\n formatEmitOutput,\n} from '../utils/formatters/emit';\nimport { formatStyledHeader, formatSuccessMessage } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface ContractEmitOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nfunction mapDiagnosticsToIssues(\n failure: EmitFailure,\n): ReadonlyArray<{ kind: string; message: string }> {\n const diagnostics = failure.diagnostics?.diagnostics ?? [];\n return diagnostics.map((diagnostic) => {\n const location =\n diagnostic.sourceId && diagnostic.span\n ? ` (${diagnostic.sourceId}:${diagnostic.span.start.line}:${diagnostic.span.start.column})`\n : diagnostic.sourceId\n ? ` (${diagnostic.sourceId})`\n : '';\n return {\n kind: diagnostic.code,\n message: `${diagnostic.message}${location}`,\n };\n });\n}\n\n/**\n * Maps an EmitFailure to a CliStructuredError for consistent error handling.\n */\nfunction mapEmitFailure(\n failure: EmitFailure,\n context?: { readonly configPath?: string },\n): CliStructuredError {\n if (failure.code === 'CONTRACT_SOURCE_INVALID') {\n const issues = mapDiagnosticsToIssues(failure);\n return errorRuntime(failure.summary, {\n why: failure.why ?? 'Contract source provider failed',\n fix: 'Check your contract source provider in prisma-next.config.ts and ensure it returns Result<Contract, Diagnostics>',\n ...(issues.length > 0 ? { meta: { issues } } : {}),\n });\n }\n\n if (failure.code === 'CONTRACT_VALIDATION_FAILED') {\n return errorContractValidationFailed(\n failure.why ?? 'Contract validation failed while emitting',\n context?.configPath ? { where: { path: context.configPath } } : undefined,\n );\n }\n\n if (failure.code === 'EMIT_FAILED') {\n return errorRuntime(failure.summary, {\n why: failure.why ?? 'Failed to emit contract',\n fix: 'Check your contract configuration and ensure the source is valid',\n });\n }\n\n // Exhaustive check - TypeScript will error if a new code is added but not handled\n const exhaustive: never = failure.code;\n throw new Error(`Unhandled EmitFailure code: ${exhaustive}`);\n}\n\n/**\n * Executes the contract emit command and returns a structured Result.\n */\nasync function executeContractEmitCommand(\n options: ContractEmitOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<EmitContractResult, CliStructuredError>> {\n // Load config\n let config: Awaited<ReturnType<typeof loadConfig>>;\n try {\n config = await loadConfig(options.config);\n } catch (error) {\n // Convert thrown CliStructuredError to Result\n if (error instanceof CliStructuredError) {\n return notOk(error);\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 // Resolve contract from config\n if (!config.contract) {\n return notOk(\n errorContractConfigMissing({\n why: 'Config.contract is required for emit. Define it in your config: contract: { source: ..., output: ... }',\n }),\n );\n }\n\n // Contract config is already normalized by defineConfig() with defaults applied\n const contractConfig = config.contract;\n\n // Resolve artifact paths from config (already normalized by defineConfig() with defaults)\n if (!contractConfig.output) {\n return notOk(\n errorContractConfigMissing({\n why: 'Contract config must have output path. This should not happen if defineConfig() was used.',\n }),\n );\n }\n let outputPaths: ReturnType<typeof getEmittedArtifactPaths>;\n try {\n outputPaths = getEmittedArtifactPaths(contractConfig.output);\n } catch (error) {\n return notOk(\n errorContractConfigMissing({\n why: error instanceof Error ? error.message : String(error),\n }),\n );\n }\n const { jsonPath: outputJsonPath, dtsPath: outputDtsPath } = outputPaths;\n\n // Output header to stderr (decoration)\n if (!flags.json && !flags.quiet) {\n const contractPath = relative(process.cwd(), outputJsonPath);\n const typesPath = relative(process.cwd(), outputDtsPath);\n const header = formatStyledHeader({\n command: 'contract emit',\n description: 'Emit your contract artifacts',\n url: 'https://pris.ly/contract-emit',\n details: [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'types', value: typesPath },\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n // Create control client (no driver needed for emit)\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n // Create progress adapter\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n // Call emit with progress callback\n const result = await client.emit({\n contractConfig: {\n source: contractConfig.source,\n output: outputJsonPath,\n },\n onProgress,\n });\n\n // Handle failures by mapping to CLI structured error\n if (!result.ok) {\n return notOk(mapEmitFailure(result.failure, { configPath }));\n }\n\n // Create directories if needed\n mkdirSync(dirname(outputJsonPath), { recursive: true });\n mkdirSync(dirname(outputDtsPath), { recursive: true });\n\n // Write the results to files\n writeFileSync(outputJsonPath, result.value.contractJson, 'utf-8');\n writeFileSync(outputDtsPath, result.value.contractDts, 'utf-8');\n\n // Validate that contract.d.ts type imports are resolvable\n const { validateContractDeps } = await import('../utils/validate-contract-deps');\n const depsValidation = validateContractDeps(result.value.contractDts, dirname(outputDtsPath));\n if (depsValidation.warning) {\n ui.warn(depsValidation.warning);\n }\n\n // Convert success result to CLI output format\n const emitResult: EmitContractResult = {\n storageHash: result.value.storageHash,\n ...(result.value.executionHash ? { executionHash: result.value.executionHash } : {}),\n profileHash: result.value.profileHash,\n outDir: dirname(outputJsonPath),\n files: {\n json: outputJsonPath,\n dts: outputDtsPath,\n },\n timings: { total: Date.now() - startTime },\n };\n\n return ok(emitResult);\n } catch (error) {\n // Use static type guard to work across module boundaries\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n // Wrap unexpected errors\n return notOk(\n errorUnexpected('Unexpected error during contract emit', {\n why: error instanceof Error ? error.message : String(error),\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createContractEmitCommand(): Command {\n const command = new Command('emit');\n setCommandDescriptions(\n command,\n 'Emit your contract artifacts',\n 'Reads your contract source (TypeScript or Prisma schema) and emits contract.json and\\n' +\n 'contract.d.ts. The contract.json contains the canonical contract structure, and\\n' +\n 'contract.d.ts provides TypeScript types for type-safe query building.',\n );\n setCommandExamples(command, [\n 'prisma-next contract emit',\n 'prisma-next contract emit --config ./custom-config.ts',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: ContractEmitOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const startTime = Date.now();\n\n const result = await executeContractEmitCommand(options, flags, ui, startTime);\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, ui, (emitResult) => {\n if (flags.json) {\n ui.output(formatEmitJson(emitResult));\n } else {\n const output = formatEmitOutput(emitResult, flags);\n if (output) {\n ui.log(output);\n }\n if (!flags.quiet) {\n ui.success(formatSuccessMessage(flags));\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}