prisma-next 0.5.0-dev.66 → 0.5.0-dev.68

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 (115) hide show
  1. package/dist/{cli-errors-By1iVE3z.mjs → cli-errors-D3_sMh2K.mjs} +2 -3
  2. package/dist/{cli-errors-By1iVE3z.mjs.map → cli-errors-D3_sMh2K.mjs.map} +1 -1
  3. package/dist/{cli-errors-DDeVsP2Y.d.mts → cli-errors-QH8kf-C2.d.mts} +0 -2
  4. package/dist/cli.mjs +12 -76
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/client-0ZX24FXF.mjs +1398 -0
  7. package/dist/client-0ZX24FXF.mjs.map +1 -0
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +2 -4
  10. package/dist/commands/contract-infer.d.mts.map +1 -1
  11. package/dist/commands/contract-infer.mjs +2 -4
  12. package/dist/commands/db-init.d.mts.map +1 -1
  13. package/dist/commands/db-init.mjs +11 -11
  14. package/dist/commands/db-init.mjs.map +1 -1
  15. package/dist/commands/db-schema.d.mts.map +1 -1
  16. package/dist/commands/db-schema.mjs +5 -7
  17. package/dist/commands/db-schema.mjs.map +1 -1
  18. package/dist/commands/db-sign.d.mts.map +1 -1
  19. package/dist/commands/db-sign.mjs +8 -9
  20. package/dist/commands/db-sign.mjs.map +1 -1
  21. package/dist/commands/db-update.d.mts.map +1 -1
  22. package/dist/commands/db-update.mjs +11 -11
  23. package/dist/commands/db-update.mjs.map +1 -1
  24. package/dist/commands/db-verify.d.mts.map +1 -1
  25. package/dist/commands/db-verify.mjs +1 -321
  26. package/dist/commands/migration-apply.d.mts.map +1 -1
  27. package/dist/commands/migration-apply.mjs +16 -17
  28. package/dist/commands/migration-apply.mjs.map +1 -1
  29. package/dist/commands/migration-new.d.mts +0 -1
  30. package/dist/commands/migration-new.d.mts.map +1 -1
  31. package/dist/commands/migration-new.mjs +10 -11
  32. package/dist/commands/migration-new.mjs.map +1 -1
  33. package/dist/commands/migration-plan.d.mts.map +1 -1
  34. package/dist/commands/migration-plan.mjs +1 -345
  35. package/dist/commands/migration-ref.d.mts +1 -1
  36. package/dist/commands/migration-ref.d.mts.map +1 -1
  37. package/dist/commands/migration-ref.mjs +5 -6
  38. package/dist/commands/migration-ref.mjs.map +1 -1
  39. package/dist/commands/migration-show.d.mts +1 -1
  40. package/dist/commands/migration-show.d.mts.map +1 -1
  41. package/dist/commands/migration-show.mjs +13 -13
  42. package/dist/commands/migration-show.mjs.map +1 -1
  43. package/dist/commands/migration-status.d.mts.map +1 -1
  44. package/dist/commands/migration-status.mjs +2 -4
  45. package/dist/{config-loader-ih8ViDb_.mjs → config-loader-B6sJjXTv.mjs} +2 -4
  46. package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
  47. package/dist/config-loader.d.mts +0 -1
  48. package/dist/config-loader.d.mts.map +1 -1
  49. package/dist/config-loader.mjs +2 -3
  50. package/dist/{contract-emit-CnTXVVbF.mjs → contract-emit-B3ChISB_.mjs} +22 -13
  51. package/dist/contract-emit-B3ChISB_.mjs.map +1 -0
  52. package/dist/{contract-emit-CcZr3HS9.mjs → contract-emit-DkMqO7f2.mjs} +8 -10
  53. package/dist/contract-emit-DkMqO7f2.mjs.map +1 -0
  54. package/dist/{contract-enrichment-xDeJBC-o.mjs → contract-enrichment-CF6ogEJ_.mjs} +2 -2
  55. package/dist/contract-enrichment-CF6ogEJ_.mjs.map +1 -0
  56. package/dist/{contract-infer-sER84Le-.mjs → contract-infer-BDKAE0B0.mjs} +5 -7
  57. package/dist/{contract-infer-sER84Le-.mjs.map → contract-infer-BDKAE0B0.mjs.map} +1 -1
  58. package/dist/db-verify-B4TdDKOI.mjs +403 -0
  59. package/dist/db-verify-B4TdDKOI.mjs.map +1 -0
  60. package/dist/exports/config-types.mjs +1 -2
  61. package/dist/exports/control-api.d.mts +202 -7
  62. package/dist/exports/control-api.d.mts.map +1 -1
  63. package/dist/exports/control-api.mjs +4 -6
  64. package/dist/exports/index.d.mts.map +1 -1
  65. package/dist/exports/index.mjs +28 -30
  66. package/dist/exports/index.mjs.map +1 -1
  67. package/dist/exports/init-output.d.mts +2 -4
  68. package/dist/exports/init-output.d.mts.map +1 -1
  69. package/dist/exports/init-output.mjs +2 -3
  70. package/dist/{framework-components-Bgcre3Z6.mjs → framework-components-gwAHl7ml.mjs} +3 -4
  71. package/dist/{framework-components-Bgcre3Z6.mjs.map → framework-components-gwAHl7ml.mjs.map} +1 -1
  72. package/dist/{init-DC4sL4Rp.mjs → init-Deo7U8_U.mjs} +13 -30
  73. package/dist/init-Deo7U8_U.mjs.map +1 -0
  74. package/dist/{inspect-live-schema-BQN21nNO.mjs → inspect-live-schema-BAgQMYpD.mjs} +7 -8
  75. package/dist/inspect-live-schema-BAgQMYpD.mjs.map +1 -0
  76. package/dist/migration-cli.d.mts +0 -1
  77. package/dist/migration-cli.d.mts.map +1 -1
  78. package/dist/migration-cli.mjs +2 -3
  79. package/dist/migration-cli.mjs.map +1 -1
  80. package/dist/{migration-command-scaffold-DLmYGRug.mjs → migration-command-scaffold-B8J702Uh.mjs} +7 -8
  81. package/dist/migration-command-scaffold-B8J702Uh.mjs.map +1 -0
  82. package/dist/migration-plan-BcKNnTM7.mjs +530 -0
  83. package/dist/migration-plan-BcKNnTM7.mjs.map +1 -0
  84. package/dist/{migration-status-CDW4RDsO.mjs → migration-status-CjwB2of-.mjs} +10 -14
  85. package/dist/migration-status-CjwB2of-.mjs.map +1 -0
  86. package/dist/{migrations-MEoKMiV5.mjs → migrations-CIK94AJf.mjs} +3 -4
  87. package/dist/migrations-CIK94AJf.mjs.map +1 -0
  88. package/dist/{output-BpcQrnnq.mjs → output-DnjfCC_u.mjs} +9 -3
  89. package/dist/output-DnjfCC_u.mjs.map +1 -0
  90. package/dist/{progress-adapter-DgRGldpT.mjs → progress-adapter-xASh41wr.mjs} +2 -2
  91. package/dist/{progress-adapter-DgRGldpT.mjs.map → progress-adapter-xASh41wr.mjs.map} +1 -1
  92. package/dist/{result-handler-Ch6hVnOo.mjs → result-handler-DWb1rFS-.mjs} +20 -10
  93. package/dist/result-handler-DWb1rFS-.mjs.map +1 -0
  94. package/dist/{terminal-ui-u2YgKghu.mjs → terminal-ui-zaRDhJnP.mjs} +2 -6
  95. package/dist/{terminal-ui-u2YgKghu.mjs.map → terminal-ui-zaRDhJnP.mjs.map} +1 -1
  96. package/dist/{verify-BT9tgCOH.mjs → verify-BEIa9638.mjs} +3 -4
  97. package/dist/verify-BEIa9638.mjs.map +1 -0
  98. package/package.json +17 -17
  99. package/dist/client-hUCMXFE_.mjs +0 -1031
  100. package/dist/client-hUCMXFE_.mjs.map +0 -1
  101. package/dist/commands/db-verify.mjs.map +0 -1
  102. package/dist/commands/migration-plan.mjs.map +0 -1
  103. package/dist/config-loader-ih8ViDb_.mjs.map +0 -1
  104. package/dist/contract-emit-BkRH9lGt.mjs +0 -4
  105. package/dist/contract-emit-CcZr3HS9.mjs.map +0 -1
  106. package/dist/contract-emit-CnTXVVbF.mjs.map +0 -1
  107. package/dist/contract-enrichment-xDeJBC-o.mjs.map +0 -1
  108. package/dist/init-DC4sL4Rp.mjs.map +0 -1
  109. package/dist/inspect-live-schema-BQN21nNO.mjs.map +0 -1
  110. package/dist/migration-command-scaffold-DLmYGRug.mjs.map +0 -1
  111. package/dist/migration-status-CDW4RDsO.mjs.map +0 -1
  112. package/dist/migrations-MEoKMiV5.mjs.map +0 -1
  113. package/dist/output-BpcQrnnq.mjs.map +0 -1
  114. package/dist/result-handler-Ch6hVnOo.mjs.map +0 -1
  115. package/dist/verify-BT9tgCOH.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"db-update.mjs","names":["exhaustive: never"],"sources":["../../src/commands/db-update.ts"],"sourcesContent":["import { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { ContractValidationError } from '../control-api/errors';\nimport type { DbUpdateFailure } from '../control-api/types';\nimport {\n CliStructuredError,\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorContractValidationFailed,\n errorDestructiveChanges,\n errorMigrationPlanningFailed,\n errorRunnerFailed,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport type { MigrationCommandOptions } from '../utils/command-helpers';\nimport {\n sanitizeErrorMessage,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport {\n formatMigrationApplyOutput,\n formatMigrationJson,\n formatMigrationPlanOutput,\n type MigrationCommandResult,\n} from '../utils/formatters/migrations';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport {\n addMigrationCommandOptions,\n prepareMigrationContext,\n} from '../utils/migration-command-scaffold';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ntype DbUpdateOptions = MigrationCommandOptions;\n\n/**\n * Maps a DbUpdateFailure to a CliStructuredError for consistent error handling.\n */\nfunction mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {\n if (failure.code === 'PLANNING_FAILED') {\n return errorMigrationPlanningFailed({ conflicts: failure.conflicts ?? [] });\n }\n\n if (failure.code === 'RUNNER_FAILED') {\n return errorRunnerFailed(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n if (failure.code === 'DESTRUCTIVE_CHANGES') {\n return errorDestructiveChanges(failure.summary, {\n ...ifDefined('why', failure.why),\n fix: 'Re-run with `-y` to apply destructive changes, or use `--dry-run` to preview first',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n const exhaustive: never = failure.code;\n throw new Error(`Unhandled DbUpdateFailure code: ${exhaustive}`);\n}\n\n/**\n * Executes the db update command and returns a structured Result.\n */\nasync function executeDbUpdateCommand(\n options: DbUpdateOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationCommandResult, CliStructuredError>> {\n // Prepare shared migration context (config, contract, connection, client)\n const ctxResult = await prepareMigrationContext(options, flags, ui, {\n commandName: 'db update',\n description: 'Update your database schema to match your contract',\n url: 'https://pris.ly/db-update',\n });\n if (!ctxResult.ok) {\n return ctxResult;\n }\n const { client, contractJson, dbConnection, onProgress, contractPathAbsolute } = ctxResult.value;\n\n try {\n // Call dbUpdate with connection and progress callback\n const result = await client.dbUpdate({\n contract: contractJson,\n mode: options.dryRun ? 'plan' : 'apply',\n connection: dbConnection,\n ...(flags.yes ? { acceptDataLoss: true } : {}),\n onProgress,\n });\n\n // Handle failures by mapping to CLI structured error\n if (!result.ok) {\n return notOk(mapDbUpdateFailure(result.failure));\n }\n\n // Convert success result to CLI output format\n const dbUpdateResult: MigrationCommandResult = {\n ok: true,\n mode: result.value.mode,\n plan: {\n targetId: ctxResult.value.config.target.targetId,\n destination: {\n storageHash: result.value.destination.storageHash,\n ...ifDefined('profileHash', result.value.destination.profileHash),\n },\n operations: result.value.plan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n ...ifDefined('preview', result.value.plan.preview),\n },\n ...ifDefined(\n 'execution',\n result.value.execution\n ? {\n operationsPlanned: result.value.execution.operationsPlanned,\n operationsExecuted: result.value.execution.operationsExecuted,\n }\n : undefined,\n ),\n ...ifDefined(\n 'marker',\n result.value.marker\n ? {\n storageHash: result.value.marker.storageHash,\n ...ifDefined('profileHash', result.value.marker.profileHash),\n }\n : undefined,\n ),\n summary: result.value.summary,\n timings: { total: Date.now() - startTime },\n };\n\n return ok(dbUpdateResult);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during db update: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createDbUpdateCommand(): Command {\n const command = new Command('update');\n setCommandDescriptions(\n command,\n 'Update your database schema to match your contract',\n 'Compares your database schema to the emitted contract and applies the necessary\\n' +\n 'changes. Works on any database, whether or not it has been initialized with `db init`.\\n' +\n 'Destructive operations prompt for confirmation in interactive mode. Use -y to\\n' +\n 'auto-accept or --dry-run to preview first.',\n );\n setCommandExamples(command, [\n 'prisma-next db update --db $DATABASE_URL',\n 'prisma-next db update --db $DATABASE_URL --dry-run',\n ]);\n addMigrationCommandOptions(command);\n command.action(async (options: DbUpdateOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n let result = await executeDbUpdateCommand(options, flags, ui, startTime);\n\n // Interactive confirmation for destructive operations:\n // When the control API rejects destructive changes, prompt the user instead of failing.\n // In non-interactive mode (CI, piped, --no-interactive, --json), the error is returned as-is.\n if (\n !result.ok &&\n result.failure.code === ERROR_CODE_DESTRUCTIVE_CHANGES &&\n flags.interactive &&\n !flags.json &&\n !flags.yes\n ) {\n const meta = result.failure.meta as\n | { destructiveOperations?: readonly { id: string; label: string }[] }\n | undefined;\n const destructiveOps = meta?.destructiveOperations ?? [];\n\n if (destructiveOps.length > 0) {\n ui.warn(\n `${destructiveOps.length} destructive operation(s) that may cause data loss:\\n${destructiveOps.map((op) => ` ${ui.yellow('▸')} ${op.label}`).join('\\n')}`,\n );\n }\n\n const confirmed = await ui.confirm('Apply destructive changes? This cannot be undone.');\n\n if (confirmed) {\n result = await executeDbUpdateCommand(options, { ...flags, yes: true }, ui, Date.now());\n }\n }\n\n const exitCode = handleResult(result, flags, ui, (dbUpdateResult) => {\n if (flags.json) {\n ui.output(formatMigrationJson(dbUpdateResult));\n } else {\n const output =\n dbUpdateResult.mode === 'plan'\n ? formatMigrationPlanOutput(dbUpdateResult, flags)\n : formatMigrationApplyOutput(dbUpdateResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"db-update.mjs","names":[],"sources":["../../src/commands/db-update.ts"],"sourcesContent":["import { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { ContractValidationError } from '../control-api/errors';\nimport type { DbUpdateFailure } from '../control-api/types';\nimport {\n CliStructuredError,\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorContractValidationFailed,\n errorDestructiveChanges,\n errorMigrationPlanningFailed,\n errorRunnerFailed,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport type { MigrationCommandOptions } from '../utils/command-helpers';\nimport {\n resolveMigrationPaths,\n sanitizeErrorMessage,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport {\n formatMigrationApplyOutput,\n formatMigrationJson,\n formatMigrationPlanOutput,\n type MigrationCommandResult,\n} from '../utils/formatters/migrations';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport {\n addMigrationCommandOptions,\n prepareMigrationContext,\n} from '../utils/migration-command-scaffold';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ntype DbUpdateOptions = MigrationCommandOptions;\n\n/**\n * Maps a DbUpdateFailure to a CliStructuredError for consistent error handling.\n */\nfunction mapDbUpdateFailure(failure: DbUpdateFailure): CliStructuredError {\n if (failure.code === 'PLANNING_FAILED') {\n return errorMigrationPlanningFailed({ conflicts: failure.conflicts ?? [] });\n }\n\n if (failure.code === 'RUNNER_FAILED') {\n return errorRunnerFailed(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Inspect the reported conflict, reconcile schema drift if needed, then re-run `prisma-next db update`',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n if (failure.code === 'DESTRUCTIVE_CHANGES') {\n return errorDestructiveChanges(failure.summary, {\n ...ifDefined('why', failure.why),\n fix: 'Re-run with `-y` to apply destructive changes, or use `--dry-run` to preview first',\n ...ifDefined('meta', failure.meta),\n });\n }\n\n const exhaustive: never = failure.code;\n throw new Error(`Unhandled DbUpdateFailure code: ${exhaustive}`);\n}\n\n/**\n * Executes the db update command and returns a structured Result.\n */\nasync function executeDbUpdateCommand(\n options: DbUpdateOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationCommandResult, CliStructuredError>> {\n // Prepare shared migration context (config, contract, connection, client)\n const ctxResult = await prepareMigrationContext(options, flags, ui, {\n commandName: 'db update',\n description: 'Update your database schema to match your contract',\n url: 'https://pris.ly/db-update',\n });\n if (!ctxResult.ok) {\n return ctxResult;\n }\n const { client, config, contractJson, dbConnection, onProgress, contractPathAbsolute } =\n ctxResult.value;\n const { migrationsDir } = resolveMigrationPaths(options.config, config);\n\n try {\n await client.connect(dbConnection);\n\n const result = await client.dbUpdate({\n contract: contractJson,\n mode: options.dryRun ? 'plan' : 'apply',\n migrationsDir,\n ...(flags.yes ? { acceptDataLoss: true } : {}),\n onProgress,\n });\n\n // Handle failures by mapping to CLI structured error\n if (!result.ok) {\n return notOk(mapDbUpdateFailure(result.failure));\n }\n\n // Convert success result to CLI output format\n const dbUpdateResult: MigrationCommandResult = {\n ok: true,\n mode: result.value.mode,\n plan: {\n targetId: ctxResult.value.config.target.targetId,\n destination: {\n storageHash: result.value.destination.storageHash,\n ...ifDefined('profileHash', result.value.destination.profileHash),\n },\n operations: result.value.plan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n ...ifDefined('preview', result.value.plan.preview),\n },\n ...ifDefined(\n 'execution',\n result.value.execution\n ? {\n operationsPlanned: result.value.execution.operationsPlanned,\n operationsExecuted: result.value.execution.operationsExecuted,\n }\n : undefined,\n ),\n ...ifDefined(\n 'marker',\n result.value.marker\n ? {\n storageHash: result.value.marker.storageHash,\n ...ifDefined('profileHash', result.value.marker.profileHash),\n }\n : undefined,\n ),\n summary: result.value.summary,\n timings: { total: Date.now() - startTime },\n };\n\n return ok(dbUpdateResult);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n if (error instanceof ContractValidationError) {\n return notOk(\n errorContractValidationFailed(`Contract validation failed: ${error.message}`, {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during db update: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createDbUpdateCommand(): Command {\n const command = new Command('update');\n setCommandDescriptions(\n command,\n 'Update your database schema to match your contract',\n 'Compares your database schema to the emitted contract and applies the necessary\\n' +\n 'changes. Works on any database, whether or not it has been initialized with `db init`.\\n' +\n 'Destructive operations prompt for confirmation in interactive mode. Use -y to\\n' +\n 'auto-accept or --dry-run to preview first.',\n );\n setCommandExamples(command, [\n 'prisma-next db update --db $DATABASE_URL',\n 'prisma-next db update --db $DATABASE_URL --dry-run',\n ]);\n addMigrationCommandOptions(command);\n command.action(async (options: DbUpdateOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n let result = await executeDbUpdateCommand(options, flags, ui, startTime);\n\n // Interactive confirmation for destructive operations:\n // When the control API rejects destructive changes, prompt the user instead of failing.\n // In non-interactive mode (CI, piped, --no-interactive, --json), the error is returned as-is.\n if (\n !result.ok &&\n result.failure.code === ERROR_CODE_DESTRUCTIVE_CHANGES &&\n flags.interactive &&\n !flags.json &&\n !flags.yes\n ) {\n const meta = result.failure.meta as\n | { destructiveOperations?: readonly { id: string; label: string }[] }\n | undefined;\n const destructiveOps = meta?.destructiveOperations ?? [];\n\n if (destructiveOps.length > 0) {\n ui.warn(\n `${destructiveOps.length} destructive operation(s) that may cause data loss:\\n${destructiveOps.map((op) => ` ${ui.yellow('▸')} ${op.label}`).join('\\n')}`,\n );\n }\n\n const confirmed = await ui.confirm('Apply destructive changes? This cannot be undone.');\n\n if (confirmed) {\n result = await executeDbUpdateCommand(options, { ...flags, yes: true }, ui, Date.now());\n }\n }\n\n const exitCode = handleResult(result, flags, ui, (dbUpdateResult) => {\n if (flags.json) {\n ui.output(formatMigrationJson(dbUpdateResult));\n } else {\n const output =\n dbUpdateResult.mode === 'plan'\n ? formatMigrationPlanOutput(dbUpdateResult, flags)\n : formatMigrationApplyOutput(dbUpdateResult, flags);\n if (output) {\n ui.log(output);\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"db-verify.d.mts","names":[],"sources":["../../src/commands/db-verify.ts"],"sourcesContent":[],"mappings":";;;iBAmcgB,qBAAA,CAAA,GAAyB"}
1
+ {"version":3,"file":"db-verify.d.mts","names":[],"sources":["../../src/commands/db-verify.ts"],"mappings":";;;iBAmegB,qBAAA,CAAA,GAAyB,OAAA"}
@@ -1,322 +1,2 @@
1
- import { t as loadConfig } from "../config-loader-ih8ViDb_.mjs";
2
- import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, d as errorMarkerMissing, g as errorTargetMismatch, l as errorFileNotFound, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, u as errorHashMismatch } from "../cli-errors-By1iVE3z.mjs";
3
- import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
- import { c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, n as addGlobalOptions, o as maskConnectionUrl, t as handleResult, y as formatStyledHeader } from "../result-handler-Ch6hVnOo.mjs";
5
- import { t as createProgressAdapter } from "../progress-adapter-DgRGldpT.mjs";
6
- import { n as ContractValidationError, t as createControlClient } from "../client-hUCMXFE_.mjs";
7
- import { c as formatVerifyOutput, i as formatSchemaVerifyOutput, r as formatSchemaVerifyJson, s as formatVerifyJson } from "../verify-BT9tgCOH.mjs";
8
- import { Command } from "commander";
9
- import { ifDefined } from "@prisma-next/utils/defined";
10
- import { notOk, ok } from "@prisma-next/utils/result";
11
- import { relative, resolve } from "pathe";
12
- import { readFile } from "node:fs/promises";
13
- import { VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
14
-
15
- //#region src/commands/db-verify.ts
16
- /**
17
- * Maps a VerifyDatabaseResult failure to a CliStructuredError.
18
- */
19
- function mapVerifyFailure(verifyResult) {
20
- if (!verifyResult.ok && verifyResult.code) {
21
- if (verifyResult.code === VERIFY_CODE_MARKER_MISSING) return errorMarkerMissing();
22
- if (verifyResult.code === VERIFY_CODE_HASH_MISMATCH) {
23
- const storageMatch = verifyResult.marker?.storageHash === verifyResult.contract.storageHash;
24
- const profileMatch = !verifyResult.contract.profileHash || verifyResult.marker?.profileHash === verifyResult.contract.profileHash;
25
- if (!storageMatch) return errorHashMismatch({
26
- why: "Contract storageHash does not match database marker",
27
- expected: verifyResult.contract.storageHash,
28
- ...ifDefined("actual", verifyResult.marker?.storageHash)
29
- });
30
- return errorHashMismatch({
31
- why: profileMatch ? "Contract hash does not match database marker" : "Contract profileHash does not match database marker",
32
- ...ifDefined("expected", verifyResult.contract.profileHash),
33
- ...ifDefined("actual", verifyResult.marker?.profileHash)
34
- });
35
- }
36
- if (verifyResult.code === VERIFY_CODE_TARGET_MISMATCH) return errorTargetMismatch(verifyResult.target.expected, verifyResult.target.actual ?? "unknown");
37
- }
38
- return errorRuntime(verifyResult.summary);
39
- }
40
- function errorInvalidVerifyMode(options) {
41
- return new CliStructuredError("4012", "Invalid verify mode", {
42
- domain: "CLI",
43
- why: options.why,
44
- fix: options.fix,
45
- docsUrl: "https://pris.ly/db-verify"
46
- });
47
- }
48
- function resolveDbVerifyMode(options) {
49
- if (options.markerOnly && options.schemaOnly) return notOk(errorInvalidVerifyMode({
50
- why: "`--marker-only` and `--schema-only` cannot be used together",
51
- fix: "Choose one mode: omit both to check the marker and schema, use `--marker-only` to check only the marker, or use `--schema-only` to check only the live schema."
52
- }));
53
- if (options.markerOnly && options.strict) return notOk(errorInvalidVerifyMode({
54
- why: "`--strict` requires schema verification, but `--marker-only` skips it",
55
- fix: "Remove `--strict`, or use `db verify` / `db verify --schema-only` when you want to check the live schema in strict mode."
56
- }));
57
- if (options.schemaOnly) return ok("schema-only");
58
- if (options.markerOnly) return ok("marker-only");
59
- return ok("full");
60
- }
61
- function formatDbVerifyModeLabel(mode, strict) {
62
- if (mode === "marker-only") return "marker only";
63
- if (mode === "schema-only") return `schema only (${strict ? "strict" : "tolerant"})`;
64
- return `full (marker + schema, ${strict ? "strict" : "tolerant"})`;
65
- }
66
- function formatDbVerifyInvocation(mode, strict) {
67
- const args = ["db verify"];
68
- if (mode === "marker-only") args.push("--marker-only");
69
- if (mode === "schema-only") args.push("--schema-only");
70
- if (strict) args.push("--strict");
71
- return args.join(" ");
72
- }
73
- function createDbVerifyConnectionRequiredError(options) {
74
- const invocation = formatDbVerifyInvocation(options.mode, options.strict);
75
- return errorDatabaseConnectionRequired({
76
- why: `Database connection is required for ${invocation} (set db.connection in ${options.configPath}, or pass --db <url>)`,
77
- retryCommand: `prisma-next ${invocation} --db <url>`
78
- });
79
- }
80
- function renderVerifyHeader(paths, options, mode, flags, ui) {
81
- if (flags.json || flags.quiet) return;
82
- const description = mode === "schema-only" ? "Check whether the live database schema matches your contract" : mode === "marker-only" ? "Check whether the database marker matches your contract" : "Check whether the database marker and live schema match your contract";
83
- const details = [
84
- {
85
- label: "config",
86
- value: paths.configPath
87
- },
88
- {
89
- label: "contract",
90
- value: paths.contractPath
91
- },
92
- {
93
- label: "mode",
94
- value: formatDbVerifyModeLabel(mode, options.strict ?? false)
95
- }
96
- ];
97
- if (options.db) details.push({
98
- label: "database",
99
- value: maskConnectionUrl(options.db)
100
- });
101
- ui.stderr(formatStyledHeader({
102
- command: "db verify",
103
- description,
104
- url: "https://pris.ly/db-verify",
105
- details,
106
- flags
107
- }));
108
- }
109
- async function resolveVerifyPaths(options) {
110
- const config = await loadConfig(options.config);
111
- const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
112
- const contractPathAbsolute = resolveContractPath(config);
113
- return {
114
- config,
115
- configPath,
116
- contractPathAbsolute,
117
- contractPath: relative(process.cwd(), contractPathAbsolute)
118
- };
119
- }
120
- async function resolveVerifySetup(paths, options, mode) {
121
- const { config, configPath, contractPathAbsolute, contractPath } = paths;
122
- let contractJsonContent;
123
- try {
124
- contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
125
- } catch (error) {
126
- if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
127
- why: `Contract file not found at ${contractPathAbsolute}`,
128
- fix: `Run \`prisma-next contract emit\` to generate ${contractPath}, or update \`config.contract.output\` in ${configPath}`
129
- }));
130
- return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}` }));
131
- }
132
- let contractJson;
133
- try {
134
- contractJson = JSON.parse(contractJsonContent);
135
- } catch (error) {
136
- return notOk(errorContractValidationFailed(`Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
137
- }
138
- const dbConnection = options.db ?? config.db?.connection;
139
- if (typeof dbConnection !== "string" || dbConnection.length === 0) return notOk(createDbVerifyConnectionRequiredError({
140
- configPath,
141
- mode,
142
- strict: options.strict ?? false
143
- }));
144
- if (!config.driver) return notOk(errorDriverRequired({ why: `Config.driver is required for ${formatDbVerifyInvocation(mode, options.strict ?? false)}` }));
145
- return ok({
146
- ...paths,
147
- contractJson,
148
- dbConnection
149
- });
150
- }
151
- function createVerifyClient(setup) {
152
- return createControlClient({
153
- family: setup.config.family,
154
- target: setup.config.target,
155
- adapter: setup.config.adapter,
156
- driver: setup.config.driver,
157
- extensionPacks: setup.config.extensionPacks ?? []
158
- });
159
- }
160
- function wrapVerifyError(error, contractPathAbsolute, modeLabel) {
161
- if (error instanceof CliStructuredError) return notOk(error);
162
- if (error instanceof ContractValidationError) return notOk(errorContractValidationFailed(`Contract validation failed: ${error.message}`, { where: { path: contractPathAbsolute } }));
163
- return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Unexpected error during ${modeLabel}: ${error instanceof Error ? error.message : String(error)}` }));
164
- }
165
- /**
166
- * Executes the db verify command and returns a structured Result.
167
- */
168
- async function executeDbVerifyCommand(options, flags, ui, mode) {
169
- const startTime = Date.now();
170
- const paths = await resolveVerifyPaths(options);
171
- renderVerifyHeader(paths, options, mode, flags, ui);
172
- const setupResult = await resolveVerifySetup(paths, options, mode);
173
- if (!setupResult.ok) return setupResult;
174
- const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
175
- const client = createVerifyClient(setupResult.value);
176
- const onProgress = createProgressAdapter({
177
- ui,
178
- flags
179
- });
180
- try {
181
- const verifyResult = await client.verify({
182
- contract: contractJson,
183
- connection: dbConnection,
184
- onProgress
185
- });
186
- if (!verifyResult.ok) return notOk(mapVerifyFailure(verifyResult));
187
- if (mode === "marker-only") return ok({
188
- ok: true,
189
- mode: "marker-only",
190
- summary: "Database marker matches contract",
191
- contract: verifyResult.contract,
192
- marker: verifyResult.marker,
193
- target: verifyResult.target,
194
- ...ifDefined("missingCodecs", verifyResult.missingCodecs),
195
- ...ifDefined("codecCoverageSkipped", verifyResult.codecCoverageSkipped),
196
- warning: "Schema verification skipped because --marker-only was provided",
197
- meta: {
198
- ...verifyResult.meta ?? {},
199
- schemaVerification: "skipped"
200
- },
201
- timings: { total: Date.now() - startTime }
202
- });
203
- const schemaVerifyResult = await client.schemaVerify({
204
- contract: contractJson,
205
- strict: options.strict ?? false,
206
- onProgress
207
- });
208
- if (!schemaVerifyResult.ok) return notOk(schemaVerifyResult);
209
- return ok({
210
- ok: true,
211
- mode: "full",
212
- summary: "Database marker and schema match contract",
213
- contract: verifyResult.contract,
214
- marker: verifyResult.marker,
215
- target: verifyResult.target,
216
- ...ifDefined("missingCodecs", verifyResult.missingCodecs),
217
- ...ifDefined("codecCoverageSkipped", verifyResult.codecCoverageSkipped),
218
- schema: {
219
- summary: schemaVerifyResult.summary,
220
- counts: schemaVerifyResult.schema.counts,
221
- strict: schemaVerifyResult.meta?.strict ?? false
222
- },
223
- meta: {
224
- ...verifyResult.meta ?? {},
225
- schemaVerification: "performed"
226
- },
227
- timings: { total: Date.now() - startTime }
228
- });
229
- } catch (error) {
230
- return wrapVerifyError(error, contractPathAbsolute, "db verify");
231
- } finally {
232
- await client.close();
233
- }
234
- }
235
- async function executeDbSchemaOnlyVerifyCommand(options, flags, ui) {
236
- const paths = await resolveVerifyPaths(options);
237
- renderVerifyHeader(paths, options, "schema-only", flags, ui);
238
- const setupResult = await resolveVerifySetup(paths, options, "schema-only");
239
- if (!setupResult.ok) return setupResult;
240
- const { contractJson, dbConnection, contractPathAbsolute } = setupResult.value;
241
- const client = createVerifyClient(setupResult.value);
242
- const onProgress = createProgressAdapter({
243
- ui,
244
- flags
245
- });
246
- try {
247
- return ok(await client.schemaVerify({
248
- contract: contractJson,
249
- strict: options.strict ?? false,
250
- connection: dbConnection,
251
- onProgress
252
- }));
253
- } catch (error) {
254
- return wrapVerifyError(error, contractPathAbsolute, "db verify --schema-only");
255
- } finally {
256
- await client.close();
257
- }
258
- }
259
- function createDbVerifyCommand() {
260
- const command = new Command("verify");
261
- setCommandDescriptions(command, "Check whether the database marker and live schema match your contract", "Verifies the database marker first, then checks the database schema matches your contract.\nUse `--marker-only` for marker-only verification, `--schema-only` to skip marker checks and\ninspect only the live schema, and `--strict` to fail if the database includes elements\nnot present in the contract.");
262
- setCommandExamples(command, [
263
- "prisma-next db verify --db $DATABASE_URL",
264
- "prisma-next db verify --db $DATABASE_URL --strict",
265
- "prisma-next db verify --db $DATABASE_URL --schema-only",
266
- "prisma-next db verify --db $DATABASE_URL --schema-only --strict",
267
- "prisma-next db verify --db $DATABASE_URL --marker-only",
268
- "prisma-next db verify --db $DATABASE_URL --json"
269
- ]);
270
- addGlobalOptions(command).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--marker-only", "Skip schema verification and only check the database marker").option("--schema-only", "Skip marker verification and only check whether the live schema satisfies the contract").option("--strict", "Strict mode: schema elements not present in the contract are considered an error", false).action(async (options) => {
271
- const flags = parseGlobalFlags(options);
272
- const ui = new TerminalUI({
273
- color: flags.color,
274
- interactive: flags.interactive
275
- });
276
- const modeResult = resolveDbVerifyMode(options);
277
- if (!modeResult.ok) {
278
- const exitCode = handleResult(modeResult, flags, ui);
279
- process.exit(exitCode);
280
- }
281
- const mode = modeResult.value;
282
- if (mode === "schema-only") {
283
- const result$1 = await executeDbSchemaOnlyVerifyCommand(options, flags, ui);
284
- const exitCode = handleResult(result$1, flags, ui, (schemaVerifyResult) => {
285
- if (flags.json) ui.output(formatSchemaVerifyJson(schemaVerifyResult));
286
- else {
287
- const output = formatSchemaVerifyOutput(schemaVerifyResult, flags);
288
- if (output) ui.log(output);
289
- }
290
- });
291
- if (result$1.ok && !result$1.value.ok) process.exit(1);
292
- process.exit(exitCode);
293
- }
294
- const result = await executeDbVerifyCommand(options, flags, ui, mode);
295
- if (result.ok) {
296
- if (flags.json) ui.output(formatVerifyJson(result.value));
297
- else {
298
- const output = formatVerifyOutput(result.value, flags);
299
- if (output) ui.log(output);
300
- }
301
- process.exit(0);
302
- }
303
- if (CliStructuredError.is(result.failure)) {
304
- const exitCode = handleResult(result, flags, ui);
305
- process.exit(exitCode);
306
- }
307
- if (flags.json) ui.output(formatSchemaVerifyJson(result.failure));
308
- else {
309
- const output = formatSchemaVerifyOutput(result.failure, {
310
- ...flags,
311
- quiet: false
312
- });
313
- if (output) ui.log(output);
314
- }
315
- process.exit(1);
316
- });
317
- return command;
318
- }
319
-
320
- //#endregion
1
+ import { t as createDbVerifyCommand } from "../db-verify-B4TdDKOI.mjs";
321
2
  export { createDbVerifyCommand };
322
- //# sourceMappingURL=db-verify.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-apply.d.mts","names":[],"sources":["../../src/commands/migration-apply.ts"],"sourcesContent":[],"mappings":";;;UAqDiB,oBAAA;;EAAA,SAAA,iBAAoB,EAAA,MAAA;EA+WrB,SAAA,eAAA,EAAA,MAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA3B,2BAAA,CAAA,GAA+B"}
1
+ {"version":3,"file":"migration-apply.d.mts","names":[],"sources":["../../src/commands/migration-apply.ts"],"mappings":";;;UAqDiB,oBAAA;EAAA,SACN,EAAA;EAAA,SACA,iBAAA;EAAA,SACA,eAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA;IAAA,SACE,OAAA;IAAA,SACA,IAAA;IAAA,SACA,EAAA;IAAA,SACA,kBAAA;EAAA;EAAA,SAEF,OAAA;EAAA,SACA,YAAA;IAAA,SACE,QAAA;IAAA,SACA,MAAA;IAAA,SACA,gBAAA;IAAA,SACA,eAAA;IAAA,SACA,OAAA;IAAA,SACA,kBAAA;IAAA,SACA,mBAAA;IAAA,SACA,YAAA;MAAA,SACE,OAAA;MAAA,SACA,aAAA;MAAA,SACA,IAAA;MAAA,SACA,EAAA;MAAA,SACA,UAAA;IAAA;EAAA;EAAA,SAGJ,OAAA;IAAA,SACE,KAAA;EAAA;AAAA;AAAA,iBAkVG,2BAAA,CAAA,GAA+B,OAAA"}
@@ -1,9 +1,9 @@
1
- import { t as loadConfig } from "../config-loader-ih8ViDb_.mjs";
2
- import { _ as errorUnexpected, c as errorDriverRequired, h as errorTargetMigrationNotSupported, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, v as mapMigrationToolsError } from "../cli-errors-By1iVE3z.mjs";
3
- import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
- import { a as loadMigrationPackages, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, h as toStructuralEdge, l as resolveMigrationPaths, m as toPathDecisionResult, n as addGlobalOptions, o as maskConnectionUrl, p as targetSupportsMigrations, r as collectDeclaredInvariants, s as readContractEnvelope, t as handleResult, y as formatStyledHeader } from "../result-handler-Ch6hVnOo.mjs";
5
- import { t as createControlClient } from "../client-hUCMXFE_.mjs";
6
- import { t as formatMigrationApplyCommandOutput } from "../migrations-MEoKMiV5.mjs";
1
+ import { t as loadConfig } from "../config-loader-B6sJjXTv.mjs";
2
+ import { _ as errorUnexpected, c as errorDriverRequired, h as errorTargetMigrationNotSupported, m as errorRuntime, o as errorDatabaseConnectionRequired, t as CliStructuredError, v as mapMigrationToolsError } from "../cli-errors-D3_sMh2K.mjs";
3
+ import { t as TerminalUI } from "../terminal-ui-zaRDhJnP.mjs";
4
+ import { a as loadMigrationPackages, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, h as toStructuralEdge, l as resolveMigrationPaths, m as toPathDecisionResult, n as addGlobalOptions, o as maskConnectionUrl, p as targetSupportsMigrations, r as collectDeclaredInvariants, s as readContractEnvelope, t as handleResult, y as formatStyledHeader } from "../result-handler-DWb1rFS-.mjs";
5
+ import { t as createControlClient } from "../client-0ZX24FXF.mjs";
6
+ import { t as formatMigrationApplyCommandOutput } from "../migrations-CIK94AJf.mjs";
7
7
  import { Command } from "commander";
8
8
  import { ifDefined } from "@prisma-next/utils/defined";
9
9
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -11,7 +11,6 @@ import { findPathWithDecision } from "@prisma-next/migration-tools/migration-gra
11
11
  import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
12
12
  import { MigrationToolsError, errorNoInvariantPath, errorUnknownInvariant } from "@prisma-next/migration-tools/errors";
13
13
  import { readRefs, resolveRef } from "@prisma-next/migration-tools/refs";
14
-
15
14
  //#region src/commands/migration-apply.ts
16
15
  function mapApplyFailure(failure) {
17
16
  return errorRuntime(failure.summary, {
@@ -32,7 +31,7 @@ function packageToStep(pkg) {
32
31
  }
33
32
  async function executeMigrationApplyCommand(options, flags, ui, startTime) {
34
33
  const config = await loadConfig(options.config);
35
- const { configPath, migrationsDir, migrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
34
+ const { configPath, appMigrationsDir, appMigrationsRelative, refsDir } = resolveMigrationPaths(options.config, config);
36
35
  const dbConnection = options.db ?? config.db?.connection;
37
36
  if (!dbConnection) return notOk(errorDatabaseConnectionRequired({
38
37
  why: `Database connection is required for migration apply (set db.connection in ${configPath}, or pass --db <url>)`,
@@ -64,7 +63,7 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
64
63
  value: configPath
65
64
  }, {
66
65
  label: "migrations",
67
- value: migrationsRelative
66
+ value: appMigrationsRelative
68
67
  }];
69
68
  if (typeof dbConnection === "string") details.push({
70
69
  label: "database",
@@ -85,7 +84,7 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
85
84
  }
86
85
  let migrations;
87
86
  try {
88
- migrations = await loadMigrationPackages(migrationsDir);
87
+ migrations = await loadMigrationPackages(appMigrationsDir);
89
88
  } catch (error) {
90
89
  if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
91
90
  throw error;
@@ -113,19 +112,19 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
113
112
  }
114
113
  if (migrations.bundles.length === 0) {
115
114
  if (marker?.storageHash) return notOk(errorRuntime("Database has state but no migrations exist", {
116
- why: `The database marker hash "${marker.storageHash}" exists but no migrations were found in ${migrationsRelative}`,
115
+ why: `The database marker hash "${marker.storageHash}" exists but no migrations were found in ${appMigrationsRelative}`,
117
116
  fix: "Ensure the migrations directory is correct. If the database was managed with `db init` or `db update`, run `prisma-next db sign` to update the marker.",
118
117
  meta: {
119
118
  markerHash: marker.storageHash,
120
- migrationsDir: migrationsRelative
119
+ migrationsDir: appMigrationsRelative
121
120
  }
122
121
  }));
123
122
  if (destinationHash !== EMPTY_CONTRACT_HASH) return notOk(errorRuntime("Current contract has no planned migrations", {
124
- why: `No migrations were found in ${migrationsRelative}, but current contract hash is "${destinationHash}"`,
123
+ why: `No migrations were found in ${appMigrationsRelative}, but current contract hash is "${destinationHash}"`,
125
124
  fix: "Run `prisma-next migration plan` to create a migration for the current contract.",
126
125
  meta: {
127
126
  destinationHash,
128
- migrationsDir: migrationsRelative
127
+ migrationsDir: appMigrationsRelative
129
128
  }
130
129
  }));
131
130
  return ok({
@@ -145,7 +144,7 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
145
144
  }));
146
145
  const markerHash = marker?.storageHash;
147
146
  if (markerHash !== void 0 && !migrations.graph.nodes.has(markerHash)) return notOk(errorRuntime("Database marker does not match any known migration", {
148
- why: `The database marker hash "${markerHash}" is not found in the migration history at ${migrationsRelative}`,
147
+ why: `The database marker hash "${markerHash}" is not found in the migration history at ${appMigrationsRelative}`,
149
148
  fix: "Ensure the migrations directory matches this database. If the database was managed with `db init` or `db update`, run `prisma-next db sign` to update the marker.",
150
149
  meta: {
151
150
  markerHash,
@@ -153,7 +152,7 @@ async function executeMigrationApplyCommand(options, flags, ui, startTime) {
153
152
  }
154
153
  }));
155
154
  if (!migrations.graph.nodes.has(destinationHash)) return notOk(errorRuntime("Current contract has no planned migration path", {
156
- why: `Current contract hash "${destinationHash}" is not present in the migration history at ${migrationsRelative}`,
155
+ why: `Current contract hash "${destinationHash}" is not present in the migration history at ${appMigrationsRelative}`,
157
156
  fix: "Run `prisma-next migration plan` to create a migration for the current contract, then re-run apply.",
158
157
  meta: {
159
158
  destinationHash,
@@ -246,7 +245,7 @@ function createMigrationApplyCommand() {
246
245
  });
247
246
  return command;
248
247
  }
249
-
250
248
  //#endregion
251
249
  export { createMigrationApplyCommand };
250
+
252
251
  //# sourceMappingURL=migration-apply.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-apply.mjs","names":["refEntry: RefEntry | undefined","envelopeHash: string | undefined","details: Array<{ label: string; value: string }>","migrations: Awaited<ReturnType<typeof loadMigrationPackages>>","pendingMigrations: MigrationApplyStep[]"],"sources":["../../src/commands/migration-apply.ts"],"sourcesContent":["import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport {\n errorNoInvariantPath,\n errorUnknownInvariant,\n MigrationToolsError,\n} from '@prisma-next/migration-tools/errors';\nimport { findPathWithDecision } from '@prisma-next/migration-tools/migration-graph';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport type { RefEntry } from '@prisma-next/migration-tools/refs';\nimport { readRefs, resolveRef } from '@prisma-next/migration-tools/refs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\n\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type { MigrationApplyFailure, MigrationApplyStep } from '../control-api/types';\nimport {\n CliStructuredError,\n type CliStructuredError as CliStructuredErrorType,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n collectDeclaredInvariants,\n loadMigrationPackages,\n maskConnectionUrl,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n targetSupportsMigrations,\n toPathDecisionResult,\n toStructuralEdge,\n} from '../utils/command-helpers';\nimport { formatMigrationApplyCommandOutput } 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 MigrationApplyCommandOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly ref?: string;\n}\n\nexport interface MigrationApplyResult {\n readonly ok: boolean;\n readonly migrationsApplied: number;\n readonly migrationsTotal: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly dirName: string;\n readonly from: string | null;\n readonly to: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n readonly pathDecision?: {\n readonly fromHash: string;\n readonly toHash: string;\n readonly alternativeCount: number;\n readonly tieBreakReasons: readonly string[];\n readonly refName?: string;\n readonly requiredInvariants: readonly string[];\n readonly satisfiedInvariants: readonly string[];\n readonly selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly invariants: readonly string[];\n }[];\n };\n readonly timings: {\n readonly total: number;\n };\n}\n\nfunction mapApplyFailure(failure: MigrationApplyFailure): CliStructuredErrorType {\n return errorRuntime(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Fix the issue and re-run `prisma-next migration apply` — previously applied migrations are preserved.',\n meta: failure.meta ?? {},\n });\n}\n\nfunction packageToStep(pkg: OnDiskMigrationPackage): MigrationApplyStep {\n return {\n dirName: pkg.dirName,\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n toContract: pkg.metadata.toContract,\n operations: pkg.ops,\n providedInvariants: pkg.metadata.providedInvariants,\n };\n}\n\nasync function executeMigrationApplyCommand(\n options: MigrationApplyCommandOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationApplyResult, CliStructuredErrorType>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for migration apply (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'migration apply',\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: 'Config.driver is required for migration apply',\n }),\n );\n }\n\n if (!targetSupportsMigrations(config.target)) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n let refEntry: RefEntry | undefined;\n let envelopeHash: string | undefined;\n const refName = options.ref;\n\n if (refName) {\n try {\n const refs = await readRefs(refsDir);\n refEntry = resolveRef(refs, refName);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n } else {\n try {\n const envelope = await readContractEnvelope(config);\n envelopeHash = envelope.storageHash;\n } catch (error) {\n return notOk(\n errorRuntime('Current contract is unavailable', {\n why: `Failed to read contract: ${error instanceof Error ? error.message : String(error)}`,\n fix: 'Run `prisma-next contract emit` to generate a valid contract.json, then retry apply.',\n }),\n );\n }\n }\n const destinationHash = refEntry?.hash ?? envelopeHash!;\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 (typeof dbConnection === 'string') {\n details.push({\n label: 'database',\n value: maskConnectionUrl(dbConnection),\n });\n }\n if (refName) {\n details.push({ label: 'ref', value: refName });\n }\n const header = formatStyledHeader({\n command: 'migration apply',\n description: 'Apply planned migrations to the database',\n url: 'https://pris.ly/migration-apply',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Read migrations and build migration chain model (offline — no DB needed)\n let migrations: Awaited<ReturnType<typeof loadMigrationPackages>>;\n try {\n migrations = await loadMigrationPackages(migrationsDir);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n try {\n await client.connect(dbConnection);\n const marker = await client.readMarker();\n\n // Pre-check unknown invariants against `(declared by graph) ∪\n // (already on the marker)`. The union catches the edge case where the\n // ref carries an invariant whose declaring migration was retired (e.g.\n // history rewritten) but whose id is recorded on the marker —\n // surfacing that as MIGRATION.UNKNOWN_INVARIANT would be misleading\n // because the database has already satisfied the requirement, so the\n // marker-subtraction below empties `effectiveRequired` and apply\n // short-circuits to \"Already up to date\".\n if (refEntry && refEntry.invariants.length > 0) {\n const declared = collectDeclaredInvariants(migrations.graph);\n const known = new Set<string>(declared);\n for (const id of marker?.invariants ?? []) known.add(id);\n const unknown = refEntry.invariants.filter((id) => !known.has(id));\n if (unknown.length > 0) {\n return notOk(\n mapMigrationToolsError(\n errorUnknownInvariant({\n ...ifDefined('refName', refName),\n unknown,\n declared: [...declared].sort(),\n }),\n ),\n );\n }\n }\n\n // --- No migrations on disk ---\n if (migrations.bundles.length === 0) {\n if (marker?.storageHash) {\n return notOk(\n errorRuntime('Database has state but no migrations exist', {\n why: `The database marker hash \"${marker.storageHash}\" exists but no migrations were found in ${migrationsRelative}`,\n fix: 'Ensure the migrations directory is correct. If the database was managed with `db init` or `db update`, run `prisma-next db sign` to update the marker.',\n meta: { markerHash: marker.storageHash, migrationsDir: migrationsRelative },\n }),\n );\n }\n // Non-empty contract + no migrations = user needs to plan first.\n if (destinationHash !== EMPTY_CONTRACT_HASH) {\n return notOk(\n errorRuntime('Current contract has no planned migrations', {\n why: `No migrations were found in ${migrationsRelative}, but current contract hash is \"${destinationHash}\"`,\n fix: 'Run `prisma-next migration plan` to create a migration for the current contract.',\n meta: { destinationHash, migrationsDir: migrationsRelative },\n }),\n );\n }\n // Empty contract + no migrations = nothing to do.\n return ok({\n ok: true,\n migrationsApplied: 0,\n migrationsTotal: 0,\n markerHash: EMPTY_CONTRACT_HASH,\n applied: [],\n summary: 'No migrations found',\n timings: { total: Date.now() - startTime },\n });\n }\n\n // --- Validate marker state ---\n\n // The empty sentinel should never appear in a real marker row — if it does,\n // the marker was corrupted and replaying all migrations would be dangerous.\n if (marker?.storageHash === EMPTY_CONTRACT_HASH) {\n return notOk(\n errorRuntime('Database marker contains the empty sentinel hash', {\n why: `The marker row exists but contains the empty sentinel value \"${EMPTY_CONTRACT_HASH}\". This should never happen — the marker should contain the hash of the last applied contract.`,\n fix: 'The marker is corrupted. Run `prisma-next db sign` to overwrite it with the correct contract hash, or drop and recreate the database.',\n meta: { markerHash: EMPTY_CONTRACT_HASH },\n }),\n );\n }\n\n const markerHash = marker?.storageHash;\n\n if (markerHash !== undefined && !migrations.graph.nodes.has(markerHash)) {\n return notOk(\n errorRuntime('Database marker does not match any known migration', {\n why: `The database marker hash \"${markerHash}\" is not found in the migration history at ${migrationsRelative}`,\n fix: 'Ensure the migrations directory matches this database. If the database was managed with `db init` or `db update`, run `prisma-next db sign` to update the marker.',\n meta: { markerHash, knownNodes: [...migrations.graph.nodes] },\n }),\n );\n }\n\n if (!migrations.graph.nodes.has(destinationHash)) {\n return notOk(\n errorRuntime('Current contract has no planned migration path', {\n why: `Current contract hash \"${destinationHash}\" is not present in the migration history at ${migrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration for the current contract, then re-run apply.',\n meta: { destinationHash, knownNodes: [...migrations.graph.nodes] },\n }),\n );\n }\n\n // \"No marker\" means the database is fresh — start from the empty contract hash.\n const originHash = markerHash ?? EMPTY_CONTRACT_HASH;\n\n const appliedInvariants = new Set(marker?.invariants ?? []);\n const effectiveRequired = new Set(\n (refEntry?.invariants ?? []).filter((id) => !appliedInvariants.has(id)),\n );\n\n const outcome = findPathWithDecision(migrations.graph, originHash, destinationHash, {\n ...ifDefined('refName', refName),\n required: effectiveRequired,\n });\n if (outcome.kind === 'unsatisfiable') {\n return notOk(\n mapMigrationToolsError(\n errorNoInvariantPath({\n ...ifDefined('refName', refName),\n required: [...effectiveRequired].sort(),\n missing: outcome.missing,\n structuralPath: outcome.structuralPath.map(toStructuralEdge),\n }),\n ),\n );\n }\n if (outcome.kind === 'unreachable') {\n return notOk(\n errorRuntime('No migration path from current state to target', {\n why: `Cannot find a path from \"${originHash}\" to target \"${destinationHash}\"`,\n fix: 'Check the migration history for gaps or inconsistencies.',\n meta: { markerHash: originHash, destinationHash },\n }),\n );\n }\n\n const pathDecision = toPathDecisionResult(outcome.decision);\n\n if (outcome.decision.selectedPath.length === 0) {\n return ok({\n ok: true,\n migrationsApplied: 0,\n migrationsTotal: 0,\n markerHash: originHash,\n applied: [],\n summary: 'Already up to date',\n pathDecision,\n timings: { total: Date.now() - startTime },\n });\n }\n\n const bundleByDir = new Map(migrations.bundles.map((b) => [b.dirName, b]));\n const pendingMigrations: MigrationApplyStep[] = [];\n for (const migration of outcome.decision.selectedPath) {\n const pkg = bundleByDir.get(migration.dirName);\n if (!pkg) {\n return notOk(\n errorRuntime(`Migration package not found: ${migration.dirName}`, {\n why: `The migration directory for path segment ${migration.from} → ${migration.to} was not found`,\n fix: 'Ensure all migration directories are present and intact.',\n }),\n );\n }\n pendingMigrations.push(packageToStep(pkg));\n }\n\n if (!flags.quiet && !flags.json) {\n for (const migration of pendingMigrations) {\n ui.step(`Pending ${migration.dirName}`);\n }\n }\n\n const applyResult = await client.migrationApply({\n originHash,\n destinationHash,\n pendingMigrations,\n });\n\n if (!applyResult.ok) {\n return notOk(mapApplyFailure(applyResult.failure));\n }\n\n const { value } = applyResult;\n\n return ok({\n ok: true,\n migrationsApplied: value.migrationsApplied,\n migrationsTotal: outcome.decision.selectedPath.length,\n markerHash: value.markerHash,\n applied: value.applied,\n summary: value.summary,\n pathDecision,\n timings: { total: Date.now() - startTime },\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during migration apply: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createMigrationApplyCommand(): Command {\n const command = new Command('apply');\n setCommandDescriptions(\n command,\n 'Apply planned migrations to the database',\n 'Applies previously planned migrations (created by `migration plan`) to a live database.\\n' +\n 'Compares the database marker against the migration history to determine which\\n' +\n 'migrations are pending, then executes them sequentially. Each migration runs\\n' +\n 'in its own transaction. Does not plan new migrations — run `migration plan` first.',\n );\n setCommandExamples(command, ['prisma-next migration apply --db $DATABASE_URL']);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--ref <name>', 'Target ref name from migrations/refs/')\n .action(async (options: MigrationApplyCommandOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({\n color: flags.color,\n interactive: flags.interactive,\n });\n\n const result = await executeMigrationApplyCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (applyResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(applyResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationApplyCommandOutput(applyResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsFA,SAAS,gBAAgB,SAAwD;AAC/E,QAAO,aAAa,QAAQ,SAAS;EACnC,KAAK,QAAQ,OAAO;EACpB,KAAK;EACL,MAAM,QAAQ,QAAQ,EAAE;EACzB,CAAC;;AAGJ,SAAS,cAAc,KAAiD;AACtE,QAAO;EACL,SAAS,IAAI;EACb,MAAM,IAAI,SAAS;EACnB,IAAI,IAAI,SAAS;EACjB,YAAY,IAAI,SAAS;EACzB,YAAY,IAAI;EAChB,oBAAoB,IAAI,SAAS;EAClC;;AAGH,eAAe,6BACb,SACA,OACA,IACA,WAC+D;CAC/D,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,EAAE,YAAY,eAAe,oBAAoB,YAAY,sBACjE,QAAQ,QACR,OACD;CAED,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,6EAA6E,WAAW;EAC7F,aAAa;EACd,CAAC,CACH;AAGH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAClB,KAAK,iDACN,CAAC,CACH;AAGH,KAAI,CAAC,yBAAyB,OAAO,OAAO,CAC1C,QAAO,MACL,iCAAiC,EAC/B,KAAK,WAAW,OAAO,OAAO,GAAG,gCAClC,CAAC,CACH;CAGH,IAAIA;CACJ,IAAIC;CACJ,MAAM,UAAU,QAAQ;AAExB,KAAI,QACF,KAAI;AAEF,aAAW,WADE,MAAM,SAAS,QAAQ,EACR,QAAQ;UAC7B,OAAO;AACd,MAAI,oBAAoB,GAAG,MAAM,CAC/B,QAAO,MAAM,uBAAuB,MAAM,CAAC;AAE7C,QAAM;;KAGR,KAAI;AAEF,kBADiB,MAAM,qBAAqB,OAAO,EAC3B;UACjB,OAAO;AACd,SAAO,MACL,aAAa,mCAAmC;GAC9C,KAAK,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACvF,KAAK;GACN,CAAC,CACH;;CAGL,MAAM,kBAAkB,UAAU,QAAQ;AAE1C,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMC,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,EACtC;GAAE,OAAO;GAAc,OAAO;GAAoB,CACnD;AACD,MAAI,OAAO,iBAAiB,SAC1B,SAAQ,KAAK;GACX,OAAO;GACP,OAAO,kBAAkB,aAAa;GACvC,CAAC;AAEJ,MAAI,QACF,SAAQ,KAAK;GAAE,OAAO;GAAO,OAAO;GAAS,CAAC;EAEhD,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb,KAAK;GACL;GACA;GACD,CAAC;AACF,KAAG,OAAO,OAAO;;CAInB,IAAIC;AACJ,KAAI;AACF,eAAa,MAAM,sBAAsB,cAAc;UAChD,OAAO;AACd,MAAI,oBAAoB,GAAG,MAAM,CAC/B,QAAO,MAAM,uBAAuB,MAAM,CAAC;AAE7C,QAAM;;CAGR,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;AAEF,KAAI;AACF,QAAM,OAAO,QAAQ,aAAa;EAClC,MAAM,SAAS,MAAM,OAAO,YAAY;AAUxC,MAAI,YAAY,SAAS,WAAW,SAAS,GAAG;GAC9C,MAAM,WAAW,0BAA0B,WAAW,MAAM;GAC5D,MAAM,QAAQ,IAAI,IAAY,SAAS;AACvC,QAAK,MAAM,MAAM,QAAQ,cAAc,EAAE,CAAE,OAAM,IAAI,GAAG;GACxD,MAAM,UAAU,SAAS,WAAW,QAAQ,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;AAClE,OAAI,QAAQ,SAAS,EACnB,QAAO,MACL,uBACE,sBAAsB;IACpB,GAAG,UAAU,WAAW,QAAQ;IAChC;IACA,UAAU,CAAC,GAAG,SAAS,CAAC,MAAM;IAC/B,CAAC,CACH,CACF;;AAKL,MAAI,WAAW,QAAQ,WAAW,GAAG;AACnC,OAAI,QAAQ,YACV,QAAO,MACL,aAAa,8CAA8C;IACzD,KAAK,6BAA6B,OAAO,YAAY,2CAA2C;IAChG,KAAK;IACL,MAAM;KAAE,YAAY,OAAO;KAAa,eAAe;KAAoB;IAC5E,CAAC,CACH;AAGH,OAAI,oBAAoB,oBACtB,QAAO,MACL,aAAa,8CAA8C;IACzD,KAAK,+BAA+B,mBAAmB,kCAAkC,gBAAgB;IACzG,KAAK;IACL,MAAM;KAAE;KAAiB,eAAe;KAAoB;IAC7D,CAAC,CACH;AAGH,UAAO,GAAG;IACR,IAAI;IACJ,mBAAmB;IACnB,iBAAiB;IACjB,YAAY;IACZ,SAAS,EAAE;IACX,SAAS;IACT,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;IAC3C,CAAC;;AAOJ,MAAI,QAAQ,gBAAgB,oBAC1B,QAAO,MACL,aAAa,oDAAoD;GAC/D,KAAK,gEAAgE,oBAAoB;GACzF,KAAK;GACL,MAAM,EAAE,YAAY,qBAAqB;GAC1C,CAAC,CACH;EAGH,MAAM,aAAa,QAAQ;AAE3B,MAAI,eAAe,UAAa,CAAC,WAAW,MAAM,MAAM,IAAI,WAAW,CACrE,QAAO,MACL,aAAa,sDAAsD;GACjE,KAAK,6BAA6B,WAAW,6CAA6C;GAC1F,KAAK;GACL,MAAM;IAAE;IAAY,YAAY,CAAC,GAAG,WAAW,MAAM,MAAM;IAAE;GAC9D,CAAC,CACH;AAGH,MAAI,CAAC,WAAW,MAAM,MAAM,IAAI,gBAAgB,CAC9C,QAAO,MACL,aAAa,kDAAkD;GAC7D,KAAK,0BAA0B,gBAAgB,+CAA+C;GAC9F,KAAK;GACL,MAAM;IAAE;IAAiB,YAAY,CAAC,GAAG,WAAW,MAAM,MAAM;IAAE;GACnE,CAAC,CACH;EAIH,MAAM,aAAa,cAAc;EAEjC,MAAM,oBAAoB,IAAI,IAAI,QAAQ,cAAc,EAAE,CAAC;EAC3D,MAAM,oBAAoB,IAAI,KAC3B,UAAU,cAAc,EAAE,EAAE,QAAQ,OAAO,CAAC,kBAAkB,IAAI,GAAG,CAAC,CACxE;EAED,MAAM,UAAU,qBAAqB,WAAW,OAAO,YAAY,iBAAiB;GAClF,GAAG,UAAU,WAAW,QAAQ;GAChC,UAAU;GACX,CAAC;AACF,MAAI,QAAQ,SAAS,gBACnB,QAAO,MACL,uBACE,qBAAqB;GACnB,GAAG,UAAU,WAAW,QAAQ;GAChC,UAAU,CAAC,GAAG,kBAAkB,CAAC,MAAM;GACvC,SAAS,QAAQ;GACjB,gBAAgB,QAAQ,eAAe,IAAI,iBAAiB;GAC7D,CAAC,CACH,CACF;AAEH,MAAI,QAAQ,SAAS,cACnB,QAAO,MACL,aAAa,kDAAkD;GAC7D,KAAK,4BAA4B,WAAW,eAAe,gBAAgB;GAC3E,KAAK;GACL,MAAM;IAAE,YAAY;IAAY;IAAiB;GAClD,CAAC,CACH;EAGH,MAAM,eAAe,qBAAqB,QAAQ,SAAS;AAE3D,MAAI,QAAQ,SAAS,aAAa,WAAW,EAC3C,QAAO,GAAG;GACR,IAAI;GACJ,mBAAmB;GACnB,iBAAiB;GACjB,YAAY;GACZ,SAAS,EAAE;GACX,SAAS;GACT;GACA,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAC3C,CAAC;EAGJ,MAAM,cAAc,IAAI,IAAI,WAAW,QAAQ,KAAK,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;EAC1E,MAAMC,oBAA0C,EAAE;AAClD,OAAK,MAAM,aAAa,QAAQ,SAAS,cAAc;GACrD,MAAM,MAAM,YAAY,IAAI,UAAU,QAAQ;AAC9C,OAAI,CAAC,IACH,QAAO,MACL,aAAa,gCAAgC,UAAU,WAAW;IAChE,KAAK,4CAA4C,UAAU,KAAK,KAAK,UAAU,GAAG;IAClF,KAAK;IACN,CAAC,CACH;AAEH,qBAAkB,KAAK,cAAc,IAAI,CAAC;;AAG5C,MAAI,CAAC,MAAM,SAAS,CAAC,MAAM,KACzB,MAAK,MAAM,aAAa,kBACtB,IAAG,KAAK,WAAW,UAAU,UAAU;EAI3C,MAAM,cAAc,MAAM,OAAO,eAAe;GAC9C;GACA;GACA;GACD,CAAC;AAEF,MAAI,CAAC,YAAY,GACf,QAAO,MAAM,gBAAgB,YAAY,QAAQ,CAAC;EAGpD,MAAM,EAAE,UAAU;AAElB,SAAO,GAAG;GACR,IAAI;GACJ,mBAAmB,MAAM;GACzB,iBAAiB,QAAQ,SAAS,aAAa;GAC/C,YAAY,MAAM;GAClB,SAAS,MAAM;GACf,SAAS,MAAM;GACf;GACA,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAC3C,CAAC;UACK,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;AAErB,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,4CAA4C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACxG,CAAC,CACH;WACO;AACR,QAAM,OAAO,OAAO;;;AAIxB,SAAgB,8BAAuC;CACrD,MAAM,UAAU,IAAI,QAAQ,QAAQ;AACpC,wBACE,SACA,4CACA,2UAID;AACD,oBAAmB,SAAS,CAAC,iDAAiD,CAAC;AAC/E,kBAAiB,QAAQ,CACtB,OAAO,cAAc,6BAA6B,CAClD,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,gBAAgB,wCAAwC,CAC/D,OAAO,OAAO,YAA0C;EACvD,MAAM,QAAQ,iBAAiB,QAAQ;EACvC,MAAM,YAAY,KAAK,KAAK;EAE5B,MAAM,KAAK,IAAI,WAAW;GACxB,OAAO,MAAM;GACb,aAAa,MAAM;GACpB,CAAC;EAIF,MAAM,WAAW,aAFF,MAAM,6BAA6B,SAAS,OAAO,IAAI,UAAU,EAE1C,OAAO,KAAK,gBAAgB;AAChE,OAAI,MAAM,KACR,IAAG,OAAO,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC;YACtC,CAAC,MAAM,MAChB,IAAG,IAAI,kCAAkC,aAAa,MAAM,CAAC;IAE/D;AAEF,UAAQ,KAAK,SAAS;GACtB;AAEJ,QAAO"}
1
+ {"version":3,"file":"migration-apply.mjs","names":[],"sources":["../../src/commands/migration-apply.ts"],"sourcesContent":["import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport {\n errorNoInvariantPath,\n errorUnknownInvariant,\n MigrationToolsError,\n} from '@prisma-next/migration-tools/errors';\nimport { findPathWithDecision } from '@prisma-next/migration-tools/migration-graph';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport type { RefEntry } from '@prisma-next/migration-tools/refs';\nimport { readRefs, resolveRef } from '@prisma-next/migration-tools/refs';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\n\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type { MigrationApplyFailure, MigrationApplyStep } from '../control-api/types';\nimport {\n CliStructuredError,\n type CliStructuredError as CliStructuredErrorType,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n collectDeclaredInvariants,\n loadMigrationPackages,\n maskConnectionUrl,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n targetSupportsMigrations,\n toPathDecisionResult,\n toStructuralEdge,\n} from '../utils/command-helpers';\nimport { formatMigrationApplyCommandOutput } 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 MigrationApplyCommandOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly ref?: string;\n}\n\nexport interface MigrationApplyResult {\n readonly ok: boolean;\n readonly migrationsApplied: number;\n readonly migrationsTotal: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly dirName: string;\n readonly from: string | null;\n readonly to: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n readonly pathDecision?: {\n readonly fromHash: string;\n readonly toHash: string;\n readonly alternativeCount: number;\n readonly tieBreakReasons: readonly string[];\n readonly refName?: string;\n readonly requiredInvariants: readonly string[];\n readonly satisfiedInvariants: readonly string[];\n readonly selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly invariants: readonly string[];\n }[];\n };\n readonly timings: {\n readonly total: number;\n };\n}\n\nfunction mapApplyFailure(failure: MigrationApplyFailure): CliStructuredErrorType {\n return errorRuntime(failure.summary, {\n why: failure.why ?? 'Migration runner failed',\n fix: 'Fix the issue and re-run `prisma-next migration apply` — previously applied migrations are preserved.',\n meta: failure.meta ?? {},\n });\n}\n\nfunction packageToStep(pkg: OnDiskMigrationPackage): MigrationApplyStep {\n return {\n dirName: pkg.dirName,\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n toContract: pkg.metadata.toContract,\n operations: pkg.ops,\n providedInvariants: pkg.metadata.providedInvariants,\n };\n}\n\nasync function executeMigrationApplyCommand(\n options: MigrationApplyCommandOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationApplyResult, CliStructuredErrorType>> {\n const config = await loadConfig(options.config);\n const { configPath, appMigrationsDir, appMigrationsRelative, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for migration apply (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'migration apply',\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: 'Config.driver is required for migration apply',\n }),\n );\n }\n\n if (!targetSupportsMigrations(config.target)) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n let refEntry: RefEntry | undefined;\n let envelopeHash: string | undefined;\n const refName = options.ref;\n\n if (refName) {\n try {\n const refs = await readRefs(refsDir);\n refEntry = resolveRef(refs, refName);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n } else {\n try {\n const envelope = await readContractEnvelope(config);\n envelopeHash = envelope.storageHash;\n } catch (error) {\n return notOk(\n errorRuntime('Current contract is unavailable', {\n why: `Failed to read contract: ${error instanceof Error ? error.message : String(error)}`,\n fix: 'Run `prisma-next contract emit` to generate a valid contract.json, then retry apply.',\n }),\n );\n }\n }\n const destinationHash = refEntry?.hash ?? envelopeHash!;\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (typeof dbConnection === 'string') {\n details.push({\n label: 'database',\n value: maskConnectionUrl(dbConnection),\n });\n }\n if (refName) {\n details.push({ label: 'ref', value: refName });\n }\n const header = formatStyledHeader({\n command: 'migration apply',\n description: 'Apply planned migrations to the database',\n url: 'https://pris.ly/migration-apply',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Read migrations and build migration chain model (offline — no DB needed)\n let migrations: Awaited<ReturnType<typeof loadMigrationPackages>>;\n try {\n migrations = await loadMigrationPackages(appMigrationsDir);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n try {\n await client.connect(dbConnection);\n const marker = await client.readMarker();\n\n // Pre-check unknown invariants against `(declared by graph) ∪\n // (already on the marker)`. The union catches the edge case where the\n // ref carries an invariant whose declaring migration was retired (e.g.\n // history rewritten) but whose id is recorded on the marker —\n // surfacing that as MIGRATION.UNKNOWN_INVARIANT would be misleading\n // because the database has already satisfied the requirement, so the\n // marker-subtraction below empties `effectiveRequired` and apply\n // short-circuits to \"Already up to date\".\n if (refEntry && refEntry.invariants.length > 0) {\n const declared = collectDeclaredInvariants(migrations.graph);\n const known = new Set<string>(declared);\n for (const id of marker?.invariants ?? []) known.add(id);\n const unknown = refEntry.invariants.filter((id) => !known.has(id));\n if (unknown.length > 0) {\n return notOk(\n mapMigrationToolsError(\n errorUnknownInvariant({\n ...ifDefined('refName', refName),\n unknown,\n declared: [...declared].sort(),\n }),\n ),\n );\n }\n }\n\n // --- No migrations on disk ---\n if (migrations.bundles.length === 0) {\n if (marker?.storageHash) {\n return notOk(\n errorRuntime('Database has state but no migrations exist', {\n why: `The database marker hash \"${marker.storageHash}\" exists but no migrations were found in ${appMigrationsRelative}`,\n fix: 'Ensure the migrations directory is correct. If the database was managed with `db init` or `db update`, run `prisma-next db sign` to update the marker.',\n meta: { markerHash: marker.storageHash, migrationsDir: appMigrationsRelative },\n }),\n );\n }\n // Non-empty contract + no migrations = user needs to plan first.\n if (destinationHash !== EMPTY_CONTRACT_HASH) {\n return notOk(\n errorRuntime('Current contract has no planned migrations', {\n why: `No migrations were found in ${appMigrationsRelative}, but current contract hash is \"${destinationHash}\"`,\n fix: 'Run `prisma-next migration plan` to create a migration for the current contract.',\n meta: { destinationHash, migrationsDir: appMigrationsRelative },\n }),\n );\n }\n // Empty contract + no migrations = nothing to do.\n return ok({\n ok: true,\n migrationsApplied: 0,\n migrationsTotal: 0,\n markerHash: EMPTY_CONTRACT_HASH,\n applied: [],\n summary: 'No migrations found',\n timings: { total: Date.now() - startTime },\n });\n }\n\n // --- Validate marker state ---\n\n // The empty sentinel should never appear in a real marker row — if it does,\n // the marker was corrupted and replaying all migrations would be dangerous.\n if (marker?.storageHash === EMPTY_CONTRACT_HASH) {\n return notOk(\n errorRuntime('Database marker contains the empty sentinel hash', {\n why: `The marker row exists but contains the empty sentinel value \"${EMPTY_CONTRACT_HASH}\". This should never happen — the marker should contain the hash of the last applied contract.`,\n fix: 'The marker is corrupted. Run `prisma-next db sign` to overwrite it with the correct contract hash, or drop and recreate the database.',\n meta: { markerHash: EMPTY_CONTRACT_HASH },\n }),\n );\n }\n\n const markerHash = marker?.storageHash;\n\n if (markerHash !== undefined && !migrations.graph.nodes.has(markerHash)) {\n return notOk(\n errorRuntime('Database marker does not match any known migration', {\n why: `The database marker hash \"${markerHash}\" is not found in the migration history at ${appMigrationsRelative}`,\n fix: 'Ensure the migrations directory matches this database. If the database was managed with `db init` or `db update`, run `prisma-next db sign` to update the marker.',\n meta: { markerHash, knownNodes: [...migrations.graph.nodes] },\n }),\n );\n }\n\n if (!migrations.graph.nodes.has(destinationHash)) {\n return notOk(\n errorRuntime('Current contract has no planned migration path', {\n why: `Current contract hash \"${destinationHash}\" is not present in the migration history at ${appMigrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration for the current contract, then re-run apply.',\n meta: { destinationHash, knownNodes: [...migrations.graph.nodes] },\n }),\n );\n }\n\n // \"No marker\" means the database is fresh — start from the empty contract hash.\n const originHash = markerHash ?? EMPTY_CONTRACT_HASH;\n\n const appliedInvariants = new Set(marker?.invariants ?? []);\n const effectiveRequired = new Set(\n (refEntry?.invariants ?? []).filter((id) => !appliedInvariants.has(id)),\n );\n\n const outcome = findPathWithDecision(migrations.graph, originHash, destinationHash, {\n ...ifDefined('refName', refName),\n required: effectiveRequired,\n });\n if (outcome.kind === 'unsatisfiable') {\n return notOk(\n mapMigrationToolsError(\n errorNoInvariantPath({\n ...ifDefined('refName', refName),\n required: [...effectiveRequired].sort(),\n missing: outcome.missing,\n structuralPath: outcome.structuralPath.map(toStructuralEdge),\n }),\n ),\n );\n }\n if (outcome.kind === 'unreachable') {\n return notOk(\n errorRuntime('No migration path from current state to target', {\n why: `Cannot find a path from \"${originHash}\" to target \"${destinationHash}\"`,\n fix: 'Check the migration history for gaps or inconsistencies.',\n meta: { markerHash: originHash, destinationHash },\n }),\n );\n }\n\n const pathDecision = toPathDecisionResult(outcome.decision);\n\n if (outcome.decision.selectedPath.length === 0) {\n return ok({\n ok: true,\n migrationsApplied: 0,\n migrationsTotal: 0,\n markerHash: originHash,\n applied: [],\n summary: 'Already up to date',\n pathDecision,\n timings: { total: Date.now() - startTime },\n });\n }\n\n const bundleByDir = new Map(migrations.bundles.map((b) => [b.dirName, b]));\n const pendingMigrations: MigrationApplyStep[] = [];\n for (const migration of outcome.decision.selectedPath) {\n const pkg = bundleByDir.get(migration.dirName);\n if (!pkg) {\n return notOk(\n errorRuntime(`Migration package not found: ${migration.dirName}`, {\n why: `The migration directory for path segment ${migration.from} → ${migration.to} was not found`,\n fix: 'Ensure all migration directories are present and intact.',\n }),\n );\n }\n pendingMigrations.push(packageToStep(pkg));\n }\n\n if (!flags.quiet && !flags.json) {\n for (const migration of pendingMigrations) {\n ui.step(`Pending ${migration.dirName}`);\n }\n }\n\n const applyResult = await client.migrationApply({\n originHash,\n destinationHash,\n pendingMigrations,\n });\n\n if (!applyResult.ok) {\n return notOk(mapApplyFailure(applyResult.failure));\n }\n\n const { value } = applyResult;\n\n return ok({\n ok: true,\n migrationsApplied: value.migrationsApplied,\n migrationsTotal: outcome.decision.selectedPath.length,\n markerHash: value.markerHash,\n applied: value.applied,\n summary: value.summary,\n pathDecision,\n timings: { total: Date.now() - startTime },\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during migration apply: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createMigrationApplyCommand(): Command {\n const command = new Command('apply');\n setCommandDescriptions(\n command,\n 'Apply planned migrations to the database',\n 'Applies previously planned migrations (created by `migration plan`) to a live database.\\n' +\n 'Compares the database marker against the migration history to determine which\\n' +\n 'migrations are pending, then executes them sequentially. Each migration runs\\n' +\n 'in its own transaction. Does not plan new migrations — run `migration plan` first.',\n );\n setCommandExamples(command, ['prisma-next migration apply --db $DATABASE_URL']);\n addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--ref <name>', 'Target ref name from migrations/refs/')\n .action(async (options: MigrationApplyCommandOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({\n color: flags.color,\n interactive: flags.interactive,\n });\n\n const result = await executeMigrationApplyCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (applyResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(applyResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationApplyCommandOutput(applyResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;AAsFA,SAAS,gBAAgB,SAAwD;CAC/E,OAAO,aAAa,QAAQ,SAAS;EACnC,KAAK,QAAQ,OAAO;EACpB,KAAK;EACL,MAAM,QAAQ,QAAQ,EAAE;EACzB,CAAC;;AAGJ,SAAS,cAAc,KAAiD;CACtE,OAAO;EACL,SAAS,IAAI;EACb,MAAM,IAAI,SAAS;EACnB,IAAI,IAAI,SAAS;EACjB,YAAY,IAAI,SAAS;EACzB,YAAY,IAAI;EAChB,oBAAoB,IAAI,SAAS;EAClC;;AAGH,eAAe,6BACb,SACA,OACA,IACA,WAC+D;CAC/D,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,EAAE,YAAY,kBAAkB,uBAAuB,YAAY,sBACvE,QAAQ,QACR,OACD;CAED,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;CAC9C,IAAI,CAAC,cACH,OAAO,MACL,gCAAgC;EAC9B,KAAK,6EAA6E,WAAW;EAC7F,aAAa;EACd,CAAC,CACH;CAGH,IAAI,CAAC,OAAO,QACV,OAAO,MACL,oBAAoB,EAClB,KAAK,iDACN,CAAC,CACH;CAGH,IAAI,CAAC,yBAAyB,OAAO,OAAO,EAC1C,OAAO,MACL,iCAAiC,EAC/B,KAAK,WAAW,OAAO,OAAO,GAAG,gCAClC,CAAC,CACH;CAGH,IAAI;CACJ,IAAI;CACJ,MAAM,UAAU,QAAQ;CAExB,IAAI,SACF,IAAI;EAEF,WAAW,WAAW,MADH,SAAS,QAAQ,EACR,QAAQ;UAC7B,OAAO;EACd,IAAI,oBAAoB,GAAG,MAAM,EAC/B,OAAO,MAAM,uBAAuB,MAAM,CAAC;EAE7C,MAAM;;MAGR,IAAI;EAEF,gBAAe,MADQ,qBAAqB,OAAO,EAC3B;UACjB,OAAO;EACd,OAAO,MACL,aAAa,mCAAmC;GAC9C,KAAK,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GACvF,KAAK;GACN,CAAC,CACH;;CAGL,MAAM,kBAAkB,UAAU,QAAQ;CAE1C,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAM,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,EACtC;GAAE,OAAO;GAAc,OAAO;GAAuB,CACtD;EACD,IAAI,OAAO,iBAAiB,UAC1B,QAAQ,KAAK;GACX,OAAO;GACP,OAAO,kBAAkB,aAAa;GACvC,CAAC;EAEJ,IAAI,SACF,QAAQ,KAAK;GAAE,OAAO;GAAO,OAAO;GAAS,CAAC;EAEhD,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb,KAAK;GACL;GACA;GACD,CAAC;EACF,GAAG,OAAO,OAAO;;CAInB,IAAI;CACJ,IAAI;EACF,aAAa,MAAM,sBAAsB,iBAAiB;UACnD,OAAO;EACd,IAAI,oBAAoB,GAAG,MAAM,EAC/B,OAAO,MAAM,uBAAuB,MAAM,CAAC;EAE7C,MAAM;;CAGR,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CAEF,IAAI;EACF,MAAM,OAAO,QAAQ,aAAa;EAClC,MAAM,SAAS,MAAM,OAAO,YAAY;EAUxC,IAAI,YAAY,SAAS,WAAW,SAAS,GAAG;GAC9C,MAAM,WAAW,0BAA0B,WAAW,MAAM;GAC5D,MAAM,QAAQ,IAAI,IAAY,SAAS;GACvC,KAAK,MAAM,MAAM,QAAQ,cAAc,EAAE,EAAE,MAAM,IAAI,GAAG;GACxD,MAAM,UAAU,SAAS,WAAW,QAAQ,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;GAClE,IAAI,QAAQ,SAAS,GACnB,OAAO,MACL,uBACE,sBAAsB;IACpB,GAAG,UAAU,WAAW,QAAQ;IAChC;IACA,UAAU,CAAC,GAAG,SAAS,CAAC,MAAM;IAC/B,CAAC,CACH,CACF;;EAKL,IAAI,WAAW,QAAQ,WAAW,GAAG;GACnC,IAAI,QAAQ,aACV,OAAO,MACL,aAAa,8CAA8C;IACzD,KAAK,6BAA6B,OAAO,YAAY,2CAA2C;IAChG,KAAK;IACL,MAAM;KAAE,YAAY,OAAO;KAAa,eAAe;KAAuB;IAC/E,CAAC,CACH;GAGH,IAAI,oBAAoB,qBACtB,OAAO,MACL,aAAa,8CAA8C;IACzD,KAAK,+BAA+B,sBAAsB,kCAAkC,gBAAgB;IAC5G,KAAK;IACL,MAAM;KAAE;KAAiB,eAAe;KAAuB;IAChE,CAAC,CACH;GAGH,OAAO,GAAG;IACR,IAAI;IACJ,mBAAmB;IACnB,iBAAiB;IACjB,YAAY;IACZ,SAAS,EAAE;IACX,SAAS;IACT,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;IAC3C,CAAC;;EAOJ,IAAI,QAAQ,gBAAgB,qBAC1B,OAAO,MACL,aAAa,oDAAoD;GAC/D,KAAK,gEAAgE,oBAAoB;GACzF,KAAK;GACL,MAAM,EAAE,YAAY,qBAAqB;GAC1C,CAAC,CACH;EAGH,MAAM,aAAa,QAAQ;EAE3B,IAAI,eAAe,KAAA,KAAa,CAAC,WAAW,MAAM,MAAM,IAAI,WAAW,EACrE,OAAO,MACL,aAAa,sDAAsD;GACjE,KAAK,6BAA6B,WAAW,6CAA6C;GAC1F,KAAK;GACL,MAAM;IAAE;IAAY,YAAY,CAAC,GAAG,WAAW,MAAM,MAAM;IAAE;GAC9D,CAAC,CACH;EAGH,IAAI,CAAC,WAAW,MAAM,MAAM,IAAI,gBAAgB,EAC9C,OAAO,MACL,aAAa,kDAAkD;GAC7D,KAAK,0BAA0B,gBAAgB,+CAA+C;GAC9F,KAAK;GACL,MAAM;IAAE;IAAiB,YAAY,CAAC,GAAG,WAAW,MAAM,MAAM;IAAE;GACnE,CAAC,CACH;EAIH,MAAM,aAAa,cAAc;EAEjC,MAAM,oBAAoB,IAAI,IAAI,QAAQ,cAAc,EAAE,CAAC;EAC3D,MAAM,oBAAoB,IAAI,KAC3B,UAAU,cAAc,EAAE,EAAE,QAAQ,OAAO,CAAC,kBAAkB,IAAI,GAAG,CAAC,CACxE;EAED,MAAM,UAAU,qBAAqB,WAAW,OAAO,YAAY,iBAAiB;GAClF,GAAG,UAAU,WAAW,QAAQ;GAChC,UAAU;GACX,CAAC;EACF,IAAI,QAAQ,SAAS,iBACnB,OAAO,MACL,uBACE,qBAAqB;GACnB,GAAG,UAAU,WAAW,QAAQ;GAChC,UAAU,CAAC,GAAG,kBAAkB,CAAC,MAAM;GACvC,SAAS,QAAQ;GACjB,gBAAgB,QAAQ,eAAe,IAAI,iBAAiB;GAC7D,CAAC,CACH,CACF;EAEH,IAAI,QAAQ,SAAS,eACnB,OAAO,MACL,aAAa,kDAAkD;GAC7D,KAAK,4BAA4B,WAAW,eAAe,gBAAgB;GAC3E,KAAK;GACL,MAAM;IAAE,YAAY;IAAY;IAAiB;GAClD,CAAC,CACH;EAGH,MAAM,eAAe,qBAAqB,QAAQ,SAAS;EAE3D,IAAI,QAAQ,SAAS,aAAa,WAAW,GAC3C,OAAO,GAAG;GACR,IAAI;GACJ,mBAAmB;GACnB,iBAAiB;GACjB,YAAY;GACZ,SAAS,EAAE;GACX,SAAS;GACT;GACA,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAC3C,CAAC;EAGJ,MAAM,cAAc,IAAI,IAAI,WAAW,QAAQ,KAAK,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;EAC1E,MAAM,oBAA0C,EAAE;EAClD,KAAK,MAAM,aAAa,QAAQ,SAAS,cAAc;GACrD,MAAM,MAAM,YAAY,IAAI,UAAU,QAAQ;GAC9C,IAAI,CAAC,KACH,OAAO,MACL,aAAa,gCAAgC,UAAU,WAAW;IAChE,KAAK,4CAA4C,UAAU,KAAK,KAAK,UAAU,GAAG;IAClF,KAAK;IACN,CAAC,CACH;GAEH,kBAAkB,KAAK,cAAc,IAAI,CAAC;;EAG5C,IAAI,CAAC,MAAM,SAAS,CAAC,MAAM,MACzB,KAAK,MAAM,aAAa,mBACtB,GAAG,KAAK,WAAW,UAAU,UAAU;EAI3C,MAAM,cAAc,MAAM,OAAO,eAAe;GAC9C;GACA;GACA;GACD,CAAC;EAEF,IAAI,CAAC,YAAY,IACf,OAAO,MAAM,gBAAgB,YAAY,QAAQ,CAAC;EAGpD,MAAM,EAAE,UAAU;EAElB,OAAO,GAAG;GACR,IAAI;GACJ,mBAAmB,MAAM;GACzB,iBAAiB,QAAQ,SAAS,aAAa;GAC/C,YAAY,MAAM;GAClB,SAAS,MAAM;GACf,SAAS,MAAM;GACf;GACA,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAC3C,CAAC;UACK,OAAO;EACd,IAAI,mBAAmB,GAAG,MAAM,EAC9B,OAAO,MAAM,MAAM;EAErB,OAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,4CAA4C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACxG,CAAC,CACH;WACO;EACR,MAAM,OAAO,OAAO;;;AAIxB,SAAgB,8BAAuC;CACrD,MAAM,UAAU,IAAI,QAAQ,QAAQ;CACpC,uBACE,SACA,4CACA,2UAID;CACD,mBAAmB,SAAS,CAAC,iDAAiD,CAAC;CAC/E,iBAAiB,QAAQ,CACtB,OAAO,cAAc,6BAA6B,CAClD,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,gBAAgB,wCAAwC,CAC/D,OAAO,OAAO,YAA0C;EACvD,MAAM,QAAQ,iBAAiB,QAAQ;EACvC,MAAM,YAAY,KAAK,KAAK;EAE5B,MAAM,KAAK,IAAI,WAAW;GACxB,OAAO,MAAM;GACb,aAAa,MAAM;GACpB,CAAC;EAIF,MAAM,WAAW,aAAa,MAFT,6BAA6B,SAAS,OAAO,IAAI,UAAU,EAE1C,OAAO,KAAK,gBAAgB;GAChE,IAAI,MAAM,MACR,GAAG,OAAO,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC;QAC1C,IAAI,CAAC,MAAM,OAChB,GAAG,IAAI,kCAAkC,aAAa,MAAM,CAAC;IAE/D;EAEF,QAAQ,KAAK,SAAS;GACtB;CAEJ,OAAO"}
@@ -1,7 +1,6 @@
1
1
  import { Command } from "commander";
2
2
 
3
3
  //#region src/commands/migration-new.d.ts
4
-
5
4
  declare function createMigrationNewCommand(): Command;
6
5
  //#endregion
7
6
  export { createMigrationNewCommand };
@@ -1 +1 @@
1
- {"version":3,"file":"migration-new.d.mts","names":[],"sources":["../../src/commands/migration-new.ts"],"sourcesContent":[],"mappings":";;;;iBAuQgB,yBAAA,CAAA,GAA6B"}
1
+ {"version":3,"file":"migration-new.d.mts","names":[],"sources":["../../src/commands/migration-new.ts"],"mappings":";;;iBAuQgB,yBAAA,CAAA,GAA6B,OAAA"}