@prisma-next/cli 0.5.0-dev.26 → 0.5.0-dev.27

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 (47) hide show
  1. package/dist/cli.mjs +2 -2
  2. package/dist/{client-enZIahga.mjs → client-CJT9lqBd.mjs} +12 -10
  3. package/dist/client-CJT9lqBd.mjs.map +1 -0
  4. package/dist/commands/contract-infer.mjs +1 -1
  5. package/dist/commands/db-init.mjs +3 -3
  6. package/dist/commands/db-schema.mjs +1 -1
  7. package/dist/commands/db-sign.mjs +1 -1
  8. package/dist/commands/db-update.mjs +3 -3
  9. package/dist/commands/db-verify.mjs +1 -1
  10. package/dist/commands/migration-apply.d.mts +1 -1
  11. package/dist/commands/migration-apply.mjs +2 -2
  12. package/dist/commands/migration-apply.mjs.map +1 -1
  13. package/dist/commands/migration-new.d.mts.map +1 -1
  14. package/dist/commands/migration-new.mjs +1 -3
  15. package/dist/commands/migration-new.mjs.map +1 -1
  16. package/dist/commands/migration-plan.d.mts +1 -1
  17. package/dist/commands/migration-plan.d.mts.map +1 -1
  18. package/dist/commands/migration-plan.mjs +1 -3
  19. package/dist/commands/migration-plan.mjs.map +1 -1
  20. package/dist/commands/migration-show.d.mts +1 -2
  21. package/dist/commands/migration-show.d.mts.map +1 -1
  22. package/dist/commands/migration-show.mjs +1 -2
  23. package/dist/commands/migration-show.mjs.map +1 -1
  24. package/dist/commands/migration-status.mjs +1 -1
  25. package/dist/{contract-infer-BjzkcwQt.mjs → contract-infer-CPQRrGmy.mjs} +2 -2
  26. package/dist/{contract-infer-BjzkcwQt.mjs.map → contract-infer-CPQRrGmy.mjs.map} +1 -1
  27. package/dist/exports/control-api.d.mts +2 -2
  28. package/dist/exports/control-api.mjs +1 -1
  29. package/dist/{inspect-live-schema-QklSDLt_.mjs → inspect-live-schema-CLchu1d-.mjs} +2 -2
  30. package/dist/{inspect-live-schema-QklSDLt_.mjs.map → inspect-live-schema-CLchu1d-.mjs.map} +1 -1
  31. package/dist/{migration-command-scaffold-BfloSWPZ.mjs → migration-command-scaffold-BP50SzoG.mjs} +2 -2
  32. package/dist/{migration-command-scaffold-BfloSWPZ.mjs.map → migration-command-scaffold-BP50SzoG.mjs.map} +1 -1
  33. package/dist/{migration-status-C5VYA5r9.mjs → migration-status-CMjpUefa.mjs} +2 -2
  34. package/dist/{migration-status-C5VYA5r9.mjs.map → migration-status-CMjpUefa.mjs.map} +1 -1
  35. package/dist/{migrations-CSaDHNpB.mjs → migrations-CYYmURZx.mjs} +2 -3
  36. package/dist/{migrations-CSaDHNpB.mjs.map → migrations-CYYmURZx.mjs.map} +1 -1
  37. package/package.json +14 -14
  38. package/src/commands/migration-apply.ts +1 -1
  39. package/src/commands/migration-new.ts +2 -4
  40. package/src/commands/migration-plan.ts +2 -4
  41. package/src/commands/migration-show.ts +1 -3
  42. package/src/control-api/operations/db-init.ts +3 -2
  43. package/src/control-api/operations/db-update.ts +3 -2
  44. package/src/control-api/operations/migration-apply.ts +14 -9
  45. package/src/control-api/types.ts +2 -2
  46. package/src/utils/formatters/migrations.ts +2 -4
  47. package/dist/client-enZIahga.mjs.map +0 -1
package/dist/cli.mjs CHANGED
@@ -4,7 +4,7 @@ import "./config-loader-ih8ViDb_.mjs";
4
4
  import { n as installShutdownHandlers } from "./terminal-ui-u2YgKghu.mjs";
5
5
  import { d as setCommandExamples, g as formatRootHelp, h as formatCommandHelp, m as parseGlobalFlags, n as addGlobalOptions, u as setCommandDescriptions } from "./result-handler-BmVh8AeV.mjs";
6
6
  import { t as createContractEmitCommand } from "./contract-emit-DWtGQYCD.mjs";
7
- import { t as createContractInferCommand } from "./contract-infer-BjzkcwQt.mjs";
7
+ import { t as createContractInferCommand } from "./contract-infer-CPQRrGmy.mjs";
8
8
  import { createDbInitCommand } from "./commands/db-init.mjs";
9
9
  import { createDbSchemaCommand } from "./commands/db-schema.mjs";
10
10
  import { createDbSignCommand } from "./commands/db-sign.mjs";
@@ -15,7 +15,7 @@ import { createMigrationNewCommand } from "./commands/migration-new.mjs";
15
15
  import { createMigrationPlanCommand } from "./commands/migration-plan.mjs";
16
16
  import { createMigrationRefCommand } from "./commands/migration-ref.mjs";
17
17
  import { createMigrationShowCommand } from "./commands/migration-show.mjs";
18
- import { t as createMigrationStatusCommand } from "./migration-status-C5VYA5r9.mjs";
18
+ import { t as createMigrationStatusCommand } from "./migration-status-CMjpUefa.mjs";
19
19
  import { Command } from "commander";
20
20
  import { distance } from "closest-match";
21
21
 
@@ -99,7 +99,7 @@ async function executeDbInit(options) {
99
99
  contract,
100
100
  schema: schemaIR,
101
101
  policy,
102
- fromHash: "",
102
+ fromHash: null,
103
103
  frameworkComponents
104
104
  });
105
105
  if (plannerResult.kind === "failure") {
@@ -308,7 +308,7 @@ async function executeDbUpdate(options) {
308
308
  contract,
309
309
  schema: schemaIR,
310
310
  policy,
311
- fromHash: "",
311
+ fromHash: null,
312
312
  frameworkComponents
313
313
  });
