prisma-next 0.12.0-dev.27 → 0.12.0-dev.29
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.
- package/dist/cli.mjs +12 -12
- package/dist/{client-V7BkIQrQ.mjs → client-xeWpMlq1.mjs} +22 -11
- package/dist/client-xeWpMlq1.mjs.map +1 -0
- package/dist/{command-helpers-DlrUCI7s.mjs → command-helpers-DK_5ItoJ.mjs} +253 -2
- package/dist/command-helpers-DK_5ItoJ.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +4 -5
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +10 -7
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +1 -1
- package/dist/commands/migrate.mjs +5 -6
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.d.mts +12 -15
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +84 -51
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +14 -5
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +1 -187
- package/dist/commands/migration-log.d.mts +2 -2
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.mjs +3 -4
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +21 -3
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -3
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +3 -3
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-DlZHXSkI.mjs → contract-at-errors-DG3kjgoz.mjs} +2 -2
- package/dist/{contract-at-errors-DlZHXSkI.mjs.map → contract-at-errors-DG3kjgoz.mjs.map} +1 -1
- package/dist/{contract-emit-S53EyBRV.mjs → contract-emit-BO0l6fnT.mjs} +3 -3
- package/dist/{contract-emit-S53EyBRV.mjs.map → contract-emit-BO0l6fnT.mjs.map} +1 -1
- package/dist/{contract-emit-CaKp92-Q.mjs → contract-emit-C0Bs0VRj.mjs} +3 -3
- package/dist/{contract-emit-CaKp92-Q.mjs.map → contract-emit-C0Bs0VRj.mjs.map} +1 -1
- package/dist/{contract-infer-Cebb-_Qx.mjs → contract-infer-2wtPflGH.mjs} +3 -3
- package/dist/{contract-infer-Cebb-_Qx.mjs.map → contract-infer-2wtPflGH.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-Dvl1SJ4C.mjs → contract-space-aggregate-loader-Dbr3-jHF.mjs} +3 -3
- package/dist/{contract-space-aggregate-loader-Dvl1SJ4C.mjs.map → contract-space-aggregate-loader-Dbr3-jHF.mjs.map} +1 -1
- package/dist/{db-verify-B1OoWEWn.mjs → db-verify-CxHiSiTG.mjs} +4 -4
- package/dist/{db-verify-B1OoWEWn.mjs.map → db-verify-CxHiSiTG.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/{framework-components-DCAT1uUC.mjs → framework-components-CxOVKAAh.mjs} +2 -2
- package/dist/{framework-components-DCAT1uUC.mjs.map → framework-components-CxOVKAAh.mjs.map} +1 -1
- package/dist/{init-Kf3T4A4W.mjs → init-R272pxux.mjs} +3 -3
- package/dist/{init-Kf3T4A4W.mjs.map → init-R272pxux.mjs.map} +1 -1
- package/dist/{inspect-live-schema-DTqflZ8X.mjs → inspect-live-schema-RekOwfi5.mjs} +3 -3
- package/dist/{inspect-live-schema-DTqflZ8X.mjs.map → inspect-live-schema-RekOwfi5.mjs.map} +1 -1
- package/dist/{migration-check-Ccyd0QKb.mjs → migration-check-Dc0cOhKH.mjs} +2 -2
- package/dist/{migration-check-Ccyd0QKb.mjs.map → migration-check-Dc0cOhKH.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-DI7_SFL0.mjs → migration-command-scaffold-ApB3NxWY.mjs} +3 -3
- package/dist/{migration-command-scaffold-DI7_SFL0.mjs.map → migration-command-scaffold-ApB3NxWY.mjs.map} +1 -1
- package/dist/{migration-graph-tree-render-DyDBuJEX.mjs → migration-graph-space-render-dmLLWift.mjs} +389 -210
- package/dist/migration-graph-space-render-dmLLWift.mjs.map +1 -0
- package/dist/migration-list-C5sXrl0U.mjs +228 -0
- package/dist/migration-list-C5sXrl0U.mjs.map +1 -0
- package/dist/{migration-list-types-DV9PBc7Z.d.mts → migration-list-types-DS63IdFd.d.mts} +1 -1
- package/dist/{migration-list-types-DV9PBc7Z.d.mts.map → migration-list-types-DS63IdFd.d.mts.map} +1 -1
- package/dist/{migration-log-Des4seHP.mjs → migration-log-DD_vCbYW.mjs} +4 -4
- package/dist/{migration-log-Des4seHP.mjs.map → migration-log-DD_vCbYW.mjs.map} +1 -1
- package/dist/{migration-plan-DxDTBzGS.mjs → migration-plan-CeTjQOIG.mjs} +5 -5
- package/dist/{migration-plan-DxDTBzGS.mjs.map → migration-plan-CeTjQOIG.mjs.map} +1 -1
- package/dist/{migration-status-CCwqA-vi.mjs → migration-status-qV8ctwPy.mjs} +61 -45
- package/dist/migration-status-qV8ctwPy.mjs.map +1 -0
- package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-V1o-9LVK.mjs} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-V1o-9LVK.mjs.map} +1 -1
- package/dist/{telemetry-LFFQmqHd.mjs → telemetry-S-NGi9U6.mjs} +2 -2
- package/dist/{telemetry-LFFQmqHd.mjs.map → telemetry-S-NGi9U6.mjs.map} +1 -1
- package/dist/{terminal-ui-C3xGyxW-.d.mts → terminal-ui-5Y6mrg93.d.mts} +1 -1
- package/dist/{terminal-ui-C3xGyxW-.d.mts.map → terminal-ui-5Y6mrg93.d.mts.map} +1 -1
- package/dist/{types-BdS8PoKM.d.mts → types-Mh7mdPHM.d.mts} +5 -1
- package/dist/types-Mh7mdPHM.d.mts.map +1 -0
- package/dist/{verify-C0TARc6h.mjs → verify-BdI-BgYi.mjs} +2 -2
- package/dist/{verify-C0TARc6h.mjs.map → verify-BdI-BgYi.mjs.map} +1 -1
- package/package.json +11 -11
- package/dist/client-V7BkIQrQ.mjs.map +0 -1
- package/dist/command-helpers-DlrUCI7s.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/migration-graph-tree-render-DyDBuJEX.mjs.map +0 -1
- package/dist/migration-status-CCwqA-vi.mjs.map +0 -1
- package/dist/migration-types-CAQ-0TEE.d.mts +0 -15
- package/dist/migration-types-CAQ-0TEE.d.mts.map +0 -1
- package/dist/migrations-B3H6RTXb.mjs +0 -228
- package/dist/migrations-B3H6RTXb.mjs.map +0 -1
- package/dist/types-BdS8PoKM.d.mts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client-V7BkIQrQ.mjs","names":["SPAN_IDS","emitContractArtifacts"],"sources":["../src/control-api/errors.ts","../src/control-api/operations/apply.ts","../src/control-api/operations/migration-helpers.ts","../src/control-api/operations/db-apply.ts","../src/control-api/operations/db-init.ts","../src/control-api/operations/db-update.ts","../src/control-api/operations/db-verify.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 { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n MigrationOperationPolicy,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport type { ContractSpaceAggregate, PerSpacePlan } from '@prisma-next/migration-tools/aggregate';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport type { OnControlProgress, PerSpaceExecutionEntry } from '../types';\n\n/**\n * Span id emitted via `onProgress` for the apply phase. Stable\n * identifier consumed by the structured-output renderer and by tests.\n */\nconst APPLY_SPAN_ID = 'apply' as const;\n\n/**\n * Action that originated this apply call. Threaded into `OnControlProgress`\n * events so the parent CLI command can attribute the span correctly,\n * and used to compose action-specific summary phrasing.\n */\nexport type ApplyAction = 'dbInit' | 'dbUpdate' | 'migrationApply';\n\n/**\n * Failure variant emitted by {@link applyMigration} when the runner\n * itself rejects the apply. Mirrors the failure shape callers\n * already wrap into their own action-specific failure envelopes\n * (`DbInitFailure`, `DbUpdateFailure`, `MigrationApplyFailure`) so each\n * caller keeps owning its own discriminated failure code.\n */\nexport interface ApplyRunnerFailure {\n readonly summary: string;\n readonly why?: string;\n readonly meta: Record<string, unknown>;\n}\n\nexport interface ApplyMigrationInputs<TFamilyId extends string, TTargetId extends string> {\n readonly aggregate: ContractSpaceAggregate;\n /**\n * Per-space plans, keyed by `spaceId`. Produced by either the full\n * {@link planMigration} pipeline (`db init` / `db update` — synth\n * for the app, graph-walk for extensions) or by direct\n * {@link graphWalkStrategy} calls (`migrate` — graph-walk\n * for every member). Either way, the runner consumes the same shape.\n */\n readonly perSpacePlans: ReadonlyMap<string, PerSpacePlan>;\n /**\n * Canonical schedule order — extensions alphabetically by `spaceId`,\n * then app. Mirrors {@link import('@prisma-next/migration-tools/concatenate-space-apply-inputs').concatenateSpaceApplyInputs}'s\n * convention so `MigrationRunnerFailure.failingSpace` attribution\n * stays byte-for-byte stable across callers.\n */\n readonly applyOrder: readonly string[];\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly policy: MigrationOperationPolicy;\n readonly action: ApplyAction;\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Resolved per-space plan in canonical schedule order. Surfaced from\n * {@link applyMigration} to callers so each one can build its own\n * action-specific success envelope (e.g. `DbInitSuccess` vs\n * `MigrationApplySuccess`) without re-deriving the ordering.\n */\nexport interface OrderedResolution {\n readonly spaceId: string;\n readonly entry: PerSpacePlan;\n}\n\nexport interface ApplyMigrationValue {\n readonly orderedResolutions: readonly OrderedResolution[];\n readonly totalOpsPlanned: number;\n readonly totalOpsExecuted: number;\n /**\n * Per-space breakdown ready to thread into action-specific success\n * envelopes. Each entry carries the post-apply marker (live storage hash\n * plus invariants) so callers can render it directly without re-reading.\n */\n readonly perSpace: readonly PerSpaceExecutionEntry[];\n}\n\nexport type ApplyMigrationResult = Result<ApplyMigrationValue, ApplyRunnerFailure>;\n\n/**\n * Runner-driving tail shared by every apply caller — `db init`,\n * `db update`, and `migrate`. Consumes already-resolved per-space\n * plans (the planner-vs-replay distinction is owned by the caller) and\n * dispatches them to the runner in canonical order.\n *\n * Marker advancement is part of the runner's per-space transaction\n * (the SQL family runner writes the marker as the last step of each\n * space's transaction), so this primitive does not advance markers\n * separately — by the time `execute` returns ok, every\n * space's marker has been advanced to its plan's destination.\n *\n * Span emission (`spanStart 'apply'` / `spanEnd 'apply'`) is owned here\n * so callers don't have to duplicate it; the `action` field on each\n * progress event is taken from the caller's `action` argument.\n */\nexport async function applyMigration<TFamilyId extends string, TTargetId extends string>(\n inputs: ApplyMigrationInputs<TFamilyId, TTargetId>,\n): Promise<ApplyMigrationResult> {\n const {\n aggregate,\n perSpacePlans,\n applyOrder,\n driver,\n familyInstance,\n migrations,\n frameworkComponents,\n policy,\n action,\n onProgress,\n } = inputs;\n\n const orderedResolutions = collectOrdered(applyOrder, perSpacePlans);\n\n const runner = migrations.createRunner(familyInstance);\n\n onProgress?.({\n action,\n kind: 'spanStart',\n spanId: APPLY_SPAN_ID,\n label: progressLabelForAction(action),\n });\n\n const perSpaceOptions = orderedResolutions.map((r) => ({\n space: r.spaceId,\n plan: r.entry.plan,\n driver,\n destinationContract: r.entry.destinationContract,\n policy,\n frameworkComponents,\n migrationEdges: r.entry.migrationEdges,\n // Per-space post-apply schema verification is non-strict: each\n // space's `destinationContract` describes only its own slice; a\n // strict verifier would treat every other space's tables as\n // `extras`. Tolerant mode still catches missing tables / columns.\n strictVerification: false,\n }));\n\n const runnerResult = await runner.execute({ driver, perSpaceOptions });\n\n if (!runnerResult.ok) {\n onProgress?.({ action, kind: 'spanEnd', spanId: APPLY_SPAN_ID, outcome: 'error' });\n return notOk({\n summary: runnerResult.failure.summary,\n ...ifDefined('why', runnerResult.failure.why),\n meta: {\n ...(runnerResult.failure.meta ?? {}),\n failingSpace: runnerResult.failure.failingSpace,\n runnerErrorCode: runnerResult.failure.code,\n },\n });\n }\n onProgress?.({ action, kind: 'spanEnd', spanId: APPLY_SPAN_ID, outcome: 'ok' });\n\n const totalOpsPlanned = runnerResult.value.perSpaceResults.reduce(\n (sum, r) => sum + r.value.operationsPlanned,\n 0,\n );\n const totalOpsExecuted = runnerResult.value.perSpaceResults.reduce(\n (sum, r) => sum + r.value.operationsExecuted,\n 0,\n );\n\n const perSpace = buildPerSpaceBreakdown(orderedResolutions, aggregate.app.spaceId, {\n includeMarkers: true,\n });\n\n return ok({\n orderedResolutions,\n totalOpsPlanned,\n totalOpsExecuted,\n perSpace,\n });\n}\n\n/**\n * Project the planner's per-space resolutions into the\n * `PerSpaceExecutionEntry[]` shape the CLI surfaces.\n *\n * `includeMarkers` is `true` for apply-mode (each space's marker is\n * the `destination.storageHash` of its plan, which the runner\n * advances as the last step of each space's transaction) and `false`\n * for plan-mode (no marker has been written yet).\n *\n * Exported alongside {@link applyMigration} so plan-mode callers can\n * assemble the same per-space block without going through the runner.\n */\nexport function buildPerSpaceBreakdown(\n orderedResolutions: readonly OrderedResolution[],\n appSpaceId: string,\n options: { readonly includeMarkers: boolean },\n): readonly PerSpaceExecutionEntry[] {\n return orderedResolutions.map((r) => {\n const operations = r.entry.displayOps.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n }));\n const base: PerSpaceExecutionEntry = {\n spaceId: r.spaceId,\n kind: r.spaceId === appSpaceId ? 'app' : 'extension',\n operations,\n };\n if (!options.includeMarkers) return base;\n return {\n ...base,\n marker: { storageHash: r.entry.plan.destination.storageHash },\n };\n });\n}\n\n/**\n * Materialise the `applyOrder` ordering into resolved per-space\n * entries. Throws if the planner output is missing a member listed\n * in `applyOrder` — a wiring bug that should never reach runtime.\n *\n * Exported so callers building their own success envelopes after a\n * plan-mode dispatch can replay the same ordering.\n */\nexport function collectOrdered(\n applyOrder: readonly string[],\n perSpace: ReadonlyMap<string, PerSpacePlan>,\n): readonly OrderedResolution[] {\n return applyOrder.map((spaceId) => {\n const entry = perSpace.get(spaceId);\n if (!entry) {\n throw new Error(`planner output missing per-space plan for \"${spaceId}\"`);\n }\n return { spaceId, entry };\n });\n}\n\n/**\n * Action-appropriate label for the `spanStart` event the apply\n * primitive emits. `applyMigration` is shared by `db init`, `db update`,\n * and `migrate`; the span label tracks the user-visible action\n * so structured-progress output reads naturally for each surface.\n */\nexport function progressLabelForAction(action: ApplyAction): string {\n switch (action) {\n case 'dbInit':\n return 'Initialising database across spaces';\n case 'dbUpdate':\n return 'Updating database across spaces';\n case 'migrationApply':\n return 'Applying migration plan across spaces';\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 ControlExtensionDescriptor,\n ControlFamilyInstance,\n MigrationOperationPolicy,\n MigrationPlanOperation,\n OperationPreview,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { hasOperationPreview } from '@prisma-next/framework-components/control';\nimport {\n type ContractSpaceAggregate,\n type PlannerError,\n planMigration,\n} from '@prisma-next/migration-tools/aggregate';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { CliStructuredError } from '../../utils/cli-errors';\nimport {\n type BuildAggregateInputs,\n buildContractSpaceAggregate,\n} from '../../utils/contract-space-aggregate-loader';\nimport type {\n DbInitFailure,\n DbInitResult,\n DbInitSuccess,\n DbUpdateFailure,\n DbUpdateResult,\n DbUpdateSuccess,\n OnControlProgress,\n PerSpaceExecutionEntry,\n} from '../types';\nimport { applyMigration, buildPerSpaceBreakdown, collectOrdered } from './apply';\nimport { stripOperations } from './migration-helpers';\n\n/**\n * Span IDs emitted via `onProgress` during the apply flow.\n * Stable identifiers consumed by the structured-output renderer and by\n * tests asserting on span ids. The `apply` span itself is owned by\n * the {@link applyMigration} primitive — only the introspect / plan\n * spans are emitted directly here.\n */\nconst SPAN_IDS = {\n introspect: 'introspect',\n plan: 'plan',\n} as const;\n\n/**\n * Inputs shared by `db init` and `db update` apply flows.\n *\n * Accepts the already-validated app contract + descriptor list — the\n * loader gathers the rest from disk + descriptors. The CLI is the\n * descriptor-import boundary; everything downstream is descriptor-free.\n */\nexport interface ExecuteApplyOptions<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 migrationsDir: string;\n readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n readonly targetId: TTargetId;\n readonly policy: MigrationOperationPolicy;\n readonly action: 'dbInit' | 'dbUpdate';\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Loader → planner → runner pipeline shared by `db init` and `db update`.\n *\n * The pipeline:\n *\n * 1. **Load**: build a {@link ContractSpaceAggregate} from the descriptor\n * set + on-disk on-disk artefacts. Any layout / drift / disjointness /\n * integrity violation short-circuits with a structured error.\n * 2. **Read DB state**: marker rows (`familyInstance.readAllMarkers`)\n * + introspected schema (`familyInstance.introspect`).\n * 3. **Plan**: {@link planMigration} chooses graph-walk vs synth per\n * member according to `callerPolicy.ignoreGraphFor`. The app member\n * is forced through synth (today's daily-driver behaviour); every\n * extension member walks its on-disk graph.\n * 4. **Apply** (when `mode === 'apply'`): every per-space `MigrationPlan`\n * feeds into the runner's `execute` — one outer\n * transaction across every space; failure on any space rolls back\n * every space's writes.\n */\nexport async function executeApply<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteApplyOptions<TFamilyId, TTargetId>,\n): Promise<DbInitResult | DbUpdateResult> {\n const {\n driver,\n familyInstance,\n contract,\n mode,\n migrations,\n frameworkComponents,\n migrationsDir,\n extensionPacks,\n targetId,\n policy,\n action,\n onProgress,\n } = options;\n\n // 1. Load aggregate from descriptors + on-disk state.\n const loadInputs: BuildAggregateInputs<TFamilyId, TTargetId> = {\n targetId,\n migrationsDir,\n appContract: contract,\n extensionPacks,\n deserializeContract: (json) => familyInstance.deserializeContract(json),\n };\n const loaded = await buildContractSpaceAggregate(loadInputs);\n if (!loaded.ok) {\n throw loaded.failure;\n }\n const aggregate = loaded.value;\n\n // 2. Read live DB state (markers + schema).\n const markerRows = await familyInstance.readAllMarkers({ driver });\n\n // 2a. Orphan-marker pre-flight: refuse to *apply* when a marker row\n // exists for a space that is not declared in the aggregate. Plan mode\n // (`db init/update --dry-run`) must still be able to introspect the\n // aggregate plan in this state — a retired extension whose marker\n // happens to linger should not block the user from inspecting what a\n // run would do. Apply mode tells the user to clean up the orphan\n // before silently advancing the app's marker.\n if (mode === 'apply') {\n const orphanMarkerError = detectOrphanMarkers(aggregate, markerRows);\n if (orphanMarkerError !== null) {\n throw orphanMarkerError;\n }\n }\n\n onProgress?.({\n action,\n kind: 'spanStart',\n spanId: SPAN_IDS.introspect,\n label: 'Introspecting database schema',\n });\n const schemaIR = await familyInstance.introspect({ driver });\n onProgress?.({ action, kind: 'spanEnd', spanId: SPAN_IDS.introspect, outcome: 'ok' });\n\n // 3. Plan via aggregate planner. App is forced through synth (today's\n // `db init` / `db update` daily-driver behaviour); extensions walk\n // their on-disk migration graphs.\n onProgress?.({\n action,\n kind: 'spanStart',\n spanId: SPAN_IDS.plan,\n label: 'Planning migration',\n });\n const planResult = await planMigration<TFamilyId, TTargetId>({\n aggregate,\n currentDBState: { markersBySpaceId: markerRows, schemaIntrospection: schemaIR },\n familyInstance,\n migrations,\n frameworkComponents,\n callerPolicy: { ignoreGraphFor: new Set([aggregate.app.spaceId]) },\n operationPolicy: policy,\n });\n if (!planResult.ok) {\n onProgress?.({ action, kind: 'spanEnd', spanId: SPAN_IDS.plan, outcome: 'error' });\n return mapPlannerError(planResult.failure);\n }\n onProgress?.({ action, kind: 'spanEnd', spanId: SPAN_IDS.plan, outcome: 'ok' });\n\n const orderedResolutions = collectOrdered(planResult.value.applyOrder, planResult.value.perSpace);\n\n // The destination's structural shape comes from the app's plan — its\n // `destination` is the storage hash users see in CLI output.\n const appResolution = orderedResolutions.find((r) => r.spaceId === aggregate.app.spaceId);\n if (!appResolution) {\n throw new Error(\n 'Aggregate planner returned no plan for the app member — the planner is supposed to always emit one.',\n );\n }\n const appPlan = appResolution.entry.plan;\n\n // 4. Plan-mode: surface aggregate operations without applying.\n if (mode === 'plan') {\n const aggregateOps = orderedResolutions.flatMap((r) => r.entry.displayOps);\n const preview = hasOperationPreview(familyInstance)\n ? familyInstance.toOperationPreview(aggregateOps)\n : undefined;\n const perSpace = buildPerSpaceBreakdown(orderedResolutions, aggregate.app.spaceId, {\n includeMarkers: false,\n });\n const summary = `Planned ${aggregateOps.length} operation(s) across ${orderedResolutions.length} space(s)`;\n return wrapPlanResult({\n operations: aggregateOps,\n destination: appPlan.destination,\n preview,\n perSpace,\n summary,\n });\n }\n\n // 5. Apply mode: hand off to the shared `applyMigration` primitive.\n // The runner-driving tail is identical for `db init` / `db update` /\n // `migrate` — only how each caller produces `perSpacePlans`\n // differs (synth + graph-walk via planMigration here; graph-walk\n // only for migrate). Each caller produces perSpacePlans differently;\n // this helper handles the shared apply tail.\n const applied = await applyMigration({\n aggregate,\n perSpacePlans: planResult.value.perSpace,\n applyOrder: planResult.value.applyOrder,\n driver,\n familyInstance,\n migrations,\n frameworkComponents,\n policy,\n action,\n ...ifDefined('onProgress', onProgress),\n });\n if (!applied.ok) {\n return buildRunnerFailure({\n summary: applied.failure.summary,\n ...ifDefined('why', applied.failure.why),\n meta: applied.failure.meta,\n });\n }\n\n const aggregateOps = applied.value.orderedResolutions.flatMap((r) => r.entry.displayOps);\n const summary =\n action === 'dbInit'\n ? `Applied ${applied.value.totalOpsExecuted} operation(s) across ${applied.value.orderedResolutions.length} space(s), database signed`\n : applied.value.totalOpsExecuted === 0\n ? `Database already matches contract across ${applied.value.orderedResolutions.length} space(s), signature updated`\n : `Applied ${applied.value.totalOpsExecuted} operation(s) across ${applied.value.orderedResolutions.length} space(s), signature updated`;\n\n return wrapApplyResult({\n operations: aggregateOps,\n destination: appPlan.destination,\n operationsPlanned: applied.value.totalOpsPlanned,\n operationsExecuted: applied.value.totalOpsExecuted,\n perSpace: applied.value.perSpace,\n summary,\n });\n}\n\n/**\n * Compare the live `_prisma_marker` rows against the aggregate's\n * declared members. Any marker row whose `space` is not a member of\n * the aggregate is an \"orphan\" — typically a marker left behind by\n * an extension that was removed from `extensionPacks` without first\n * cleaning up its on-disk migrations / database tables.\n *\n * Returns a {@link CliStructuredError} envelope (code `5002`,\n * `kind: 'orphanMarker'`) for the first orphan it finds, or `null`\n * when every marker row maps to a declared member. Mirrors the M2\n * `runContractSpaceVerifierMarkerCheck` envelope so downstream\n * tooling (integration tests, JSON consumers) keeps asserting on the\n * same shape.\n */\nfunction detectOrphanMarkers(\n aggregate: ContractSpaceAggregate,\n markerRows: ReadonlyMap<string, unknown>,\n): CliStructuredError | null {\n const memberSpaceIds = new Set<string>([\n aggregate.app.spaceId,\n ...aggregate.extensions.map((m) => m.spaceId),\n ]);\n const orphans: string[] = [];\n for (const [spaceId, row] of markerRows) {\n if (row !== null && row !== undefined && !memberSpaceIds.has(spaceId)) {\n orphans.push(spaceId);\n }\n }\n if (orphans.length === 0) return null;\n orphans.sort((a, b) => a.localeCompare(b));\n const summary =\n orphans.length === 1\n ? `Orphan contract-space marker detected for \"${orphans[0]}\"`\n : `Orphan contract-space markers detected for ${orphans.length} spaces`;\n return new CliStructuredError('5002', summary, {\n domain: 'MIG',\n why: `The database has \\`_prisma_marker\\` rows for spaces (${orphans\n .map((s) => `\"${s}\"`)\n .join(\n ', ',\n )}) that are not declared in the project's \\`extensionPacks\\`. The aggregate pipeline refuses to advance markers it cannot account for.`,\n fix: 'Either re-declare the missing extension(s) in `extensionPacks` (so the aggregate owns them again), or remove the orphan marker row(s) from `_prisma_marker` once you have confirmed the corresponding tables can be safely retired.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: orphans.map((spaceId) => ({ kind: 'orphanMarker', spaceId })),\n },\n });\n}\n\nfunction mapPlannerError(error: PlannerError): DbInitResult | DbUpdateResult {\n if (error.kind === 'appSynthFailure') {\n const failure: DbInitFailure | DbUpdateFailure = {\n code: 'PLANNING_FAILED',\n summary: 'Migration planning failed due to conflicts',\n conflicts: error.conflicts,\n why: undefined,\n meta: undefined,\n };\n return notOk(failure) as DbInitResult | DbUpdateResult;\n }\n if (error.kind === 'extensionPathUnreachable') {\n return buildRunnerFailure({\n summary: `Cannot resolve apply path for extension space \"${error.spaceId}\"`,\n why: `No path in the on-disk migration graph for extension space \"${error.spaceId}\" reaches the on-disk head ref hash \"${error.target}\".`,\n meta: { spaceId: error.spaceId, target: error.target },\n });\n }\n if (error.kind === 'extensionPathUnsatisfiable') {\n return buildRunnerFailure({\n summary: `Cannot resolve apply path for extension space \"${error.spaceId}\"`,\n why: `On-disk migration graph for extension space \"${error.spaceId}\" reaches the on-disk head ref but does not cover required invariants: ${error.missingInvariants.join(', ')}.`,\n meta: { spaceId: error.spaceId, missingInvariants: error.missingInvariants },\n });\n }\n // policyConflict — surfaces as a runner-style failure naming the\n // space; conceptually a configuration bug, but mapping it onto the\n // existing failure surface keeps callers untouched.\n return buildRunnerFailure({\n summary: `Aggregate planner policy conflict for space \"${error.spaceId}\"`,\n why: error.detail,\n meta: { spaceId: error.spaceId },\n });\n}\n\nfunction wrapPlanResult(args: {\n readonly operations: readonly MigrationPlanOperation[];\n readonly destination: { readonly storageHash: string; readonly profileHash?: string };\n readonly preview: OperationPreview | undefined;\n readonly perSpace: readonly PerSpaceExecutionEntry[];\n readonly summary: string;\n}): DbInitResult | DbUpdateResult {\n const success: DbInitSuccess | DbUpdateSuccess = {\n mode: 'plan',\n plan: {\n operations: stripOperations(args.operations),\n ...ifDefined('preview', args.preview),\n },\n destination: {\n storageHash: args.destination.storageHash,\n ...ifDefined('profileHash', args.destination.profileHash),\n },\n perSpace: args.perSpace,\n summary: args.summary,\n };\n return ok(success);\n}\n\nfunction wrapApplyResult(args: {\n readonly operations: readonly MigrationPlanOperation[];\n readonly destination: { readonly storageHash: string; readonly profileHash?: string };\n readonly operationsPlanned: number;\n readonly operationsExecuted: number;\n readonly perSpace: readonly PerSpaceExecutionEntry[];\n readonly summary: string;\n}): DbInitResult | DbUpdateResult {\n const success: DbInitSuccess | DbUpdateSuccess = {\n mode: 'apply',\n plan: { operations: stripOperations(args.operations) },\n destination: {\n storageHash: args.destination.storageHash,\n ...ifDefined('profileHash', args.destination.profileHash),\n },\n execution: {\n operationsPlanned: args.operationsPlanned,\n operationsExecuted: args.operationsExecuted,\n },\n marker: args.destination.profileHash\n ? { storageHash: args.destination.storageHash, profileHash: args.destination.profileHash }\n : { storageHash: args.destination.storageHash },\n perSpace: args.perSpace,\n summary: args.summary,\n };\n return ok(success);\n}\n\nfunction buildRunnerFailure(args: {\n readonly summary: string;\n readonly why?: string;\n readonly meta: Record<string, unknown>;\n}): DbInitResult | DbUpdateResult {\n const failure: DbInitFailure | DbUpdateFailure = {\n code: 'RUNNER_FAILED',\n summary: args.summary,\n why: args.why,\n meta: args.meta,\n conflicts: undefined,\n };\n return notOk(failure) as DbInitResult | DbUpdateResult;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlFamilyInstance,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { DbInitResult, OnControlProgress } from '../types';\nimport { executeApply } from './db-apply';\n\n/**\n * Options for executing the `db init` operation.\n *\n * `db init` runs the loader → planner → runner pipeline:\n *\n * 1. {@link executeApply} loads a `ContractSpaceAggregate` via\n * {@link import('@prisma-next/migration-tools/aggregate').loadContractSpaceAggregate}\n * from the supplied descriptor set + on-disk on-disk artefacts.\n * 2. The aggregate planner runs with `callerPolicy.ignoreGraphFor`\n * locked to the app member — synth strategy for the app, graph-walk\n * for every extension.\n * 3. The runner's `execute` applies the per-space plans\n * inside one outer transaction.\n *\n * `extensionPacks` mirrors `Config.extensionPacks` (descriptor list).\n * The loader (sub-spec § Loader) is the sole descriptor-import boundary.\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 /**\n * On-disk migrations directory the aggregate loader reads on-disk\n * artefacts from. Required.\n */\n readonly migrationsDir: string;\n /**\n * Resolved adapter target id. Threaded through to the loader for\n * target-consistency checks across descriptors and the app contract.\n */\n readonly targetId: TTargetId;\n /**\n * Declared extension descriptors. Defaults to an empty list, which\n * routes through the same loader → planner → runner pipeline with no\n * extension members in the aggregate.\n */\n readonly extensionPacks?: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n /** Optional progress callback for observing operation progress */\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Execute `db init` against the configured contract.\n *\n * Routes through the loader → planner → runner pipeline (sub-spec\n * \"Commit-by-commit § Commit 4\"). Always additive-only; destructive\n * changes belong to `db update`.\n */\nexport async function executeDbInit<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbInitOptions<TFamilyId, TTargetId>,\n): Promise<DbInitResult> {\n const result = await executeApply<TFamilyId, TTargetId>({\n driver: options.driver,\n familyInstance: options.familyInstance,\n contract: options.contract,\n mode: options.mode,\n migrations: options.migrations,\n frameworkComponents: options.frameworkComponents,\n migrationsDir: options.migrationsDir,\n targetId: options.targetId,\n extensionPacks: options.extensionPacks ?? [],\n policy: { allowedOperationClasses: ['additive'] },\n action: 'dbInit',\n ...ifDefined('onProgress', options.onProgress),\n });\n return result as DbInitResult;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlFamilyInstance,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk } from '@prisma-next/utils/result';\nimport type { DbUpdateResult, OnControlProgress } from '../types';\nimport { executeApply } from './db-apply';\n\nconst DB_UPDATE_POLICY = {\n allowedOperationClasses: ['additive', 'widening', 'destructive'] as const,\n} as const;\n\n/**\n * Options for the `db update` operation.\n *\n * Same loader → planner → runner pipeline as `db init`, but with the\n * widened operation policy (additive + widening + destructive). The\n * destructive-change confirmation gate runs at this layer: when\n * `mode === 'apply'` and `acceptDataLoss` is `false`, the operation\n * pre-plans, surfaces destructive ops to the caller, and aborts.\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 readonly migrationsDir: string;\n readonly targetId: TTargetId;\n readonly extensionPacks?: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Execute `db update` against the configured contract.\n *\n * Routes through the loader → planner → runner pipeline. Destructive\n * operations require either `acceptDataLoss: true` or a prior\n * `mode: 'plan'` invocation that surfaces the destructive ops; the\n * confirmation gate is implemented here so the lower-level applier\n * remains policy-agnostic.\n */\nexport async function executeDbUpdate<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbUpdateOptions<TFamilyId, TTargetId>,\n): Promise<DbUpdateResult> {\n const sharedInputs = {\n driver: options.driver,\n familyInstance: options.familyInstance,\n contract: options.contract,\n migrations: options.migrations,\n frameworkComponents: options.frameworkComponents,\n migrationsDir: options.migrationsDir,\n targetId: options.targetId,\n extensionPacks: options.extensionPacks ?? [],\n policy: DB_UPDATE_POLICY,\n action: 'dbUpdate' as const,\n ...ifDefined('onProgress', options.onProgress),\n };\n if (options.mode === 'apply' && !options.acceptDataLoss) {\n const gate = await guardDestructiveChanges<TFamilyId, TTargetId>(sharedInputs);\n if (gate !== null) return gate;\n }\n return (await executeApply<TFamilyId, TTargetId>({\n ...sharedInputs,\n mode: options.mode,\n })) as DbUpdateResult;\n}\n\n/**\n * Pre-plan once when running `db update apply` without `acceptDataLoss`.\n * Surfaces destructive operations across every space; if any are\n * planned, returns a `DESTRUCTIVE_CHANGES` failure that the CLI shows\n * as a confirmation prompt. Returns `null` when the apply is safe to\n * run.\n */\nasync function guardDestructiveChanges<TFamilyId extends string, TTargetId extends string>(\n sharedInputs: Omit<Parameters<typeof executeApply<TFamilyId, TTargetId>>[0], 'mode'>,\n): Promise<DbUpdateResult | null> {\n const planResult = (await executeApply<TFamilyId, TTargetId>({\n ...sharedInputs,\n mode: 'plan',\n })) as DbUpdateResult;\n if (!planResult.ok) return planResult;\n const destructiveOps = planResult.value.plan.operations\n .filter((op) => op.operationClass === 'destructive')\n .map((op) => ({ id: op.id, label: op.label }));\n if (destructiveOps.length === 0) return null;\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","import type { Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlExtensionDescriptor,\n ControlFamilyInstance,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n type ContractSpaceMember,\n requireHeadRef,\n type VerifierOutput,\n verifyMigration,\n} from '@prisma-next/migration-tools/aggregate';\nimport { castAs } from '@prisma-next/utils/casts';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { CliStructuredError } from '../../utils/cli-errors';\nimport {\n type BuildAggregateInputs,\n buildContractSpaceAggregate,\n} from '../../utils/contract-space-aggregate-loader';\nimport type { OnControlProgress } from '../types';\n\n/**\n * Span IDs emitted via `onProgress` during the aggregate verify flow.\n * Mirrors the span identifiers used by the legacy precheck / marker-check\n * helpers so structured-output renderers and progress tests keep working.\n */\nconst SPAN_IDS = {\n introspect: 'introspect',\n verify: 'verify',\n} as const;\n\n/**\n * Inputs for the aggregate `db verify` operation.\n *\n * Loader → verifier pipeline. The loader (sole descriptor-import\n * boundary) builds a {@link import('@prisma-next/migration-tools/aggregate').ContractSpaceAggregate};\n * the aggregate verifier bundles `markerCheck` + per-space pre-projected\n * `schemaCheck`. `mode: 'strict' | 'lenient'` maps directly to the user\n * facing `--strict` flag.\n */\nexport interface ExecuteDbVerifyOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly contract: Contract;\n readonly migrationsDir: string;\n readonly targetId: TTargetId;\n readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly mode: 'strict' | 'lenient';\n readonly skipSchema: boolean;\n readonly skipMarker: boolean;\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Result of the aggregate verify operation.\n *\n * Marker-check failures are surfaced as a {@link CliStructuredError}\n * (same envelope code `5002` the legacy `runContractSpaceVerifierMarkerCheck`\n * emitted, so downstream tooling and integration tests assert on the\n * same shape).\n *\n * On success, the per-space schema results are returned for the CLI to\n * render. When `skipSchema` is true (`--marker-only`), the schema map\n * is empty.\n */\nexport interface ExecuteDbVerifySuccess {\n readonly schemaResults: ReadonlyMap<string, VerifyDatabaseSchemaResult>;\n readonly memberOrder: readonly string[];\n readonly appSpaceId: string;\n}\n\nexport type ExecuteDbVerifyResult = Result<ExecuteDbVerifySuccess, CliStructuredError>;\n\n/**\n * Loader → verifier pipeline shared by `db verify` modes (`full`,\n * `marker-only`, `schema-only`).\n *\n * 1. **Load**: build a {@link import('@prisma-next/migration-tools/aggregate').ContractSpaceAggregate}\n * from descriptors + on-disk on-disk artefacts. Layout / drift /\n * integrity / disjointness violations short-circuit with a\n * structured CLI error.\n * 2. **Read DB state**: marker rows + (when `skipSchema` is `false`)\n * schema introspection.\n * 3. **Verify**: {@link verifyMigration} returns per-space\n * `markerCheck` + per-space pre-projected `schemaCheck` (closes F23).\n * Marker mismatches map to `CliStructuredError` (code `5002`) so\n * callers (CLI command) can render and exit. Schema results are\n * returned to the caller verbatim.\n */\nexport async function executeDbVerify<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbVerifyOptions<TFamilyId, TTargetId>,\n): Promise<ExecuteDbVerifyResult> {\n const { driver, familyInstance, onProgress, skipSchema, skipMarker } = options;\n const loaded = await buildContractSpaceAggregate(buildLoadInputs(options));\n if (!loaded.ok) return notOk(loaded.failure);\n const aggregate = loaded.value;\n\n const markersBySpaceId = await familyInstance.readAllMarkers({ driver });\n const schemaIntrospection = skipSchema\n ? null\n : await runIntrospection({ driver, familyInstance, onProgress });\n\n emitVerifySpan(onProgress, 'spanStart');\n const verifyResult = verifyMigration({\n aggregate,\n markersBySpaceId,\n schemaIntrospection,\n mode: options.mode,\n verifySchemaForMember: createPerMemberVerifier(options),\n });\n return finaliseVerifyResult({ verifyResult, aggregate, skipMarker, onProgress });\n}\n\nfunction buildLoadInputs<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbVerifyOptions<TFamilyId, TTargetId>,\n): BuildAggregateInputs<TFamilyId, TTargetId> {\n return {\n targetId: options.targetId,\n migrationsDir: options.migrationsDir,\n appContract: options.contract,\n extensionPacks: options.extensionPacks,\n deserializeContract: (json) => options.familyInstance.deserializeContract(json),\n };\n}\n\nasync function runIntrospection<TFamilyId extends string, TTargetId extends string>(args: {\n driver: ControlDriverInstance<TFamilyId, TTargetId>;\n familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n onProgress: OnControlProgress | undefined;\n}): Promise<unknown> {\n const { driver, familyInstance, onProgress } = args;\n onProgress?.({\n action: 'dbVerify',\n kind: 'spanStart',\n spanId: SPAN_IDS.introspect,\n label: 'Introspecting database schema',\n });\n try {\n const result = await familyInstance.introspect({ driver });\n onProgress?.({\n action: 'dbVerify',\n kind: 'spanEnd',\n spanId: SPAN_IDS.introspect,\n outcome: 'ok',\n });\n return result;\n } catch (error) {\n onProgress?.({\n action: 'dbVerify',\n kind: 'spanEnd',\n spanId: SPAN_IDS.introspect,\n outcome: 'error',\n });\n throw error;\n }\n}\n\n/**\n * Build the per-member schema callback handed to the aggregate verifier.\n * When `skipSchema` is true the callback short-circuits with a synthetic\n * `ok` result so the verifier still runs the (cheap) schemaCheck loop\n * without invoking the family's verification path.\n */\nexport function createPerMemberVerifier<TFamilyId extends string, TTargetId extends string>(\n options: ExecuteDbVerifyOptions<TFamilyId, TTargetId>,\n): (\n projectedSchema: unknown,\n member: ContractSpaceMember,\n verifyMode: 'strict' | 'lenient',\n) => VerifyDatabaseSchemaResult {\n const { skipSchema, familyInstance, frameworkComponents } = options;\n return (projectedSchema, member, verifyMode) => {\n if (skipSchema) return buildSkippedSchemaResult(member);\n return familyInstance.verifySchema({\n contract: member.contract(),\n // The family's `TSchemaIR` is opaque to migration-tools; the\n // aggregate verifier passes through whatever we hand it. The\n // family expects its own IR shape on the way back.\n schema: projectedSchema as never,\n strict: verifyMode === 'strict',\n frameworkComponents,\n });\n };\n}\n\nfunction emitVerifySpan(\n onProgress: OnControlProgress | undefined,\n kind: 'spanStart' | 'spanEndOk' | 'spanEndError',\n): void {\n if (kind === 'spanStart') {\n onProgress?.({\n action: 'dbVerify',\n kind: 'spanStart',\n spanId: SPAN_IDS.verify,\n label: 'Verifying contract spaces',\n });\n return;\n }\n onProgress?.({\n action: 'dbVerify',\n kind: 'spanEnd',\n spanId: SPAN_IDS.verify,\n outcome: kind === 'spanEndOk' ? 'ok' : 'error',\n });\n}\n\n/**\n * Map an {@link VerifierOutput} to the operation's\n * {@link ExecuteDbVerifyResult}, applying the `skipMarker` policy used\n * by the CLI's `--schema-only` mode.\n */\nfunction finaliseVerifyResult(args: {\n verifyResult: VerifierOutput<VerifyDatabaseSchemaResult>;\n aggregate: {\n readonly app: { readonly spaceId: string };\n readonly extensions: ReadonlyArray<{ readonly spaceId: string }>;\n };\n skipMarker: boolean;\n onProgress: OnControlProgress | undefined;\n}): ExecuteDbVerifyResult {\n const { verifyResult, aggregate, skipMarker, onProgress } = args;\n if (!verifyResult.ok) {\n emitVerifySpan(onProgress, 'spanEndError');\n return notOk(\n new CliStructuredError('5002', 'Aggregate verifier introspection failed', {\n domain: 'MIG',\n why: verifyResult.failure.detail,\n fix: 'Check database connectivity and the introspection tooling.',\n docsUrl: 'https://pris.ly/contract-spaces',\n }),\n );\n }\n const markerError = skipMarker\n ? null\n : mapMarkerCheckFailures(aggregate.app.spaceId, verifyResult.value.markerCheck);\n if (markerError !== null) {\n emitVerifySpan(onProgress, 'spanEndError');\n return notOk(markerError);\n }\n emitVerifySpan(onProgress, 'spanEndOk');\n return ok({\n schemaResults: verifyResult.value.schemaCheck.perSpace,\n memberOrder: [aggregate.app.spaceId, ...aggregate.extensions.map((e) => e.spaceId)],\n appSpaceId: aggregate.app.spaceId,\n });\n}\n\nfunction buildSkippedSchemaResult(member: ContractSpaceMember): VerifyDatabaseSchemaResult {\n const contract = member.contract();\n const headRef = requireHeadRef(member);\n const profileHash = castAs<{ profileHash?: string }>(contract).profileHash;\n return {\n ok: true,\n summary: 'Schema verification skipped',\n contract: {\n storageHash: headRef.hash,\n ...(profileHash ? { profileHash } : {}),\n },\n target: { expected: contract.target },\n schema: {\n issues: [],\n root: {\n status: 'pass',\n kind: 'skipped',\n name: member.spaceId,\n contractPath: '',\n code: 'SKIPPED',\n message: 'Schema verification skipped',\n expected: undefined,\n actual: undefined,\n children: [],\n },\n counts: { pass: 0, warn: 0, fail: 0, totalNodes: 0 },\n },\n timings: { total: 0 },\n };\n}\n\n/**\n * Translate per-space marker check failures and orphan markers into a\n * single CLI structured error envelope. Preserves the legacy code\n * `5002` (was emitted by `runContractSpaceVerifierMarkerCheck`).\n */\nfunction mapMarkerCheckFailures(\n appSpaceId: string,\n section: {\n readonly perSpace: ReadonlyMap<\n string,\n | { readonly kind: 'ok' }\n | { readonly kind: 'absent' }\n | { readonly kind: 'hashMismatch'; readonly markerHash: string; readonly expected: string }\n | { readonly kind: 'missingInvariants'; readonly missing: readonly string[] }\n >;\n readonly orphanMarkers: readonly { readonly spaceId: string; readonly row: unknown }[];\n },\n): CliStructuredError | null {\n const violations: Array<{\n kind: string;\n spaceId: string;\n remediation: string;\n }> = [];\n for (const [spaceId, result] of section.perSpace) {\n if (result.kind === 'ok' || result.kind === 'absent') continue;\n if (result.kind === 'hashMismatch') {\n violations.push({\n kind: 'hashMismatch',\n spaceId,\n remediation:\n spaceId === appSpaceId\n ? 'Run `prisma-next db update` to advance the marker, or roll the database back to the recorded hash.'\n : `Apply on-disk migrations under \\`migrations/${spaceId}/\\` to advance the marker, or remove the conflicting marker row.`,\n });\n continue;\n }\n if (result.kind === 'missingInvariants') {\n violations.push({\n kind: 'invariantsMismatch',\n spaceId,\n remediation: `Re-apply the migrations under \\`migrations/${spaceId}/\\` so the marker carries invariants: ${result.missing.join(', ')}.`,\n });\n }\n }\n for (const orphan of section.orphanMarkers) {\n violations.push({\n kind: 'orphanMarker',\n spaceId: orphan.spaceId,\n remediation: `Add the corresponding extension to \\`extensionPacks\\` in \\`prisma-next.config.ts\\`, or delete the orphan marker row for \"${orphan.spaceId}\".`,\n });\n }\n if (violations.length === 0) return null;\n const lines = violations.map((v) => `- [${v.kind}] ${v.spaceId}: ${v.remediation}`);\n const summary =\n violations.length === 1\n ? 'Contract-space verifier found a violation'\n : `Contract-space verifier found violations (${violations.length})`;\n return new CliStructuredError('5002', summary, {\n domain: 'MIG',\n why: `The on-disk \\`migrations/\\` directory, the \\`extensionPacks\\` declaration, and the live database marker rows are not in agreement.\\n${lines.join('\\n')}`,\n fix: violations[0]?.remediation ?? 'Review and reconcile the violations listed above.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: { violations },\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 ControlExtensionDescriptor,\n ControlFamilyInstance,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport {\n buildSynthMigrationEdge,\n type ContractMarkerRecordLike,\n type ContractSpaceAggregate,\n type ContractSpaceMember,\n graphWalkStrategy,\n type PerSpacePlan,\n requireHeadRef,\n} from '@prisma-next/migration-tools/aggregate';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { errorNoInvariantPath } from '@prisma-next/migration-tools/errors';\nimport { findPathWithDecision } from '@prisma-next/migration-tools/migration-graph';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport {\n type BuildAggregateInputs,\n buildContractSpaceAggregate,\n} from '../../utils/contract-space-aggregate-loader';\nimport type {\n MigrationApplyFailure,\n MigrationApplyPathDecision,\n MigrationApplyResult,\n MigrationApplySuccess,\n OnControlProgress,\n PerSpaceExecutionEntry,\n} from '../types';\nimport { applyMigration, buildPerSpaceBreakdown } from './apply';\n\n/**\n * Inputs for the aggregate-walking `migrate` control-api\n * operation.\n *\n * The CLI command resolves the descriptor surface (config, refs,\n * contract envelope) and hands a flat input through. The operation\n * is the single descriptor-free seam between the CLI and the\n * aggregate runtime.\n */\nexport interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetId extends string> {\n readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n /** Already-validated app contract (the canonical \"where we are heading\" hash). */\n readonly contract: Contract;\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly migrationsDir: string;\n readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n readonly targetId: TTargetId;\n /**\n * Optional app-space ref override. When provided, the app member's\n * graph-walk targets this hash instead of `member.headRef.hash`.\n * Extensions are unaffected — they always walk to their own head.\n */\n readonly refHash?: string;\n /**\n * Required invariants attached to the user-supplied app-space ref.\n * Threaded into the graph-walk's `required` calculation so the\n * planner picks an invariant-bearing path and surfaces the\n * required/satisfied set on the success envelope. When `refHash`\n * is absent the file's `member.headRef.invariants` are used.\n */\n readonly refInvariants?: readonly string[];\n /**\n * Resolved name of the user-supplied app-space ref. Surfaces in\n * `pathDecision.refName` and in `MIGRATION.NO_INVARIANT_PATH`\n * error envelopes so diagnostics name what the user actually\n * passed (`--ref prod`) instead of a synthetic placeholder.\n * Ignored when `refHash` is absent.\n */\n readonly refName?: string;\n readonly onProgress?: OnControlProgress;\n}\n\n/**\n * Apply pending migrations across every contract space (app +\n * extensions). Replay-only: graph-walk against the on-disk graph for\n * every member; no synth, no introspection.\n *\n * Pipeline:\n *\n * 1. Load aggregate from disk (loader hydrates extension graphs;\n * caller provides app-space packages).\n * 2. Read live marker rows per space (`familyInstance.readAllMarkers`).\n * 3. Per member: `graphWalkStrategy` plots the path from the live\n * marker to `member.headRef.hash` (or `refHash` for the app\n * member when provided). Empty-graph members fail loudly — a\n * \"never planned\" space is a user-error condition for replay.\n * 4. Hand off to {@link applyMigration} (the runner-driving tail\n * shared with `db init` / `db update`). Marker advancement is\n * inside the per-space transaction.\n *\n * Encodes the replay-only contract: every contract space must have an\n * authored migration graph on disk before this operation can advance it.\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 contract,\n migrations,\n frameworkComponents,\n migrationsDir,\n extensionPacks,\n targetId,\n refHash,\n refInvariants,\n refName,\n onProgress,\n } = options;\n\n const loadInputs: BuildAggregateInputs<TFamilyId, TTargetId> = {\n targetId,\n migrationsDir,\n appContract: contract,\n extensionPacks,\n deserializeContract: (json) => familyInstance.deserializeContract(json),\n };\n const loaded = await buildContractSpaceAggregate(loadInputs);\n if (!loaded.ok) {\n throw loaded.failure;\n }\n const aggregate = loaded.value;\n\n const markerRows = await familyInstance.readAllMarkers({ driver });\n\n // Plan every member via graph-walk. App member targets `refHash`\n // when provided, otherwise its own head; extensions always walk\n // to their own head ref.\n const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];\n const perSpacePlans = new Map<string, PerSpacePlan>();\n // Already-at-head empty-graph members (typically extensions whose\n // head ref is the empty sentinel, or whose live marker already\n // matches the target). Kept out of the runner schedule so we don't\n // write spurious markers for greenfield extensions, but merged back\n // into the success envelope so every loaded member is represented.\n const atHeadResolutions = new Map<string, PerSpacePlan>();\n for (const member of allMembers) {\n const isAppMember = member.spaceId === aggregate.app.spaceId;\n // The aggregate passed the integrity gate, so every member's head ref\n // is resolved (the app's is synthesised from the live contract).\n const headRef = requireHeadRef(member);\n const targetHash = isAppMember && refHash !== undefined ? refHash : headRef.hash;\n const liveMarker = markerRows.get(member.spaceId) ?? null;\n\n // Empty-graph members fail loudly: replay needs an on-disk path\n // and an empty graph means the user has never planned this space.\n if (member.graph().nodes.size === 0) {\n // Edge case: target == EMPTY (greenfield, nothing to do) or\n // the live marker already matches the target. Loader integrity\n // allows this for extensions whose head ref is the empty\n // sentinel. Record a zero-op resolution so the aggregate result\n // still surfaces the member in `perSpace[]` as already-at-head;\n // the runner is not invoked for these members because they have\n // no authored ops and (for greenfield extensions) no marker to\n // advance.\n const liveHash = liveMarker?.storageHash;\n if (\n targetHash === liveHash ||\n (liveHash === undefined && targetHash === EMPTY_CONTRACT_HASH)\n ) {\n atHeadResolutions.set(\n member.spaceId,\n buildAtHeadResolution({\n aggregateTargetId: aggregate.targetId,\n member,\n targetHash,\n liveMarker,\n }),\n );\n continue;\n }\n return notOk(buildNeverPlannedFailure(member.spaceId, targetHash));\n }\n\n const targetInvariants =\n isAppMember && refHash !== undefined && refInvariants !== undefined\n ? refInvariants\n : headRef.invariants;\n const targetMember: ContractSpaceMember =\n targetHash === headRef.hash && targetInvariants === headRef.invariants\n ? member\n : { ...member, headRef: { hash: targetHash, invariants: targetInvariants } };\n\n const walked = graphWalkStrategy({\n aggregateTargetId: aggregate.targetId,\n member: targetMember,\n currentMarker: liveMarker,\n ...(isAppMember && refName !== undefined ? { refName } : {}),\n });\n if (walked.kind === 'unreachable') {\n return notOk(buildPathNotFoundFailure(member.spaceId, liveMarker, targetHash));\n }\n if (walked.kind === 'unsatisfiable') {\n // Surface the canonical MIGRATION.NO_INVARIANT_PATH envelope\n // (the error rendering pipeline maps it to meta.code +\n // meta.required + meta.missing + meta.structuralPath that the\n // cli-journeys invariant suite asserts on).\n // Greenfield runs (no marker yet) use the canonical empty-hash\n // sentinel so the structural path stays attached to the\n // `MIGRATION.NO_INVARIANT_PATH` error envelope. Using an empty\n // string here would leave the structural lookup with a hash that\n // is never a graph node, producing an empty `structuralPath` and\n // a less actionable diagnostic.\n const fromHash = liveMarker?.storageHash ?? EMPTY_CONTRACT_HASH;\n const structural = findPathWithDecision(targetMember.graph(), fromHash, targetHash, {\n required: new Set<string>(),\n });\n const structuralPath =\n structural.kind === 'ok'\n ? structural.decision.selectedPath.map((edge) => ({\n dirName: edge.dirName,\n migrationHash: edge.migrationHash,\n from: edge.from,\n to: edge.to,\n invariants: edge.invariants,\n }))\n : [];\n throw errorNoInvariantPath({\n ...(isAppMember && refName !== undefined ? { refName } : {}),\n required: targetInvariants,\n missing: walked.missing,\n structuralPath,\n });\n }\n\n perSpacePlans.set(member.spaceId, walked.result);\n }\n\n const canonicalOrder = [...aggregate.extensions.map((m) => m.spaceId), aggregate.app.spaceId];\n const applyOrder = canonicalOrder.filter((spaceId) => perSpacePlans.has(spaceId));\n\n // Short-circuit: nothing pending across any space (no runner-bound\n // plans). Surfaces every loaded member — including at-head empty-\n // graph extensions — in `perSpace[]` so the result reflects the\n // full aggregate, not just the spaces the runner would have touched.\n const totalPlannedOps = sumPlannedOps(applyOrder, perSpacePlans);\n if (totalPlannedOps === 0) {\n const ordered = canonicalOrder\n .filter((spaceId) => perSpacePlans.has(spaceId) || atHeadResolutions.has(spaceId))\n .map((spaceId) => {\n const entry = perSpacePlans.get(spaceId) ?? atHeadResolutions.get(spaceId);\n if (entry === undefined) {\n throw new Error(`Unreachable: missing per-space plan for \"${spaceId}\"`);\n }\n return { spaceId, entry };\n });\n const perSpace = buildPerSpaceBreakdown(ordered, aggregate.app.spaceId, {\n includeMarkers: true,\n });\n const totalSpaces = ordered.length;\n return ok(\n buildSuccess({\n aggregate,\n orderedResolutions: ordered,\n perSpace,\n totalOpsExecuted: 0,\n summary:\n totalSpaces === 0\n ? 'Already up to date — no contract spaces are loaded'\n : totalSpaces === 1\n ? 'Already up to date'\n : `Already up to date across ${totalSpaces} space(s)`,\n }),\n );\n }\n\n const applied = await applyMigration({\n aggregate,\n perSpacePlans,\n applyOrder,\n driver,\n familyInstance,\n migrations,\n frameworkComponents,\n policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },\n action: 'migrationApply',\n ...ifDefined('onProgress', onProgress),\n });\n\n if (!applied.ok) {\n const failure: MigrationApplyFailure = {\n code: 'RUNNER_FAILED',\n summary: applied.failure.summary,\n why: applied.failure.why,\n meta: applied.failure.meta,\n };\n return notOk(failure);\n }\n\n // Merge at-head zero-op resolutions back into the canonical order\n // so the success envelope surfaces every loaded member, not just\n // those the runner executed.\n const orderedAll = canonicalOrder\n .filter((spaceId) => perSpacePlans.has(spaceId) || atHeadResolutions.has(spaceId))\n .map((spaceId) => {\n if (perSpacePlans.has(spaceId)) {\n const fromRunner = applied.value.orderedResolutions.find((r) => r.spaceId === spaceId);\n if (fromRunner !== undefined) return fromRunner;\n }\n const entry = atHeadResolutions.get(spaceId);\n if (entry === undefined) {\n throw new Error(`Unreachable: missing per-space plan for \"${spaceId}\"`);\n }\n return { spaceId, entry };\n });\n const perSpaceAll = buildPerSpaceBreakdown(orderedAll, aggregate.app.spaceId, {\n includeMarkers: true,\n });\n const totalMigrationsApplied = applied.value.orderedResolutions.reduce(\n (sum, r) => sum + r.entry.migrationEdges.length,\n 0,\n );\n const summary = `Applied ${totalMigrationsApplied} migration(s) (${applied.value.totalOpsExecuted} operation(s)) across ${orderedAll.length} contract space(s)`;\n\n return ok(\n buildSuccess({\n aggregate,\n orderedResolutions: orderedAll,\n perSpace: perSpaceAll,\n totalOpsExecuted: applied.value.totalOpsExecuted,\n summary,\n }),\n );\n}\n\n/**\n * Build a zero-op {@link PerSpacePlan} for an empty-graph\n * member whose live marker already matches the target. Lets the apply\n * pipeline thread the member through `perSpacePlans` -> `applyOrder`\n * -> the success envelope's `perSpace[]` block so the result reflects\n * every loaded space, even when there is nothing to execute.\n */\nfunction buildAtHeadResolution(args: {\n readonly aggregateTargetId: string;\n readonly member: ContractSpaceMember;\n readonly targetHash: string;\n readonly liveMarker: ContractMarkerRecordLike | null;\n}): PerSpacePlan {\n const { aggregateTargetId, member, targetHash, liveMarker } = args;\n return {\n plan: {\n targetId: aggregateTargetId,\n spaceId: member.spaceId,\n origin: liveMarker === null ? null : { storageHash: liveMarker.storageHash },\n destination: { storageHash: targetHash },\n operations: [],\n providedInvariants: [],\n },\n displayOps: [],\n destinationContract: member.contract(),\n strategy: 'graph-walk',\n migrationEdges: [\n buildSynthMigrationEdge({\n currentMarkerStorageHash: liveMarker?.storageHash,\n destinationStorageHash: targetHash,\n operationCount: 0,\n }),\n ],\n };\n}\n\nfunction sumPlannedOps(\n applyOrder: readonly string[],\n perSpacePlans: ReadonlyMap<string, PerSpacePlan>,\n): number {\n let total = 0;\n for (const spaceId of applyOrder) {\n const entry = perSpacePlans.get(spaceId);\n if (!entry) continue;\n total += entry.plan.operations.length;\n }\n return total;\n}\n\ninterface BuildSuccessArgs {\n readonly aggregate: ContractSpaceAggregate;\n readonly orderedResolutions: ReadonlyArray<{\n readonly spaceId: string;\n readonly entry: PerSpacePlan;\n }>;\n readonly perSpace: ReadonlyArray<PerSpaceExecutionEntry>;\n readonly totalOpsExecuted: number;\n readonly summary: string;\n}\n\nfunction buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {\n // The marker hash surfaced at the top level is the **app member's**\n // post-apply marker (the top-level `markerHash` field).\n // Per-space markers live on `perSpace[].marker.storageHash`.\n const appResolution = args.orderedResolutions.find(\n (r) => r.spaceId === args.aggregate.app.spaceId,\n );\n const appMarkerHash =\n appResolution?.entry.plan.destination.storageHash ?? requireHeadRef(args.aggregate.app).hash;\n\n // Per-migration entries (one per authored edge) preserve the\n // `migrationsApplied` count semantics for back-compat with existing\n // JSON-shape consumers (e.g. `parsed.applied.length` in integration\n // tests). The aggregate per-space breakdown lives on `perSpace[]`.\n const applied = args.orderedResolutions.flatMap((r) => {\n const edges = r.entry.migrationEdges;\n return edges.map((edge) => ({\n spaceId: r.spaceId,\n dirName: edge.dirName,\n migrationHash: edge.migrationHash,\n from: edge.from,\n to: edge.to,\n operationsExecuted: edge.operationCount,\n }));\n });\n\n const appPlan = appResolution?.entry;\n const pathDecision: MigrationApplyPathDecision | undefined = appPlan?.pathDecision\n ? {\n fromHash: appPlan.pathDecision.fromHash,\n toHash: appPlan.pathDecision.toHash,\n alternativeCount: appPlan.pathDecision.alternativeCount,\n tieBreakReasons: appPlan.pathDecision.tieBreakReasons,\n ...(appPlan.pathDecision.refName !== undefined\n ? { refName: appPlan.pathDecision.refName }\n : {}),\n requiredInvariants: appPlan.pathDecision.requiredInvariants ?? [],\n satisfiedInvariants: appPlan.pathDecision.satisfiedInvariants ?? [],\n selectedPath: appPlan.pathDecision.selectedPath.map((entry) => ({\n dirName: entry.dirName,\n migrationHash: entry.migrationHash,\n from: entry.from,\n to: entry.to,\n invariants: entry.invariants,\n })),\n }\n : undefined;\n\n return {\n migrationsApplied: applied.length,\n markerHash: appMarkerHash,\n applied,\n summary: args.summary,\n perSpace: args.perSpace,\n ...(pathDecision !== undefined ? { pathDecision } : {}),\n };\n}\n\n/**\n * Build the `neverPlanned` failure raised when a contract space has no on-disk\n * migration graph but migrate was asked to reach a target hash. The `why`\n * states only the condition; the recovery sequence is composed by\n * `errorPathUnreachable`'s `fix`.\n *\n * @internal Exported for testing only.\n */\nexport function buildNeverPlannedFailure(\n spaceId: string,\n targetHash: string,\n): MigrationApplyFailure {\n return {\n code: 'MIGRATION_PATH_NOT_FOUND',\n summary: `No on-disk migrations for contract space \"${spaceId}\"`,\n why: `migrate is replay-only: every contract space must have an authored migration graph on disk. Space \"${spaceId}\" has no migrations under \\`migrations/${spaceId}/\\` but its head ref targets \"${targetHash}\".`,\n meta: { spaceId, target: targetHash, kind: 'neverPlanned' },\n };\n}\n\n/**\n * Build the `pathUnreachable` failure raised when an emitted contract has no\n * on-disk migration edge from the current marker to the target. The `why`\n * states only the condition (no edge between the two named states, and migrate\n * replays edges rather than inventing them); the recovery sequence — plan the\n * edge, then re-apply — is composed by `errorPathUnreachable`'s `fix`, so the\n * two read as one non-redundant plan-then-apply story.\n *\n * @internal Exported for testing only.\n */\nexport function buildPathNotFoundFailure(\n spaceId: string,\n marker: ContractMarkerRecordLike | null,\n targetHash: string,\n): MigrationApplyFailure {\n const fromHash = marker?.storageHash ?? '<empty>';\n // The app-case phrasing names the user-visible condition (a\n // contract has been emitted that no on-disk migration reaches) so\n // the error reads naturally for the app member. Extension spaces\n // see the same condition expressed against the offending space.\n const summary =\n spaceId === 'app'\n ? 'Current contract has no planned migration path'\n : `Current contract has no planned migration path for contract space \"${spaceId}\"`;\n return {\n code: 'MIGRATION_PATH_NOT_FOUND',\n summary,\n why: `No migration edge connects the current state \"${fromHash}\" to the target \"${targetHash}\" in contract space \"${spaceId}\". The on-disk migration graph does not join the two, and migrate replays existing edges — it never invents one.`,\n meta: { spaceId, fromHash, targetHash, kind: 'pathUnreachable' },\n };\n}\n","import type {\n Contract,\n ContractMarkerRecord,\n LedgerEntryRecord,\n} 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 MigrationPlanOperation,\n OperationPreview,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n APP_SPACE_ID,\n createControlStack,\n hasMigrations,\n hasOperationPreview,\n hasPslContractInfer,\n hasSchemaView,\n} from '@prisma-next/framework-components/control';\nimport type { PslDocumentAst } from '@prisma-next/framework-components/psl-ast';\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 { type ExecuteDbVerifyResult, executeDbVerify } from './operations/db-verify';\nimport { executeMigrationApply } from './operations/migration-apply';\n\nimport type {\n ControlActionName,\n ControlClient,\n ControlClientOptions,\n DbInitOptions,\n DbInitResult,\n DbUpdateOptions,\n DbUpdateResult,\n DbVerifyOptions,\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.deserializeContract(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.deserializeContract(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 // Introspect the live schema, then verify the contract against\n // it. Composing the two primitives here keeps the family\n // interface a single synchronous verifier and gives callers\n // (and tests) explicit control over the introspected schema.\n const schema = await familyInstance.introspect({ driver, contract });\n const result = familyInstance.verifySchema({\n contract,\n schema,\n strict: options.strict ?? false,\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.deserializeContract(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.deserializeContract(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 migrationsDir: options.migrationsDir,\n targetId: this.options.target.targetId,\n extensionPacks: this.options.extensionPacks ?? [],\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.deserializeContract(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 migrationsDir: options.migrationsDir,\n targetId: this.options.target.targetId,\n extensionPacks: this.options.extensionPacks ?? [],\n ...ifDefined('acceptDataLoss', options.acceptDataLoss),\n ...ifDefined('onProgress', onProgress),\n });\n }\n\n async dbVerify(options: DbVerifyOptions): Promise<ExecuteDbVerifyResult> {\n const { onProgress } = options;\n await this.connectWithProgress(options.connection, 'dbVerify', onProgress);\n const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();\n\n return executeDbVerify({\n driver,\n familyInstance,\n contract: options.contract,\n migrationsDir: options.migrationsDir,\n targetId: this.options.target.targetId,\n extensionPacks: this.options.extensionPacks ?? [],\n frameworkComponents,\n mode: options.strict ? 'strict' : 'lenient',\n skipSchema: options.skipSchema,\n skipMarker: options.skipMarker,\n ...ifDefined('onProgress', onProgress),\n });\n }\n\n async readMarker(): Promise<ContractMarkerRecord | null> {\n const { driver, familyInstance } = await this.ensureConnected();\n // The CLI client's readMarker reads the app's marker. Per-extension\n // readers go through the orchestrator's per-space planner / runner\n // boundary, which threads the extension's space id through the\n // family interface explicitly.\n return familyInstance.readMarker({ driver, space: APP_SPACE_ID });\n }\n\n async readAllMarkers(): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const { driver, familyInstance } = await this.ensureConnected();\n return familyInstance.readAllMarkers({ driver });\n }\n\n /** Reads the per-migration journal; omit `space` to return every space. */\n async readLedger(space?: string): Promise<readonly LedgerEntryRecord[]> {\n const { driver, familyInstance } = await this.ensureConnected();\n return familyInstance.readLedger({ driver, ...ifDefined('space', space) });\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 let contract: Contract;\n try {\n contract = familyInstance.deserializeContract(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 executeMigrationApply({\n driver,\n familyInstance,\n contract,\n migrations: this.options.target.migrations,\n frameworkComponents,\n migrationsDir: options.migrationsDir,\n extensionPacks: this.options.extensionPacks ?? [],\n targetId: this.options.target.targetId,\n ...ifDefined('refHash', options.refHash),\n ...ifDefined('refInvariants', options.refInvariants),\n ...ifDefined('refName', options.refName),\n ...ifDefined('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 inferPslContract(schemaIR: unknown): PslDocumentAst | undefined {\n this.init();\n if (this.familyInstance && hasPslContractInfer(this.familyInstance)) {\n return this.familyInstance.inferPslContract(schemaIR);\n }\n return undefined;\n }\n\n toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview | undefined {\n this.init();\n if (this.familyInstance && hasOperationPreview(this.familyInstance)) {\n return this.familyInstance.toOperationPreview(operations);\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 // Blind cast: `contractRaw` is the unverified provider\n // payload — `enrichContract` only adds capability + extension\n // metadata onto whatever shape it receives. The structural\n // check happens immediately afterwards via\n // `familyInstance.deserializeContract(enrichedIR)`, which is\n // the seam-of-record and the only thing that may surface\n // structural errors to the caller.\n const enrichedIR = enrichContract(\n contractRaw as unknown as Contract,\n this.frameworkComponents ?? [],\n );\n\n try {\n this.familyInstance.deserializeContract(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 serializeContract: (contract) =>\n this.options.target.contractSerializer.serializeContract(contract),\n },\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 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"command-helpers-DlrUCI7s.mjs","names":["LEFT_COLUMN_WIDTH","createPrismaNextBadge","formatHeaderLine","formatReadMoreLine","isCI","ciInfoIsCI","CliStructuredError","isCI","errorRuntime","APP_SPACE_ID"],"sources":["../src/utils/cli-errors.ts","../src/utils/formatters/helpers.ts","../src/utils/formatters/styled.ts","../src/utils/formatters/help.ts","../src/utils/is-ci.ts","../src/utils/formatters/errors.ts","../src/utils/result-handler.ts","../src/utils/glyph-mode.ts","../src/utils/shutdown.ts","../src/utils/terminal-ui.ts","../src/utils/global-flags.ts","../src/utils/command-helpers.ts"],"sourcesContent":["/**\n * Re-export all domain error factories from @prisma-next/errors for convenience.\n * CLI-specific errors (e.g., Commander argument validation in the main CLI, or\n * clipanion parse errors in the migration-file CLI) can be added here if needed.\n */\nexport type { CliErrorConflict, CliErrorEnvelope } from '@prisma-next/errors/control';\n\nimport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorInvalidOutputFormat,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorOutputFormatMutex,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport type { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport type { RefResolutionError } from '@prisma-next/migration-tools/ref-resolution';\nimport type { MigrationApplyFailure } from '../control-api/types';\n\nexport {\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorDestructiveChanges,\n errorHashMismatch,\n errorMarkerMissing,\n errorMarkerRequired,\n errorRunnerFailed,\n errorRuntime,\n errorSchemaVerificationFailed,\n errorTargetMismatch,\n} from '@prisma-next/errors/execution';\nexport {\n errorMigrationFileMissing,\n errorMigrationInvalidDefaultExport,\n errorMigrationPlanNotArray,\n errorUnfilledPlaceholder,\n placeholder,\n} from '@prisma-next/errors/migration';\nexport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorInvalidOutputFormat,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorOutputFormatMutex,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n};\n\nexport function errorRefSetHashNotInGraph(\n resolvedHash: string,\n reachableHashes: readonly string[],\n graphTipHash: string | null,\n): CliStructuredError {\n const reachableList =\n reachableHashes.length > 0 ? reachableHashes.join(', ') : '(none — migration graph is empty)';\n const fix =\n reachableHashes.length > 0\n ? graphTipHash !== null\n ? `Set the ref to a graph-node hash such as ${graphTipHash}, or run \\`prisma-next migration plan\\` to extend the graph.`\n : 'Set the ref to a hash that appears in the migration graph.'\n : 'Run `prisma-next migration plan` first.';\n return errorRuntime(`Resolved contract hash is not in the migration graph: ${resolvedHash}`, {\n why:\n reachableHashes.length > 0\n ? `The migration graph reaches ${reachableList}; resolved ${resolvedHash} isn't a graph node.`\n : 'The migration graph is empty — no hashes reachable.',\n fix,\n meta: {\n code: 'MIGRATION.HASH_NOT_IN_GRAPH',\n resolvedHash,\n reachableHashes: [...reachableHashes],\n ...(graphTipHash !== null ? { graphTipHash } : {}),\n },\n });\n}\n\nexport function errorRefSetEmptySentinel(hash: string): CliStructuredError {\n return errorRuntime(`Cannot set ref to the empty-database sentinel: ${hash}`, {\n why: 'The empty-database sentinel is a planner internal; it is not a valid ref target.',\n fix: 'Set the ref to a contract hash from the migration graph, or use another ref name.',\n meta: {\n code: 'MIGRATION.REF_SET_EMPTY_SENTINEL',\n hash,\n },\n });\n}\n\n/**\n * `--space <id>` was given a value that doesn't satisfy the contract-space\n * naming rule (`[a-z][a-z0-9_-]{0,63}` per `isValidSpaceId`). Fires before\n * any fs work — the input is syntactically rejected the same way an on-disk\n * directory with that name would be skipped by the enumerator.\n */\nexport function errorInvalidSpaceId(spaceId: string): CliStructuredError {\n return errorRuntime(`Invalid contract space id: ${spaceId}`, {\n why: 'Contract space ids must match [a-z][a-z0-9_-]{0,63} (lowercase, starts with a letter, max 64 characters — the rule applied to every on-disk space directory).',\n fix: 'Pass a space id that matches the directory naming rule, or omit --space to list every space.',\n meta: {\n code: 'MIGRATION.INVALID_SPACE_ID',\n spaceId,\n },\n });\n}\n\n/**\n * `migration list --space <id>` was given a contract-space id that has no\n * directory under `migrations/`. Distinct from \"the space exists but is\n * empty\" — that path renders the empty-state line and exits 0 per the\n * slice spec § Empty-state. This error fires only when `<projectMigrationsDir>/<spaceId>`\n * does not exist on disk.\n *\n * `availableSpaces` lists the contract-space directory names actually\n * present, sorted lex-asc, so the diagnostic can suggest a near match\n * without making the user reach for `ls`.\n */\nexport function errorSpaceNotFound(\n spaceId: string,\n availableSpaces: readonly string[],\n): CliStructuredError {\n const availableList =\n availableSpaces.length > 0\n ? availableSpaces.join(', ')\n : '(none — no contract spaces on disk yet)';\n const fix =\n availableSpaces.length > 0\n ? `Pick one of: ${availableList}. Run \\`prisma-next migration list\\` (no --space) to see every space's migrations.`\n : 'Author a migration with `prisma-next migration new` to create the first contract-space directory.';\n return errorRuntime(`Unknown contract space: ${spaceId}`, {\n why: `No directory named \"${spaceId}\" exists under the migrations root.`,\n fix,\n meta: {\n code: 'MIGRATION.SPACE_NOT_FOUND',\n spaceId,\n availableSpaces: [...availableSpaces],\n },\n });\n}\n\nexport function errorRefSetBundleNotFound(hash: string): CliStructuredError {\n return errorRuntime(`No migration bundle matches graph-node hash ${hash}`, {\n why: `The hash is a graph node but no on-disk bundle has metadata.to = ${hash}.`,\n fix: 'Run `pnpm fixtures:check`, or re-emit the migration that produces this hash so its bundle is restored.',\n meta: {\n code: 'MIGRATION.REF_SET_BUNDLE_NOT_FOUND',\n hash,\n },\n });\n}\n\nexport function errorPlanForgotTheFlag(\n resolvedHash: string,\n reachableRefs: ReadonlyArray<{ readonly name: string; readonly hash: string }>,\n graphTipHash: string | null,\n): CliStructuredError {\n const reachableList =\n reachableRefs.length > 0\n ? reachableRefs.map((r) => `${r.name} (${r.hash})`).join(', ')\n : '(none)';\n const refFix =\n reachableRefs.length > 0\n ? `Run migration plan with ${reachableRefs.map((r) => `--from ${r.name}`).join(' or ')}.`\n : graphTipHash !== null\n ? `Run migration plan --from ${graphTipHash}.`\n : 'Commit pending migrations first, then run migration plan.';\n return errorRuntime(`Resolved from-hash is not in the migration graph: ${resolvedHash}`, {\n why: `The migration graph reaches ${reachableList}; resolved ${resolvedHash} isn't a graph node.`,\n fix: refFix,\n meta: {\n code: 'MIGRATION.HASH_NOT_IN_GRAPH',\n resolvedHash,\n reachableRefs: reachableRefs.map((r) => r.name),\n ...(graphTipHash !== null ? { graphTipHash } : {}),\n },\n });\n}\n\nexport function errorSnapshotMissing(\n identifier: string,\n options?: { readonly viaRef?: boolean },\n): CliStructuredError {\n const viaRef = options?.viaRef !== false;\n const fix = viaRef\n ? `Run \"prisma-next db update --advance-ref ${identifier}\" to repopulate the snapshot, or \"prisma-next ref delete ${identifier}\" to clear the orphan pointer.`\n : `No contract source exists for hash \"${identifier}\" on an empty migration graph. Use --from with a ref name that has a paired snapshot, or run db update first.`;\n return errorRuntime(\n viaRef\n ? `Ref \"${identifier}\" has no paired contract snapshot`\n : `No contract source for from-hash \"${identifier}\"`,\n {\n why: viaRef\n ? `Ref \"${identifier}\" exists but its paired snapshot files are missing.`\n : `Hash \"${identifier}\" is not a graph node and no paired ref snapshot supplies a contract.`,\n fix,\n meta: {\n code: 'MIGRATION.SNAPSHOT_MISSING',\n identifier,\n viaRef,\n },\n },\n );\n}\n\nexport function errorMarkerMismatch(\n markerHash: string,\n reachableHashes: readonly string[],\n graphTip: string | null,\n): CliStructuredError {\n const reachableList =\n reachableHashes.length > 0 ? reachableHashes.join(', ') : '(none — migration graph is empty)';\n const planFromFix =\n graphTip !== null\n ? `Run \\`prisma-next migration plan --from ${graphTip}\\` if the live marker is canonical and the on-disk graph needs catching up.`\n : 'Run `prisma-next migration plan` if the live marker is canonical and the on-disk graph needs catching up.';\n return errorRuntime('Database marker is not reachable in the on-disk migration graph', {\n why: `DB marker is ${markerHash}, but the on-disk migration graph reaches: ${reachableList}.`,\n fix: [\n planFromFix,\n `Run \\`prisma-next ref set db ${markerHash}\\` if the on-disk graph is canonical and the local \\`db\\` ref drifted.`,\n 'Investigate whether the database was migrated by an out-of-band process.',\n ].join('\\n'),\n meta: {\n code: 'MIGRATION.MARKER_MISMATCH',\n markerHash,\n reachableHashes: [...reachableHashes],\n ...(graphTip !== null ? { graphTip } : {}),\n },\n });\n}\n\nexport function errorPathUnreachable(failure: MigrationApplyFailure): CliStructuredError {\n const meta = failure.meta ?? {};\n const fromHashMeta = typeof meta['fromHash'] === 'string' ? meta['fromHash'] : null;\n // `buildPathNotFoundFailure` uses this sentinel in meta when the live marker is null.\n const planFromHash = fromHashMeta === '<empty>' ? null : fromHashMeta;\n const targetHash =\n typeof meta['targetHash'] === 'string'\n ? meta['targetHash']\n : typeof meta['target'] === 'string'\n ? meta['target']\n : null;\n const deadEnds = meta['deadEnds'];\n const deadEndsSuffix =\n Array.isArray(deadEnds) && deadEnds.length > 0\n ? ` Dead-ends: ${deadEnds.map(String).join(', ')}.`\n : '';\n // Plan-then-apply recovery. The planner destination is the missing edge's\n // target; `migration plan --to` (built for arbitrary targets) makes this a\n // real command, so the diagnostic that sends you here is now honest.\n const planCommand = (() => {\n if (planFromHash !== null && targetHash !== null) {\n return `prisma-next migration plan --from ${planFromHash} --to ${targetHash} --name <slug>`;\n }\n if (targetHash !== null) {\n return `prisma-next migration plan --to ${targetHash} --name <slug>`;\n }\n if (planFromHash !== null) {\n return `prisma-next migration plan --from ${planFromHash} --name <slug>`;\n }\n return 'prisma-next migration plan';\n })();\n const applyCommand =\n targetHash !== null ? `prisma-next migrate --to ${targetHash}` : 'prisma-next migrate';\n return errorRuntime(failure.summary, {\n why:\n failure.why ??\n `Cannot reach target \"${targetHash ?? '<unknown>'}\" from current marker \"${fromHashMeta ?? '<unknown>'}\".${deadEndsSuffix}`,\n fix: [\n 'Plan the missing edge, then apply it:',\n ` 1. ${planCommand}`,\n ` 2. ${applyCommand}`,\n 'A rollback (reverse) plan is expected to contain destructive (DROP) operations — review them before applying.',\n 'Narrower cases (rename inference, re-adding a NOT NULL column without a safe default, or a type change that needs data) may additionally need a hint in the planned migration.',\n 'Inspect the on-disk graph with `prisma-next migration list`, or `prisma-next migration show <bundle>` for any bundle in the path you expected.',\n ].join('\\n'),\n meta: {\n ...meta,\n code: 'MIGRATION.PATH_UNREACHABLE',\n },\n });\n}\n\n/**\n * Maps a `MigrationToolsError` raised by the migration-tools loader/graph\n * surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,\n * `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.\n *\n * The full `error.details` payload is forwarded into `meta` so machine\n * consumers (`--json`) see structural fields like `dir`, `storedHash`,\n * `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable\n * `code`. The user-visible `summary`/`why`/`fix` text is unchanged.\n *\n * Callers are expected to gate on `MigrationToolsError.is(error)` first\n * (mirroring the original inline pattern); non-`MigrationToolsError`\n * values are caller-classified (rethrow, wrap with command-specific\n * `errorUnexpected`, etc.).\n */\nexport function mapMigrationToolsError(error: MigrationToolsError): CliStructuredError {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n}\n\n/**\n * Maps a `RefResolutionError` from the contract/migration reference\n * resolver into a CLI structured error envelope.\n */\nexport function mapRefResolutionError(error: RefResolutionError): CliStructuredError {\n switch (error.kind) {\n case 'not-found':\n return errorRuntime(`Not a known ${error.grammar} reference: \"${error.input}\"`, {\n why: `No ${error.grammar} matching \"${error.input}\" exists in the migration graph or refs index.`,\n fix:\n error.grammar === 'contract'\n ? 'Provide a valid contract hash, ref name, or migration directory name.'\n : 'Provide a valid migration directory name or migration hash.',\n meta: { input: error.input, grammar: error.grammar },\n });\n case 'ambiguous':\n return errorRuntime(`Ambiguous ${error.grammar} reference: \"${error.input}\"`, {\n why: `\"${error.input}\" matches multiple ${error.grammar}s: ${error.candidates.join(', ')}`,\n fix: 'Provide a longer prefix or use the full hash to disambiguate.',\n meta: { input: error.input, candidates: error.candidates, grammar: error.grammar },\n });\n case 'wrong-grammar':\n return errorRuntime(error.message, {\n why: error.message,\n fix: error.fix,\n meta: { input: error.input, expectedGrammar: error.expectedGrammar },\n });\n case 'invalid-format':\n return errorRuntime(`Invalid reference format: \"${error.input}\"`, {\n why: error.reason,\n fix: 'Provide a valid contract hash, ref name, or migration directory name.',\n meta: { input: error.input },\n });\n }\n}\n","import { dim } from 'colorette';\n\nimport type { GlobalFlags } from '../global-flags';\n\n/**\n * Checks if verbose output is enabled at the specified level.\n */\nexport function isVerbose(flags: GlobalFlags, level: 1 | 2): boolean {\n return (flags.verbose ?? 0) >= level;\n}\n\n/**\n * Creates a color-aware formatter function.\n * Returns a function that applies the color only if colors are enabled.\n */\nexport function createColorFormatter<T extends (text: string) => string>(\n useColor: boolean,\n colorFn: T,\n): (text: string) => string {\n return useColor ? colorFn : (text: string) => text;\n}\n\n/**\n * Formats text with dim styling if colors are enabled.\n */\nexport function formatDim(useColor: boolean, text: string): string {\n return useColor ? dim(text) : text;\n}\n","import { blue, bold, cyan, green } from 'colorette';\nimport type { Command } from 'commander';\nimport stringWidth from 'string-width';\nimport stripAnsi from 'strip-ansi';\n\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim } from './helpers';\n\n// ============================================================================\n// Styled Output Formatters\n// ============================================================================\n\n/**\n * Fixed width for left column in help output.\n */\nconst LEFT_COLUMN_WIDTH = 20;\n\n/**\n * Creates an arrow segment badge with green background and white text.\n * Body: green background with white \"prisma-next\" text\n * Tip: dark grey arrow pointing right (Powerline separator)\n */\nfunction createPrismaNextBadge(useColor: boolean): string {\n if (!useColor) {\n return 'prisma-next';\n }\n return bold('prisma-next');\n}\n\n/**\n * Creates a padding function.\n */\nfunction createPadFunction(): (s: string, w: number) => string {\n return (s: string, w: number) => s + ' '.repeat(Math.max(0, w - s.length));\n}\n\n/**\n * Formats a header line: brand + operation + intent\n */\nfunction formatHeaderLine(options: {\n readonly brand: string;\n readonly operation: string;\n readonly intent: string;\n}): string {\n if (options.operation) {\n return `${options.brand} ${options.operation} → ${options.intent}`;\n }\n return `${options.brand} ${options.intent}`;\n}\n\n/**\n * Formats a \"Read more\" URL line.\n * The \"Read more\" label is in default color (not cyan), and the URL is blue.\n */\nfunction formatReadMoreLine(options: {\n readonly url: string;\n readonly maxLabelWidth: number;\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n}): string {\n const pad = createPadFunction();\n const labelPadded = pad('Read more', options.maxLabelWidth);\n // Label is default color (not cyan)\n const valueColored = options.useColor ? blue(options.url) : options.url;\n return `${options.formatDimText('│')} ${labelPadded} ${valueColored}`;\n}\n\n/**\n * Pads text to a fixed width, accounting for ANSI escape codes.\n * Uses string-width to measure the actual display width.\n */\nexport function padToFixedWidth(text: string, width: number): string {\n const actualWidth = stringWidth(text);\n const padding = Math.max(0, width - actualWidth);\n return text + ' '.repeat(padding);\n}\n\n/**\n * Renders a command tree structure.\n * Handles both single-level (subcommands of a command) and multi-level (top-level commands with subcommands) trees.\n */\nexport function renderCommandTree(options: {\n readonly commands: readonly Command[];\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n readonly hasItemsAfter: boolean;\n readonly continuationPrefix?: string;\n}): string[] {\n const { commands, useColor, formatDimText, hasItemsAfter, continuationPrefix } = options;\n const lines: string[] = [];\n\n if (commands.length === 0) {\n return lines;\n }\n\n // Format each command\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (!cmd) continue;\n\n const subcommands = cmd.commands.filter((subcmd) => !subcmd.name().startsWith('_'));\n const isLastCommand = i === commands.length - 1;\n\n if (subcommands.length > 0) {\n // Command with subcommands - show command name, then tree-structured subcommands\n const treeChar = isLastCommand && !hasItemsAfter ? formatDimText('└') : formatDimText('├');\n // For top-level command, pad name to fixed width (accounting for \"| |-- \" = 5 chars)\n const treePrefix = `${treeChar}─ `;\n const treePrefixWidth = stringWidth(stripAnsi(treePrefix));\n const remainingWidth = LEFT_COLUMN_WIDTH - treePrefixWidth;\n const commandNamePadded = padToFixedWidth(cmd.name(), remainingWidth);\n const commandNameColored = useColor ? cyan(commandNamePadded) : commandNamePadded;\n lines.push(`${formatDimText('│')} ${treePrefix}${commandNameColored}`);\n\n for (let j = 0; j < subcommands.length; j++) {\n const subcmd = subcommands[j];\n if (!subcmd) continue;\n\n const isLastSubcommand = j === subcommands.length - 1;\n const shortDescription = subcmd.description() || '';\n\n // Use tree characters: -- for last subcommand, |-- for others\n const treeChar = isLastSubcommand ? '└' : '├';\n const continuation =\n continuationPrefix ??\n (isLastCommand && isLastSubcommand && !hasItemsAfter ? ' ' : formatDimText('│'));\n // For subcommands, account for \"| | -- \" = 7 chars (or \"| -- \" = 6 chars if continuation is space)\n const continuationStr = continuation === ' ' ? ' ' : continuation;\n const subTreePrefix = `${continuationStr} ${formatDimText(treeChar)}─ `;\n const subTreePrefixWidth = stringWidth(stripAnsi(subTreePrefix));\n const subRemainingWidth = LEFT_COLUMN_WIDTH - subTreePrefixWidth;\n const subcommandNamePadded = padToFixedWidth(subcmd.name(), subRemainingWidth);\n const subcommandNameColored = useColor ? cyan(subcommandNamePadded) : subcommandNamePadded;\n lines.push(\n `${formatDimText('│')} ${subTreePrefix}${subcommandNameColored} ${shortDescription}`,\n );\n }\n } else {\n // Standalone command - show command name and description on same line\n const treeChar = isLastCommand && !hasItemsAfter ? formatDimText('└') : formatDimText('├');\n const treePrefix = `${treeChar}─ `;\n const treePrefixWidth = stringWidth(stripAnsi(treePrefix));\n const remainingWidth = LEFT_COLUMN_WIDTH - treePrefixWidth;\n const commandNamePadded = padToFixedWidth(cmd.name(), remainingWidth);\n const commandNameColored = useColor ? cyan(commandNamePadded) : commandNamePadded;\n const shortDescription = cmd.description() || '';\n lines.push(`${formatDimText('│')} ${treePrefix}${commandNameColored} ${shortDescription}`);\n }\n }\n\n return lines;\n}\n\n/**\n * Formats the header in the new experimental visual style.\n * This header appears at the start of command output, showing the operation,\n * intent, documentation link, and parameters.\n */\nexport function formatStyledHeader(options: {\n readonly command: string;\n readonly description: string;\n readonly url?: string;\n readonly details: ReadonlyArray<{ readonly label: string; readonly value: string }>;\n readonly flags: GlobalFlags;\n}): string {\n const lines: string[] = [];\n const useColor = options.flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Header: arrow + operation badge + intent\n const brand = createPrismaNextBadge(useColor);\n // Use full command path (e.g., \"contract emit\" not just \"emit\")\n const operation = useColor ? bold(options.command) : options.command;\n const intent = formatDimText(options.description);\n lines.push(formatHeaderLine({ brand, operation, intent }));\n lines.push(formatDimText('│')); // Vertical line separator between command and params\n\n // Format details using fixed left column width (same style as help text options)\n for (const detail of options.details) {\n // Add colon to label, then pad to fixed width using padToFixedWidth for ANSI-aware padding\n const labelWithColon = `${detail.label}:`;\n const labelPadded = padToFixedWidth(labelWithColon, LEFT_COLUMN_WIDTH);\n const labelColored = useColor ? cyan(labelPadded) : labelPadded;\n lines.push(`${formatDimText('│')} ${labelColored} ${detail.value}`);\n }\n\n // Add \"Read more\" URL if present (same style as help text)\n if (options.url) {\n lines.push(formatDimText('│')); // Separator line before \"Read more\"\n lines.push(\n formatReadMoreLine({\n url: options.url,\n maxLabelWidth: LEFT_COLUMN_WIDTH,\n useColor,\n formatDimText,\n }),\n );\n }\n\n lines.push(formatDimText('└'));\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Formats a success message in the styled output format.\n */\nexport function formatSuccessMessage(flags: GlobalFlags): string {\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n return `${formatGreen('✔')} Success`;\n}\n","import { blue, bold, cyan, dim, green, magenta } from 'colorette';\nimport type { Command } from 'commander';\nimport wrapAnsi from 'wrap-ansi';\n\nimport { getCommandExamples, getCommandSeeAlso, getLongDescription } from '../command-helpers';\nimport type { GlobalFlags } from '../global-flags';\nimport { formatDim } from './helpers';\nimport { padToFixedWidth, renderCommandTree } from './styled';\n\n// ============================================================================\n// Help Output Formatters\n// ============================================================================\n\n/**\n * Fixed width for left column in help output.\n * Must match the value in styled.ts.\n */\nconst LEFT_COLUMN_WIDTH = 20;\n\n/**\n * Minimum width for right column wrapping in help output.\n */\nconst RIGHT_COLUMN_MIN_WIDTH = 40;\n\n/**\n * Maximum width for right column wrapping in help output (when terminal is wide enough).\n */\nconst RIGHT_COLUMN_MAX_WIDTH = 90;\n\n/**\n * Gets the terminal width, or returns a default if not available.\n */\nfunction getTerminalWidth(): number {\n // Help text goes to stderr, so prefer stderr columns. Fall back to stdout, then CLI_WIDTH env.\n const terminalWidth = process.stderr.columns || process.stdout.columns;\n const envWidth = Number.parseInt(process.env['CLI_WIDTH'] || '', 10);\n return terminalWidth || (Number.isFinite(envWidth) ? envWidth : 80);\n}\n\n/**\n * Calculates the available width for the right column based on terminal width.\n */\nfunction calculateRightColumnWidth(): number {\n const terminalWidth = getTerminalWidth();\n const availableWidth = terminalWidth - 2 - LEFT_COLUMN_WIDTH - 2;\n return Math.max(RIGHT_COLUMN_MIN_WIDTH, Math.min(availableWidth, RIGHT_COLUMN_MAX_WIDTH));\n}\n\n/**\n * Creates the CLI brand badge.\n */\nfunction createPrismaNextBadge(useColor: boolean): string {\n return useColor ? bold('prisma-next') : 'prisma-next';\n}\n\n/**\n * Formats a header line: brand + operation + intent\n */\nfunction formatHeaderLine(options: {\n readonly brand: string;\n readonly operation: string;\n readonly intent: string;\n}): string {\n if (options.operation) {\n return `${options.brand} ${options.operation} → ${options.intent}`;\n }\n return `${options.brand} ${options.intent}`;\n}\n\n/**\n * Wraps text to fit within a specified width using wrap-ansi.\n */\nfunction wrapTextAnsi(text: string, width: number): string[] {\n const wrapped = wrapAnsi(text, width, { hard: false, trim: true });\n return wrapped.split('\\n');\n}\n\n/**\n * Formats a default value as \"default: <value>\" with dimming.\n */\nfunction formatDefaultValue(value: unknown, useColor: boolean): string {\n const valueStr = String(value);\n const defaultText = `default: ${valueStr}`;\n return useColor ? dim(defaultText) : defaultText;\n}\n\n/**\n * Formats a \"Read more\" URL line.\n */\nfunction formatReadMoreLine(options: {\n readonly url: string;\n readonly maxLabelWidth: number;\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n}): string {\n const labelPadded = `Read more${' '.repeat(Math.max(0, options.maxLabelWidth - 'Read more'.length))}`;\n const valueColored = options.useColor ? blue(options.url) : options.url;\n return `${options.formatDimText('│')} ${labelPadded} ${valueColored}`;\n}\n\n/**\n * Formats multiline description with \"Prisma Next\" in green.\n */\nfunction formatMultilineDescription(options: {\n readonly descriptionLines: readonly string[];\n readonly useColor: boolean;\n readonly formatDimText: (text: string) => string;\n}): string[] {\n const lines: string[] = [];\n const formatGreen = (text: string) => (options.useColor ? green(text) : text);\n\n const rightColumnWidth = calculateRightColumnWidth();\n const totalWidth = 2 + LEFT_COLUMN_WIDTH + 2 + rightColumnWidth;\n const wrapWidth = totalWidth - 2;\n\n for (const descLine of options.descriptionLines) {\n const formattedLine = descLine.replace(/Prisma Next/g, (match) => formatGreen(match));\n const wrappedLines = wrapTextAnsi(formattedLine, wrapWidth);\n for (const wrappedLine of wrappedLines) {\n lines.push(`${options.formatDimText('│')} ${wrappedLine}`);\n }\n }\n return lines;\n}\n\n/**\n * Maps command paths to their documentation URLs.\n */\nfunction getCommandDocsUrl(commandPath: string): string | undefined {\n const docsMap: Record<string, string> = {\n 'contract emit': 'https://pris.ly/contract-emit',\n 'contract infer': 'https://pris.ly/contract-infer',\n 'db schema': 'https://pris.ly/db-schema',\n 'db verify': 'https://pris.ly/db-verify',\n 'db update': 'https://pris.ly/db-update',\n 'migration plan': 'https://pris.ly/migration-plan',\n migrate: 'https://pris.ly/migrate',\n 'migration show': 'https://pris.ly/migration-show',\n 'migration status': 'https://pris.ly/migration-status',\n };\n return docsMap[commandPath];\n}\n\n/**\n * Builds the full command path from a command and its parents.\n */\nfunction buildCommandPath(command: Command): string {\n const parts: string[] = [];\n let current: Command | undefined = command;\n while (current && current.name() !== 'prisma-next') {\n parts.unshift(current.name());\n current = current.parent ?? undefined;\n }\n return parts.join(' ');\n}\n\n/**\n * Formats help output for a command using the styled format.\n */\nexport function formatCommandHelp(options: {\n readonly command: Command;\n readonly flags: GlobalFlags;\n}): string {\n const { command, flags } = options;\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Build full command path (e.g., \"db verify\")\n const commandPath = buildCommandPath(command);\n const shortDescription = command.description() || '';\n const longDescription = getLongDescription(command);\n\n // Include positional arguments in the header line\n const argsSuffix = command.registeredArguments\n .map((arg) => (arg.required ? `<${arg.name()}>` : `[${arg.name()}]`))\n .join(' ');\n const brand = createPrismaNextBadge(useColor);\n const commandWithArgs = argsSuffix ? `${commandPath} ${argsSuffix}` : commandPath;\n const operation = useColor ? bold(commandWithArgs) : commandWithArgs;\n const intent = formatDimText(shortDescription);\n lines.push(formatHeaderLine({ brand, operation, intent }));\n lines.push(formatDimText('│'));\n\n // Extract options and format them\n const optionsList = command.options.map((opt) => {\n const description = opt.description || '';\n // Commander.js stores default value in defaultValue property\n const defaultValue = (opt as { defaultValue?: unknown }).defaultValue;\n return { flags: opt.flags, description, defaultValue };\n });\n\n // Extract subcommands if any\n const subcommands = command.commands.filter((cmd) => !cmd.name().startsWith('_'));\n\n // Format subcommands as a tree if present\n if (subcommands.length > 0) {\n const hasItemsAfter = optionsList.length > 0;\n const treeLines = renderCommandTree({\n commands: subcommands,\n useColor,\n formatDimText,\n hasItemsAfter,\n });\n lines.push(...treeLines);\n }\n\n // Add separator between subcommands and options if both exist\n if (subcommands.length > 0 && optionsList.length > 0) {\n lines.push(formatDimText('│'));\n }\n\n // Format options with fixed width, wrapping, and default values\n if (optionsList.length > 0) {\n for (const opt of optionsList) {\n // Format flag with fixed 30-char width\n const flagsPadded = padToFixedWidth(opt.flags, LEFT_COLUMN_WIDTH);\n let flagsColored = flagsPadded;\n if (useColor) {\n // Color placeholders in magenta, then wrap in cyan\n flagsColored = flagsPadded.replace(/(<[^>]+>)/g, (match: string) => magenta(match));\n flagsColored = cyan(flagsColored);\n }\n\n // Wrap description based on terminal width\n const rightColumnWidth = calculateRightColumnWidth();\n const wrappedDescription = wrapTextAnsi(opt.description, rightColumnWidth);\n\n // First line: flag + first line of description\n lines.push(`${formatDimText('│')} ${flagsColored} ${wrappedDescription[0] || ''}`);\n\n // Continuation lines: empty label (30 spaces) + wrapped lines\n for (let i = 1; i < wrappedDescription.length; i++) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${wrappedDescription[i] || ''}`);\n }\n\n // Default value line (if present)\n if (opt.defaultValue !== undefined) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n const defaultText = formatDefaultValue(opt.defaultValue, useColor);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${defaultText}`);\n }\n }\n }\n\n // Add docs URL if available (with separator line before it)\n const docsUrl = getCommandDocsUrl(commandPath);\n if (docsUrl) {\n lines.push(formatDimText('│')); // Separator line between params and docs\n lines.push(\n formatReadMoreLine({\n url: docsUrl,\n maxLabelWidth: LEFT_COLUMN_WIDTH,\n useColor,\n formatDimText,\n }),\n );\n }\n\n // Examples (copy-pastable)\n const examples = getCommandExamples(command);\n if (examples && examples.length > 0) {\n lines.push(formatDimText('│'));\n lines.push(`${formatDimText('│')} ${formatDimText('Examples:')}`);\n for (const example of examples) {\n lines.push(`${formatDimText('│')} ${useColor ? dim('$') : '$'} ${example}`);\n }\n }\n\n // See also (cross-references to related commands)\n const seeAlso = getCommandSeeAlso(command);\n if (seeAlso && seeAlso.length > 0) {\n lines.push(formatDimText('│'));\n lines.push(`${formatDimText('│')} ${formatDimText('See also:')}`);\n for (const ref of seeAlso) {\n lines.push(`${formatDimText('│')} ${ref.verb} ${formatDimText(ref.oneLiner)}`);\n }\n }\n\n // Multi-line description (if present) - shown after all other content\n if (longDescription) {\n lines.push(formatDimText('│'));\n const descriptionLines = longDescription.split('\\n').filter((line) => line.trim().length > 0);\n lines.push(...formatMultilineDescription({ descriptionLines, useColor, formatDimText }));\n }\n\n lines.push(formatDimText('└'));\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Formats help output for the root program using the styled format.\n */\nexport function formatRootHelp(options: {\n readonly program: Command;\n readonly flags: GlobalFlags;\n}): string {\n const { program, flags } = options;\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Header: \"prisma-next -> Manage your data layer\"\n const brand = createPrismaNextBadge(useColor);\n const shortDescription = 'Manage your data layer';\n const intent = formatDimText(shortDescription);\n lines.push(formatHeaderLine({ brand, operation: '', intent }));\n lines.push(formatDimText('│')); // Vertical line separator after header\n\n // Extract top-level commands (exclude hidden commands starting with '_' and the 'help' command)\n const topLevelCommands = program.commands.filter(\n (cmd) => !cmd.name().startsWith('_') && cmd.name() !== 'help',\n );\n\n // Extract global options (needed to determine if last command)\n const globalOptions = program.options.map((opt) => {\n const description = opt.description || '';\n // Commander.js stores default value in defaultValue property\n const defaultValue = (opt as { defaultValue?: unknown }).defaultValue;\n return { flags: opt.flags, description, defaultValue };\n });\n\n // Build command tree\n if (topLevelCommands.length > 0) {\n const hasItemsAfter = globalOptions.length > 0;\n const treeLines = renderCommandTree({\n commands: topLevelCommands,\n useColor,\n formatDimText,\n hasItemsAfter,\n });\n lines.push(...treeLines);\n }\n\n // Add separator between commands and options if both exist\n if (topLevelCommands.length > 0 && globalOptions.length > 0) {\n lines.push(formatDimText('│'));\n }\n\n // Format global options with fixed width, wrapping, and default values\n if (globalOptions.length > 0) {\n for (const opt of globalOptions) {\n // Format flag with fixed 30-char width\n const flagsPadded = padToFixedWidth(opt.flags, LEFT_COLUMN_WIDTH);\n let flagsColored = flagsPadded;\n if (useColor) {\n // Color placeholders in magenta, then wrap in cyan\n flagsColored = flagsPadded.replace(/(<[^>]+>)/g, (match: string) => magenta(match));\n flagsColored = cyan(flagsColored);\n }\n\n // Wrap description based on terminal width\n const rightColumnWidth = calculateRightColumnWidth();\n const wrappedDescription = wrapTextAnsi(opt.description, rightColumnWidth);\n\n // First line: flag + first line of description\n lines.push(`${formatDimText('│')} ${flagsColored} ${wrappedDescription[0] || ''}`);\n\n // Continuation lines: empty label (30 spaces) + wrapped lines\n for (let i = 1; i < wrappedDescription.length; i++) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${wrappedDescription[i] || ''}`);\n }\n\n // Default value line (if present)\n if (opt.defaultValue !== undefined) {\n const emptyLabel = ' '.repeat(LEFT_COLUMN_WIDTH);\n const defaultText = formatDefaultValue(opt.defaultValue, useColor);\n lines.push(`${formatDimText('│')} ${emptyLabel} ${defaultText}`);\n }\n }\n }\n\n // Multi-line description (white, not dimmed, with \"Prisma Next\" in green) - shown at bottom\n const formatGreen = (text: string) => (useColor ? green(text) : text);\n const descriptionLines = [\n `Use ${formatGreen('Prisma Next')} to define your data layer as a contract. Sign your database and application with the same contract to guarantee compatibility. Plan and apply migrations to safely evolve your schema.`,\n ];\n if (descriptionLines.length > 0) {\n lines.push(formatDimText('│')); // Separator line before description\n lines.push(...formatMultilineDescription({ descriptionLines, useColor, formatDimText }));\n }\n\n lines.push(formatDimText('└'));\n\n return `${lines.join('\\n')}\\n`;\n}\n","import { isCI as ciInfoIsCI } from 'ci-info';\n\n/**\n * Returns true when the process is running in any CI environment recognised\n * by the `ci-info` package. The single source of truth for CI detection\n * across this CLI — colour-output suppression and telemetry-skip both call\n * this helper, so neither path drifts from the other when a new CI provider\n * is added upstream.\n *\n * `ci-info` checks the standard `CI=true` marker plus dozens of\n * provider-specific environment variables (Buildkite, Jenkins, Drone,\n * Bitbucket Pipelines, Azure Pipelines, AWS CodeBuild, …) that the raw\n * `process.env.CI` read misses.\n *\n */\nexport function isCI(): boolean {\n return ciInfoIsCI;\n}\n","import { red } from 'colorette';\n\nimport type { CliErrorConflict, CliErrorEnvelope } from '../cli-errors';\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim, isVerbose } from './helpers';\n\n/**\n * Formats error output for human-readable display.\n */\nexport function formatErrorOutput(error: CliErrorEnvelope, flags: GlobalFlags): string {\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatRed = createColorFormatter(useColor, red);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n lines.push(`${formatRed('✖')} ${error.summary} (${error.code})`);\n\n if (error.why) {\n lines.push(`${formatDimText(` Why: ${error.why}`)}`);\n }\n if (error.fix) {\n lines.push(`${formatDimText(` Fix: ${error.fix}`)}`);\n }\n if (error.where?.path) {\n const whereLine = error.where.line\n ? `${error.where.path}:${error.where.line}`\n : error.where.path;\n lines.push(`${formatDimText(` Where: ${whereLine}`)}`);\n }\n // Show conflicts list if present (always show a short list; show full list when verbose)\n if (error.meta?.['conflicts']) {\n const conflicts = error.meta['conflicts'] as readonly CliErrorConflict[];\n if (conflicts.length > 0) {\n const maxToShow = isVerbose(flags, 1) ? conflicts.length : Math.min(3, conflicts.length);\n const header = isVerbose(flags, 1)\n ? ' Conflicts:'\n : ` Conflicts (showing ${maxToShow} of ${conflicts.length}):`;\n lines.push(`${formatDimText(header)}`);\n for (const conflict of conflicts.slice(0, maxToShow)) {\n lines.push(`${formatDimText(` - [${conflict.kind}] ${conflict.summary}`)}`);\n }\n if (!isVerbose(flags, 1) && conflicts.length > maxToShow) {\n lines.push(`${formatDimText(' Re-run with -v/--verbose to see all conflicts')}`);\n }\n }\n }\n // Show issues list if present (always show a short list; show full list when verbose)\n if (error.meta?.['issues']) {\n const issues = error.meta['issues'] as readonly { kind?: string; message?: string }[];\n if (issues.length > 0) {\n const maxToShow = isVerbose(flags, 1) ? issues.length : Math.min(3, issues.length);\n const header = isVerbose(flags, 1)\n ? ' Issues:'\n : ` Issues (showing ${maxToShow} of ${issues.length}):`;\n lines.push(`${formatDimText(header)}`);\n for (const issue of issues.slice(0, maxToShow)) {\n const kind = issue.kind ?? 'issue';\n const message = issue.message ?? '';\n lines.push(`${formatDimText(` - [${kind}] ${message}`)}`);\n }\n if (!isVerbose(flags, 1) && issues.length > maxToShow) {\n lines.push(`${formatDimText(' Re-run with -v/--verbose to see all issues')}`);\n }\n }\n }\n if (error.docsUrl && isVerbose(flags, 1)) {\n lines.push(formatDimText(error.docsUrl));\n }\n if (isVerbose(flags, 2) && error.meta) {\n lines.push(`${formatDimText(` Meta: ${JSON.stringify(error.meta, null, 2)}`)}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats error output as JSON.\n */\nexport function formatErrorJson(error: CliErrorEnvelope): string {\n return JSON.stringify(error, null, 2);\n}\n","import type { Result } from '@prisma-next/utils/result';\nimport type { CliStructuredError } from './cli-errors';\nimport { formatErrorJson, formatErrorOutput } from './formatters/errors';\nimport type { GlobalFlags } from './global-flags';\nimport type { TerminalUI } from './terminal-ui';\n\n/**\n * Processes a CLI command result, handling both success and error cases.\n * Formats output appropriately and returns the exit code.\n * Never throws - returns exit code for commands to use with process.exit().\n *\n * Error output:\n * - JSON mode: JSON error to stdout (piped) via ui.output(), human sees nothing on stderr.\n * - Interactive: human-readable error to stderr.\n */\nexport function handleResult<T>(\n result: Result<T, CliStructuredError>,\n flags: GlobalFlags,\n ui: TerminalUI,\n onSuccess?: (value: T) => void,\n): number {\n if (result.ok) {\n if (onSuccess) {\n onSuccess(result.value);\n }\n return 0;\n }\n\n // Convert to CLI envelope\n const envelope = result.failure.toEnvelope();\n\n if (flags.json) {\n // JSON error → stdout only\n ui.output(formatErrorJson(envelope));\n } else {\n // Human-readable error → stderr\n ui.error(formatErrorOutput(envelope, flags));\n }\n\n // Infer exit code from error domain: CLI errors = 2, RUN errors = 1\n const exitCode = result.failure.domain === 'CLI' ? 2 : 1;\n return exitCode;\n}\n","export type GlyphMode = 'unicode' | 'ascii';\n\nexport interface GlyphModeInput {\n readonly isTTY: boolean;\n readonly env: Readonly<Record<string, string | undefined>>;\n}\n\nfunction localeString(env: Readonly<Record<string, string | undefined>>): string {\n return env['LC_ALL'] ?? env['LC_CTYPE'] ?? env['LANG'] ?? '';\n}\n\nfunction isUtf8Locale(env: Readonly<Record<string, string | undefined>>): boolean {\n const locale = localeString(env);\n if (locale.length === 0) return false;\n return /UTF-8|utf8/i.test(locale);\n}\n\nexport function detectGlyphMode(input: GlyphModeInput): GlyphMode {\n if (!input.isTTY) return 'ascii';\n if (!isUtf8Locale(input.env)) return 'ascii';\n return 'unicode';\n}\n","/**\n * Global shutdown controller for graceful SIGINT/SIGTERM handling.\n *\n * The CLI installs signal handlers once at startup. When a signal fires:\n * 1. The AbortController is aborted — in-flight async work (DB queries, emit) can check `signal.aborted`.\n * 2. A 3-second grace timer starts — gives `finally` blocks time to close connections.\n * 3. If the process hasn't exited by then, force-exit with code 130 (128 + SIGINT).\n * 4. A second signal during the grace period force-exits immediately.\n */\n\n/**\n * Creates a shutdown handler with its own AbortController.\n * Exposed for testing — production code uses the singleton below.\n */\nexport interface ShutdownHandler {\n readonly signal: AbortSignal;\n readonly isShuttingDown: () => boolean;\n readonly onSignal: () => void;\n readonly clearGraceTimer: () => void;\n}\n\nexport function createShutdownHandler(options?: {\n readonly exit?: (code: number) => void;\n readonly gracePeriodMs?: number;\n}): ShutdownHandler {\n const exit = options?.exit ?? ((code: number) => process.exit(code));\n const gracePeriodMs = options?.gracePeriodMs ?? 3000;\n\n const controller = new AbortController();\n let shuttingDown = false;\n let graceTimer: ReturnType<typeof setTimeout> | undefined;\n\n const onSignal = () => {\n if (shuttingDown) {\n // Second signal — force exit\n exit(130);\n return;\n }\n shuttingDown = true;\n controller.abort();\n\n // Give finally blocks time to clean up, then force-exit\n graceTimer = setTimeout(() => exit(130), gracePeriodMs);\n graceTimer.unref();\n };\n\n return {\n signal: controller.signal,\n isShuttingDown: () => shuttingDown,\n onSignal,\n clearGraceTimer: () => {\n if (graceTimer !== undefined) {\n clearTimeout(graceTimer);\n graceTimer = undefined;\n }\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Singleton for production use\n// ---------------------------------------------------------------------------\n\nconst globalHandler = createShutdownHandler();\n\n/**\n * The global AbortSignal. Pass this to any async operation that should\n * be cancellable on Ctrl+C (e.g., DB queries, long-running emit).\n */\nexport const shutdownSignal: AbortSignal = globalHandler.signal;\n\n/**\n * Whether a shutdown has been initiated.\n */\nexport function isShuttingDown(): boolean {\n return globalHandler.isShuttingDown();\n}\n\n/**\n * Installs SIGINT and SIGTERM handlers. Call once at CLI startup.\n *\n * - First signal: aborts the controller, starts a 3s grace timer.\n * - Second signal: force-exits immediately.\n */\nlet installed = false;\n\nexport function installShutdownHandlers(): void {\n if (installed) return;\n installed = true;\n process.on('SIGINT', globalHandler.onSignal);\n process.on('SIGTERM', globalHandler.onSignal);\n}\n","import * as clack from '@clack/prompts';\nimport { bold, cyan, dim, green, red, yellow } from 'colorette';\nimport type { GlobalFlags } from './global-flags';\nimport { detectGlyphMode, type GlyphMode, type GlyphModeInput } from './glyph-mode';\nimport { shutdownSignal } from './shutdown';\n\nexport interface TerminalUIRuntime extends GlyphModeInput {}\n\n/**\n * Composable CLI output abstraction.\n *\n * Follows the Unix convention of separating data from decoration:\n * - **stdout** — data output only (`ui.output()`). This is what scripts and pipes capture.\n * - **stderr** — all decoration (spinners, logs, notes, intro/outro). Visible in terminal, invisible in pipes.\n *\n * Rules:\n * 1. All methods except `output()` and `error()` write to stderr only in interactive mode.\n * 2. `output(data)` always writes to stdout — if a command calls it, there is data to emit.\n * 3. `error()` always writes to stderr — errors matter even when piped.\n * 4. Decoration is suppressed when piped unless `--format pretty` was explicit (`forcePretty`).\n * 5. Never write data to stderr — decoration methods are for human context only.\n * 6. Never write decoration to stdout — it breaks pipes, `$(...)` captures, and `> file` redirects.\n */\nexport class TerminalUI {\n /**\n * True when stdout is a TTY (interactive terminal).\n * False when piped (e.g., `prisma-next db verify | jq`).\n */\n readonly isInteractive: boolean;\n\n /**\n * Whether color output is enabled.\n */\n readonly useColor: boolean;\n\n /**\n * When true, decoration methods write even on non-TTY stdout\n * (explicit `--format pretty`).\n */\n readonly forcePretty: boolean;\n\n /**\n * Whether stdout is a TTY — used for migration-list graph glyph detection.\n */\n readonly stdoutIsTTY: boolean;\n\n /**\n * Process environment snapshot for locale-aware glyph detection.\n */\n readonly env: Readonly<Record<string, string | undefined>>;\n\n private static readonly stderrOpts = { output: process.stderr } as const;\n\n constructor(options?: {\n readonly color?: boolean | undefined;\n readonly interactive?: boolean | undefined;\n readonly forcePretty?: boolean | undefined;\n readonly stdoutIsTTY?: boolean | undefined;\n readonly env?: Readonly<Record<string, string | undefined>> | undefined;\n }) {\n // --interactive/--no-interactive override TTY detection\n this.isInteractive = options?.interactive ?? !!process.stdout.isTTY;\n this.forcePretty = options?.forcePretty ?? false;\n this.useColor = options?.color ?? (this.isInteractive || this.forcePretty);\n this.stdoutIsTTY = options?.stdoutIsTTY ?? !!process.stdout.isTTY;\n this.env = options?.env ?? process.env;\n }\n\n get isTTY(): boolean {\n return this.stdoutIsTTY;\n }\n\n /**\n * Resolve glyph mode for migration list/tree output. `--ascii` forces ASCII;\n * otherwise delegates to the pure {@link detectGlyphMode} helper.\n */\n resolveGlyphMode(forceAscii: boolean): GlyphMode {\n if (forceAscii) {\n return 'ascii';\n }\n return detectGlyphMode(this.glyphModeInput());\n }\n\n glyphModeInput(): GlyphModeInput {\n return { isTTY: this.stdoutIsTTY, env: this.env };\n }\n\n private get shouldDecorate(): boolean {\n return this.isInteractive || this.forcePretty;\n }\n\n // ---------------------------------------------------------------------------\n // Decoration → stderr (interactive mode, or explicit --format pretty)\n // ---------------------------------------------------------------------------\n\n /**\n * Log a message line to stderr. No-op when piped unless forcePretty.\n */\n log(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.message(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log a success message to stderr. No-op when piped unless forcePretty.\n */\n success(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.success(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log a warning message to stderr. No-op when piped unless forcePretty.\n */\n warn(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.warn(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log an error message to stderr. Always writes (errors matter even in pipes).\n */\n error(message: string): void {\n clack.log.error(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log an info message to stderr. No-op when piped unless forcePretty.\n */\n info(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.info(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Log a step message to stderr. No-op when piped unless forcePretty.\n */\n step(message: string): void {\n if (!this.shouldDecorate) return;\n clack.log.step(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Display a note box on stderr. No-op when piped unless forcePretty.\n */\n note(message: string, title?: string): void {\n if (!this.shouldDecorate) return;\n clack.note(message, title, TerminalUI.stderrOpts);\n }\n\n /**\n * Display intro banner on stderr. No-op when piped unless forcePretty.\n */\n intro(title?: string): void {\n if (!this.shouldDecorate) return;\n clack.intro(title, TerminalUI.stderrOpts);\n }\n\n /**\n * Display outro banner on stderr. No-op when piped unless forcePretty.\n */\n outro(message?: string): void {\n if (!this.shouldDecorate) return;\n clack.outro(message, TerminalUI.stderrOpts);\n }\n\n /**\n * Create a Clack spinner on stderr with a 100ms delay threshold.\n * The spinner only appears if the operation takes longer than the threshold,\n * avoiding flicker for fast operations. Returns a no-op spinner when not decorating.\n */\n spinner(delayMs = 100): clack.SpinnerResult {\n const noop: clack.SpinnerResult = {\n start: () => {},\n stop: () => {},\n cancel: () => {},\n error: () => {},\n message: () => {},\n clear: () => {},\n get isCancelled() {\n return false;\n },\n };\n\n if (!this.shouldDecorate) {\n return noop;\n }\n\n // Wrap the real spinner with a delay: only show it after `delayMs`\n let inner: clack.SpinnerResult | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let pendingMsg: string | undefined;\n let settled = false;\n\n const ensureCleared = () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n timer = undefined;\n }\n };\n\n // Cancel the spinner if a shutdown signal fires\n const onAbort = () => {\n if (!settled) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.cancel('Interrupted');\n }\n }\n };\n if (!shutdownSignal.aborted) {\n shutdownSignal.addEventListener('abort', onAbort, { once: true });\n }\n\n return {\n start(msg?: string) {\n pendingMsg = msg;\n timer = setTimeout(() => {\n if (!settled) {\n inner = clack.spinner(TerminalUI.stderrOpts);\n inner.start(pendingMsg);\n }\n }, delayMs);\n },\n stop(msg?: string) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.stop(msg);\n }\n },\n cancel(msg?: string) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.cancel(msg);\n }\n },\n error(msg?: string) {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.error(msg);\n }\n },\n message(msg?: string) {\n pendingMsg = msg;\n if (inner) {\n inner.message(msg);\n }\n },\n clear() {\n settled = true;\n ensureCleared();\n if (inner) {\n inner.clear();\n }\n },\n get isCancelled() {\n return inner?.isCancelled ?? false;\n },\n };\n }\n\n /**\n * Prompt for yes/no confirmation on stderr. Returns true if confirmed.\n * In non-interactive mode or when cancelled (Ctrl-C), returns false.\n */\n async confirm(message: string): Promise<boolean> {\n if (!this.isInteractive) return false;\n const result = await clack.confirm({\n message,\n ...TerminalUI.stderrOpts,\n });\n if (clack.isCancel(result)) return false;\n return result;\n }\n\n /**\n * Write a raw line to stderr. No-op when piped unless forcePretty.\n * Use for decoration that doesn't fit Clack's log format (e.g. styled headers).\n */\n stderr(message: string): void {\n if (!this.shouldDecorate) return;\n process.stderr.write(`${message}\\n`);\n }\n\n // ---------------------------------------------------------------------------\n // Data → stdout (only when piped)\n // ---------------------------------------------------------------------------\n\n /**\n * Write machine-readable data to stdout.\n * Always writes — if a command calls output(), there is data to emit.\n *\n * This is what scripts and pipes capture: `prisma-next db verify --json | jq .ok`\n */\n output(data: string): void {\n process.stdout.write(`${data}\\n`);\n }\n\n // ---------------------------------------------------------------------------\n // Color helpers\n // ---------------------------------------------------------------------------\n\n green(text: string): string {\n return this.useColor ? green(text) : text;\n }\n red(text: string): string {\n return this.useColor ? red(text) : text;\n }\n cyan(text: string): string {\n return this.useColor ? cyan(text) : text;\n }\n dim(text: string): string {\n return this.useColor ? dim(text) : text;\n }\n bold(text: string): string {\n return this.useColor ? bold(text) : text;\n }\n yellow(text: string): string {\n return this.useColor ? yellow(text) : text;\n }\n}\n\nexport function createTerminalUI(\n flags: GlobalFlags,\n runtime?: Partial<TerminalUIRuntime>,\n): TerminalUI {\n return new TerminalUI({\n color: flags.color,\n interactive: flags.interactive,\n forcePretty: flags.format === 'pretty' && flags.explicitFormat,\n stdoutIsTTY: runtime?.isTTY,\n env: runtime?.env,\n });\n}\n","import { notOk } from '@prisma-next/utils/result';\nimport { CliStructuredError, errorInvalidOutputFormat, errorOutputFormatMutex } from './cli-errors';\nimport { isCI } from './is-ci';\nimport { handleResult } from './result-handler';\nimport { createTerminalUI } from './terminal-ui';\n\nexport type OutputFormat = 'pretty' | 'json';\n\nexport interface GlobalFlags {\n readonly format: OutputFormat;\n readonly explicitFormat: boolean;\n readonly json?: boolean;\n readonly quiet?: boolean;\n readonly verbose?: number;\n readonly color?: boolean;\n readonly interactive?: boolean;\n readonly yes?: boolean;\n}\n\n/**\n * Common options parsed by Commander.js for every command.\n * Extend this for command-specific options instead of duplicating these fields.\n */\nexport interface CommonCommandOptions {\n readonly format?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly trace?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n readonly interactive?: boolean;\n readonly 'no-interactive'?: boolean;\n readonly yes?: boolean;\n readonly y?: boolean;\n}\n\nfunction isJsonFlagSet(json: string | boolean | undefined): boolean {\n return json === true;\n}\n\ninterface ResolvedOutputFormat {\n readonly format: OutputFormat;\n readonly explicitFormat: boolean;\n}\n\nfunction resolveOutputFormat(options: CommonCommandOptions): ResolvedOutputFormat {\n const formatOption = options.format;\n const jsonFlag = isJsonFlagSet(options.json);\n\n if (formatOption !== undefined) {\n if (formatOption !== 'pretty' && formatOption !== 'json') {\n throw errorInvalidOutputFormat(formatOption);\n }\n if (jsonFlag && formatOption === 'pretty') {\n throw errorOutputFormatMutex();\n }\n return { format: formatOption, explicitFormat: true };\n }\n\n if (jsonFlag) {\n return { format: 'json', explicitFormat: false };\n }\n\n if (!process.stdout.isTTY) {\n return { format: 'json', explicitFormat: false };\n }\n\n return { format: 'pretty', explicitFormat: false };\n}\n\nfunction inferJsonModeForParseError(options: CommonCommandOptions): boolean {\n if (options.format === 'json') {\n return true;\n }\n if (isJsonFlagSet(options.json) && options.format !== 'pretty') {\n return true;\n }\n if (options.format !== undefined) {\n return false;\n }\n return !process.stdout.isTTY;\n}\n\nfunction emitGlobalFlagParseError(error: CliStructuredError, options: CommonCommandOptions): never {\n const jsonMode = inferJsonModeForParseError(options);\n const flags: GlobalFlags = {\n format: jsonMode ? 'json' : 'pretty',\n explicitFormat: false,\n ...(jsonMode ? { json: true } : {}),\n color: false,\n verbose: 0,\n interactive: false,\n };\n const ui = createTerminalUI(flags);\n const exitCode = handleResult(notOk(error), flags, ui);\n process.exit(exitCode);\n}\n\n/**\n * Parses global flags from CLI options.\n * Handles verbosity flags (-v, --trace), output format (--format, --json),\n * quiet mode, color, interactivity (--interactive/--no-interactive), and\n * auto-accept (-y/--yes).\n *\n * On invalid or conflicting format flags, prints a structured CLI error\n * envelope and exits with code 2.\n */\nexport function parseGlobalFlagsOrExit(options: CommonCommandOptions): GlobalFlags {\n try {\n return parseGlobalFlags(options);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n emitGlobalFlagParseError(error, options);\n }\n throw error;\n }\n}\n\n/**\n * Parses global flags from CLI options.\n * Handles verbosity flags (-v, --trace), output format (--format, --json),\n * quiet mode, color, interactivity (--interactive/--no-interactive), and\n * auto-accept (-y/--yes).\n *\n * Throws {@link CliStructuredError} for invalid or conflicting format flags.\n */\nexport function parseGlobalFlags(options: CommonCommandOptions): GlobalFlags {\n const { format, explicitFormat } = resolveOutputFormat(options);\n const flags: {\n format: OutputFormat;\n explicitFormat: boolean;\n json?: boolean;\n quiet?: boolean;\n verbose?: number;\n color?: boolean;\n interactive?: boolean;\n yes?: boolean;\n } = { format, explicitFormat };\n\n if (format === 'json') {\n flags.json = true;\n }\n\n if (options.quiet || options.q) {\n flags.quiet = true;\n }\n\n if (options.trace || process.env['PRISMA_NEXT_TRACE'] === '1') {\n flags.verbose = 2;\n } else if (options.verbose || options.v || process.env['PRISMA_NEXT_DEBUG'] === '1') {\n flags.verbose = 1;\n } else {\n flags.verbose = 0;\n }\n\n if (process.env['NO_COLOR'] || flags.json) {\n flags.color = false;\n } else if (options['no-color']) {\n flags.color = false;\n } else if (options.color !== undefined) {\n flags.color = options.color;\n } else {\n flags.color = process.stdout.isTTY && !isCI();\n }\n\n if (options['no-interactive']) {\n flags.interactive = false;\n } else if (options.interactive !== undefined) {\n flags.interactive = options.interactive;\n } else {\n flags.interactive = !!process.stdout.isTTY;\n }\n\n if (options.yes || options.y) {\n flags.yes = true;\n }\n\n return flags as GlobalFlags;\n}\n\n/**\n * Bridges the two TTY checks (stdout via `flags`, stdin via\n * `process.stdin.isTTY`) into the `canPrompt` boolean the interactive\n * `init` flow consumes.\n *\n * Per the [Style Guide § Interactivity](../../../../../../../docs/CLI%20Style%20Guide.md#interactivity):\n *\n * - `flags.interactive` governs *decoration* (TerminalUI, intro/outro,\n * spinners) and is derived from stdout-TTY by `parseGlobalFlags`,\n * honouring `--interactive` / `--no-interactive`.\n * - Prompting additionally requires a stdin TTY — closing stdin is a\n * common signal in CI / agent environments even when stdout stays\n * attached.\n * - `--interactive` is the explicit override: when the user passes it,\n * we honour it (e.g. testing flows where stdin is stubbed).\n *\n * Single source of truth for the interactive-prompt decision: both the\n * `init` action handler and the preAction telemetry bridge derive\n * prompt-eligibility from this helper so they cannot drift. Lives in\n * `global-flags` (alongside `parseGlobalFlags`) to keep\n * `utils/telemetry` and `commands/init/index` free of an import cycle.\n *\n * Exported so callers and tests can derive the same value without\n * touching `process` globals.\n */\nexport function deriveCanPrompt(opts: {\n readonly flagsInteractive: boolean | undefined;\n readonly optionInteractive: boolean | undefined;\n readonly stdinIsTTY: boolean;\n}): boolean {\n if (opts.optionInteractive === true) return true;\n if (opts.flagsInteractive === false) return false;\n return opts.stdinIsTTY;\n}\n","import { readFile } from 'node:fs/promises';\nimport type { ControlTargetDescriptor } from '@prisma-next/framework-components/control';\nimport { hasMigrations } from '@prisma-next/framework-components/control';\nimport type { NoInvariantPathStructuralEdge } from '@prisma-next/migration-tools/errors';\nimport type { MigrationEdge, MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport type { PathDecision } from '@prisma-next/migration-tools/migration-graph';\nimport { APP_SPACE_ID, spaceMigrationDirectory } from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { errorRuntime } from './cli-errors';\nimport { formatCommandHelp } from './formatters/help';\nimport type { CommonCommandOptions } from './global-flags';\nimport { parseGlobalFlags } from './global-flags';\n\nconst longDescriptions = new WeakMap<Command, string>();\nconst commandExamples = new WeakMap<Command, readonly string[]>();\nconst commandSeeAlso = new WeakMap<\n Command,\n readonly { readonly verb: string; readonly oneLiner: string }[]\n>();\n\n/**\n * Sets both short and long descriptions for a command.\n * The short description is used in command trees and headers.\n * The long description is shown at the bottom of help output.\n */\nexport function setCommandDescriptions(\n command: Command,\n shortDescription: string,\n longDescription?: string,\n): Command {\n command.description(shortDescription);\n if (longDescription) {\n longDescriptions.set(command, longDescription);\n }\n return command;\n}\n\n/**\n * Sets copy-pastable examples for a command, shown in help text.\n */\nexport function setCommandExamples(command: Command, examples: readonly string[]): Command {\n commandExamples.set(command, examples);\n return command;\n}\n\n/**\n * Gets the long description from a command if it was set via setCommandDescriptions.\n */\nexport function getLongDescription(command: Command): string | undefined {\n return longDescriptions.get(command);\n}\n\n/**\n * Gets examples from a command if set via setCommandExamples.\n */\nexport function getCommandExamples(command: Command): readonly string[] | undefined {\n return commandExamples.get(command);\n}\n\n/**\n * Sets cross-references to related commands, rendered in a \"See also\"\n * section below the Examples block in help output.\n */\nexport function setCommandSeeAlso(\n command: Command,\n refs: readonly { readonly verb: string; readonly oneLiner: string }[],\n): Command {\n commandSeeAlso.set(command, refs);\n return command;\n}\n\n/**\n * Gets the see-also cross-references from a command.\n */\nexport function getCommandSeeAlso(\n command: Command,\n): readonly { readonly verb: string; readonly oneLiner: string }[] | undefined {\n return commandSeeAlso.get(command);\n}\n\n/**\n * Shared CLI options interface for migration commands (db init, db update).\n * These are the Commander.js parsed options common to both commands.\n */\nexport interface MigrationCommandOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly dryRun?: boolean;\n}\n\n/**\n * Resolves the absolute path to contract.json from the config.\n */\nexport function resolveContractPath(config: { contract?: { output?: string } }): string {\n if (config.contract?.output === undefined) {\n throw errorRuntime('config.contract.output is required to resolve the contract path', {\n why: 'CLI commands read the emitted contract from config.contract.output; the config has no value to read.',\n fix: 'Ensure your prisma-next.config.ts goes through `defineConfig()`, which normalises a default output when the provider supplies an input path, or set `contract.output` explicitly.',\n });\n }\n return resolve(config.contract.output);\n}\n\n/**\n * Resolves the migrations directory and config path from CLI options.\n * Shared by migrate, migration-plan, and migration-status.\n *\n * - `migrationsDir` is the project's top-level `migrations/` directory\n * (the root that the aggregate loader walks for every contract space).\n * - `appMigrationsDir` is the app subspace directory under it\n * (`<migrationsDir>/<APP_SPACE_ID>/`). Every per-app reader / writer\n * (`migration new`, `migration plan`, `migrate`,\n * `migration status`, `migration show`, `migration ref`) operates on\n * this directory. Extensions own their own `migrations/<spaceId>/`.\n * - `refsDir` is the app's refs directory (`<appMigrationsDir>/refs/`).\n * The framework does not maintain refs at the migrations root.\n */\nexport function resolveMigrationPaths(\n configOption: string | undefined,\n config: { migrations?: { dir?: string } },\n): {\n configPath: string;\n migrationsDir: string;\n migrationsRelative: string;\n appMigrationsDir: string;\n appMigrationsRelative: string;\n refsDir: string;\n} {\n const configPath = configOption\n ? relative(process.cwd(), resolve(configOption))\n : 'prisma-next.config.ts';\n const migrationsDir = resolve(\n configOption ? resolve(configOption, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n const appMigrationsDir = spaceMigrationDirectory(migrationsDir, APP_SPACE_ID);\n const appMigrationsRelative = relative(process.cwd(), appMigrationsDir);\n const refsDir = resolve(appMigrationsDir, 'refs');\n return {\n configPath,\n migrationsDir,\n migrationsRelative,\n appMigrationsDir,\n appMigrationsRelative,\n refsDir,\n };\n}\n\n/**\n * Slim representation of a PathDecision for CLI JSON output.\n * Strips internal fields (createdAt) from path entries.\n */\nexport interface PathDecisionResult {\n readonly fromHash: string;\n readonly toHash: string;\n readonly alternativeCount: number;\n readonly tieBreakReasons: readonly string[];\n readonly refName?: string;\n readonly requiredInvariants: readonly string[];\n readonly satisfiedInvariants: readonly string[];\n readonly selectedPath: readonly {\n readonly dirName: string;\n readonly migrationHash: string;\n readonly from: string;\n readonly to: string;\n readonly invariants: readonly string[];\n }[];\n}\n\nexport function collectDeclaredInvariants(graph: MigrationGraph): ReadonlySet<string> {\n const declared = new Set<string>();\n for (const edges of graph.forwardChain.values()) {\n for (const edge of edges) {\n for (const inv of edge.invariants) {\n declared.add(inv);\n }\n }\n }\n return declared;\n}\n\n/**\n * Maps a `MigrationEdge` to the structural-edge shape used in the\n * `MIGRATION.NO_INVARIANT_PATH` error envelope. Shared between\n * `migrate` and `migration status` so both commands surface\n * the same JSON wire shape when an invariant-aware route is unsatisfiable.\n */\nexport function toStructuralEdge(edge: MigrationEdge): NoInvariantPathStructuralEdge {\n return {\n dirName: edge.dirName,\n migrationHash: edge.migrationHash,\n from: edge.from,\n to: edge.to,\n invariants: edge.invariants,\n };\n}\n\n/**\n * Maps a PathDecision to the slim CLI output representation.\n */\nexport function toPathDecisionResult(decision: PathDecision): PathDecisionResult {\n return {\n fromHash: decision.fromHash,\n toHash: decision.toHash,\n alternativeCount: decision.alternativeCount,\n tieBreakReasons: decision.tieBreakReasons,\n requiredInvariants: decision.requiredInvariants ?? [],\n satisfiedInvariants: decision.satisfiedInvariants ?? [],\n ...ifDefined('refName', decision.refName),\n selectedPath: decision.selectedPath.map((entry) => ({\n dirName: entry.dirName,\n migrationHash: entry.migrationHash,\n from: entry.from,\n to: entry.to,\n invariants: entry.invariants,\n })),\n };\n}\n\nexport function targetSupportsMigrations(target: ControlTargetDescriptor<string, string>): boolean {\n return hasMigrations(target);\n}\n\nexport function getTargetMigrations(target: ControlTargetDescriptor<string, string>) {\n return hasMigrations(target) ? target.migrations : undefined;\n}\n\n/**\n * The subset of the emitted contract.json that the framework layer can\n * safely type. The emitter adds these fields on top of the family-specific\n * storage/models/relations. Other fields exist in the JSON but are opaque\n * at this layer — the index signature preserves them for downstream\n * consumers that operate at the family level (e.g., the control client).\n */\nexport interface ContractEnvelope {\n readonly storageHash: string;\n readonly schemaVersion: string;\n readonly target: string;\n readonly targetFamily: string;\n readonly profileHash?: string;\n readonly [key: string]: unknown;\n}\n\n/**\n * Reads and parses contract.json, validating the framework-level envelope\n * fields (storageHash, schemaVersion, target, targetFamily).\n *\n * Family-specific validation (storage structure, codec mappings, etc.)\n * happens downstream in the control client via the family instance.\n */\nexport async function readContractEnvelope(config: {\n contract?: { output?: string };\n}): Promise<ContractEnvelope> {\n const contractPath = resolveContractPath(config);\n const content = await readFile(contractPath, 'utf-8');\n const json = JSON.parse(content) as Record<string, unknown>;\n\n const { schemaVersion, target, targetFamily, profileHash } = json;\n const storage = json['storage'] as Record<string, unknown> | undefined;\n const storageHash = storage?.['storageHash'];\n\n if (typeof storageHash !== 'string') {\n throw new Error(\n `Contract at ${relative(process.cwd(), contractPath)} is missing a valid storage.storageHash. Run \\`prisma-next contract emit\\` to regenerate.`,\n );\n }\n if (typeof schemaVersion !== 'string') {\n throw new Error(\n `Contract at ${relative(process.cwd(), contractPath)} is missing schemaVersion.`,\n );\n }\n if (typeof target !== 'string') {\n throw new Error(`Contract at ${relative(process.cwd(), contractPath)} is missing target.`);\n }\n if (typeof targetFamily !== 'string') {\n throw new Error(\n `Contract at ${relative(process.cwd(), contractPath)} is missing targetFamily.`,\n );\n }\n\n return {\n ...json,\n storageHash,\n schemaVersion,\n target,\n targetFamily,\n ...(typeof profileHash === 'string' ? { profileHash } : {}),\n };\n}\n\n/**\n * Masks credentials in a database connection URL.\n * Handles standard URLs (username + password + query params) and libpq-style key=value strings.\n */\nexport function maskConnectionUrl(url: string): string {\n try {\n const parsed = new URL(url);\n if (parsed.username) {\n parsed.username = '****';\n }\n if (parsed.password) {\n parsed.password = '****';\n }\n // Also mask password in query parameters (e.g., ?password=secret, ?sslpassword=secret)\n for (const key of [...parsed.searchParams.keys()]) {\n if (/password/i.test(key)) {\n parsed.searchParams.set(key, '****');\n }\n }\n return parsed.toString();\n } catch {\n // Fallback for libpq-style key=value connection strings (e.g., \"host=localhost password=secret user=admin\")\n return url\n .replace(/password\\s*=\\s*\\S+/gi, 'password=****')\n .replace(/user\\s*=\\s*\\S+/gi, 'user=****');\n }\n}\n\n/**\n * Strips raw connection URL fragments from an error message to prevent credential leakage.\n * Call this before surfacing driver errors to the user.\n */\nexport function sanitizeErrorMessage(message: string, connectionUrl?: string): string {\n if (!connectionUrl) {\n return message;\n }\n try {\n const parsed = new URL(connectionUrl);\n // Replace the full URL (with and without trailing slash)\n let sanitized = message;\n sanitized = sanitized.replaceAll(connectionUrl, maskConnectionUrl(connectionUrl));\n // Also replace the password and username individually if they appear\n if (parsed.password) {\n sanitized = sanitized.replaceAll(parsed.password, '****');\n }\n if (parsed.username) {\n sanitized = sanitized.replaceAll(parsed.username, '****');\n }\n return sanitized;\n } catch {\n // For libpq-style strings, mask password and user values in the message\n return message\n .replace(/password\\s*=\\s*\\S+/gi, 'password=****')\n .replace(/user\\s*=\\s*\\S+/gi, 'user=****');\n }\n}\n\n/**\n * Registers the global CLI options shared by every command:\n * --format, --json, -q/--quiet, -v/--verbose, --trace, --color, --no-color,\n * --interactive, --no-interactive, -y/--yes.\n *\n * Also sets up the styled help formatter.\n */\nexport function addGlobalOptions(command: Command): Command {\n return command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option(\n '--format <pretty|json>',\n 'Output format (default: pretty, or json when stdout is not a TTY)',\n )\n .option('--json', 'Output as JSON (alias for --format json)')\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('--trace', 'Trace output: deep internals, stack traces')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .option('--interactive', 'Force interactive mode')\n .option('--no-interactive', 'Disable interactive prompts')\n .option('-y, --yes', 'Auto-accept prompts');\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration-list.mjs","names":[],"sources":["../../src/commands/migration-list.ts"],"sourcesContent":["import type {\n ContractSpaceAggregate,\n ContractSpaceMember,\n} from '@prisma-next/migration-tools/aggregate';\nimport { HEAD_REF_NAME, refsByContractHash } from '@prisma-next/migration-tools/refs';\nimport {\n APP_SPACE_ID,\n isValidSpaceId,\n listContractSpaceDirectories,\n RESERVED_SPACE_SUBDIR_NAMES,\n} from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliStructuredError,\n errorInvalidSpaceId,\n errorSpaceNotFound,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport { renderMigrationListWithStyle } from '../utils/formatters/migration-list-render';\nimport { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';\nimport type {\n MigrationListEntry,\n MigrationListResult,\n MigrationSpaceListEntry,\n} from '../utils/formatters/migration-list-types';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport type { GlyphMode } from '../utils/glyph-mode';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\nfunction compareSpaceIds(a: string, b: string): number {\n if (a === APP_SPACE_ID) return b === APP_SPACE_ID ? 0 : -1;\n if (b === APP_SPACE_ID) return 1;\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\nfunction compareDirNamesDescending(a: MigrationListEntry, b: MigrationListEntry): number {\n if (a.dirName < b.dirName) return 1;\n if (a.dirName > b.dirName) return -1;\n return 0;\n}\n\n/**\n * Ref names decorating a space's destination contract hashes. The\n * tolerant `member.refs` deliberately omits the structural `head.json`;\n * for extension spaces the old enumerator surfaced it as a `head`\n * decoration on the tip migration, so fold `member.headRef` back in to\n * keep that output. The app space synthesises its head, so it carries\n * no on-disk `head` ref to restore.\n */\nexport function listRefsByContractHash(\n member: ContractSpaceMember,\n): ReadonlyMap<string, readonly string[]> {\n const byHash = new Map(refsByContractHash(member.refs));\n if (member.spaceId !== APP_SPACE_ID && member.headRef !== null) {\n const hash = member.headRef.hash;\n const bucket = byHash.get(hash) ?? [];\n if (!bucket.includes(HEAD_REF_NAME)) {\n byHash.set(hash, [...bucket, HEAD_REF_NAME].sort());\n }\n }\n return byHash;\n}\n\nasync function orderedOnDiskSpaceIds(projectMigrationsDir: string): Promise<readonly string[]> {\n const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);\n return candidateDirs\n .filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name))\n .filter(isValidSpaceId)\n .sort(compareSpaceIds);\n}\n\n/**\n * Project the loaded {@link ContractSpaceAggregate} into the render-ready\n * {@link MigrationSpaceListEntry} rows `migration list` displays.\n *\n * Space membership matches the on-disk contract-space directories (not the\n * aggregate's always-present synthesized app member when `migrations/app/`\n * is absent); package and ref data come from `aggregate.space(id)`.\n */\nexport async function migrationSpaceListEntriesFromAggregate(\n aggregate: ContractSpaceAggregate,\n projectMigrationsDir: string,\n): Promise<readonly MigrationSpaceListEntry[]> {\n const spaceIds = await orderedOnDiskSpaceIds(projectMigrationsDir);\n const spaces: MigrationSpaceListEntry[] = [];\n\n for (const spaceId of spaceIds) {\n const member = aggregate.space(spaceId);\n if (member === undefined) {\n continue;\n }\n const refsByHash = listRefsByContractHash(member);\n const migrations: MigrationListEntry[] = member.packages\n .map((pkg) => ({\n dirName: pkg.dirName,\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n operationCount: pkg.ops.length,\n createdAt: pkg.metadata.createdAt,\n refs: refsByHash.get(pkg.metadata.to) ?? [],\n providedInvariants: pkg.metadata.providedInvariants,\n }))\n .sort(compareDirNamesDescending);\n\n spaces.push({ spaceId, migrations });\n }\n\n return spaces;\n}\n\ninterface MigrationListOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n readonly ascii?: boolean;\n}\n\nexport interface MigrationListHumanRenderOptions {\n readonly glyphMode: GlyphMode;\n readonly useColor: boolean;\n}\n\nexport function renderMigrationListHumanOutput(\n result: MigrationListResult,\n options: MigrationListHumanRenderOptions,\n): string {\n const styler = createAnsiMigrationListStyler({ useColor: options.useColor });\n return renderMigrationListWithStyle(result, styler, options.glyphMode, {\n colorize: options.useColor,\n });\n}\n\n/**\n * Inputs for {@link runMigrationList} — the policy core of `migration list`\n * that tests exercise directly.\n *\n * The core does not call `loadConfig`, parse CLI flags, render a styled\n * header, or write to any stream. Enumeration is supplied by the caller\n * (the CLI shell builds it from {@link migrationSpaceListEntriesFromAggregate}).\n */\nexport interface RunMigrationListInputs {\n readonly spaces: readonly MigrationSpaceListEntry[];\n readonly spaceFilter?: string;\n}\n\nfunction computeSummary(spaces: readonly MigrationSpaceListEntry[]): string {\n const totalMigrations = spaces.reduce((count, space) => count + space.migrations.length, 0);\n if (spaces.length <= 1) {\n return `${totalMigrations} migration(s) on disk`;\n }\n return `${totalMigrations} migration(s) across ${spaces.length} contract space(s)`;\n}\n\n/**\n * Policy core of `migration list`: validates `--space`, narrows the\n * pre-enumerated spaces, and assembles a {@link MigrationListResult}.\n *\n * - `migrations/` missing or contains no valid space directories →\n * caller passes `spaces: []`; this synthesizes `[{ spaceId: APP_SPACE_ID, migrations: [] }]`.\n * - `--space <id>` on an existing-but-empty space → `{ spaceId, migrations: [] }` in the input.\n * - `--space <id>` on a non-existent (or reserved) space → `SPACE_NOT_FOUND`.\n */\nexport function runMigrationList(\n inputs: RunMigrationListInputs,\n): Result<MigrationListResult, CliStructuredError> {\n const { spaces, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\n }\n\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()));\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n const resultSpaces: readonly MigrationSpaceListEntry[] =\n scopedSpaces.length === 0 ? [{ spaceId: APP_SPACE_ID, migrations: [] }] : scopedSpaces;\n\n return ok({\n ok: true,\n spaces: resultSpaces,\n summary: computeSummary(resultSpaces),\n });\n}\n\n/**\n * CLI shell: loads config, resolves paths, prints the styled header on\n * stderr (interactive mode only), and delegates to {@link runMigrationList}.\n * Kept intentionally thin so the unit-testable surface lives in the core.\n */\nexport async function executeMigrationListCommand(\n options: MigrationListOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationListResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration list',\n description: 'List on-disk migrations per contract space',\n details: [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ...(options.space !== undefined ? [{ label: 'space', value: options.space }] : []),\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n const loaded = await buildReadAggregate(config, { migrationsDir });\n if (!loaded.ok) {\n return notOk(loaded.failure);\n }\n\n const spaces = await migrationSpaceListEntriesFromAggregate(\n loaded.value.aggregate,\n migrationsDir,\n );\n\n return runMigrationList({\n spaces,\n ...ifDefined('spaceFilter', options.space),\n });\n}\n\nexport function createMigrationListCommand(): Command {\n const command = new Command('list');\n setCommandDescriptions(\n command,\n 'List on-disk migrations per contract space',\n 'Enumerates every on-disk migration under migrations/<space>/ for every\\n' +\n 'contract space found on disk. Offline — does not consult the database.\\n' +\n 'Human output draws the shared migration graph tree with operation counts,\\n' +\n 'invariants on each migration row, and refs on destination contract nodes.\\n' +\n 'Pass --space <id> to narrow to one contract space. --ascii forces ASCII\\n' +\n 'tree glyphs (orthogonal to --no-color).',\n );\n setCommandExamples(command, [\n 'prisma-next migration list',\n 'prisma-next migration list --space app',\n 'prisma-next migration list --ascii',\n 'prisma-next migration list --json',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration status', oneLiner: 'Show migration path and pending status' },\n { verb: 'migration log', oneLiner: 'Show executed migration history' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n { verb: 'migration show', oneLiner: 'Display migration package contents' },\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--space <id>', 'Narrow output to a single contract space')\n .option('--ascii', 'Use ASCII kind glyphs (pipe-friendly)')\n .action(async (options: MigrationListOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const result = await executeMigrationListCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (listResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(listResult, null, 2));\n } else if (!flags.quiet) {\n ui.output(\n renderMigrationListHumanOutput(listResult, {\n glyphMode: ui.resolveGlyphMode(options.ascii === true),\n useColor: ui.useColor,\n }),\n );\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
|