314
314
  if (plannerResult.kind === "failure") {
@@ -461,31 +461,33 @@ async function executeMigrationApply(options) {
461
461
  }
462
462
  const firstMigration = pendingMigrations[0];
463
463
  const lastMigration = pendingMigrations[pendingMigrations.length - 1];
464
- if (firstMigration.from !== originHash || lastMigration.to !== destinationHash) return notOk({
464
+ const firstFromMarker = firstMigration.from ?? EMPTY_CONTRACT_HASH;
465
+ if (firstFromMarker !== originHash || lastMigration.to !== destinationHash) return notOk({
465
466
  code: "MIGRATION_PATH_NOT_FOUND",
466
467
  summary: "Migration apply path does not match requested origin and destination",
467
- why: `Path resolved as ${firstMigration.from} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,
468
+ why: `Path resolved as ${firstFromMarker} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,
468
469
  meta: {
469
470
  originHash,
470
471
  destinationHash,
471
- pathOrigin: firstMigration.from,
472
+ pathOrigin: firstFromMarker,
472
473
  pathDestination: lastMigration.to
473
474
  }
474
475
  });
475
476
  for (let i = 1; i < pendingMigrations.length; i++) {
476
477
  const previous = pendingMigrations[i - 1];
477
478
  const current = pendingMigrations[i];
478
- if (previous.to !== current.from) return notOk({
479
+ const currentFromMarker = current.from ?? EMPTY_CONTRACT_HASH;
480
+ if (previous.to !== currentFromMarker) return notOk({
479
481
  code: "MIGRATION_PATH_NOT_FOUND",
480
482
  summary: "Migration apply path contains a discontinuity between adjacent migrations",
481
- why: `Migration "${previous.dirName}" ends at ${previous.to}, but next migration "${current.dirName}" starts at ${current.from}`,
483
+ why: `Migration "${previous.dirName}" ends at ${previous.to}, but next migration "${current.dirName}" starts at ${currentFromMarker}`,
482
484
  meta: {
483
485
  originHash,
484
486
  destinationHash,
485
487
  previousDirName: previous.dirName,
486
488
  previousTo: previous.to,
487
489
  currentDirName: current.dirName,
488
- currentFrom: current.from,
490
+ currentFrom: currentFromMarker,
489
491
  discontinuityIndex: i
490
492
  }
491
493
  });
@@ -509,7 +511,7 @@ async function executeMigrationApply(options) {
509
511
  ] };
510
512
  const plan = {
511
513
  targetId,
512
- origin: migration.from === EMPTY_CONTRACT_HASH ? null : { storageHash: migration.from },
514
+ origin: migration.from === null ? null : { storageHash: migration.from },
513
515
  destination: { storageHash: migration.to },
514
516
  operations
515
517
  };
@@ -1009,4 +1011,4 @@ var ControlClientImpl = class {
1009
1011
 
1010
1012
  //#endregion
1011
1013
  export { ContractValidationError as n, createControlClient as t };
1012
- //# sourceMappingURL=client-enZIahga.mjs.map
1014
+ //# sourceMappingURL=client-CJT9lqBd.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-CJT9lqBd.mjs","names":["plannerResult: MigrationPlannerResult","migrationPlan: MigrationPlan","runnerResult: MigrationRunnerResult","plannerResult: MigrationPlannerResult","runnerResult: MigrationRunnerResult","applied: MigrationApplyAppliedEntry[]","runnerResult: MigrationRunnerResult","contract: Contract","contractRaw: unknown","emitContractArtifacts"],"sources":["../src/control-api/errors.ts","../src/control-api/operations/migration-helpers.ts","../src/control-api/operations/db-init.ts","../src/control-api/operations/db-update.ts","../src/control-api/operations/migration-apply.ts","../src/control-api/client.ts"],"sourcesContent":["export class ContractValidationError extends Error {\n override readonly cause?: unknown;\n\n constructor(message: string, cause?: unknown) {\n super(message);\n this.name = 'ContractValidationError';\n this.cause = cause;\n }\n}\n","import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\nimport type { ControlActionName, OnControlProgress } from '../types';\n\n/**\n * Strips operation objects to their public shape (id, label, operationClass).\n * Used at the API boundary to avoid leaking internal fields (precheck, execute, postcheck, etc.).\n */\nexport function stripOperations(\n operations: readonly MigrationPlanOperation[],\n): ReadonlyArray<{ readonly id: string; readonly label: string; readonly operationClass: string }> {\n return operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n }));\n}\n\n/**\n * Creates per-operation progress callbacks for the runner.\n * Returns undefined when no onProgress callback is provided.\n */\nexport function createOperationCallbacks(\n onProgress: OnControlProgress | undefined,\n action: ControlActionName,\n parentSpanId: string,\n) {\n if (!onProgress) {\n return undefined;\n }\n return {\n onOperationStart: (op: MigrationPlanOperation) => {\n onProgress({\n action,\n kind: 'spanStart',\n spanId: `operation:${op.id}`,\n parentSpanId,\n label: op.label,\n });\n },\n onOperationComplete: (op: MigrationPlanOperation) => {\n onProgress({\n action,\n kind: 'spanEnd',\n spanId: `operation:${op.id}`,\n outcome: 'ok',\n });\n },\n };\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n MigrationPlan,\n MigrationPlannerResult,\n MigrationRunnerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport type { DbInitResult, DbInitSuccess, OnControlProgress } from '../types';\nimport { extractOperationStatements } from './extract-operation-statements';\nimport { createOperationCallbacks, stripOperations } from './migration-helpers';\n\n/**\n * Options for executing dbInit operation.\n */\nexport interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly contract: Contract;\n readonly mode: 'plan' | 'apply';\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n /** Optional progress callback for observing operation progress */\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Executes the dbInit operation.\n *\n * This is the core logic extracted from the CLI command, without any file I/O,\n * process.exit(), or console output. It uses the Result pattern to return\n * success or failure details.\n *\n * @param options - The options for executing dbInit\n * @returns Result with DbInitSuccess on success, DbInitFailure on failure\n */\nexport async function executeDbInit<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbInitOptions<TFamilyId, TTargetId>,\n): Promise<DbInitResult> {\n const { driver, familyInstance, contract, mode, migrations, frameworkComponents, onProgress } =\n options;\n\n // Create planner and runner from target migrations capability\n const planner = migrations.createPlanner(familyInstance);\n const runner = migrations.createRunner(familyInstance);\n\n // Introspect live schema\n const introspectSpanId = 'introspect';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: introspectSpanId,\n label: 'Introspecting database schema',\n });\n const schemaIR = await familyInstance.introspect({ driver });\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: introspectSpanId,\n outcome: 'ok',\n });\n\n // Policy for init mode (additive only)\n const policy = { allowedOperationClasses: ['additive'] as const };\n\n // Plan migration\n const planSpanId = 'plan';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: planSpanId,\n label: 'Planning migration',\n });\n const plannerResult: MigrationPlannerResult = await planner.plan({\n contract,\n schema: schemaIR,\n policy,\n // `db init` does not produce a `migration.ts`, so the from-hash on the\n // resulting plan is never surfaced to authoring — pass null (the\n // baseline encoding for `MigrationPlanner.plan({ fromHash })`).\n fromHash: null,\n frameworkComponents,\n });\n\n if (plannerResult.kind === 'failure') {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'PLANNING_FAILED' as const,\n summary: 'Migration planning failed due to conflicts',\n conflicts: plannerResult.conflicts,\n why: undefined,\n meta: undefined,\n });\n }\n\n const migrationPlan: MigrationPlan = plannerResult.plan;\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'ok',\n });\n\n // Check for existing marker - handle idempotency and mismatch errors\n const checkMarkerSpanId = 'checkMarker';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: checkMarkerSpanId,\n label: 'Checking database signature',\n });\n const existingMarker = await familyInstance.readMarker({ driver });\n if (existingMarker) {\n const markerMatchesDestination =\n existingMarker.storageHash === migrationPlan.destination.storageHash &&\n (!migrationPlan.destination.profileHash ||\n existingMarker.profileHash === migrationPlan.destination.profileHash);\n\n if (markerMatchesDestination) {\n // Already at destination - return success with no operations\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'skipped',\n });\n const result: DbInitSuccess = {\n mode,\n plan: { operations: [] },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n ...ifDefined('profileHash', migrationPlan.destination.profileHash),\n },\n ...ifDefined(\n 'execution',\n mode === 'apply' ? { operationsPlanned: 0, operationsExecuted: 0 } : undefined,\n ),\n ...ifDefined(\n 'marker',\n mode === 'apply'\n ? {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n }\n : undefined,\n ),\n summary: 'Database already at target contract state',\n };\n return ok(result);\n }\n\n // Marker exists but doesn't match destination - fail\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'MARKER_ORIGIN_MISMATCH' as const,\n summary: 'Existing contract marker does not match plan destination',\n marker: {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n },\n why: undefined,\n conflicts: undefined,\n meta: undefined,\n });\n }\n\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: checkMarkerSpanId,\n outcome: 'ok',\n });\n\n // Plan mode - don't execute\n if (mode === 'plan') {\n const planSql = extractOperationStatements(familyInstance.familyId, migrationPlan.operations);\n const result: DbInitSuccess = {\n mode: 'plan',\n plan: {\n operations: stripOperations(migrationPlan.operations),\n ...ifDefined('sql', planSql),\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n ...ifDefined('profileHash', migrationPlan.destination.profileHash),\n },\n summary: `Planned ${migrationPlan.operations.length} operation(s)`,\n };\n return ok(result);\n }\n\n // Apply mode - execute runner\n const applySpanId = 'apply';\n onProgress?.({\n action: 'dbInit',\n kind: 'spanStart',\n spanId: applySpanId,\n label: 'Applying migration plan',\n });\n\n const callbacks = createOperationCallbacks(onProgress, 'dbInit', applySpanId);\n\n const runnerResult: MigrationRunnerResult = await runner.execute({\n plan: migrationPlan,\n driver,\n destinationContract: contract,\n policy,\n ...ifDefined('callbacks', callbacks),\n // db init plans and applies back-to-back from a fresh introspection, so per-operation\n // pre/postchecks and the idempotency probe are usually redundant overhead. We still\n // enforce marker/origin compatibility and a full schema verification after apply.\n executionChecks: {\n prechecks: false,\n postchecks: false,\n idempotencyChecks: false,\n },\n frameworkComponents,\n });\n\n if (!runnerResult.ok) {\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'RUNNER_FAILED' as const,\n summary: runnerResult.failure.summary,\n why: runnerResult.failure.why,\n meta: runnerResult.failure.meta,\n conflicts: undefined,\n });\n }\n\n const execution = runnerResult.value;\n\n onProgress?.({\n action: 'dbInit',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'ok',\n });\n\n const result: DbInitSuccess = {\n mode: 'apply',\n plan: {\n operations: stripOperations(migrationPlan.operations),\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n ...ifDefined('profileHash', migrationPlan.destination.profileHash),\n },\n execution: {\n operationsPlanned: execution.operationsPlanned,\n operationsExecuted: execution.operationsExecuted,\n },\n marker: migrationPlan.destination.profileHash\n ? {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n }\n : { storageHash: migrationPlan.destination.storageHash },\n summary: `Applied ${execution.operationsExecuted} operation(s), database signed`,\n };\n return ok(result);\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n MigrationPlannerResult,\n MigrationRunnerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport type { DbUpdateResult, DbUpdateSuccess, OnControlProgress } from '../types';\nimport { extractOperationStatements } from './extract-operation-statements';\nimport { createOperationCallbacks, stripOperations } from './migration-helpers';\n\n// F12: db update allows additive, widening, and destructive operations.\nconst DB_UPDATE_POLICY = {\n allowedOperationClasses: ['additive', 'widening', 'destructive'] as const,\n} as const;\n\n/**\n * Options for the executeDbUpdate operation.\n * Config-agnostic: receives pre-resolved driver, family, contract, and migrations capability.\n */\nexport interface ExecuteDbUpdateOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly contract: Contract;\n readonly mode: 'plan' | 'apply';\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly acceptDataLoss?: boolean;\n /** Optional progress callback for observing operation progress. */\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Executes the db update operation: introspect → plan → (optionally) apply → marker.\n *\n * db update is a pure reconciliation command: it introspects the live schema, plans the diff\n * to the destination contract, and applies operations. The marker is bookkeeping only — written\n * after apply so that `verify` and `db init` can reference it, but never read or validated\n * by db update itself. The runner creates the marker table if it does not exist.\n */\nexport async function executeDbUpdate<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbUpdateOptions<TFamilyId, TTargetId>,\n): Promise<DbUpdateResult> {\n const { driver, familyInstance, contract, mode, migrations, frameworkComponents, onProgress } =\n options;\n\n const planner = migrations.createPlanner(familyInstance);\n const runner = migrations.createRunner(familyInstance);\n\n const introspectSpanId = 'introspect';\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanStart',\n spanId: introspectSpanId,\n label: 'Introspecting database schema',\n });\n const schemaIR = await familyInstance.introspect({ driver });\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanEnd',\n spanId: introspectSpanId,\n outcome: 'ok',\n });\n\n const policy = DB_UPDATE_POLICY;\n\n const planSpanId = 'plan';\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanStart',\n spanId: planSpanId,\n label: 'Planning migration',\n });\n const plannerResult: MigrationPlannerResult = await planner.plan({\n contract,\n schema: schemaIR,\n policy,\n // `db update` does not produce a `migration.ts`, so the from-hash on the\n // resulting plan is never surfaced to authoring — pass null (the\n // baseline encoding for `MigrationPlanner.plan({ fromHash })`).\n fromHash: null,\n frameworkComponents,\n });\n if (plannerResult.kind === 'failure') {\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'PLANNING_FAILED',\n summary: 'Migration planning failed due to conflicts',\n conflicts: plannerResult.conflicts,\n why: undefined,\n meta: undefined,\n });\n }\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanEnd',\n spanId: planSpanId,\n outcome: 'ok',\n });\n\n const migrationPlan = plannerResult.plan;\n\n if (mode === 'plan') {\n const planSql = extractOperationStatements(familyInstance.familyId, migrationPlan.operations);\n const result: DbUpdateSuccess = {\n mode: 'plan',\n plan: {\n operations: stripOperations(migrationPlan.operations),\n ...(planSql !== undefined ? { sql: planSql } : {}),\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n ...ifDefined('profileHash', migrationPlan.destination.profileHash),\n },\n summary: `Planned ${migrationPlan.operations.length} operation(s)`,\n };\n return ok(result);\n }\n\n // When applying, require explicit acceptance for destructive operations\n if (!options.acceptDataLoss) {\n const destructiveOps = migrationPlan.operations\n .filter((op) => op.operationClass === 'destructive')\n .map((op) => ({ id: op.id, label: op.label }));\n if (destructiveOps.length > 0) {\n return notOk({\n code: 'DESTRUCTIVE_CHANGES',\n summary: `Planned ${destructiveOps.length} destructive operation(s) that require confirmation`,\n why: 'Destructive operations require confirmation — re-run with -y to accept',\n conflicts: undefined,\n meta: { destructiveOperations: destructiveOps },\n });\n }\n }\n\n const applySpanId = 'apply';\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanStart',\n spanId: applySpanId,\n label: 'Applying migration plan',\n });\n\n const callbacks = createOperationCallbacks(onProgress, 'dbUpdate', applySpanId);\n\n const runnerResult: MigrationRunnerResult = await runner.execute({\n plan: migrationPlan,\n driver,\n destinationContract: contract,\n policy,\n ...(callbacks ? { callbacks } : {}),\n // db update plans and applies from a single introspection pass, so per-operation pre/postchecks\n // and idempotency probes are intentionally disabled to avoid redundant roundtrips.\n executionChecks: {\n prechecks: false,\n postchecks: false,\n idempotencyChecks: false,\n },\n frameworkComponents,\n });\n\n if (!runnerResult.ok) {\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'RUNNER_FAILED',\n summary: runnerResult.failure.summary,\n why: runnerResult.failure.why,\n meta: runnerResult.failure.meta,\n conflicts: undefined,\n });\n }\n\n const execution = runnerResult.value;\n onProgress?.({\n action: 'dbUpdate',\n kind: 'spanEnd',\n spanId: applySpanId,\n outcome: 'ok',\n });\n\n const result: DbUpdateSuccess = {\n mode: 'apply',\n plan: {\n operations: stripOperations(migrationPlan.operations),\n },\n destination: {\n storageHash: migrationPlan.destination.storageHash,\n ...ifDefined('profileHash', migrationPlan.destination.profileHash),\n },\n execution: {\n operationsPlanned: execution.operationsPlanned,\n operationsExecuted: execution.operationsExecuted,\n },\n marker: migrationPlan.destination.profileHash\n ? {\n storageHash: migrationPlan.destination.storageHash,\n profileHash: migrationPlan.destination.profileHash,\n }\n : { storageHash: migrationPlan.destination.storageHash },\n summary:\n execution.operationsExecuted === 0\n ? 'Database already matches contract, signature updated'\n : `Applied ${execution.operationsExecuted} operation(s), signature updated`,\n };\n return ok(result);\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n MigrationRunnerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport type {\n MigrationApplyAppliedEntry,\n MigrationApplyResult,\n MigrationApplyStep,\n OnControlProgress,\n} from '../types';\n\nexport interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly originHash: string;\n readonly destinationHash: string;\n readonly pendingMigrations: readonly MigrationApplyStep[];\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly targetId: string;\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Apply a sequence of migration packages against the configured driver.\n *\n * Validates the path's continuity (origin → ... → destination, no gaps),\n * then drives the family/target's migration runner over each package's\n * operations in order, surfacing per-migration progress through `onProgress`.\n *\n * The `pendingMigrations` parameter is trusted input. Callers are responsible\n * for upstream verification of the originating migration packages — typically\n * by loading them via `readMigrationPackage` from\n * `@prisma-next/migration-tools/io`, which performs hash-integrity checks at\n * the load boundary. This operation does not re-verify the packages and\n * assumes the `(metadata, ops)` pairs on disk have not been tampered with\n * since emit.\n */\nexport async function executeMigrationApply<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteMigrationApplyOptions<TFamilyId, TTargetId>,\n): Promise<MigrationApplyResult> {\n const {\n driver,\n familyInstance,\n originHash,\n destinationHash,\n pendingMigrations,\n migrations,\n frameworkComponents,\n targetId,\n onProgress,\n } = options;\n\n if (pendingMigrations.length === 0) {\n if (originHash !== destinationHash) {\n return notOk({\n code: 'MIGRATION_PATH_NOT_FOUND' as const,\n summary: 'No migrations provided for requested origin and destination',\n why: `Requested ${originHash} -> ${destinationHash} but pendingMigrations is empty`,\n meta: { originHash, destinationHash },\n });\n }\n return ok({\n migrationsApplied: 0,\n markerHash: originHash,\n applied: [],\n summary: 'Already up to date',\n });\n }\n\n const firstMigration = pendingMigrations[0]!;\n const lastMigration = pendingMigrations[pendingMigrations.length - 1]!;\n // Manifest `from` is `string | null` (null = baseline). The live-marker\n // layer encodes \"no prior state\" as EMPTY_CONTRACT_HASH; bridge here so the\n // string comparisons below work uniformly.\n const firstFromMarker = firstMigration.from ?? EMPTY_CONTRACT_HASH;\n if (firstFromMarker !== originHash || lastMigration.to !== destinationHash) {\n return notOk({\n code: 'MIGRATION_PATH_NOT_FOUND' as const,\n summary: 'Migration apply path does not match requested origin and destination',\n why: `Path resolved as ${firstFromMarker} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,\n meta: {\n originHash,\n destinationHash,\n pathOrigin: firstFromMarker,\n pathDestination: lastMigration.to,\n },\n });\n }\n\n for (let i = 1; i < pendingMigrations.length; i++) {\n const previous = pendingMigrations[i - 1]!;\n const current = pendingMigrations[i]!;\n const currentFromMarker = current.from ?? EMPTY_CONTRACT_HASH;\n if (previous.to !== currentFromMarker) {\n return notOk({\n code: 'MIGRATION_PATH_NOT_FOUND' as const,\n summary: 'Migration apply path contains a discontinuity between adjacent migrations',\n why: `Migration \"${previous.dirName}\" ends at ${previous.to}, but next migration \"${current.dirName}\" starts at ${currentFromMarker}`,\n meta: {\n originHash,\n destinationHash,\n previousDirName: previous.dirName,\n previousTo: previous.to,\n currentDirName: current.dirName,\n currentFrom: currentFromMarker,\n discontinuityIndex: i,\n },\n });\n }\n }\n\n const runner = migrations.createRunner(familyInstance);\n const applied: MigrationApplyAppliedEntry[] = [];\n\n for (const migration of pendingMigrations) {\n const migrationSpanId = `migration:${migration.dirName}`;\n onProgress?.({\n action: 'migrationApply',\n kind: 'spanStart',\n spanId: migrationSpanId,\n label: `Applying ${migration.dirName}`,\n });\n\n const { operations } = migration;\n\n // Allow all operation classes. The policy gate belongs at plan time, not\n // apply time — the planner already decided what to emit. Restricting here\n // would be a tautology (the allowed set would just mirror what's in ops).\n const policy = {\n allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] as const,\n };\n\n // Manifest `from === null` means \"no prior state\" — the runner expects\n // `origin: null` for a fresh database (no marker present).\n const plan = {\n targetId,\n origin: migration.from === null ? null : { storageHash: migration.from },\n destination: { storageHash: migration.to },\n operations,\n };\n\n const destinationContract = familyInstance.validateContract(migration.toContract);\n\n const runnerResult: MigrationRunnerResult = await runner.execute({\n plan,\n driver,\n destinationContract,\n policy,\n executionChecks: {\n prechecks: true,\n postchecks: true,\n idempotencyChecks: true,\n },\n frameworkComponents,\n });\n\n if (!runnerResult.ok) {\n onProgress?.({\n action: 'migrationApply',\n kind: 'spanEnd',\n spanId: migrationSpanId,\n outcome: 'error',\n });\n return notOk({\n code: 'RUNNER_FAILED' as const,\n summary: runnerResult.failure.summary,\n why: runnerResult.failure.why,\n meta: {\n migration: migration.dirName,\n from: migration.from,\n to: migration.to,\n ...(runnerResult.failure.meta ?? {}),\n },\n });\n }\n\n onProgress?.({\n action: 'migrationApply',\n kind: 'spanEnd',\n spanId: migrationSpanId,\n outcome: 'ok',\n });\n\n applied.push({\n dirName: migration.dirName,\n from: migration.from,\n to: migration.to,\n operationsExecuted: runnerResult.value.operationsExecuted,\n });\n }\n\n const finalHash = pendingMigrations[pendingMigrations.length - 1]!.to;\n const totalOps = applied.reduce((sum, a) => sum + a.operationsExecuted, 0);\n\n return ok({\n migrationsApplied: applied.length,\n markerHash: finalHash,\n applied,\n summary: `Applied ${applied.length} migration(s) (${totalOps} operation(s)), marker at ${finalHash}`,\n });\n}\n","import type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport { emit as emitContractArtifacts } from '@prisma-next/emitter';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlStack,\n CoreSchemaView,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n createControlStack,\n hasMigrations,\n hasSchemaView,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport { enrichContract } from './contract-enrichment';\nimport { ContractValidationError } from './errors';\nimport { executeDbInit } from './operations/db-init';\nimport { executeDbUpdate } from './operations/db-update';\nimport { executeMigrationApply } from './operations/migration-apply';\nimport type {\n ControlActionName,\n ControlClient,\n ControlClientOptions,\n DbInitOptions,\n DbInitResult,\n DbUpdateOptions,\n DbUpdateResult,\n EmitOptions,\n EmitResult,\n IntrospectOptions,\n MigrationApplyOptions,\n MigrationApplyResult,\n OnControlProgress,\n SchemaVerifyOptions,\n SignOptions,\n VerifyOptions,\n} from './types';\n\n/**\n * Creates a programmatic control client for Prisma Next operations.\n *\n * The client accepts framework component descriptors at creation time,\n * manages driver lifecycle via connect()/close(), and exposes domain\n * operations that delegate to the existing family instance methods.\n *\n * @see {@link ControlClient} for the client interface\n * @see README.md \"Programmatic Control API\" section for usage examples\n */\nexport function createControlClient(options: ControlClientOptions): ControlClient {\n return new ControlClientImpl(options);\n}\n\n/**\n * Implementation of ControlClient.\n * Manages initialization and connection state, delegates operations to family instance.\n */\nclass ControlClientImpl implements ControlClient {\n private readonly options: ControlClientOptions;\n private stack: ControlStack | null = null;\n private driver: ControlDriverInstance<string, string> | null = null;\n private familyInstance: ControlFamilyInstance<string, unknown> | null = null;\n private frameworkComponents: ReadonlyArray<\n TargetBoundComponentDescriptor<string, string>\n > | null = null;\n private initialized = false;\n private readonly defaultConnection: unknown;\n\n constructor(options: ControlClientOptions) {\n this.options = options;\n this.defaultConnection = options.connection;\n }\n\n init(): void {\n if (this.initialized) {\n return; // Idempotent\n }\n\n this.stack = createControlStack({\n family: this.options.family,\n target: this.options.target,\n adapter: this.options.adapter,\n driver: this.options.driver,\n extensionPacks: this.options.extensionPacks,\n });\n\n this.familyInstance = this.options.family.create(this.stack);\n\n // Validate and type-narrow framework components\n const rawComponents = [\n this.options.target,\n this.options.adapter,\n ...(this.options.extensionPacks ?? []),\n ];\n this.frameworkComponents = assertFrameworkComponentsCompatible(\n this.options.family.familyId,\n this.options.target.targetId,\n rawComponents,\n );\n\n this.initialized = true;\n }\n\n async connect(connection?: unknown): Promise<void> {\n // Auto-init if needed\n this.init();\n\n if (this.driver) {\n throw new Error('Already connected. Call close() before reconnecting.');\n }\n\n // Resolve connection: argument > default from options\n const resolvedConnection = connection ?? this.defaultConnection;\n if (resolvedConnection === undefined) {\n throw new Error(\n 'No connection provided. Pass a connection to connect() or provide a default connection when creating the client.',\n );\n }\n\n // Check for driver descriptor\n if (!this.stack?.driver) {\n throw new Error(\n 'Driver is not configured. Pass a driver descriptor when creating the control client to enable database operations.',\n );\n }\n\n // biome-ignore lint/suspicious/noExplicitAny: required for runtime connection type flexibility\n this.driver = await this.stack.driver.create(resolvedConnection as any);\n }\n\n async close(): Promise<void> {\n if (this.driver) {\n await this.driver.close();\n this.driver = null;\n }\n }\n\n private async ensureConnected(): Promise<{\n driver: ControlDriverInstance<string, string>;\n familyInstance: ControlFamilyInstance<string, unknown>;\n frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;\n }> {\n // Auto-init if needed\n this.init();\n\n // Auto-connect if not connected and default connection is available\n if (!this.driver && this.defaultConnection !== undefined) {\n await this.connect(this.defaultConnection);\n }\n\n if (!this.driver || !this.familyInstance || !this.frameworkComponents) {\n throw new Error('Not connected. Call connect(connection) first.');\n }\n return {\n driver: this.driver,\n familyInstance: this.familyInstance,\n frameworkComponents: this.frameworkComponents,\n };\n }\n\n private async connectWithProgress(\n connection: unknown | undefined,\n action: ControlActionName,\n onProgress?: OnControlProgress,\n ): Promise<void> {\n if (connection === undefined) return;\n onProgress?.({\n action,\n kind: 'spanStart',\n spanId: 'connect',\n label: 'Connecting to database...',\n });\n try {\n await this.connect(connection);\n onProgress?.({ action, kind: 'spanEnd', spanId: 'connect', outcome: 'ok' });\n } catch (error) {\n onProgress?.({ action, kind: 'spanEnd', spanId: 'connect', outcome: 'error' });\n throw error;\n }\n }\n\n async verify(options: VerifyOptions): Promise<VerifyDatabaseResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'verify', onProgress);\n const { driver, familyInstance } = await this.ensureConnected();\n\n // Validate contract using family instance\n let contract: Contract;\n try {\n contract = familyInstance.validateContract(options.contract);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ContractValidationError(message, error);\n }\n\n // Emit verify span\n onProgress?.({\n action: 'verify',\n kind: 'spanStart',\n spanId: 'verify',\n label: 'Verifying database marker...',\n });\n\n try {\n // Delegate to family instance verify method\n // Note: We pass empty strings for contractPath/configPath since the programmatic\n // API doesn't deal with file paths. The family instance accepts these as optional\n // metadata for error reporting.\n const result = await familyInstance.verify({\n driver,\n contract,\n expectedTargetId: this.options.target.targetId,\n contractPath: '',\n });\n\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'verify',\n outcome: result.ok ? 'ok' : 'error',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'verify',\n kind: 'spanEnd',\n spanId: 'verify',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'schemaVerify', onProgress);\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n // Validate contract using family instance\n let contract: Contract;\n try {\n contract = familyInstance.validateContract(options.contract);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ContractValidationError(message, error);\n }\n\n // Emit schemaVerify span\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanStart',\n spanId: 'schemaVerify',\n label: 'Verifying database schema...',\n });\n\n try {\n // Delegate to family instance schemaVerify method\n const result = await familyInstance.schemaVerify({\n driver,\n contract,\n strict: options.strict ?? false,\n contractPath: '',\n frameworkComponents,\n });\n\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'schemaVerify',\n outcome: result.ok ? 'ok' : 'error',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'schemaVerify',\n kind: 'spanEnd',\n spanId: 'schemaVerify',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async sign(options: SignOptions): Promise<SignDatabaseResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'sign', onProgress);\n const { driver, familyInstance } = await this.ensureConnected();\n\n // Validate contract using family instance\n let contract: Contract;\n try {\n contract = familyInstance.validateContract(options.contract);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ContractValidationError(message, error);\n }\n\n // Emit sign span\n onProgress?.({\n action: 'sign',\n kind: 'spanStart',\n spanId: 'sign',\n label: 'Signing database...',\n });\n\n try {\n // Delegate to family instance sign method\n const result = await familyInstance.sign({\n driver,\n contract,\n contractPath: options.contractPath ?? '',\n ...ifDefined('configPath', options.configPath),\n });\n\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'sign',\n outcome: 'ok',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'sign',\n kind: 'spanEnd',\n spanId: 'sign',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n async dbInit(options: DbInitOptions): Promise<DbInitResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'dbInit', onProgress);\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n if (!hasMigrations(this.options.target)) {\n throw new Error(`Target \"${this.options.target.targetId}\" does not support migrations`);\n }\n\n let contract: Contract;\n try {\n contract = familyInstance.validateContract(options.contract);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ContractValidationError(message, error);\n }\n\n return executeDbInit({\n driver,\n familyInstance,\n contract,\n mode: options.mode,\n migrations: this.options.target.migrations,\n frameworkComponents,\n ...ifDefined('onProgress', onProgress),\n });\n }\n\n async dbUpdate(options: DbUpdateOptions): Promise<DbUpdateResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'dbUpdate', onProgress);\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n if (!hasMigrations(this.options.target)) {\n throw new Error(`Target \"${this.options.target.targetId}\" does not support migrations`);\n }\n\n let contract: Contract;\n try {\n contract = familyInstance.validateContract(options.contract);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new ContractValidationError(message, error);\n }\n\n return executeDbUpdate({\n driver,\n familyInstance,\n contract,\n mode: options.mode,\n migrations: this.options.target.migrations,\n frameworkComponents,\n ...ifDefined('acceptDataLoss', options.acceptDataLoss),\n ...ifDefined('onProgress', onProgress),\n });\n }\n\n async readMarker(): Promise<ContractMarkerRecord | null> {\n const { driver, familyInstance } = await this.ensureConnected();\n return familyInstance.readMarker({ driver });\n }\n\n async migrationApply(options: MigrationApplyOptions): Promise<MigrationApplyResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'migrationApply', onProgress);\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n if (!hasMigrations(this.options.target)) {\n throw new Error(`Target \"${this.options.target.targetId}\" does not support migrations`);\n }\n\n return executeMigrationApply({\n driver,\n familyInstance,\n originHash: options.originHash,\n destinationHash: options.destinationHash,\n pendingMigrations: options.pendingMigrations,\n migrations: this.options.target.migrations,\n frameworkComponents,\n targetId: this.options.target.targetId,\n ...(onProgress ? { onProgress } : {}),\n });\n }\n\n async introspect(options?: IntrospectOptions): Promise<unknown> {\n const onProgress = options?.onProgress;\n await this.connectWithProgress(options?.connection, 'introspect', onProgress);\n const { driver, familyInstance } = await this.ensureConnected();\n\n // TODO: Pass schema option to familyInstance.introspect when schema filtering is implemented\n const _schema = options?.schema;\n void _schema;\n\n // Emit introspect span\n onProgress?.({\n action: 'introspect',\n kind: 'spanStart',\n spanId: 'introspect',\n label: 'Introspecting database schema...',\n });\n\n try {\n const result = await familyInstance.introspect({ driver });\n\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'introspect',\n outcome: 'ok',\n });\n\n return result;\n } catch (error) {\n onProgress?.({\n action: 'introspect',\n kind: 'spanEnd',\n spanId: 'introspect',\n outcome: 'error',\n });\n throw error;\n }\n }\n\n toSchemaView(schemaIR: unknown): CoreSchemaView | undefined {\n this.init();\n if (this.familyInstance && hasSchemaView(this.familyInstance)) {\n return this.familyInstance.toSchemaView(schemaIR);\n }\n return undefined;\n }\n\n async emit(options: EmitOptions): Promise<EmitResult> {\n const { onProgress, contractConfig } = options;\n\n // Ensure initialized (creates stack and family instance)\n // emit() does NOT require a database connection\n this.init();\n\n if (!this.familyInstance) {\n throw new Error('Family instance was not initialized. This is a bug.');\n }\n\n let contractRaw: unknown;\n onProgress?.({\n action: 'emit',\n kind: 'spanStart',\n spanId: 'resolveSource',\n label: 'Resolving contract source...',\n });\n\n try {\n const stack = this.stack!;\n const sourceContext = {\n composedExtensionPacks: stack.extensionPacks.map((p) => p.id),\n scalarTypeDescriptors: stack.scalarTypeDescriptors,\n authoringContributions: stack.authoringContributions,\n codecLookup: stack.codecLookup,\n controlMutationDefaults: stack.controlMutationDefaults,\n resolvedInputs: contractConfig.source.inputs ?? [],\n };\n const providerResult = await contractConfig.source.load(sourceContext);\n if (!providerResult.ok) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'error',\n });\n\n return notOk({\n code: 'CONTRACT_SOURCE_INVALID',\n summary: providerResult.failure.summary,\n why: providerResult.failure.summary,\n meta: providerResult.failure.meta,\n diagnostics: providerResult.failure,\n });\n }\n contractRaw = providerResult.value;\n\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'ok',\n });\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'resolveSource',\n outcome: 'error',\n });\n\n const message = error instanceof Error ? error.message : String(error);\n return notOk({\n code: 'CONTRACT_SOURCE_INVALID',\n summary: 'Failed to resolve contract source',\n why: message,\n diagnostics: {\n summary: 'Contract source provider threw an exception',\n diagnostics: [\n {\n code: 'PROVIDER_THROW',\n message,\n },\n ],\n },\n meta: undefined,\n });\n }\n\n // Emit contract\n onProgress?.({\n action: 'emit',\n kind: 'spanStart',\n spanId: 'emit',\n label: 'Emitting contract...',\n });\n\n try {\n const enrichedIR = enrichContract(contractRaw as Contract, this.frameworkComponents ?? []);\n\n try {\n this.familyInstance.validateContract(enrichedIR);\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'error',\n });\n const message = error instanceof Error ? error.message : String(error);\n return notOk({\n code: 'CONTRACT_VALIDATION_FAILED',\n summary: 'Contract validation failed',\n why: message,\n meta: undefined,\n });\n }\n\n const result = await emitContractArtifacts(\n enrichedIR,\n this.stack!,\n this.options.family.emission,\n );\n\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'ok',\n });\n\n return ok({\n storageHash: result.storageHash,\n ...ifDefined('executionHash', result.executionHash),\n profileHash: result.profileHash,\n contractJson: result.contractJson,\n contractDts: result.contractDts,\n });\n } catch (error) {\n onProgress?.({\n action: 'emit',\n kind: 'spanEnd',\n spanId: 'emit',\n outcome: 'error',\n });\n\n return notOk({\n code: 'EMIT_FAILED',\n summary: 'Failed to emit contract',\n why: error instanceof Error ? error.message : String(error),\n meta: undefined,\n });\n }\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import "../config-loader-ih8ViDb_.mjs";
2
- import { t as createContractInferCommand } from "../contract-infer-BjzkcwQt.mjs";
2
+ import { t as createContractInferCommand } from "../contract-infer-CPQRrGmy.mjs";
3
3
 
4
4
  export { createContractInferCommand };
@@ -2,9 +2,9 @@ import "../config-loader-ih8ViDb_.mjs";
2
2
  import { _ as errorUnexpected, a as errorContractValidationFailed, f as errorMigrationPlanningFailed, m as errorRuntime, p as errorRunnerFailed, t as CliStructuredError } from "../cli-errors-By1iVE3z.mjs";
3
3
  import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
4
  import { d as setCommandExamples, l as sanitizeErrorMessage, m as parseGlobalFlags, t as handleResult, u as setCommandDescriptions } from "../result-handler-BmVh8AeV.mjs";
5
- import { n as ContractValidationError } from "../client-enZIahga.mjs";
6
- import { i as formatMigrationPlanOutput, n as formatMigrationApplyOutput, r as formatMigrationJson } from "../migrations-CSaDHNpB.mjs";
7
- import { n as prepareMigrationContext, t as addMigrationCommandOptions } from "../migration-command-scaffold-BfloSWPZ.mjs";
5
+ import { n as ContractValidationError } from "../client-CJT9lqBd.mjs";
6
+ import { i as formatMigrationPlanOutput, n as formatMigrationApplyOutput, r as formatMigrationJson } from "../migrations-CYYmURZx.mjs";
7
+ import { n as prepareMigrationContext, t as addMigrationCommandOptions } from "../migration-command-scaffold-BP50SzoG.mjs";
8
8
  import { Command } from "commander";
9
9
  import { ifDefined } from "@prisma-next/utils/defined";
10
10
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -1,7 +1,7 @@
1
1
  import "../config-loader-ih8ViDb_.mjs";
2
2
  import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
3
3
  import { d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions } from "../result-handler-BmVh8AeV.mjs";
4
- import { t as inspectLiveSchema } from "../inspect-live-schema-QklSDLt_.mjs";
4
+ import { t as inspectLiveSchema } from "../inspect-live-schema-CLchu1d-.mjs";
5
5
  import { n as formatIntrospectOutput, t as formatIntrospectJson } from "../verify-BumcH6Ry.mjs";
6
6
  import { Command } from "commander";
7
7
 
@@ -3,7 +3,7 @@ import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDri
3
3
  import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
4
  import { _ as formatStyledHeader, a as maskConnectionUrl, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, s as resolveContractPath, t as handleResult, u as setCommandDescriptions } from "../result-handler-BmVh8AeV.mjs";
5
5
  import { t as createProgressAdapter } from "../progress-adapter-DgRGldpT.mjs";
6
- import { n as ContractValidationError, t as createControlClient } from "../client-enZIahga.mjs";
6
+ import { n as ContractValidationError, t as createControlClient } from "../client-CJT9lqBd.mjs";
7
7
  import { a as formatSignJson, i as formatSchemaVerifyOutput, o as formatSignOutput, r as formatSchemaVerifyJson } from "../verify-BumcH6Ry.mjs";
8
8
  import { Command } from "commander";
9
9
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -2,9 +2,9 @@ import "../config-loader-ih8ViDb_.mjs";
2
2
  import { _ as errorUnexpected, a as errorContractValidationFailed, f as errorMigrationPlanningFailed, n as ERROR_CODE_DESTRUCTIVE_CHANGES, p as errorRunnerFailed, s as errorDestructiveChanges, t as CliStructuredError } from "../cli-errors-By1iVE3z.mjs";
3
3
  import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
4
  import { d as setCommandExamples, l as sanitizeErrorMessage, m as parseGlobalFlags, t as handleResult, u as setCommandDescriptions } from "../result-handler-BmVh8AeV.mjs";
5
- import { n as ContractValidationError } from "../client-enZIahga.mjs";
6
- import { i as formatMigrationPlanOutput, n as formatMigrationApplyOutput, r as formatMigrationJson } from "../migrations-CSaDHNpB.mjs";
7
- import { n as prepareMigrationContext, t as addMigrationCommandOptions } from "../migration-command-scaffold-BfloSWPZ.mjs";
5
+ import { n as ContractValidationError } from "../client-CJT9lqBd.mjs";
6
+ import { i as formatMigrationPlanOutput, n as formatMigrationApplyOutput, r as formatMigrationJson } from "../migrations-CYYmURZx.mjs";
7
+ import { n as prepareMigrationContext, t as addMigrationCommandOptions } from "../migration-command-scaffold-BP50SzoG.mjs";
8
8
  import { Command } from "commander";
9
9
  import { ifDefined } from "@prisma-next/utils/defined";
10
10
  import { notOk, ok } from "@prisma-next/utils/result";
@@ -3,7 +3,7 @@ import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDri
3
3
  import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
4
  import { _ as formatStyledHeader, a as maskConnectionUrl, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, s as resolveContractPath, t as handleResult, u as setCommandDescriptions } from "../result-handler-BmVh8AeV.mjs";
5
5
  import { t as createProgressAdapter } from "../progress-adapter-DgRGldpT.mjs";
6
- import { n as ContractValidationError, t as createControlClient } from "../client-enZIahga.mjs";
6
+ import { n as ContractValidationError, t as createControlClient } from "../client-CJT9lqBd.mjs";
7
7
  import { c as formatVerifyOutput, i as formatSchemaVerifyOutput, r as formatSchemaVerifyJson, s as formatVerifyJson } from "../verify-BumcH6Ry.mjs";
8
8
  import { Command } from "commander";
9
9
  import { ifDefined } from "@prisma-next/utils/defined";
@@ -8,7 +8,7 @@ interface MigrationApplyResult {
8
8
  readonly markerHash: string;
9
9
  readonly applied: readonly {
10
10
  readonly dirName: string;
11
- readonly from: string;
11
+ readonly from: string | null;
12
12
  readonly to: string;
13
13
  readonly operationsExecuted: number;
14
14
  }[];
@@ -2,8 +2,8 @@ import { t as loadConfig } from "../config-loader-ih8ViDb_.mjs";
2
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
3
  import { t as TerminalUI } from "../terminal-ui-u2YgKghu.mjs";
4
4
  import { _ as formatStyledHeader, a as maskConnectionUrl, c as resolveMigrationPaths, d as setCommandExamples, f as targetSupportsMigrations, i as loadMigrationPackages, m as parseGlobalFlags, n as addGlobalOptions, o as readContractEnvelope, p as toPathDecisionResult, t as handleResult, u as setCommandDescriptions } from "../result-handler-BmVh8AeV.mjs";
5
- import { t as createControlClient } from "../client-enZIahga.mjs";
6
- import { t as formatMigrationApplyCommandOutput } from "../migrations-CSaDHNpB.mjs";
5
+ import { t as createControlClient } from "../client-CJT9lqBd.mjs";
6
+ import { t as formatMigrationApplyCommandOutput } from "../migrations-CYYmURZx.mjs";
7
7
  import { Command } from "commander";
8
8
  import { notOk, ok } from "@prisma-next/utils/result";
9
9
  import { findPathWithDecision } from "@prisma-next/migration-tools/migration-graph";
@@ -1 +1 @@
1
- {"version":3,"file":"migration-apply.mjs","names":["destinationHash: string","refName: 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 { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { findPathWithDecision } from '@prisma-next/migration-tools/migration-graph';\nimport type { MigrationPackage } from '@prisma-next/migration-tools/package';\nimport { readRefs, resolveRef } from '@prisma-next/migration-tools/refs';\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 loadMigrationPackages,\n maskConnectionUrl,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n targetSupportsMigrations,\n toPathDecisionResult,\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;\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 selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: 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: MigrationPackage): 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 };\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 destinationHash: string;\n let refName: string | undefined;\n\n if (options.ref) {\n refName = options.ref;\n try {\n const refs = await readRefs(refsDir);\n destinationHash = resolveRef(refs, refName).hash;\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 destinationHash = 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\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 // --- 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 // --- Resolve path and apply ---\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 decision = findPathWithDecision(migrations.graph, originHash, destinationHash, refName);\n if (!decision) {\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 pendingPath = decision.selectedPath;\n const pathDecision = toPathDecisionResult(decision);\n\n if (pendingPath.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 pendingPath) {\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: pendingPath.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":"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"}
1
+ {"version":3,"file":"migration-apply.mjs","names":["destinationHash: string","refName: 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 { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { findPathWithDecision } from '@prisma-next/migration-tools/migration-graph';\nimport type { MigrationPackage } from '@prisma-next/migration-tools/package';\nimport { readRefs, resolveRef } from '@prisma-next/migration-tools/refs';\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 loadMigrationPackages,\n maskConnectionUrl,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n targetSupportsMigrations,\n toPathDecisionResult,\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 selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: 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: MigrationPackage): 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 };\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 destinationHash: string;\n let refName: string | undefined;\n\n if (options.ref) {\n refName = options.ref;\n try {\n const refs = await readRefs(refsDir);\n destinationHash = resolveRef(refs, refName).hash;\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 destinationHash = 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\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 // --- 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 // --- Resolve path and apply ---\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 decision = findPathWithDecision(migrations.graph, originHash, destinationHash, refName);\n if (!decision) {\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 pendingPath = decision.selectedPath;\n const pathDecision = toPathDecisionResult(decision);\n\n if (pendingPath.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 pendingPath) {\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: pendingPath.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":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"migration-new.d.mts","names":[],"sources":["../../src/commands/migration-new.ts"],"sourcesContent":[],"mappings":";;;;iBAsQgB,yBAAA,CAAA,GAA6B"}
1
+ {"version":3,"file":"migration-new.d.mts","names":[],"sources":["../../src/commands/migration-new.ts"],"sourcesContent":[],"mappings":";;;;iBAoQgB,yBAAA,CAAA,GAA6B"}
@@ -11,7 +11,6 @@ import { createControlStack } from "@prisma-next/framework-components/control";
11
11
  import { copyFilesWithRename, formatMigrationDirName, readMigrationsDir, writeMigrationPackage } from "@prisma-next/migration-tools/io";
12
12
  import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/migration-graph";
13
13
  import { readFileSync } from "node:fs";
14
- import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
15
14
  import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
16
15
  import { computeMigrationHash } from "@prisma-next/migration-tools/hash";
17
16
  import { writeMigrationTs } from "@prisma-next/migration-tools/migration-ts";
@@ -55,7 +54,7 @@ async function executeMigrationNewCommand(options) {
55
54
  fix: "Run `prisma-next contract emit` to regenerate the contract"
56
55
  }));
57
56
  let fromContract = null;
58
- let fromHash = EMPTY_CONTRACT_HASH;
57
+ let fromHash = null;
59
58
  let fromContractSourceDir = null;
60
59
  try {
61
60
  const packages = await readMigrationsDir(migrationsDir);
@@ -95,7 +94,6 @@ async function executeMigrationNewCommand(options) {
95
94
  const baseMetadata = {
96
95
  from: fromHash,
97
96
  to: toStorageHash,
98
- kind: "regular",
99
97
  fromContract,
100
98
  toContract: toContractJson,
101
99
  hints: {
@@ -1 +1 @@
1
- {"version":3,"file":"migration-new.mjs","names":["contractJsonContent: string","toContractJson: Contract","fromContract: Contract | null","fromHash: string","fromContractSourceDir: string | null","baseMetadata: Omit<MigrationMetadata, 'migrationHash'>","metadata: MigrationMetadata"],"sources":["../../src/commands/migration-new.ts"],"sourcesContent":["/**\n * `migration new` — scaffolds a migration package with a `migration.ts` file\n * for manual authoring.\n *\n * The planner's `emptyMigration(context)` returns a\n * `MigrationPlanWithAuthoringSurface`, whose `renderTypeScript()` produces\n * the target-appropriate empty stub. The CLI writes the returned source\n * verbatim.\n */\n\nimport { readFileSync } from 'node:fs';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { computeMigrationHash } from '@prisma-next/migration-tools/hash';\nimport {\n copyFilesWithRename,\n formatMigrationDirName,\n readMigrationsDir,\n writeMigrationPackage,\n} from '@prisma-next/migration-tools/io';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport {\n findLatestMigration,\n reconstructGraph,\n} from '@prisma-next/migration-tools/migration-graph';\nimport { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';\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 {\n CliStructuredError,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\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 { parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationNewOptions extends CommonCommandOptions {\n readonly name?: string;\n readonly from?: string;\n readonly config?: string;\n}\n\ninterface MigrationNewResult {\n readonly ok: true;\n readonly dir: string;\n readonly from: string;\n readonly to: string;\n readonly summary: string;\n}\n\nasync function executeMigrationNewCommand(\n options: MigrationNewOptions,\n): Promise<Result<MigrationNewResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { migrationsDir, migrationsRelative } = resolveMigrationPaths(options.config, config);\n\n const contractPathAbsolute = resolveContractPath(config);\n\n let contractJsonContent: string;\n try {\n contractJsonContent = readFileSync(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorRuntime(`Contract file not found at ${contractPathAbsolute}`, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: 'Run `prisma-next contract emit` first to generate the contract',\n }),\n );\n }\n throw error;\n }\n\n let toContractJson: Contract;\n try {\n toContractJson = JSON.parse(contractJsonContent) as Contract;\n } catch (error) {\n return notOk(\n errorRuntime('Contract JSON is invalid', {\n why: `Failed to parse ${contractPathAbsolute}: ${error instanceof Error ? error.message : String(error)}`,\n fix: 'Run `prisma-next contract emit` to regenerate the contract',\n }),\n );\n }\n\n const toStorageHash = (\n (toContractJson as unknown as Record<string, unknown>)['storage'] as\n | Record<string, unknown>\n | undefined\n )?.['storageHash'] as string | undefined;\n if (!toStorageHash) {\n return notOk(\n errorRuntime('Contract is missing storageHash', {\n why: `Contract at ${contractPathAbsolute} has no storageHash`,\n fix: 'Run `prisma-next contract emit` to regenerate the contract',\n }),\n );\n }\n\n let fromContract: Contract | null = null;\n let fromHash: string = EMPTY_CONTRACT_HASH;\n let fromContractSourceDir: string | null = null;\n\n try {\n const packages = await readMigrationsDir(migrationsDir);\n\n if (packages.length > 0) {\n const graph = reconstructGraph(packages);\n\n if (options.from) {\n const match = packages.find((p) => p.metadata.to.startsWith(options.from!));\n if (!match) {\n return notOk(\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.',\n }),\n );\n }\n fromHash = match.metadata.to;\n fromContract = match.metadata.toContract;\n fromContractSourceDir = match.dirPath;\n } else {\n const latestMigration = findLatestMigration(graph);\n if (latestMigration) {\n fromHash = latestMigration.to;\n const leafPkg = packages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n if (leafPkg) {\n fromContract = leafPkg.metadata.toContract;\n fromContractSourceDir = leafPkg.dirPath;\n }\n }\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n if (fromHash === toStorageHash) {\n return notOk(\n errorRuntime('No changes detected', {\n why: 'The from and to contract hashes are identical — there is nothing to migrate.',\n fix: 'Change the contract and run `prisma-next contract emit` before creating a new migration.',\n }),\n );\n }\n\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 // `migration new` scaffolds an empty `migration.ts` for the user to\n // fill, so we attest over `ops: []`. Re-running self-emit after the\n // user adds operations will produce a different `migrationHash` (over\n // the real ops). This is intentional — there is no on-disk draft.\n const baseMetadata: Omit<MigrationMetadata, 'migrationHash'> = {\n from: fromHash,\n to: toStorageHash,\n kind: 'regular',\n fromContract,\n toContract: toContractJson,\n hints: {\n used: [],\n applied: [],\n plannerVersion: '1.0.0',\n },\n labels: [],\n providedInvariants: [],\n createdAt: timestamp.toISOString(),\n };\n const metadata: MigrationMetadata = {\n ...baseMetadata,\n migrationHash: computeMigrationHash(baseMetadata, []),\n };\n\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.targetId}\" does not support migrations`,\n }),\n );\n }\n\n try {\n assertFrameworkComponentsCompatible(config.family.familyId, config.target.targetId, [\n config.target,\n config.adapter,\n ...(config.extensionPacks ?? []),\n ]);\n\n await writeMigrationPackage(packageDir, metadata, []);\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\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const planner = migrations.createPlanner(familyInstance);\n const emptyPlan = planner.emptyMigration({\n packageDir,\n contractJsonPath: join(packageDir, 'end-contract.json'),\n fromHash,\n toHash: toStorageHash,\n });\n await writeMigrationTs(packageDir, emptyPlan.renderTypeScript());\n\n return ok({\n ok: true as const,\n dir: relative(process.cwd(), packageDir),\n from: fromHash,\n to: toStorageHash,\n summary: `Scaffolded migration at ${relative(process.cwd(), packageDir)}`,\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: `Failed to scaffold migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n}\n\nexport function createMigrationNewCommand(): Command {\n const command = new Command('new');\n setCommandDescriptions(\n command,\n 'Scaffold a new migration for manual authoring',\n 'Creates a migration package with a migration.ts file for manual authoring.\\n' +\n 'Write the migration body in migration.ts, then run the file with Node\\n' +\n '(`node migration.ts`) to self-emit ops.json and attest the package.',\n );\n setCommandExamples(command, [\n 'prisma-next migration new --name split-name',\n 'prisma-next migration new --name custom-fk --from sha256:abc...',\n ]);\n addGlobalOptions(command)\n .option('--name <slug>', 'Migration name (used in directory name)')\n .option('--from <hash>', 'Starting contract hash (default: latest migration target)')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: MigrationNewOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration new',\n description: 'Scaffold a new migration',\n details: [],\n flags,\n });\n ui.stderr(header);\n }\n\n const result = await executeMigrationNewCommand(options);\n\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value, null, 2));\n } else if (!flags.quiet) {\n ui.output(`\\nScaffolded migration at ${value.dir}`);\n ui.output(` from: ${value.from}`);\n ui.output(` to: ${value.to}`);\n ui.output(\n `\\nEdit migration.ts, then run it directly (\\`node \"${value.dir}/migration.ts\"\\`) to self-emit and attest.`,\n );\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"migration-new.mjs","names":["contractJsonContent: string","toContractJson: Contract","fromContract: Contract | null","fromHash: string | null","fromContractSourceDir: string | null","baseMetadata: Omit<MigrationMetadata, 'migrationHash'>","metadata: MigrationMetadata"],"sources":["../../src/commands/migration-new.ts"],"sourcesContent":["/**\n * `migration new` — scaffolds a migration package with a `migration.ts` file\n * for manual authoring.\n *\n * The planner's `emptyMigration(context)` returns a\n * `MigrationPlanWithAuthoringSurface`, whose `renderTypeScript()` produces\n * the target-appropriate empty stub. The CLI writes the returned source\n * verbatim.\n */\n\nimport { readFileSync } from 'node:fs';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { computeMigrationHash } from '@prisma-next/migration-tools/hash';\nimport {\n copyFilesWithRename,\n formatMigrationDirName,\n readMigrationsDir,\n writeMigrationPackage,\n} from '@prisma-next/migration-tools/io';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport {\n findLatestMigration,\n reconstructGraph,\n} from '@prisma-next/migration-tools/migration-graph';\nimport { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';\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 {\n CliStructuredError,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\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 { parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationNewOptions extends CommonCommandOptions {\n readonly name?: string;\n readonly from?: string;\n readonly config?: string;\n}\n\ninterface MigrationNewResult {\n readonly ok: true;\n readonly dir: string;\n readonly from: string | null;\n readonly to: string;\n readonly summary: string;\n}\n\nasync function executeMigrationNewCommand(\n options: MigrationNewOptions,\n): Promise<Result<MigrationNewResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { migrationsDir, migrationsRelative } = resolveMigrationPaths(options.config, config);\n\n const contractPathAbsolute = resolveContractPath(config);\n\n let contractJsonContent: string;\n try {\n contractJsonContent = readFileSync(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorRuntime(`Contract file not found at ${contractPathAbsolute}`, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: 'Run `prisma-next contract emit` first to generate the contract',\n }),\n );\n }\n throw error;\n }\n\n let toContractJson: Contract;\n try {\n toContractJson = JSON.parse(contractJsonContent) as Contract;\n } catch (error) {\n return notOk(\n errorRuntime('Contract JSON is invalid', {\n why: `Failed to parse ${contractPathAbsolute}: ${error instanceof Error ? error.message : String(error)}`,\n fix: 'Run `prisma-next contract emit` to regenerate the contract',\n }),\n );\n }\n\n const toStorageHash = (\n (toContractJson as unknown as Record<string, unknown>)['storage'] as\n | Record<string, unknown>\n | undefined\n )?.['storageHash'] as string | undefined;\n if (!toStorageHash) {\n return notOk(\n errorRuntime('Contract is missing storageHash', {\n why: `Contract at ${contractPathAbsolute} has no storageHash`,\n fix: 'Run `prisma-next contract emit` to regenerate the contract',\n }),\n );\n }\n\n let fromContract: Contract | null = null;\n let fromHash: string | null = null;\n let fromContractSourceDir: string | null = null;\n\n try {\n const packages = await readMigrationsDir(migrationsDir);\n\n if (packages.length > 0) {\n const graph = reconstructGraph(packages);\n\n if (options.from) {\n const match = packages.find((p) => p.metadata.to.startsWith(options.from!));\n if (!match) {\n return notOk(\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.',\n }),\n );\n }\n fromHash = match.metadata.to;\n fromContract = match.metadata.toContract;\n fromContractSourceDir = match.dirPath;\n } else {\n const latestMigration = findLatestMigration(graph);\n if (latestMigration) {\n fromHash = latestMigration.to;\n const leafPkg = packages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n if (leafPkg) {\n fromContract = leafPkg.metadata.toContract;\n fromContractSourceDir = leafPkg.dirPath;\n }\n }\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n if (fromHash === toStorageHash) {\n return notOk(\n errorRuntime('No changes detected', {\n why: 'The from and to contract hashes are identical — there is nothing to migrate.',\n fix: 'Change the contract and run `prisma-next contract emit` before creating a new migration.',\n }),\n );\n }\n\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 // `migration new` scaffolds an empty `migration.ts` for the user to\n // fill, so we attest over `ops: []`. Re-running self-emit after the\n // user adds operations will produce a different `migrationHash` (over\n // the real ops). This is intentional — there is no on-disk draft.\n const baseMetadata: Omit<MigrationMetadata, 'migrationHash'> = {\n from: fromHash,\n to: toStorageHash,\n fromContract,\n toContract: toContractJson,\n hints: {\n used: [],\n applied: [],\n plannerVersion: '1.0.0',\n },\n labels: [],\n providedInvariants: [],\n createdAt: timestamp.toISOString(),\n };\n const metadata: MigrationMetadata = {\n ...baseMetadata,\n migrationHash: computeMigrationHash(baseMetadata, []),\n };\n\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.targetId}\" does not support migrations`,\n }),\n );\n }\n\n try {\n assertFrameworkComponentsCompatible(config.family.familyId, config.target.targetId, [\n config.target,\n config.adapter,\n ...(config.extensionPacks ?? []),\n ]);\n\n await writeMigrationPackage(packageDir, metadata, []);\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\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const planner = migrations.createPlanner(familyInstance);\n const emptyPlan = planner.emptyMigration({\n packageDir,\n contractJsonPath: join(packageDir, 'end-contract.json'),\n fromHash,\n toHash: toStorageHash,\n });\n await writeMigrationTs(packageDir, emptyPlan.renderTypeScript());\n\n return ok({\n ok: true as const,\n dir: relative(process.cwd(), packageDir),\n from: fromHash,\n to: toStorageHash,\n summary: `Scaffolded migration at ${relative(process.cwd(), packageDir)}`,\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: `Failed to scaffold migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n}\n\nexport function createMigrationNewCommand(): Command {\n const command = new Command('new');\n setCommandDescriptions(\n command,\n 'Scaffold a new migration for manual authoring',\n 'Creates a migration package with a migration.ts file for manual authoring.\\n' +\n 'Write the migration body in migration.ts, then run the file with Node\\n' +\n '(`node migration.ts`) to self-emit ops.json and attest the package.',\n );\n setCommandExamples(command, [\n 'prisma-next migration new --name split-name',\n 'prisma-next migration new --name custom-fk --from sha256:abc...',\n ]);\n addGlobalOptions(command)\n .option('--name <slug>', 'Migration name (used in directory name)')\n .option('--from <hash>', 'Starting contract hash (default: latest migration target)')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: MigrationNewOptions) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration new',\n description: 'Scaffold a new migration',\n details: [],\n flags,\n });\n ui.stderr(header);\n }\n\n const result = await executeMigrationNewCommand(options);\n\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value, null, 2));\n } else if (!flags.quiet) {\n ui.output(`\\nScaffolded migration at ${value.dir}`);\n ui.output(` from: ${value.from}`);\n ui.output(` to: ${value.to}`);\n ui.output(\n `\\nEdit migration.ts, then run it directly (\\`node \"${value.dir}/migration.ts\"\\`) to self-emit and attest.`,\n );\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
@@ -5,7 +5,7 @@ import { Result } from "@prisma-next/utils/result";
5
5
  interface MigrationPlanResult {
6
6
  readonly ok: boolean;
7
7
  readonly noOp: boolean;
8
- readonly from: string;
8
+ readonly from: string | null;
9
9
  readonly to: string;
10
10
  readonly dir?: string;
11
11
  readonly operations: readonly {
@@ -1 +1 @@
1
- {"version":3,"file":"migration-plan.d.mts","names":[],"sources":["../../src/commands/migration-plan.ts"],"sourcesContent":[],"mappings":";;;;UAyDiB,mBAAA;;EAAA,SAAA,IAAA,EAAA,OAAmB;EAwVpB,SAAA,IAAA,EAAA,MAAA;EA8HJ,SAAA,EAAA,EAAA,MAAA;EAiBI,SAAA,GAAA,CAAA,EAAA,MAAA;EACI,SAAA,UAAA,EAAA,SAAA;IAEV,SAAA,EAAA,EAAA,MAAA;IAAG,SAAA,KAAA,EAAA,MAAA;IAAV,SAAA,cAAA,EAAA,MAAA;EAAM,CAAA,EAAA;;;;;;;;;;;;;iBAlJO,0BAAA,CAAA,GAA8B;KA8HlC,uBAAA;;;;;;;;;;;;;;;;;;;iBAiBI;;;;qBACI,sBAEjB,OAAO,GAAG"}
1
+ {"version":3,"file":"migration-plan.d.mts","names":[],"sources":["../../src/commands/migration-plan.ts"],"sourcesContent":[],"mappings":";;;;UAwDiB,mBAAA;;EAAA,SAAA,IAAA,EAAA,OAAmB;EAuVpB,SAAA,IAAA,EAAA,MAAA,GAAA,IAAA;EA8HJ,SAAA,EAAA,EAAA,MAAA;EAiBI,SAAA,GAAA,CAAA,EAAA,MAAA;EACI,SAAA,UAAA,EAAA,SAAA;IAEV,SAAA,EAAA,EAAA,MAAA;IAAG,SAAA,KAAA,EAAA,MAAA;IAAV,SAAA,cAAA,EAAA,MAAA;EAAM,CAAA,EAAA;;;;;;;;;;;;;iBAlJO,0BAAA,CAAA,GAA8B;KA8HlC,uBAAA;;;;;;;;;;;;;;;;;;;iBAiBI;;;;qBACI,sBAEjB,OAAO,GAAG"}
@@ -12,7 +12,6 @@ import { readFile } from "node:fs/promises";
12
12
  import { createControlStack } from "@prisma-next/framework-components/control";
13
13
  import { copyFilesWithRename, formatMigrationDirName, writeMigrationPackage } from "@prisma-next/migration-tools/io";
14
14
  import { findLatestMigration } from "@prisma-next/migration-tools/migration-graph";
15
- import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
16
15
  import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
17
16
  import { computeMigrationHash } from "@prisma-next/migration-tools/hash";
18
17
  import { writeMigrationTs } from "@prisma-next/migration-tools/migration-ts";
@@ -76,7 +75,7 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
76
75
  if (typeof rawStorageHash !== "string") return notOk(errorContractValidationFailed("Contract is missing storageHash", { where: { path: contractPathAbsolute } }));
77
76
  const toStorageHash = rawStorageHash;
78
77
  let fromContract = null;
79
- let fromHash = EMPTY_CONTRACT_HASH;
78
+ let fromHash = null;
80
79
  let fromContractSourceDir = null;
81
80
  try {
82
81
  const { bundles, graph } = await loadMigrationPackages(migrationsDir);
@@ -132,7 +131,6 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
132
131
  const baseMetadata = {
133
132
  from: fromHash,
134
133
  to: toStorageHash,
135
- kind: "regular",
136
134
  fromContract,
137
135
  toContract: toContractJson,
138
136
  hints: {