@prisma-next/cli 0.16.0-dev.3 → 0.16.0-dev.5
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/README.md +3 -4
- package/dist/cli.mjs +6 -6
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +4 -6
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +5 -8
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/migrate.mjs +2 -2
- package/dist/commands/migration-check.d.mts +3 -1
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +1 -1
- package/dist/commands/migration-graph.mjs +1 -1
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +12 -36
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +7 -9
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/{contract-at-errors-D9gEjYtg.mjs → contract-at-errors-CTtzKR6q.mjs} +6 -10
- package/dist/contract-at-errors-CTtzKR6q.mjs.map +1 -0
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{init-C3JhkHg-.mjs → init-CgKEi_t5.mjs} +53 -45
- package/dist/init-CgKEi_t5.mjs.map +1 -0
- package/dist/{migration-check-MHT3w7_v.mjs → migration-check-CcuayFB2.mjs} +49 -22
- package/dist/migration-check-CcuayFB2.mjs.map +1 -0
- package/dist/{migration-list-BAKujUjh.mjs → migration-list-6z6vuXHa.mjs} +3 -3
- package/dist/migration-list-6z6vuXHa.mjs.map +1 -0
- package/dist/{migration-plan-CreSVtWZ.mjs → migration-plan-DuMEUejG.mjs} +46 -54
- package/dist/migration-plan-DuMEUejG.mjs.map +1 -0
- package/dist/{migration-status-YgEvXf-u.mjs → migration-status-B61YOaMl.mjs} +3 -2
- package/dist/{migration-status-YgEvXf-u.mjs.map → migration-status-B61YOaMl.mjs.map} +1 -1
- package/dist/{output-mEQ74_nd.mjs → output-DWNYqZGc.mjs} +5 -6
- package/dist/output-DWNYqZGc.mjs.map +1 -0
- package/package.json +21 -21
- package/src/commands/db-sign.ts +6 -4
- package/src/commands/db-update.ts +13 -6
- package/src/commands/init/hygiene-gitattributes.ts +37 -21
- package/src/commands/init/init.ts +6 -6
- package/src/commands/init/output.ts +4 -5
- package/src/commands/init/reinit-cleanup.ts +16 -17
- package/src/commands/migration-check.ts +69 -32
- package/src/commands/migration-list.ts +1 -5
- package/src/commands/migration-new.ts +15 -39
- package/src/commands/migration-plan.ts +54 -76
- package/src/commands/ref.ts +18 -7
- package/src/utils/contract-at-errors.ts +9 -13
- package/src/utils/contract-space-seed-phase.ts +8 -6
- package/src/utils/plan-resolution.ts +1 -4
- package/dist/contract-at-errors-D9gEjYtg.mjs.map +0 -1
- package/dist/init-C3JhkHg-.mjs.map +0 -1
- package/dist/migration-check-MHT3w7_v.mjs.map +0 -1
- package/dist/migration-list-BAKujUjh.mjs.map +0 -1
- package/dist/migration-plan-CreSVtWZ.mjs.map +0 -1
- package/dist/output-mEQ74_nd.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-check-CcuayFB2.mjs","names":["migrationPathRelative","migrationFileRelative"],"sources":["../src/utils/integrity-violation-to-check-failure.ts","../src/commands/migration-check.ts"],"sourcesContent":["import type { IntegrityViolation } from '@prisma-next/migration-tools/aggregate';\nimport { join, relative } from 'pathe';\nimport type { CheckFailure } from '../commands/json/schemas';\n\nexport type { CheckFailure } from '../commands/json/schemas';\n\nfunction migrationPathRelative(dirPath: string): string {\n return relative(process.cwd(), dirPath);\n}\n\nfunction migrationFileRelative(dirPath: string, fileName: string): string {\n return join(migrationPathRelative(dirPath), fileName);\n}\n\n/**\n * Map one {@link IntegrityViolation} onto a `migration check` failure row.\n * Sole catalogue mapping from integrity violations to `MIGRATION.CHECK_*` codes.\n */\nexport function integrityViolationToCheckFailure(\n violation: IntegrityViolation,\n migrationsDir: string,\n): CheckFailure {\n const spaceRelative = (spaceId: string): string =>\n migrationPathRelative(join(migrationsDir, spaceId));\n const packageRelative = (spaceId: string, dirName: string): string =>\n migrationPathRelative(join(migrationsDir, spaceId, dirName));\n const refRelative = (spaceId: string, refName: string): string =>\n migrationPathRelative(join(migrationsDir, spaceId, 'refs', `${refName}.json`));\n\n switch (violation.kind) {\n case 'hashMismatch':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_HASH_MISMATCH',\n where: migrationFileRelative(\n join(migrationsDir, violation.spaceId, violation.dirName),\n 'migration.json',\n ),\n why: `Stored hash ${violation.stored} does not match recomputed hash ${violation.computed}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n case 'providedInvariantsMismatch':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_PROVIDED_INVARIANTS_MISMATCH',\n where: packageRelative(violation.spaceId, violation.dirName),\n why: `Migration \"${violation.dirName}\" providedInvariants in migration.json disagrees with ops.json.`,\n fix: 'Re-emit the migration package so migration.json and ops.json agree.',\n };\n case 'packageUnloadable':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_PACKAGE_UNLOADABLE',\n where: packageRelative(violation.spaceId, violation.dirName),\n why: `Migration \"${violation.dirName}\" could not be loaded: ${violation.detail}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n case 'sameSourceAndTarget':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_NOOP_SELF_EDGE',\n where: packageRelative(violation.spaceId, violation.dirName),\n why: `Migration \"${violation.dirName}\" in space \"${violation.spaceId}\" has source equal to target (${violation.hash}) with no data invariant — a true no-op self-edge.`,\n fix: 'Add a data operation if this self-edge was meant to carry a data invariant, or delete the migration if it is a true no-op.',\n };\n case 'orphanSpaceDir':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_ORPHAN_SPACE_DIR',\n where: spaceRelative(violation.spaceId),\n why: `Contract-space directory \"${violation.spaceId}\" exists on disk but no extension declares it.`,\n fix: 'Remove the orphan directory, or declare the extension in `extensionPacks`.',\n };\n case 'declaredButUnmigrated':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_DECLARED_BUT_UNMIGRATED',\n where: spaceRelative(violation.spaceId),\n why: `Extension \"${violation.spaceId}\" is declared in \\`extensionPacks\\` but has no on-disk migrations directory.`,\n fix: 'Re-emit the extension contract-space artefacts with `prisma-next contract emit` and migration planning, or remove the extension from `extensionPacks` if it is unused.',\n };\n case 'headRefMissing':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_HEAD_REF_MISSING',\n where: refRelative(violation.spaceId, 'head'),\n why: `Head ref \\`refs/head.json\\` is missing for contract space \"${violation.spaceId}\".`,\n fix: 'Re-emit the contract-space migrations and head ref artefacts, or restore `refs/head.json` from version control.',\n };\n case 'headRefNotInGraph':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_HEAD_REF_NOT_IN_GRAPH',\n where: refRelative(violation.spaceId, 'head'),\n why: `Head ref ${violation.hash} for contract space \"${violation.spaceId}\" is not present in its migration graph.`,\n fix: 'Re-emit the contract space migrations, or restore the missing migration package.',\n };\n case 'refUnreadable':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_REF_UNREADABLE',\n where: refRelative(violation.spaceId, violation.refName),\n why: `Ref \"${violation.refName}\" for contract space \"${violation.spaceId}\" is unreadable: ${violation.detail}`,\n fix: 'Repair or remove the corrupt ref file.',\n };\n case 'targetMismatch':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_TARGET_MISMATCH',\n where: spaceRelative(violation.spaceId),\n why: `Contract space \"${violation.spaceId}\" targets \"${violation.actual}\" but the project targets \"${violation.expected}\".`,\n fix: 'Update the extension to target the configured database, or change the project target.',\n };\n case 'disjointness':\n return {\n space: 'app',\n code: 'MIGRATION.CHECK_SPACE_DISJOINTNESS_VIOLATION',\n where: migrationPathRelative(migrationsDir),\n why: `Storage element \"${violation.element}\" is claimed by multiple contract spaces: ${violation.claimedBy.join(', ')}.`,\n fix: 'Update the contracts so each storage element is owned by exactly one contract space.',\n };\n case 'contractUnreadable':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_CONTRACT_UNREADABLE',\n where: migrationFileRelative(join(migrationsDir, violation.spaceId), 'contract.json'),\n why: `Contract for space \"${violation.spaceId}\" is unreadable: ${violation.detail}`,\n fix: 'Re-emit the extension contract artefacts, or fix the descriptor producing the invalid contract.',\n };\n case 'duplicateMigrationHash':\n return {\n space: violation.spaceId,\n code: 'MIGRATION.CHECK_DUPLICATE_MIGRATION_HASH',\n where: spaceRelative(violation.spaceId),\n why: `Multiple migrations in space \"${violation.spaceId}\" share migrationHash \"${violation.migrationHash}\" (${violation.dirNames.join(', ')}).`,\n fix: 'Re-emit one of the conflicting packages so each migrationHash is unique.',\n };\n }\n}\n","import { existsSync, readdirSync, statSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { loadConfig } from '@prisma-next/config-loader';\nimport { createControlStack } from '@prisma-next/framework-components/control';\nimport type {\n ContractSpaceAggregate,\n IntegrityViolation,\n} from '@prisma-next/migration-tools/aggregate';\nimport { loadContractSpaceAggregate } from '@prisma-next/migration-tools/aggregate';\nimport {\n contractSnapshotDir,\n readContractSnapshotJson,\n} from '@prisma-next/migration-tools/contract-snapshot-store';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport { verifyMigrationHash } from '@prisma-next/migration-tools/hash';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport {\n parseMigrationRef,\n type RefResolutionError,\n} from '@prisma-next/migration-tools/ref-resolution';\nimport type { Refs } from '@prisma-next/migration-tools/refs';\nimport {\n isValidSpaceId,\n listContractSpaceDirectories,\n spaceMigrationDirectory,\n spaceRefsDirectory,\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 { join, relative } from 'pathe';\nimport {\n type CliStructuredError,\n errorAmbiguousMigrationRef,\n errorInvalidSpaceId,\n errorSpaceNotFound,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport { toDeclaredExtensionsFromRaw } from '../utils/extension-pack-inputs';\nimport { formatErrorJson, formatErrorOutput } from '../utils/formatters/errors';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { integrityViolationToCheckFailure } from '../utils/integrity-violation-to-check-failure';\nimport {\n findPackageByDirPath,\n looksLikePath,\n resolveAppTargetPath,\n resolveTargetPathAcrossSpaces,\n} from '../utils/migration-path-target';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\nimport type { CheckFailure, MigrationCheckResult } from './json/schemas';\nimport { INTEGRITY_FAILED, OK, PRECONDITION } from './migration-check/exit-codes';\n\ninterface MigrationCheckOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n}\n\nexport type { CheckFailure, MigrationCheckResult } from './json/schemas';\nexport { migrationCheckResultSchema } from './json/schemas';\n\nfunction migrationPathRelative(dirPath: string): string {\n return relative(process.cwd(), dirPath);\n}\n\nfunction migrationFileRelative(dirPath: string, fileName: string): string {\n return join(migrationPathRelative(dirPath), fileName);\n}\n\nfunction checkFileExists(\n spaceId: string,\n dirPath: string,\n dirName: string,\n fileName: string,\n): CheckFailure | null {\n if (!existsSync(join(dirPath, fileName))) {\n return {\n space: spaceId,\n code: 'MIGRATION.CHECK_FILE_MISSING',\n where: migrationFileRelative(dirPath, fileName),\n why: `${fileName} is missing from ${dirName}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n }\n return null;\n}\n\n/**\n * Snapshot-store consistency check for one migration package (D6.5):\n * absent store entry is not an issue (runner independence, ADR 199 — a\n * package dir with only `migration.json` + `ops.json` is legitimate); a\n * present entry whose inner `storage.storageHash` disagrees with\n * `pkg.metadata.to` is `MIGRATION.CHECK_SNAPSHOT_HASH_MISMATCH`; an unparseable store\n * entry (or a malformed `to`) is `MIGRATION.CHECK_SNAPSHOT_UNPARSEABLE`.\n */\nasync function checkSnapshotConsistency(\n spaceId: string,\n pkg: OnDiskMigrationPackage,\n migrationsDir: string,\n): Promise<CheckFailure | null> {\n let snapshotDir: string;\n try {\n snapshotDir = contractSnapshotDir(migrationsDir, pkg.metadata.to);\n } catch {\n return {\n space: spaceId,\n code: 'MIGRATION.CHECK_SNAPSHOT_UNPARSEABLE',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" declares to=\"${pkg.metadata.to}\", which is not a well-formed contract snapshot hash.`,\n fix: 'Re-emit the migration package so migration.json declares a valid `sha256:<64hex>` to-hash.',\n };\n }\n\n let raw: unknown;\n try {\n raw = await readContractSnapshotJson(migrationsDir, pkg.metadata.to);\n } catch (error) {\n if (MigrationToolsError.is(error) && error.code === 'MIGRATION.CONTRACT_SNAPSHOT_MISSING') {\n return null;\n }\n return {\n space: spaceId,\n code: 'MIGRATION.CHECK_SNAPSHOT_UNPARSEABLE',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" has an unparseable contract snapshot at ${snapshotDir}/contract.json.`,\n fix: 'Restore migrations/snapshots/ from version control, or re-run the command that produced this migration to regenerate its snapshot.',\n };\n }\n const record = raw !== null && typeof raw === 'object' ? (raw as Record<string, unknown>) : {};\n const storage = record['storage'] as Record<string, unknown> | undefined;\n const snapshotHash = storage?.['storageHash'];\n if (typeof snapshotHash === 'string' && snapshotHash !== pkg.metadata.to) {\n return {\n space: spaceId,\n code: 'MIGRATION.CHECK_SNAPSHOT_HASH_MISMATCH',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" declares to=${pkg.metadata.to} but its contract snapshot has storageHash=${snapshotHash}`,\n fix: 'Re-emit the migration package so migration.json and its contract snapshot agree.',\n };\n }\n return null;\n}\n\n/**\n * One contract space's on-disk state, resolved for the explicit graph\n * checks `runMigrationCheck` runs per space: the space's migration\n * packages, its user-authored refs, its induced graph, and the absolute\n * `migrations/<space>/` + `migrations/<space>/refs/` directories the\n * file-existence and dangling-ref `where` paths are derived from.\n */\nexport interface CheckSpace {\n readonly spaceId: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly refs: Refs;\n readonly graph: MigrationGraph;\n readonly migrationsDir: string;\n readonly refsDir: string;\n /** Migrations root the contract-snapshot store lives under — shared by every space. */\n readonly projectMigrationsDir: string;\n}\n\n/**\n * Project the loaded {@link ContractSpaceAggregate} into the\n * {@link CheckSpace} rows the multi-space check iterates — one per on-disk\n * contract-space directory, in the aggregate's `app`-first ordering. Mirrors\n * `migration list`'s `migrationSpaceListEntriesFromAggregate`: space\n * membership matches the on-disk directories, package / ref / graph data come\n * from `aggregate.space(id)`.\n */\nexport async function enumerateCheckSpaces(\n aggregate: ContractSpaceAggregate,\n projectMigrationsDir: string,\n): Promise<readonly CheckSpace[]> {\n const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);\n const onDiskSpaceIds = new Set(candidateDirs.filter(isValidSpaceId));\n const spaces: CheckSpace[] = [];\n for (const space of aggregate.spaces()) {\n const spaceId = space.spaceId;\n if (!isValidSpaceId(spaceId)) continue;\n if (!onDiskSpaceIds.has(spaceId)) continue;\n const migrationsDir = spaceMigrationDirectory(projectMigrationsDir, spaceId);\n spaces.push({\n spaceId,\n packages: space.packages,\n refs: space.refs,\n graph: space.graph(),\n migrationsDir,\n refsDir: spaceRefsDirectory(migrationsDir),\n projectMigrationsDir,\n });\n }\n return spaces;\n}\n\nfunction checkManifestFilesPresent(space: CheckSpace): readonly CheckFailure[] {\n if (!existsSync(space.migrationsDir)) return [];\n const loadedDirNames = new Set(space.packages.map((p) => p.dirName));\n const failures: CheckFailure[] = [];\n let entries: string[];\n try {\n entries = readdirSync(space.migrationsDir);\n } catch {\n return failures;\n }\n for (const entry of entries) {\n if (entry.startsWith('.') || entry.startsWith('_') || entry === 'refs') continue;\n const entryPath = join(space.migrationsDir, entry);\n try {\n if (!statSync(entryPath).isDirectory()) continue;\n } catch {\n continue;\n }\n if (!loadedDirNames.has(entry)) {\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(space.spaceId, entryPath, entry, f);\n if (fail) failures.push(fail);\n }\n }\n }\n return failures;\n}\n\nfunction checkReachability(space: CheckSpace): readonly CheckFailure[] {\n const allToHashes = new Set(space.packages.map((p) => p.metadata.to));\n const failures: CheckFailure[] = [];\n for (const pkg of space.packages) {\n const isReachable =\n pkg.metadata.from === null ||\n allToHashes.has(pkg.metadata.from) ||\n pkg.metadata.from === 'sha256:empty';\n if (!isReachable) {\n failures.push({\n space: space.spaceId,\n code: 'MIGRATION.CHECK_UNREACHABLE_MIGRATION',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" starts from ${pkg.metadata.from} which no other migration produces`,\n fix: 'This migration is unreachable in the graph. Delete it or re-emit a connecting migration.',\n });\n }\n }\n return failures;\n}\n\nfunction checkDanglingRefs(space: CheckSpace): readonly CheckFailure[] {\n const failures: CheckFailure[] = [];\n for (const [name, entry] of Object.entries(space.refs)) {\n if (!space.graph.nodes.has(entry.hash)) {\n failures.push({\n space: space.spaceId,\n code: 'MIGRATION.CHECK_DANGLING_REF',\n where: relative(process.cwd(), join(space.refsDir, `${name}.json`)),\n why: `Ref \"${name}\" points at ${entry.hash} which does not exist in the migration graph`,\n fix: `Update the ref with \\`prisma-next ref set ${name} <valid-hash>\\` or delete it.`,\n });\n }\n }\n return failures;\n}\n\nasync function checkSpace(space: CheckSpace): Promise<readonly CheckFailure[]> {\n const snapshotFailures = await Promise.all(\n space.packages.map((pkg) =>\n checkSnapshotConsistency(space.spaceId, pkg, space.projectMigrationsDir),\n ),\n );\n return [\n ...checkManifestFilesPresent(space),\n ...snapshotFailures.filter((f): f is CheckFailure => f !== null),\n ...checkReachability(space),\n ...checkDanglingRefs(space),\n ];\n}\n\n/**\n * Inputs for {@link runMigrationCheck} — the multi-space policy core of\n * the holistic (no-arg) `migration check`. Enumeration is supplied by the\n * caller (the CLI shell builds it from {@link enumerateCheckSpaces}); the\n * core does not touch config, flags, or streams.\n */\nexport interface RunMigrationCheckInputs {\n readonly spaces: readonly CheckSpace[];\n readonly spaceFilter?: string;\n}\n\n/**\n * Policy core of the holistic `migration check`: validates `--space`,\n * narrows the pre-enumerated spaces, and runs the per-space explicit graph\n * checks (file-existence, snapshot consistency, reachability, dangling\n * refs), aggregating every failure into one {@link MigrationCheckResult}.\n *\n * `--space` validation mirrors `migration list`: an invalid id →\n * {@link errorInvalidSpaceId}; an id with no on-disk space →\n * {@link errorSpaceNotFound}. Both map to exit `PRECONDITION` at the shell.\n * Aggregate-integrity violations (which already span every space) are folded\n * in by the caller, not here.\n */\nexport async function runMigrationCheck(\n inputs: RunMigrationCheckInputs,\n): Promise<Result<MigrationCheckResult, CliStructuredError>> {\n const { spaces, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\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 failures = (await Promise.all(scopedSpaces.map(checkSpace))).flat();\n if (failures.length === 0) {\n return ok({ ok: true, failures: [], summary: 'All checks passed' });\n }\n return ok({ ok: false, failures, summary: `${failures.length} integrity failure(s)` });\n}\n\nasync function loadAggregateIntegrityViolations(\n config: Awaited<ReturnType<typeof loadConfig>>,\n migrationsDir: string,\n): Promise<readonly IntegrityViolation[]> {\n try {\n const contractJsonContent = await readFile(resolveContractPath(config), 'utf-8');\n const familyInstance = config.family.create(createControlStack(config));\n const declaredExtensions = toDeclaredExtensionsFromRaw(config.extensionPacks ?? []);\n\n const parsedAppContract: unknown = JSON.parse(contractJsonContent);\n const aggregate = await loadContractSpaceAggregate({\n migrationsDir,\n deserializeContract: (json: unknown) => familyInstance.deserializeContract(json),\n appContract: familyInstance.deserializeContract(parsedAppContract),\n });\n return aggregate.checkIntegrity({ declaredExtensions, checkContracts: true });\n } catch {\n return [];\n }\n}\n\ninterface MigrationCheckOutcome {\n readonly result?: MigrationCheckResult;\n readonly error?: CliStructuredError;\n readonly exitCode: number;\n readonly resolvedSpaceId?: string;\n}\n\nasync function executeMigrationCheckCommand(\n target: string | undefined,\n options: MigrationCheckOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<MigrationCheckOutcome> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } =\n resolveMigrationPaths(options.config, config);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration check',\n description: 'Verify artifact and graph integrity',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n const loadedAggregate = await buildReadAggregate(config, { migrationsDir });\n if (!loadedAggregate.ok) {\n return { error: loadedAggregate.failure, exitCode: PRECONDITION };\n }\n\n const spaces = await enumerateCheckSpaces(loadedAggregate.value.aggregate, migrationsDir);\n\n if (target) {\n return await checkSingleTarget(target, {\n spaces,\n ...(options.space !== undefined ? { spaceFilter: options.space } : {}),\n appMigrationsDir,\n appMigrationsRelative,\n });\n }\n\n const checkResult = await runMigrationCheck({\n spaces,\n ...(options.space !== undefined ? { spaceFilter: options.space } : {}),\n });\n if (!checkResult.ok) {\n return { error: checkResult.failure, exitCode: PRECONDITION };\n }\n\n const failures: CheckFailure[] = [...checkResult.value.failures];\n const allViolations = await loadAggregateIntegrityViolations(config, migrationsDir);\n const scopedViolations =\n options.space === undefined\n ? allViolations\n : allViolations.filter((v) => v.kind !== 'disjointness' && v.spaceId === options.space);\n for (const violation of scopedViolations) {\n failures.push(integrityViolationToCheckFailure(violation, migrationsDir));\n }\n\n if (failures.length === 0) {\n return {\n result: { ok: true, failures: [], summary: 'All checks passed' },\n exitCode: OK,\n };\n }\n\n return {\n result: { ok: false, failures, summary: `${failures.length} integrity failure(s)` },\n exitCode: INTEGRITY_FAILED,\n };\n}\n\ninterface SingleTargetInputs {\n readonly spaces: readonly CheckSpace[];\n readonly spaceFilter?: string;\n readonly appMigrationsDir: string;\n readonly appMigrationsRelative: string;\n}\n\n/**\n * Ranks ref-resolution failure kinds by how informative they are, so a\n * single-target check surfaces the most useful failure across spaces instead of\n * whichever space failed first. `not-found` (the input matched nothing here)\n * says the least; a malformed input, a wrong grammar, or an in-space ambiguity\n * all say more.\n */\nfunction refFailureSpecificity(error: RefResolutionError): number {\n switch (error.kind) {\n case 'wrong-grammar':\n return 3;\n case 'ambiguous':\n return 2;\n case 'invalid-format':\n return 1;\n case 'not-found':\n return 0;\n }\n}\n\n/**\n * Single-target (`check <ref/path>`) mode — resolves a migration reference\n * across all contract spaces (or the one space narrowed by `--space <id>`).\n *\n * Resolution:\n * - filesystem path → find the owning space by checking which space's\n * `migrationsDir` contains the resolved path; falls back to app-relative\n * validation when the path is outside every space dir.\n * - ref → `parseMigrationRef` against each in-scope space; collect every\n * (space, package) hit; 0 hits = not-found, 1 = check it, >1 = ambiguity\n * error (qualify with `--space`).\n *\n * `--space <id>` is validated the same way the holistic path does it:\n * invalid id → `errorInvalidSpaceId`; no on-disk space → `errorSpaceNotFound`.\n */\nasync function checkSingleTarget(\n target: string,\n inputs: SingleTargetInputs,\n): Promise<MigrationCheckOutcome> {\n const { spaces, spaceFilter, appMigrationsDir, appMigrationsRelative } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return { error: errorInvalidSpaceId(spaceFilter), exitCode: PRECONDITION };\n }\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return {\n error: errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()),\n exitCode: PRECONDITION,\n };\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n let matchedSpace: CheckSpace | undefined;\n let matchedPkg: OnDiskMigrationPackage | undefined;\n\n if (looksLikePath(target)) {\n const resolvedPath = resolveTargetPathAcrossSpaces(target, scopedSpaces);\n if (resolvedPath !== null) {\n for (const space of scopedSpaces) {\n const found = findPackageByDirPath(space.packages, resolvedPath);\n if (found) {\n matchedSpace = space;\n matchedPkg = found;\n break;\n }\n }\n } else {\n // Path outside every space dir — fall back to app-relative validation\n const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);\n if (!resolved.ok) {\n return { error: resolved.failure, exitCode: PRECONDITION };\n }\n const appSpace = scopedSpaces.find((s) => s.spaceId === 'app');\n if (appSpace) {\n matchedSpace = appSpace;\n matchedPkg = findPackageByDirPath(appSpace.packages, resolved.value);\n }\n }\n } else {\n // Ref resolution: try each in-scope space, collect all hits.\n const hits: Array<{ space: CheckSpace; pkg: OnDiskMigrationPackage }> = [];\n let bestParseFailure: RefResolutionError | undefined;\n for (const space of scopedSpaces) {\n const migResult = parseMigrationRef(target, { graph: space.graph, refs: space.refs });\n if (!migResult.ok) {\n // Keep scanning — a later space may hold a hit that must not be discarded.\n // When no space yields a hit, keep the most informative failure rather than\n // whichever space failed first (the kind is space-dependent).\n if (\n bestParseFailure === undefined ||\n refFailureSpecificity(migResult.failure) > refFailureSpecificity(bestParseFailure)\n ) {\n bestParseFailure = migResult.failure;\n }\n continue;\n }\n const pkg = space.packages.find(\n (p) => p.metadata.migrationHash === migResult.value.migrationHash,\n );\n if (pkg) {\n hits.push({ space, pkg });\n }\n }\n\n if (hits.length > 1) {\n const spaceIds = hits.map((h) => h.space.spaceId);\n return {\n error: errorAmbiguousMigrationRef(target, spaceIds),\n exitCode: PRECONDITION,\n };\n }\n\n if (hits.length === 1) {\n matchedSpace = hits[0]!.space;\n matchedPkg = hits[0]!.pkg;\n } else if (bestParseFailure !== undefined) {\n // The ref didn't resolve in any in-scope space — surface the most informative\n // parse failure through the shared ref-resolution envelope (CONTRACT.VERIFY_FAILED) the\n // earlier work established, rather than a bespoke string. (Ref-resolved-but-\n // no-package falls through to the \"not found on disk\" result below.)\n return { error: mapRefResolutionError(bestParseFailure), exitCode: PRECONDITION };\n }\n }\n\n if (!matchedPkg || !matchedSpace) {\n return {\n result: {\n ok: false,\n failures: [],\n summary: `Migration package for \"${target}\" not found on disk`,\n },\n exitCode: PRECONDITION,\n };\n }\n\n const failures: CheckFailure[] = [...checkManifestFilesPresent(matchedSpace)];\n\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(matchedSpace.spaceId, matchedPkg.dirPath, matchedPkg.dirName, f);\n if (fail) failures.push(fail);\n }\n\n const verification = verifyMigrationHash(matchedPkg);\n if (!verification.ok) {\n failures.push({\n space: matchedSpace.spaceId,\n code: 'MIGRATION.CHECK_HASH_MISMATCH',\n where: migrationFileRelative(matchedPkg.dirPath, 'migration.json'),\n why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,\n fix: 'Re-emit the migration package or restore from version control.',\n });\n }\n\n const snapshotFailure = await checkSnapshotConsistency(\n matchedSpace.spaceId,\n matchedPkg,\n matchedSpace.projectMigrationsDir,\n );\n if (snapshotFailure) failures.push(snapshotFailure);\n\n const resolvedSpaceId = matchedSpace.spaceId !== 'app' ? matchedSpace.spaceId : undefined;\n\n if (failures.length === 0) {\n return {\n result: { ok: true, failures: [], summary: 'All checks passed' },\n exitCode: OK,\n ...ifDefined('resolvedSpaceId', resolvedSpaceId),\n };\n }\n return {\n result: { ok: false, failures, summary: `${failures.length} integrity failure(s)` },\n exitCode: INTEGRITY_FAILED,\n ...ifDefined('resolvedSpaceId', resolvedSpaceId),\n };\n}\n\nexport function createMigrationCheckCommand(): Command {\n const command = new Command('check');\n setCommandDescriptions(\n command,\n 'Verify artifact and graph integrity',\n 'Validates that on-disk migration packages are internally consistent\\n' +\n '(hashes match, manifests are complete) and that the graph is well-formed\\n' +\n '(edges connect, refs point at valid nodes). The whole-graph check spans\\n' +\n 'every contract space by default; pass --space <id> to narrow to one. A\\n' +\n 'migration reference checks a single package, resolved across all contract\\n' +\n 'spaces (narrow with --space; an ambiguous reference is a precondition failure).\\n' +\n 'Offline — does not consult the database.\\n' +\n 'Exit codes: 0 = all checks passed, 2 = precondition failed\\n' +\n '(unresolved target or unknown --space), 4 = integrity failure(s) found.',\n );\n setCommandExamples(command, [\n 'prisma-next migration check',\n 'prisma-next migration check --space app',\n 'prisma-next migration check 20260101-add-users',\n 'prisma-next migration check 20260101-add-users --space app',\n 'prisma-next migration check --json',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration status', oneLiner: 'Show migration path and pending status' },\n { verb: 'migration list', oneLiner: 'List on-disk migrations' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n { verb: 'migration show', oneLiner: 'Display migration package contents' },\n ]);\n command.exitOverride();\n addGlobalOptions(command)\n .argument('[target]', 'Migration reference: directory name, hash/prefix, ref, or path')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--space <id>', 'Narrow output to a single contract space')\n .action(async (target: string | undefined, options: MigrationCheckOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n let outcome: MigrationCheckOutcome;\n try {\n outcome = await executeMigrationCheckCommand(target, options, flags, ui);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n outcome = {\n result: { ok: false, failures: [], summary: msg },\n exitCode: PRECONDITION,\n };\n }\n\n if (outcome.error) {\n const envelope = outcome.error.toEnvelope();\n if (flags.json) {\n ui.output(formatErrorJson(envelope));\n } else if (!flags.quiet) {\n ui.error(formatErrorOutput(envelope, flags));\n }\n process.exit(outcome.exitCode);\n }\n\n const result = outcome.result ?? {\n ok: false,\n failures: [],\n summary: 'No check result produced',\n };\n\n if (flags.json) {\n ui.output(JSON.stringify(result, null, 2));\n } else if (!flags.quiet) {\n if (result.ok) {\n const spaceSuffix =\n outcome.resolvedSpaceId !== undefined ? ` (space: ${outcome.resolvedSpaceId})` : '';\n ui.log(`✔ ${result.summary}${spaceSuffix}`);\n } else {\n for (const f of result.failures) {\n ui.log(`✗ [${f.code}] ${f.where}: ${f.why}`);\n ui.log(` fix: ${f.fix}`);\n }\n ui.log(`\\n${result.summary}`);\n }\n }\n\n process.exit(outcome.exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { Command } from "commander";
|
|
|
5
5
|
import { loadConfig } from "@prisma-next/config-loader";
|
|
6
6
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
7
7
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
8
|
-
import { APP_SPACE_ID,
|
|
8
|
+
import { APP_SPACE_ID, isValidSpaceId, listContractSpaceDirectories } from "@prisma-next/migration-tools/spaces";
|
|
9
9
|
import { HEAD_REF_NAME, refsByContractHash } from "@prisma-next/migration-tools/refs";
|
|
10
10
|
//#region src/utils/legend.ts
|
|
11
11
|
/**
|
|
@@ -55,7 +55,7 @@ function listRefsByContractHash(space) {
|
|
|
55
55
|
return byHash;
|
|
56
56
|
}
|
|
57
57
|
async function orderedOnDiskSpaceIds(projectMigrationsDir) {
|
|
58
|
-
return (await listContractSpaceDirectories(projectMigrationsDir)).filter(
|
|
58
|
+
return (await listContractSpaceDirectories(projectMigrationsDir)).filter(isValidSpaceId).sort(compareSpaceIds);
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Project the loaded {@link ContractSpaceAggregate} into the render-ready
|
|
@@ -227,4 +227,4 @@ function createMigrationListCommand() {
|
|
|
227
227
|
//#endregion
|
|
228
228
|
export { renderMigrationListHumanOutput as a, validateLegendOptions as c, migrationSpaceListEntriesFromAggregate as i, executeMigrationListCommand as n, runMigrationList as o, listRefsByContractHash as r, shouldShowLegend as s, createMigrationListCommand as t };
|
|
229
229
|
|
|
230
|
-
//# sourceMappingURL=migration-list-
|
|
230
|
+
//# sourceMappingURL=migration-list-6z6vuXHa.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-list-6z6vuXHa.mjs","names":[],"sources":["../src/utils/legend.ts","../src/commands/migration-list.ts"],"sourcesContent":["import { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { type CliStructuredError, errorLegendHumanOnly } from './cli-errors';\nimport type { GlobalFlags } from './global-flags';\n\nexport interface LegendCliOptions {\n readonly legend?: boolean;\n readonly dot?: boolean;\n}\n\n/**\n * The legend is decoration printed alongside the command header on stderr, so\n * it is suppressed for the machine-readable / silent paths (`--json`, `--dot`,\n * `--quiet`) exactly as the header is.\n */\nexport function shouldShowLegend(options: LegendCliOptions, flags: GlobalFlags): boolean {\n return (\n options.legend === true && options.dot !== true && flags.json !== true && flags.quiet !== true\n );\n}\n\nexport function validateLegendOptions(\n options: LegendCliOptions,\n flags: GlobalFlags,\n): Result<void, CliStructuredError> {\n if (options.legend !== true) {\n return ok(undefined);\n }\n if (flags.json === true) {\n return notOk(errorLegendHumanOnly('--json'));\n }\n if (flags.quiet === true) {\n return notOk(errorLegendHumanOnly('--quiet'));\n }\n if (options.dot === true) {\n return notOk(errorLegendHumanOnly('--dot'));\n }\n return ok(undefined);\n}\n","import { loadConfig } from '@prisma-next/config-loader';\nimport type {\n AggregateContractSpace,\n ContractSpaceAggregate,\n} from '@prisma-next/migration-tools/aggregate';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport { HEAD_REF_NAME, refsByContractHash } from '@prisma-next/migration-tools/refs';\nimport {\n APP_SPACE_ID,\n isValidSpaceId,\n listContractSpaceDirectories,\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 {\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 { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-labels';\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 { shouldShowLegend, validateLegendOptions } from '../utils/legend';\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.name < b.name) return 1;\n if (a.name > b.name) return -1;\n return 0;\n}\n\n/**\n * Ref names decorating a space's destination contract hashes. The\n * tolerant `space.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 `space.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 space: AggregateContractSpace,\n): ReadonlyMap<string, readonly string[]> {\n const byHash = new Map(refsByContractHash(space.refs));\n if (space.spaceId !== APP_SPACE_ID && space.headRef !== null) {\n const hash = space.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.filter(isValidSpaceId).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 space 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 space = aggregate.space(spaceId);\n if (space === undefined) {\n continue;\n }\n const refsByHash = listRefsByContractHash(space);\n const migrations: MigrationListEntry[] = space.packages\n .map((pkg) => ({\n name: pkg.dirName,\n hash: pkg.metadata.migrationHash,\n fromContract: pkg.metadata.from,\n toContract: pkg.metadata.to,\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({ space: 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 readonly legend?: boolean;\n}\n\nexport interface MigrationListExecuteResult {\n readonly list: MigrationListResult;\n readonly liveContractHash: string;\n readonly aggregate: ContractSpaceAggregate;\n}\n\nexport interface MigrationListHumanRenderOptions {\n readonly glyphMode: GlyphMode;\n readonly useColor: boolean;\n readonly liveContractHash: string;\n readonly graphForSpace: (spaceId: string) => MigrationGraph | undefined;\n readonly appSpaceId?: string;\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 liveContractHash: options.liveContractHash,\n graphForSpace: options.graphForSpace,\n ...(options.appSpaceId !== undefined ? { appSpaceId: options.appSpaceId } : {}),\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.space === spaceFilter)) {\n return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.space).sort()));\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.space === spaceFilter) : spaces;\n\n const resultSpaces: readonly MigrationSpaceListEntry[] =\n scopedSpaces.length === 0 ? [{ space: 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<MigrationListExecuteResult, 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 if (shouldShowLegend(options, flags)) {\n ui.stderr(\n renderMigrationGraphLegend({\n colorize: flags.color !== false,\n glyphMode: ui.resolveGlyphMode(options.ascii === true),\n }),\n );\n ui.stderr('');\n }\n }\n\n const loaded = await buildReadAggregate(config, { migrationsDir });\n if (!loaded.ok) {\n return notOk(loaded.failure);\n }\n\n const { aggregate, contractHash: liveContractHash } = loaded.value;\n\n const spaces = await migrationSpaceListEntriesFromAggregate(aggregate, migrationsDir);\n\n const listResult = runMigrationList({\n spaces,\n ...ifDefined('spaceFilter', options.space),\n });\n if (!listResult.ok) {\n return listResult;\n }\n return ok({ list: listResult.value, liveContractHash, aggregate });\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 --legend',\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 .option('--legend', 'Print a key for the tree glyphs and lane colors')\n .action(async (options: MigrationListOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const legendValidation = validateLegendOptions(options, flags);\n if (!legendValidation.ok) {\n process.exit(handleResult(legendValidation, flags, ui));\n }\n const result = await executeMigrationListCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, ({ list, liveContractHash, aggregate }) => {\n if (flags.json) {\n ui.output(JSON.stringify(list, null, 2));\n } else if (!flags.quiet) {\n ui.output(\n renderMigrationListHumanOutput(list, {\n glyphMode: ui.resolveGlyphMode(options.ascii === true),\n useColor: ui.useColor,\n liveContractHash,\n graphForSpace: (spaceId) => aggregate.space(spaceId)?.graph(),\n appSpaceId: aggregate.app.spaceId,\n }),\n );\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { A as formatStyledHeader, B as errorContractValidationFailed, F as CliStructuredError, Q as errorPlanForgotTheFlag, W as errorFileNotFound, X as errorMigrationPlanningFailed, _ as createTerminalUI, ct as errorUnexpected, g as parseGlobalFlagsOrExit, it as errorSnapshotMissing, l as setCommandDescriptions, lt as mapMigrationToolsError, o as resolveContractPath, ot as errorTargetMigrationNotSupported, r as getTargetMigrations, s as resolveMigrationPaths, t as addGlobalOptions, u as setCommandExamples, ut as mapRefResolutionError, y as handleResult } from "./command-helpers-Cpq44aVa.mjs";
|
|
2
2
|
import { t as assertFrameworkComponentsCompatible } from "./framework-components-CnbUbiJw.mjs";
|
|
3
3
|
import { c as toExtensionInputs, i as loadContractSpaceAggregateForCli, t as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-D_3VeHVb.mjs";
|
|
4
|
-
import { t as mapContractAtError } from "./contract-at-errors-
|
|
4
|
+
import { t as mapContractAtError } from "./contract-at-errors-CTtzKR6q.mjs";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { loadConfig } from "@prisma-next/config-loader";
|
|
7
7
|
import { getEmittedArtifactPaths } from "@prisma-next/emitter";
|
|
8
8
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
9
9
|
import { join, relative } from "pathe";
|
|
10
|
-
import {
|
|
10
|
+
import { readFile } from "node:fs/promises";
|
|
11
11
|
import { createControlStack, hasOperationPreview } from "@prisma-next/framework-components/control";
|
|
12
|
-
import {
|
|
12
|
+
import { emitContractSpaceArtifacts, planAllSpaces, readContractSpaceHeadRef, spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
|
|
13
13
|
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
14
14
|
import { assertHashIsGraphNode, findLatestMigration, isGraphNode } from "@prisma-next/migration-tools/migration-graph";
|
|
15
|
+
import { snapshotsImportPathFrom, writeContractSnapshot } from "@prisma-next/migration-tools/contract-snapshot-store";
|
|
15
16
|
import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
16
17
|
import { computeMigrationHash } from "@prisma-next/migration-tools/hash";
|
|
17
|
-
import {
|
|
18
|
+
import { formatMigrationDirName, materialiseExtensionMigrationPackageIfMissing, writeMigrationPackage } from "@prisma-next/migration-tools/io";
|
|
18
19
|
import { writeMigrationTs } from "@prisma-next/migration-tools/migration-ts";
|
|
19
|
-
import { canonicalizeJson } from "@prisma-next/framework-components/utils";
|
|
20
20
|
import { deriveProvidedInvariants } from "@prisma-next/migration-tools/invariants";
|
|
21
21
|
//#region src/utils/contract-space-seed-phase.ts
|
|
22
22
|
/**
|
|
@@ -25,9 +25,11 @@ import { deriveProvidedInvariants } from "@prisma-next/migration-tools/invariant
|
|
|
25
25
|
* For every extension that exposes a `contractSpace`:
|
|
26
26
|
*
|
|
27
27
|
* 1. Read the on-disk head ref (returns `null` on first emit).
|
|
28
|
-
* 2.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* 2. Write the head contract into the migrations-root snapshot store
|
|
29
|
+
* (write-if-absent, keyed by hash) and unconditionally re-emit
|
|
30
|
+
* `refs/head.json`, via {@link emitContractSpaceArtifacts}. The
|
|
31
|
+
* framework owns `refs/head.json`; re-emit is the contract for that
|
|
32
|
+
* file. The snapshot itself is only written once per distinct hash.
|
|
31
33
|
* 3. Materialise any descriptor-shipped migration packages not yet on
|
|
32
34
|
* disk via {@link materialiseExtensionMigrationPackageIfMissing}.
|
|
33
35
|
* Existing packages are left untouched (by-existence skip).
|
|
@@ -57,7 +59,7 @@ async function runContractSpaceSeedPhase(inputs) {
|
|
|
57
59
|
const descriptor = descriptorBySpace.get(space.spaceId);
|
|
58
60
|
if (descriptor === void 0) continue;
|
|
59
61
|
const priorHash = (await readContractSpaceHeadRef(inputs.migrationsDir, space.spaceId))?.hash ?? null;
|
|
60
|
-
await
|
|
62
|
+
await emitContractSpaceArtifacts(inputs.migrationsDir, space.spaceId, {
|
|
61
63
|
contract: descriptor.contractJson,
|
|
62
64
|
contractDts: buildPlaceholderContractDts(space.spaceId),
|
|
63
65
|
headRef: {
|
|
@@ -147,8 +149,7 @@ async function resolveContractRef(parsed, space, options) {
|
|
|
147
149
|
hash: at.hash,
|
|
148
150
|
contract: at.contract,
|
|
149
151
|
contractJson: at.contractJson,
|
|
150
|
-
contractDts: at.contractDts
|
|
151
|
-
sourceDir: at.sourceDir
|
|
152
|
+
contractDts: at.contractDts
|
|
152
153
|
});
|
|
153
154
|
} catch (error) {
|
|
154
155
|
return mapContractAtError(error, options?.artifactRole !== void 0 ? { artifactRole: options.artifactRole } : void 0);
|
|
@@ -163,8 +164,7 @@ async function resolveFromPolicy(parsed, input, refs, explicitFromLabel) {
|
|
|
163
164
|
if (resolution.value.kind === "graph-node") return ok({
|
|
164
165
|
kind: "graph-node",
|
|
165
166
|
fromHash: resolution.value.hash,
|
|
166
|
-
fromContract: resolution.value.contract
|
|
167
|
-
sourceDir: resolution.value.sourceDir
|
|
167
|
+
fromContract: resolution.value.contract
|
|
168
168
|
});
|
|
169
169
|
const { hash, contract, contractJson, contractDts } = resolution.value;
|
|
170
170
|
if (graphIsEmpty(input.space)) return ok({
|
|
@@ -248,17 +248,7 @@ async function resolveToForPlan(optionsTo, input) {
|
|
|
248
248
|
}
|
|
249
249
|
//#endregion
|
|
250
250
|
//#region src/commands/migration-plan.ts
|
|
251
|
-
async function
|
|
252
|
-
await mkdir(packageDir, { recursive: true });
|
|
253
|
-
const jsonContent = `${canonicalizeJson(contractJson)}\n`;
|
|
254
|
-
const dtsContent = contractDts.endsWith("\n") ? contractDts : `${contractDts}\n`;
|
|
255
|
-
await writeFile(join(packageDir, `${artifactBasename}.json`), jsonContent);
|
|
256
|
-
await writeFile(join(packageDir, `${artifactBasename}.d.ts`), dtsContent);
|
|
257
|
-
}
|
|
258
|
-
async function writeSnapshotStartContract(packageDir, contractJson, contractDts) {
|
|
259
|
-
await writeSnapshotContractArtifacts(packageDir, contractJson, contractDts, "start-contract");
|
|
260
|
-
}
|
|
261
|
-
async function runPlannerLeg(planner, migrations, frameworkComponents, contract, fromContract, spaceId, ownership) {
|
|
251
|
+
async function runPlannerLeg(planner, migrations, frameworkComponents, contract, fromContract, spaceId, ownership, snapshotsImportPath) {
|
|
262
252
|
const fromSchema = migrations.contractToSchema(fromContract, frameworkComponents);
|
|
263
253
|
const plannerResult = planner.plan({
|
|
264
254
|
contract,
|
|
@@ -272,7 +262,8 @@ async function runPlannerLeg(planner, migrations, frameworkComponents, contract,
|
|
|
272
262
|
fromContract,
|
|
273
263
|
frameworkComponents,
|
|
274
264
|
spaceId,
|
|
275
|
-
ownership
|
|
265
|
+
ownership,
|
|
266
|
+
snapshotsImportPath
|
|
276
267
|
});
|
|
277
268
|
if (plannerResult.kind === "failure") return notOk(errorMigrationPlanningFailed({ conflicts: plannerResult.conflicts }));
|
|
278
269
|
let plannedOps = [];
|
|
@@ -373,7 +364,6 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
373
364
|
let toArtifacts = null;
|
|
374
365
|
let fromContract = null;
|
|
375
366
|
let fromHash = null;
|
|
376
|
-
let fromContractSourceDir = null;
|
|
377
367
|
let snapshotStartContract = null;
|
|
378
368
|
let isAutoBaseline = false;
|
|
379
369
|
const tolerantAggregateResult = await loadContractSpaceAggregateForCli({
|
|
@@ -395,12 +385,12 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
395
385
|
case "graph-node":
|
|
396
386
|
fromHash = resolutionResult.value.fromHash;
|
|
397
387
|
fromContract = resolutionResult.value.fromContract;
|
|
398
|
-
fromContractSourceDir = resolutionResult.value.sourceDir;
|
|
399
388
|
break;
|
|
400
389
|
case "snapshot":
|
|
401
390
|
fromHash = resolutionResult.value.fromHash;
|
|
402
391
|
fromContract = resolutionResult.value.fromContract;
|
|
403
392
|
snapshotStartContract = {
|
|
393
|
+
fromHash: resolutionResult.value.fromHash,
|
|
404
394
|
contractJson: resolutionResult.value.contractJson,
|
|
405
395
|
contractDts: resolutionResult.value.contractDts
|
|
406
396
|
};
|
|
@@ -409,6 +399,7 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
409
399
|
fromHash = resolutionResult.value.fromHash;
|
|
410
400
|
fromContract = resolutionResult.value.fromContract;
|
|
411
401
|
snapshotStartContract = {
|
|
402
|
+
fromHash: resolutionResult.value.fromHash,
|
|
412
403
|
contractJson: resolutionResult.value.contractJson,
|
|
413
404
|
contractDts: resolutionResult.value.contractDts
|
|
414
405
|
};
|
|
@@ -465,19 +456,20 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
465
456
|
config.adapter,
|
|
466
457
|
...config.extensionPacks ?? []
|
|
467
458
|
]);
|
|
468
|
-
async function
|
|
459
|
+
async function writeDestinationSnapshot(destHash) {
|
|
469
460
|
if (toArtifacts !== null) {
|
|
470
|
-
await
|
|
461
|
+
await writeContractSnapshot(migrationsDir, destHash, {
|
|
462
|
+
contractJson: toArtifacts.contractJson,
|
|
463
|
+
contractDts: toArtifacts.contractDts
|
|
464
|
+
});
|
|
471
465
|
return;
|
|
472
466
|
}
|
|
473
467
|
const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);
|
|
474
|
-
await
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
destName: "end-contract.d.ts"
|
|
480
|
-
}]);
|
|
468
|
+
const [contractJsonRaw, contractDts] = await Promise.all([readFile(destinationArtifacts.jsonPath, "utf-8"), readFile(destinationArtifacts.dtsPath, "utf-8")]);
|
|
469
|
+
await writeContractSnapshot(migrationsDir, destHash, {
|
|
470
|
+
contractJson: JSON.parse(contractJsonRaw),
|
|
471
|
+
contractDts
|
|
472
|
+
});
|
|
481
473
|
}
|
|
482
474
|
try {
|
|
483
475
|
const planner = migrations.createPlanner(controlAdapter);
|
|
@@ -488,10 +480,13 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
488
480
|
const deltaDirName = formatMigrationDirName(deltaTimestamp, options.name ?? "migration");
|
|
489
481
|
const baselinePackageDir = join(appMigrationsDir, baselineDirName);
|
|
490
482
|
const deltaPackageDir = join(appMigrationsDir, deltaDirName);
|
|
491
|
-
const baselineLeg = await runPlannerLeg(planner, migrations, frameworkComponents, fromContract, null, aggregate.app.spaceId, aggregate);
|
|
483
|
+
const baselineLeg = await runPlannerLeg(planner, migrations, frameworkComponents, fromContract, null, aggregate.app.spaceId, aggregate, snapshotsImportPathFrom(baselinePackageDir, migrationsDir));
|
|
492
484
|
if (!baselineLeg.ok) return notOk(baselineLeg.failure);
|
|
493
485
|
await writePlannedMigrationPackage(baselinePackageDir, null, fromHash, baselineTimestamp, baselineLeg.value);
|
|
494
|
-
await
|
|
486
|
+
await writeContractSnapshot(migrationsDir, fromHash, {
|
|
487
|
+
contractJson: snapshotStartContract.contractJson,
|
|
488
|
+
contractDts: snapshotStartContract.contractDts
|
|
489
|
+
});
|
|
495
490
|
if (fromHash === toStorageHash) {
|
|
496
491
|
const baselineOps = baselineLeg.value.hasPlaceholders ? [] : baselineLeg.value.plannedOps;
|
|
497
492
|
if (baselineLeg.value.hasPlaceholders) {
|
|
@@ -528,11 +523,14 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
528
523
|
timings: { total: Date.now() - startTime }
|
|
529
524
|
});
|
|
530
525
|
}
|
|
531
|
-
const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract(), fromContract, aggregate.app.spaceId, aggregate);
|
|
526
|
+
const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract(), fromContract, aggregate.app.spaceId, aggregate, snapshotsImportPathFrom(deltaPackageDir, migrationsDir));
|
|
532
527
|
if (!deltaLeg.ok) return notOk(deltaLeg.failure);
|
|
533
528
|
await writePlannedMigrationPackage(deltaPackageDir, fromHash, toStorageHash, deltaTimestamp, deltaLeg.value);
|
|
534
|
-
await
|
|
535
|
-
await
|
|
529
|
+
await writeDestinationSnapshot(toStorageHash);
|
|
530
|
+
await writeContractSnapshot(migrationsDir, fromHash, {
|
|
531
|
+
contractJson: snapshotStartContract.contractJson,
|
|
532
|
+
contractDts: snapshotStartContract.contractDts
|
|
533
|
+
});
|
|
536
534
|
const deltaOps = deltaLeg.value.hasPlaceholders ? [] : deltaLeg.value.plannedOps;
|
|
537
535
|
if (deltaLeg.value.hasPlaceholders) return ok({
|
|
538
536
|
ok: true,
|
|
@@ -568,20 +566,14 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
568
566
|
}
|
|
569
567
|
const timestamp = /* @__PURE__ */ new Date();
|
|
570
568
|
const packageDir = join(appMigrationsDir, formatMigrationDirName(timestamp, options.name ?? "migration"));
|
|
571
|
-
const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract(), fromContract, aggregate.app.spaceId, aggregate);
|
|
569
|
+
const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract(), fromContract, aggregate.app.spaceId, aggregate, snapshotsImportPathFrom(packageDir, migrationsDir));
|
|
572
570
|
if (!deltaLeg.ok) return notOk(deltaLeg.failure);
|
|
573
571
|
await writePlannedMigrationPackage(packageDir, fromHash, toStorageHash, timestamp, deltaLeg.value);
|
|
574
|
-
await
|
|
575
|
-
if (
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
destName: "start-contract.json"
|
|
580
|
-
}, {
|
|
581
|
-
sourcePath: sourceArtifacts.dtsPath,
|
|
582
|
-
destName: "start-contract.d.ts"
|
|
583
|
-
}]);
|
|
584
|
-
} else if (snapshotStartContract !== null) await writeSnapshotStartContract(packageDir, snapshotStartContract.contractJson, snapshotStartContract.contractDts);
|
|
572
|
+
await writeDestinationSnapshot(toStorageHash);
|
|
573
|
+
if (snapshotStartContract !== null) await writeContractSnapshot(migrationsDir, snapshotStartContract.fromHash, {
|
|
574
|
+
contractJson: snapshotStartContract.contractJson,
|
|
575
|
+
contractDts: snapshotStartContract.contractDts
|
|
576
|
+
});
|
|
585
577
|
if (deltaLeg.value.hasPlaceholders) return ok({
|
|
586
578
|
ok: true,
|
|
587
579
|
noOp: false,
|
|
@@ -766,4 +758,4 @@ function resolveBundleByPrefix(bundles, needle) {
|
|
|
766
758
|
//#endregion
|
|
767
759
|
export { formatMigrationPlanOutput as n, resolveBundleByPrefix as r, createMigrationPlanCommand as t };
|
|
768
760
|
|
|
769
|
-
//# sourceMappingURL=migration-plan-
|
|
761
|
+
//# sourceMappingURL=migration-plan-DuMEUejG.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-plan-DuMEUejG.mjs","names":[],"sources":["../src/utils/contract-space-seed-phase.ts","../src/utils/plan-resolution.ts","../src/commands/migration-plan.ts"],"sourcesContent":["import { materialiseExtensionMigrationPackageIfMissing } from '@prisma-next/migration-tools/io';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport type { MigrationOps } from '@prisma-next/migration-tools/package';\nimport {\n emitContractSpaceArtifacts,\n planAllSpaces,\n readContractSpaceHeadRef,\n type SpacePlanOutput,\n spaceMigrationDirectory,\n} from '@prisma-next/migration-tools/spaces';\n\n/**\n * In-memory authored migration package shipped by an extension descriptor.\n * Mirrors `MigrationPackage` from `@prisma-next/migration-tools/io` (the\n * on-disk shape minus `dirPath`); redeclared structurally here so the\n * CLI helper does not couple to any family's `ExtensionMigrationPackage`\n * type — any family that ships pre-built migration packages can pass\n * them through unchanged.\n */\nexport interface DescriptorMigrationPackage {\n readonly dirName: string;\n readonly metadata: MigrationMetadata;\n readonly ops: MigrationOps;\n}\n\n/**\n * Minimal descriptor view consumed by the seed phase. Mirrors the shape\n * the SQL family ships on each declared extension entry; only the fields\n * the seed phase needs are surfaced.\n */\nexport interface SeedPhaseExtensionInput {\n readonly id: string;\n readonly contractSpace?: {\n readonly contractJson: unknown;\n readonly headRef: { readonly hash: string; readonly invariants: readonly string[] };\n readonly migrations: readonly DescriptorMigrationPackage[];\n };\n}\n\nexport interface ContractSpaceSeedPhaseInputs {\n readonly migrationsDir: string;\n readonly extensionPacks: ReadonlyArray<SeedPhaseExtensionInput>;\n}\n\n/**\n * One per-space record describing what the seed phase did for an\n * extension contract space. Surfaced verbatim by the caller (typically\n * `migration plan`) so users see a single line per touched extension.\n *\n * - `action: 'updated'` — either the on-disk head pointer changed, or\n * one or more new descriptor-shipped migration packages were\n * materialised into `migrations/<spaceId>/<dirName>/`.\n * - `action: 'unchanged'` — the on-disk head already matched the\n * descriptor and no new migration packages needed to be written.\n *\n * Either way, the artifacts (`contract.json`, `contract.d.ts`,\n * `refs/head.json`) are re-emitted: the framework owns those files and\n * makes the re-emit observably idempotent at the byte level.\n */\nexport interface ContractSpaceSeedPhaseRecord {\n readonly spaceId: string;\n readonly action: 'updated' | 'unchanged';\n readonly priorHash: string | null;\n readonly newHash: string;\n readonly newMigrationDirs: readonly string[];\n}\n\nexport interface ContractSpaceSeedPhaseResult {\n readonly seeded: readonly ContractSpaceSeedPhaseRecord[];\n}\n\n/**\n * Phase-1 of the two-phase `migration plan` pipeline (sub-spec § 4).\n *\n * For every extension that exposes a `contractSpace`:\n *\n * 1. Read the on-disk head ref (returns `null` on first emit).\n * 2. Write the head contract into the migrations-root snapshot store\n * (write-if-absent, keyed by hash) and unconditionally re-emit\n * `refs/head.json`, via {@link emitContractSpaceArtifacts}. The\n * framework owns `refs/head.json`; re-emit is the contract for that\n * file. The snapshot itself is only written once per distinct hash.\n * 3. Materialise any descriptor-shipped migration packages not yet on\n * disk via {@link materialiseExtensionMigrationPackageIfMissing}.\n * Existing packages are left untouched (by-existence skip).\n *\n * The return value lets the caller render a per-space status line and\n * lets the phase-2 aggregate loader run on a now-consistent disk state\n * (every loaded extension is guaranteed to have its head ref pinned\n * to the descriptor's hash and to ship every package the descriptor\n * declares).\n *\n * Output ordering is deterministic and alphabetical by spaceId (via\n * {@link planAllSpaces}, which also detects duplicate spaceIds). This\n * matches the canonical sort order used by every other aggregate\n * surface (`migrate`, `migration status`, the runner).\n */\nexport async function runContractSpaceSeedPhase(\n inputs: ContractSpaceSeedPhaseInputs,\n): Promise<ContractSpaceSeedPhaseResult> {\n const planInputs = inputs.extensionPacks\n .filter(\n (\n pack,\n ): pack is SeedPhaseExtensionInput & {\n contractSpace: NonNullable<SeedPhaseExtensionInput['contractSpace']>;\n } => pack.contractSpace !== undefined,\n )\n .map((pack) => ({\n spaceId: pack.id,\n priorContract: null,\n newContract: pack.contractSpace.contractJson,\n __pack: pack.contractSpace,\n }));\n\n // `planAllSpaces` brings deterministic alphabetical ordering and\n // duplicate-spaceId detection. The \"planner\" callback is a no-op\n // pass-through that simply returns the descriptor's pre-built\n // migration packages.\n const planned: readonly SpacePlanOutput<DescriptorMigrationPackage>[] = planAllSpaces(\n planInputs,\n (input) =>\n (\n input as typeof input & {\n readonly __pack: NonNullable<SeedPhaseExtensionInput['contractSpace']>;\n }\n ).__pack.migrations,\n );\n\n // Reassemble a spaceId → descriptor lookup so the loop below can read\n // the contractJson / headRef without leaking the typed-cast back into\n // `planAllSpaces`'s output shape.\n const descriptorBySpace = new Map<\n string,\n NonNullable<SeedPhaseExtensionInput['contractSpace']>\n >();\n for (const pack of inputs.extensionPacks) {\n if (pack.contractSpace !== undefined) descriptorBySpace.set(pack.id, pack.contractSpace);\n }\n\n const seeded: ContractSpaceSeedPhaseRecord[] = [];\n for (const space of planned) {\n const descriptor = descriptorBySpace.get(space.spaceId);\n if (descriptor === undefined) continue;\n\n const onDiskHeadRef = await readContractSpaceHeadRef(inputs.migrationsDir, space.spaceId);\n const priorHash = onDiskHeadRef?.hash ?? null;\n\n await emitContractSpaceArtifacts(inputs.migrationsDir, space.spaceId, {\n contract: descriptor.contractJson,\n contractDts: buildPlaceholderContractDts(space.spaceId),\n headRef: { hash: descriptor.headRef.hash, invariants: descriptor.headRef.invariants },\n });\n\n const spaceDir = spaceMigrationDirectory(inputs.migrationsDir, space.spaceId);\n const newMigrationDirs: string[] = [];\n for (const pkg of space.migrationPackages) {\n const { written } = await materialiseExtensionMigrationPackageIfMissing(spaceDir, pkg);\n if (written) newMigrationDirs.push(pkg.dirName);\n }\n\n const action: ContractSpaceSeedPhaseRecord['action'] =\n priorHash !== descriptor.headRef.hash || newMigrationDirs.length > 0\n ? 'updated'\n : 'unchanged';\n\n seeded.push({\n spaceId: space.spaceId,\n action,\n priorHash,\n newHash: descriptor.headRef.hash,\n newMigrationDirs,\n });\n }\n\n return { seeded };\n}\n\n/**\n * Placeholder `.d.ts` content for an extension space's on-disk mirror.\n *\n * Rendering a fully-typed `.d.ts` for an extension contract requires\n * the SQL-family renderer with the codec / typemap registry threaded\n * through; until that integration ships, the on-disk `.d.ts` is a\n * stub `export {};` module that documents how consumers should\n * validate the sibling `contract.json`. The stub typechecks on its\n * own and does not need any TypeScript suppressions.\n */\nfunction buildPlaceholderContractDts(spaceId: string): string {\n return [\n '/**',\n ` * Placeholder \\`.d.ts\\` for extension space \"${spaceId}\".`,\n ' *',\n ' * The framework re-emits this file on every `migration plan` run',\n ' * alongside `contract.json` and `refs/head.json`. A typed `.d.ts`',\n ' * rendering pass for extension contracts is tracked separately;',\n ' * until that ships, consumers should import `contract.json`',\n ' * and pass it through the target descriptor’s `contractSerializer`.',\n ' */',\n 'export {};',\n '',\n ].join('\\n');\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { AggregateContractSpace } from '@prisma-next/migration-tools/aggregate';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport {\n assertHashIsGraphNode,\n findLatestMigration,\n isGraphNode,\n} from '@prisma-next/migration-tools/migration-graph';\nimport type { ContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport type { Refs } from '@prisma-next/migration-tools/refs';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport {\n CliStructuredError,\n errorPlanForgotTheFlag,\n errorSnapshotMissing,\n mapRefResolutionError,\n} from './cli-errors';\nimport { mapContractAtError } from './contract-at-errors';\n\nconst FULL_HASH_PATTERN = /^sha256:([0-9a-f]{64}|empty)$/;\n\nexport function looksLikeFullHash(input: string): boolean {\n return FULL_HASH_PATTERN.test(input);\n}\n\nexport type FromResolution =\n | { kind: 'greenfield'; fromHash: null; fromContract: null }\n | { kind: 'graph-node'; fromHash: string; fromContract: Contract }\n | {\n kind: 'snapshot';\n fromHash: string;\n fromContract: Contract;\n contractDts: string;\n contractJson: unknown;\n }\n | {\n kind: 'auto-baseline';\n fromHash: string;\n fromContract: Contract;\n contractDts: string;\n contractJson: unknown;\n };\n\nexport interface ResolveFromForPlanInput {\n readonly optionsFrom?: string | undefined;\n readonly space: AggregateContractSpace;\n}\n\nfunction graphIsEmpty(space: AggregateContractSpace): boolean {\n return space.packages.length === 0;\n}\n\nfunction getReachableRefs(\n refs: Refs,\n graph: MigrationGraph,\n): ReadonlyArray<{ name: string; hash: string }> {\n return Object.entries(refs)\n .flatMap(([name, entry]) =>\n entry && isGraphNode(entry.hash, graph) ? [{ name, hash: entry.hash }] : [],\n )\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nexport function assertFromIsGraphNode(\n fromHash: string,\n graph: MigrationGraph,\n refs: Refs,\n graphTipHash: string | null,\n): void {\n try {\n assertHashIsGraphNode(fromHash, graph);\n } catch (error) {\n if (MigrationToolsError.is(error) && error.code === 'MIGRATION.HASH_NOT_IN_GRAPH') {\n throw errorPlanForgotTheFlag(fromHash, getReachableRefs(refs, graph), graphTipHash);\n }\n throw error;\n }\n}\n\ntype RefContractResolution =\n | {\n kind: 'snapshot';\n hash: string;\n contract: Contract;\n contractJson: unknown;\n contractDts: string;\n }\n | {\n kind: 'graph-node';\n hash: string;\n contract: Contract;\n contractJson: unknown;\n contractDts: string;\n };\n\nasync function resolveContractRef(\n parsed: ContractRef,\n space: AggregateContractSpace,\n options?: { readonly explicitLabel?: string; readonly artifactRole?: 'from' | 'to' },\n): Promise<Result<RefContractResolution, CliStructuredError>> {\n const { hash, provenance } = parsed;\n const refName = provenance.kind === 'ref' ? provenance.refName : undefined;\n\n try {\n const at = await space.contractAt(hash, refName !== undefined ? { refName } : undefined);\n\n if (at.provenance === 'snapshot') {\n return ok({\n kind: 'snapshot',\n hash: at.hash,\n contract: at.contract,\n contractJson: at.contractJson,\n contractDts: at.contractDts,\n });\n }\n\n return ok({\n kind: 'graph-node',\n hash: at.hash,\n contract: at.contract,\n contractJson: at.contractJson,\n contractDts: at.contractDts,\n });\n } catch (error) {\n return mapContractAtError(\n error,\n options?.artifactRole !== undefined ? { artifactRole: options.artifactRole } : undefined,\n );\n }\n}\n\nasync function resolveFromPolicy(\n parsed: ContractRef,\n input: ResolveFromForPlanInput,\n refs: Refs,\n explicitFromLabel?: string,\n): Promise<Result<FromResolution, CliStructuredError>> {\n const resolution = await resolveContractRef(parsed, input.space, {\n ...(explicitFromLabel !== undefined ? { explicitLabel: explicitFromLabel } : {}),\n artifactRole: 'from',\n });\n if (!resolution.ok) {\n return resolution;\n }\n\n if (resolution.value.kind === 'graph-node') {\n return ok({\n kind: 'graph-node',\n fromHash: resolution.value.hash,\n fromContract: resolution.value.contract,\n });\n }\n\n const { hash, contract, contractJson, contractDts } = resolution.value;\n if (graphIsEmpty(input.space)) {\n return ok({\n kind: 'auto-baseline',\n fromHash: hash,\n fromContract: contract,\n contractDts,\n contractJson,\n });\n }\n\n const graph = input.space.graph();\n const graphTip = findLatestMigration(graph)?.to ?? null;\n try {\n assertFromIsGraphNode(hash, graph, refs, graphTip);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n throw error;\n }\n return ok({\n kind: 'snapshot',\n fromHash: hash,\n fromContract: contract,\n contractDts,\n contractJson,\n });\n}\n\nexport async function resolveFromForPlan(\n input: ResolveFromForPlanInput,\n): Promise<Result<FromResolution, CliStructuredError>> {\n const { optionsFrom, space } = input;\n const graph = space.graph();\n const refs = space.refs;\n\n if (optionsFrom === undefined) {\n const dbRef = refs['db'];\n if (!dbRef) {\n return ok({ kind: 'greenfield', fromHash: null, fromContract: null });\n }\n return resolveFromPolicy(\n { hash: dbRef.hash, provenance: { kind: 'ref', refName: 'db' } },\n input,\n refs,\n );\n }\n\n const refResult = parseContractRef(optionsFrom, { graph, refs });\n if (!refResult.ok) {\n if (looksLikeFullHash(optionsFrom)) {\n const empty = graphIsEmpty(space);\n const graphTip = findLatestMigration(graph)?.to ?? null;\n if (empty) {\n return notOk(errorSnapshotMissing(optionsFrom, { viaRef: false }));\n }\n return notOk(errorPlanForgotTheFlag(optionsFrom, getReachableRefs(refs, graph), graphTip));\n }\n return notOk(mapRefResolutionError(refResult.failure));\n }\n\n return resolveFromPolicy(refResult.value, input, refs, optionsFrom);\n}\n\nexport interface ResolveToForPlanInput {\n readonly space: AggregateContractSpace;\n}\n\nexport interface ResolvedContractRef {\n readonly hash: string;\n readonly contract: Contract;\n readonly contractJson: unknown;\n readonly contractDts: string;\n}\n\nexport async function resolveToForPlan(\n optionsTo: string,\n input: ResolveToForPlanInput,\n): Promise<Result<ResolvedContractRef, CliStructuredError>> {\n const { space } = input;\n const graph = space.graph();\n const refs = space.refs;\n\n const refResult = parseContractRef(optionsTo, { graph, refs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n\n const resolution = await resolveContractRef(refResult.value, space, {\n explicitLabel: optionsTo,\n artifactRole: 'to',\n });\n if (!resolution.ok) {\n return resolution;\n }\n\n const { hash, contract, contractJson, contractDts } = resolution.value;\n return ok({ hash, contract, contractJson, contractDts });\n}\n","import { readFile } from 'node:fs/promises';\nimport { loadConfig } from '@prisma-next/config-loader';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport {\n createControlStack,\n hasOperationPreview,\n type MigrationPlanOperation,\n type OperationPreview,\n type SchemaOwnership,\n} from '@prisma-next/framework-components/control';\nimport {\n snapshotsImportPathFrom,\n writeContractSnapshot,\n} from '@prisma-next/migration-tools/contract-snapshot-store';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { computeMigrationHash } from '@prisma-next/migration-tools/hash';\nimport { deriveProvidedInvariants } from '@prisma-next/migration-tools/invariants';\nimport { formatMigrationDirName, writeMigrationPackage } from '@prisma-next/migration-tools/io';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport {\n type CliErrorConflict,\n CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorMigrationPlanningFailed,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport {\n buildContractSpaceAggregate,\n loadContractSpaceAggregateForCli,\n} from '../utils/contract-space-aggregate-loader';\nimport { runContractSpaceSeedPhase } from '../utils/contract-space-seed-phase';\nimport { toExtensionInputs } from '../utils/extension-pack-inputs';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { resolveFromForPlan, resolveToForPlan } from '../utils/plan-resolution';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationPlanOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly name?: string;\n readonly from?: string;\n readonly to?: string;\n}\n\ntype PlannerSuccess = {\n readonly plannedOps: readonly MigrationPlanOperation[];\n readonly migrationTsContent: string;\n readonly hasPlaceholders: boolean;\n};\n\ntype TargetMigrationsApi = NonNullable<ReturnType<typeof getTargetMigrations>>;\n\nasync function runPlannerLeg(\n planner: ReturnType<TargetMigrationsApi['createPlanner']>,\n migrations: TargetMigrationsApi,\n frameworkComponents: ReturnType<typeof assertFrameworkComponentsCompatible>,\n contract: Contract,\n fromContract: Contract | null,\n spaceId: string,\n ownership: SchemaOwnership,\n snapshotsImportPath: string,\n): Promise<Result<PlannerSuccess, CliStructuredError>> {\n const fromSchema = migrations.contractToSchema(fromContract, frameworkComponents);\n const plannerResult = planner.plan({\n contract,\n schema: fromSchema,\n policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },\n fromContract,\n frameworkComponents,\n spaceId,\n // Offline `migration plan` is the aggregate-of-(possibly one) degenerate\n // case: the same ownership consultation the live aggregate flow uses. A\n // from→to extra (a table removed from the contract) is not declared by any\n // space in the aggregate, so it stays a genuine drop; a table another\n // space owns is never dropped.\n ownership,\n snapshotsImportPath,\n });\n if (plannerResult.kind === 'failure') {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: plannerResult.conflicts as readonly CliErrorConflict[],\n }),\n );\n }\n\n let plannedOps: readonly MigrationPlanOperation[] = [];\n let hasPlaceholders = false;\n try {\n plannedOps = await Promise.all(plannerResult.plan.operations);\n if (plannedOps.length === 0) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: [\n {\n kind: 'unsupportedChange',\n summary:\n 'Contract changed but planner produced no operations. ' +\n 'This indicates unsupported or ignored changes.',\n },\n ],\n }),\n );\n }\n } catch (e) {\n if (CliStructuredError.is(e) && e.code === 'MIGRATION.UNFILLED_PLACEHOLDER') {\n hasPlaceholders = true;\n } else {\n throw e;\n }\n }\n\n return ok({\n plannedOps,\n migrationTsContent: plannerResult.plan.renderTypeScript(),\n hasPlaceholders,\n });\n}\n\nasync function writePlannedMigrationPackage(\n packageDir: string,\n fromHash: string | null,\n toHash: string,\n createdAt: Date,\n leg: PlannerSuccess,\n): Promise<void> {\n const opsForWrite = leg.hasPlaceholders ? [] : leg.plannedOps;\n const metadataWithInvariants: Omit<MigrationMetadata, 'migrationHash'> = {\n from: fromHash,\n to: toHash,\n providedInvariants: deriveProvidedInvariants(opsForWrite),\n createdAt: createdAt.toISOString(),\n };\n const metadata: MigrationMetadata = {\n ...metadataWithInvariants,\n migrationHash: computeMigrationHash(metadataWithInvariants, opsForWrite),\n };\n await writeMigrationPackage(packageDir, metadata, opsForWrite);\n await writeMigrationTs(packageDir, leg.migrationTsContent);\n}\n\nexport interface MigrationPlanResult {\n readonly ok: boolean;\n readonly noOp: boolean;\n readonly from: string | null;\n readonly to: string;\n readonly dir?: string;\n readonly baselineDir?: string;\n /**\n * Extension-space migration packages materialised onto disk during this\n * `plan` run. Each entry names a `migrations/<spaceId>/<dirName>/`\n * tree the framework wrote alongside the app-space migration directory.\n * Empty when the project has no extension packs declaring a contract\n * space, or when every extension-space package is already on disk.\n *\n * Surfacing these in the result (rather than only via `ui.step` log\n * lines) makes the cross-space side effect explicit to JSON consumers\n * and the success-summary renderer — the same cross-space side effect\n * that `migrate` will replay.\n */\n readonly emittedExtensionDirs: readonly { readonly spaceId: string; readonly dirName: string }[];\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the migration plan operations.\n * Replaces the previous `sql?: readonly string[]` field; consumers should\n * read `result.preview?.statements`.\n */\n readonly preview?: OperationPreview;\n readonly summary: string;\n /**\n * When true, `migration.ts` was written but contains unfilled\n * `placeholder(...)` calls. The user must edit the file and then run\n * `node migration.ts` to self-emit `ops.json` / `migration.json`.\n */\n readonly pendingPlaceholders?: boolean;\n readonly timings: {\n readonly total: number;\n };\n}\n\nasync function executeMigrationPlanCommand(\n options: MigrationPlanOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationPlanResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } =\n resolveMigrationPaths(options.config, config);\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (options.to) {\n details.push({ label: 'to', value: options.to });\n }\n if (options.name) {\n details.push({ label: 'name', value: options.name });\n }\n const header = formatStyledHeader({\n command: 'migration plan',\n description: 'Plan a migration from contract changes',\n url: 'https://pris.ly/migration-plan',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file (the \"to\" contract)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Construct the family instance up-front so on-disk contract reads cross the\n // serializer seam at the read site, not after the planner has already\n // started dispatching on raw shapes. See TML-2536.\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const controlAdapter = config.adapter.create(stack);\n\n let toContract: Contract;\n try {\n toContract = familyInstance.deserializeContract(JSON.parse(contractJsonContent) as unknown);\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract at ${contractPathAbsolute} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n const rawStorageHash = toContract.storage?.storageHash;\n if (typeof rawStorageHash !== 'string') {\n return notOk(\n errorContractValidationFailed('Contract is missing storageHash', {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n let toStorageHash: string = rawStorageHash;\n\n // When `--to <ref>` resolves a non-default destination, these carry its raw\n // artifacts so the planned package's destination snapshot store entry is\n // written from the resolved target rather than copied from the emitted\n // `contract.json`.\n let toArtifacts: { contractJson: unknown; contractDts: string } | null = null;\n\n let fromContract: Contract | null = null;\n let fromHash: string | null = null;\n let snapshotStartContract: {\n readonly fromHash: string;\n readonly contractJson: unknown;\n readonly contractDts: string;\n } | null = null;\n let isAutoBaseline = false;\n\n const tolerantAggregateResult = await loadContractSpaceAggregateForCli({\n targetId: config.target.targetId,\n migrationsDir,\n appContract: toContract,\n extensionPacks: config.extensionPacks ?? [],\n deserializeContract: (json: unknown) => familyInstance.deserializeContract(json),\n });\n if (!tolerantAggregateResult.ok) {\n return notOk(tolerantAggregateResult.failure);\n }\n const resolutionSpace = tolerantAggregateResult.value.app;\n\n const resolutionResult = await resolveFromForPlan({\n optionsFrom: options.from,\n space: resolutionSpace,\n });\n\n if (!resolutionResult.ok) {\n return notOk(resolutionResult.failure);\n }\n\n switch (resolutionResult.value.kind) {\n case 'greenfield':\n break;\n case 'graph-node':\n fromHash = resolutionResult.value.fromHash;\n fromContract = resolutionResult.value.fromContract;\n break;\n case 'snapshot':\n fromHash = resolutionResult.value.fromHash;\n fromContract = resolutionResult.value.fromContract;\n snapshotStartContract = {\n fromHash: resolutionResult.value.fromHash,\n contractJson: resolutionResult.value.contractJson,\n contractDts: resolutionResult.value.contractDts,\n };\n break;\n case 'auto-baseline':\n fromHash = resolutionResult.value.fromHash;\n fromContract = resolutionResult.value.fromContract;\n snapshotStartContract = {\n fromHash: resolutionResult.value.fromHash,\n contractJson: resolutionResult.value.contractJson,\n contractDts: resolutionResult.value.contractDts,\n };\n isAutoBaseline = true;\n break;\n }\n\n // `--to <ref>` swaps the planner destination to an arbitrary resolved\n // contract (e.g. an ancestor / rollback target). The from-side resolution\n // above is untouched; only the destination + its snapshot store entry\n // change.\n if (options.to !== undefined) {\n const toResolution = await resolveToForPlan(options.to, {\n space: resolutionSpace,\n });\n if (!toResolution.ok) {\n return notOk(toResolution.failure);\n }\n toContract = toResolution.value.contract;\n toStorageHash = toResolution.value.hash;\n toArtifacts = {\n contractJson: toResolution.value.contractJson,\n contractDts: toResolution.value.contractDts,\n };\n }\n\n // Phase 1 — seed: unconditionally re-emit per-space pinned artifacts\n // (contract.json / contract.d.ts / refs/head.json) and materialise any\n // descriptor-shipped migration packages not yet on disk. Runs before\n // the no-op check so that an extension bump alone (with no structural\n // app-space change) still re-pins extension artifacts on disk.\n const canonicalExtensionInputs = toExtensionInputs(config.extensionPacks ?? []);\n const seedResult = await runContractSpaceSeedPhase({\n migrationsDir,\n extensionPacks: canonicalExtensionInputs,\n });\n if (!flags.json && !flags.quiet) {\n for (const record of seedResult.seeded) {\n if (record.action === 'updated') {\n const pkgSuffix =\n record.newMigrationDirs.length > 0\n ? `; ${record.newMigrationDirs.length} new migration package(s) materialised`\n : '';\n ui.step(`Updated ${record.spaceId} to ${record.newHash}${pkgSuffix}`);\n }\n }\n }\n const emittedExtensionDirs = seedResult.seeded.flatMap((r) =>\n r.newMigrationDirs.map((dirName) => ({ spaceId: r.spaceId, dirName })),\n );\n\n // Check for no-op (same hash means no changes). Auto-baseline is exempt:\n // an empty graph with db ref at the current contract still needs a\n // null → fromHash baseline bundle so migrate can anchor the marker.\n if (fromHash === toStorageHash && !isAutoBaseline) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: true,\n from: fromHash,\n to: toStorageHash,\n operations: [],\n emittedExtensionDirs,\n summary: 'No changes detected between contracts',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n // Check target supports migrations\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n // Phase 2 — load: build the aggregate against the now-consistent disk\n // state that phase 1 just seeded. The seed phase guarantees every\n // declared extension has its head ref pinned, so the loader's\n // declaredButUnmigrated precheck always passes here. The app contract\n // was already routed through `familyInstance.deserializeContract` at the\n // read site above (see TML-2536), so it's the hydrated `Contract`\n // here — no second validation pass needed.\n const aggregateResult = await buildContractSpaceAggregate({\n targetId: config.target.targetId,\n migrationsDir,\n appContract: toContract,\n extensionPacks: config.extensionPacks ?? [],\n deserializeContract: (json: unknown) => familyInstance.deserializeContract(json),\n });\n if (!aggregateResult.ok) {\n return notOk(aggregateResult.failure);\n }\n const aggregate = aggregateResult.value;\n\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n [config.target, config.adapter, ...(config.extensionPacks ?? [])],\n );\n\n // Write the planned package's destination contract into the snapshot store.\n // With `--to`, the resolved target's raw artifacts are written; otherwise\n // the emitted `contract.json` / `contract.d.ts` are read from disk.\n async function writeDestinationSnapshot(destHash: string): Promise<void> {\n if (toArtifacts !== null) {\n await writeContractSnapshot(migrationsDir, destHash, {\n contractJson: toArtifacts.contractJson,\n contractDts: toArtifacts.contractDts,\n });\n return;\n }\n const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);\n const [contractJsonRaw, contractDts] = await Promise.all([\n readFile(destinationArtifacts.jsonPath, 'utf-8'),\n readFile(destinationArtifacts.dtsPath, 'utf-8'),\n ]);\n await writeContractSnapshot(migrationsDir, destHash, {\n contractJson: JSON.parse(contractJsonRaw) as unknown,\n contractDts,\n });\n }\n\n try {\n const planner = migrations.createPlanner(controlAdapter);\n\n if (\n isAutoBaseline &&\n fromHash !== null &&\n fromContract !== null &&\n snapshotStartContract !== null\n ) {\n const baselineTimestamp = new Date();\n const deltaTimestamp = new Date(baselineTimestamp.getTime() + 60_000);\n const baselineDirName = formatMigrationDirName(baselineTimestamp, 'baseline');\n const deltaDirName = formatMigrationDirName(deltaTimestamp, options.name ?? 'migration');\n const baselinePackageDir = join(appMigrationsDir, baselineDirName);\n const deltaPackageDir = join(appMigrationsDir, deltaDirName);\n\n const baselineLeg = await runPlannerLeg(\n planner,\n migrations,\n frameworkComponents,\n fromContract,\n null,\n aggregate.app.spaceId,\n aggregate,\n snapshotsImportPathFrom(baselinePackageDir, migrationsDir),\n );\n if (!baselineLeg.ok) {\n return notOk(baselineLeg.failure);\n }\n\n await writePlannedMigrationPackage(\n baselinePackageDir,\n null,\n fromHash,\n baselineTimestamp,\n baselineLeg.value,\n );\n await writeContractSnapshot(migrationsDir, fromHash, {\n contractJson: snapshotStartContract.contractJson,\n contractDts: snapshotStartContract.contractDts,\n });\n\n if (fromHash === toStorageHash) {\n const baselineOps = baselineLeg.value.hasPlaceholders ? [] : baselineLeg.value.plannedOps;\n if (baselineLeg.value.hasPlaceholders) {\n const baselineDir = relative(process.cwd(), baselinePackageDir);\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: baselineDir,\n baselineDir,\n operations: [],\n emittedExtensionDirs,\n pendingPlaceholders: true,\n summary:\n 'Planned baseline with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const preview = hasOperationPreview(familyInstance)\n ? familyInstance.toOperationPreview(baselineOps)\n : undefined;\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n baselineDir: relative(process.cwd(), baselinePackageDir),\n operations: baselineOps.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n emittedExtensionDirs,\n ...(preview !== undefined ? { preview } : {}),\n summary: buildAutoBaselinePlanSummary(0, emittedExtensionDirs.length),\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const deltaLeg = await runPlannerLeg(\n planner,\n migrations,\n frameworkComponents,\n aggregate.app.contract(),\n fromContract,\n aggregate.app.spaceId,\n aggregate,\n snapshotsImportPathFrom(deltaPackageDir, migrationsDir),\n );\n if (!deltaLeg.ok) {\n return notOk(deltaLeg.failure);\n }\n\n await writePlannedMigrationPackage(\n deltaPackageDir,\n fromHash,\n toStorageHash,\n deltaTimestamp,\n deltaLeg.value,\n );\n await writeDestinationSnapshot(toStorageHash);\n await writeContractSnapshot(migrationsDir, fromHash, {\n contractJson: snapshotStartContract.contractJson,\n contractDts: snapshotStartContract.contractDts,\n });\n\n const deltaOps = deltaLeg.value.hasPlaceholders ? [] : deltaLeg.value.plannedOps;\n if (deltaLeg.value.hasPlaceholders) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), deltaPackageDir),\n baselineDir: relative(process.cwd(), baselinePackageDir),\n operations: [],\n emittedExtensionDirs,\n pendingPlaceholders: true,\n summary:\n 'Planned baseline + migration with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const preview = hasOperationPreview(familyInstance)\n ? familyInstance.toOperationPreview(deltaOps)\n : undefined;\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), deltaPackageDir),\n baselineDir: relative(process.cwd(), baselinePackageDir),\n operations: deltaOps.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n emittedExtensionDirs,\n ...(preview !== undefined ? { preview } : {}),\n summary: buildAutoBaselinePlanSummary(deltaOps.length, emittedExtensionDirs.length),\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const timestamp = new Date();\n const slug = options.name ?? 'migration';\n const dirName = formatMigrationDirName(timestamp, slug);\n const packageDir = join(appMigrationsDir, dirName);\n\n const deltaLeg = await runPlannerLeg(\n planner,\n migrations,\n frameworkComponents,\n aggregate.app.contract(),\n fromContract,\n aggregate.app.spaceId,\n aggregate,\n snapshotsImportPathFrom(packageDir, migrationsDir),\n );\n if (!deltaLeg.ok) {\n return notOk(deltaLeg.failure);\n }\n\n await writePlannedMigrationPackage(\n packageDir,\n fromHash,\n toStorageHash,\n timestamp,\n deltaLeg.value,\n );\n await writeDestinationSnapshot(toStorageHash);\n if (snapshotStartContract !== null) {\n await writeContractSnapshot(migrationsDir, snapshotStartContract.fromHash, {\n contractJson: snapshotStartContract.contractJson,\n contractDts: snapshotStartContract.contractDts,\n });\n }\n\n if (deltaLeg.value.hasPlaceholders) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), packageDir),\n operations: [],\n emittedExtensionDirs,\n pendingPlaceholders: true,\n summary:\n 'Planned migration with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const plannedOps = deltaLeg.value.plannedOps;\n const preview = hasOperationPreview(familyInstance)\n ? familyInstance.toOperationPreview(plannedOps)\n : undefined;\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), packageDir),\n operations: plannedOps.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n emittedExtensionDirs,\n ...(preview !== undefined ? { preview } : {}),\n summary: buildPlanSummary(plannedOps.length, emittedExtensionDirs.length),\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n const message = error instanceof Error ? error.message : String(error);\n return notOk(\n errorUnexpected(message, {\n why: `Unexpected error during migration plan: ${message}`,\n }),\n );\n }\n}\n\nexport function createMigrationPlanCommand(): Command {\n const command = new Command('plan');\n setCommandDescriptions(\n command,\n 'Plan a migration from contract changes',\n 'Compares the emitted contract against the latest on-disk migration state and\\n' +\n 'produces a new migration package with the required operations. No database\\n' +\n 'connection is needed — this is a fully offline operation.',\n );\n setCommandExamples(command, [\n 'prisma-next migration plan',\n 'prisma-next migration plan --name add-users-table',\n 'prisma-next migration plan --to <migration-dir>^ --name rollback',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--name <slug>', 'Name slug for the migration directory', 'migration')\n .option(\n '--from <contract>',\n 'Starting contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n )\n .option(\n '--to <contract>',\n 'Destination contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path); defaults to the emitted contract',\n )\n .action(async (options: MigrationPlanOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const startTime = Date.now();\n\n const ui = createTerminalUI(flags);\n const result = await executeMigrationPlanCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (planResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(planResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationPlanOutput(planResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n\n/**\n * Compose the success-line summary so the cross-space side effect\n * (extension-space migration packages materialised on disk during\n * this `plan` run) is visible in the top line — not just in the\n * step log above it.\n *\n * Example outputs:\n * - `Planned 3 operation(s)` (app-space-only project)\n * - `Planned 3 operation(s); materialised 1 extension-space migration` (one extension)\n * - `Planned 3 operation(s); materialised 2 extension-space migrations` (two extensions)\n *\n * Locks AC3 at the summary-line level: a reader of the success line\n * can tell that something happened beyond the app space.\n */\nfunction buildPlanSummary(plannedOpsCount: number, emittedExtensionDirsCount: number): string {\n const base = `Planned ${plannedOpsCount} operation(s)`;\n if (emittedExtensionDirsCount === 0) return base;\n const noun =\n emittedExtensionDirsCount === 1 ? 'extension-space migration' : 'extension-space migrations';\n return `${base}; materialised ${emittedExtensionDirsCount} ${noun}`;\n}\n\nfunction buildAutoBaselinePlanSummary(\n deltaOpsCount: number,\n emittedExtensionDirsCount: number,\n): string {\n const base = `Planned baseline + ${deltaOpsCount} operation(s)`;\n if (emittedExtensionDirsCount === 0) return base;\n const noun =\n emittedExtensionDirsCount === 1 ? 'extension-space migration' : 'extension-space migrations';\n return `${base}; materialised ${emittedExtensionDirsCount} ${noun}`;\n}\n\nexport function formatMigrationPlanOutput(result: MigrationPlanResult, flags: GlobalFlags): string {\n const lines: string[] = [];\n const useColor = flags.color !== false;\n\n const green_ = useColor ? (s: string) => `\\x1b[32m${s}\\x1b[0m` : (s: string) => s;\n const yellow_ = useColor ? (s: string) => `\\x1b[33m${s}\\x1b[0m` : (s: string) => s;\n const dim_ = useColor ? (s: string) => `\\x1b[2m${s}\\x1b[0m` : (s: string) => s;\n\n // Renders the extension-space materialisation block + canonical apply-step\n // hint shared by the no-op, placeholder, and full-plan branches. The app\n // space short-circuits do not skip it: an extension-only bump emits new\n // `migrations/<spaceId>/<dirName>/` directories on disk that the user\n // still has to apply, so the success line must surface them.\n function appendEmittedExtensions(): void {\n if (result.emittedExtensionDirs.length === 0) return;\n lines.push('');\n lines.push(dim_('Emitted extension migrations:'));\n for (const entry of result.emittedExtensionDirs) {\n lines.push(dim_(` ${entry.spaceId} → migrations/${entry.spaceId}/${entry.dirName}`));\n }\n lines.push('');\n lines.push(\n `Next: review the extension migrations above, then run ${green_('prisma-next migrate')}.`,\n );\n }\n\n if (result.noOp) {\n lines.push(`${green_('✔')} No changes detected`);\n lines.push(dim_(` from: ${result.from}`));\n lines.push(dim_(` to: ${result.to}`));\n appendEmittedExtensions();\n return lines.join('\\n');\n }\n\n if (result.pendingPlaceholders) {\n lines.push(`${yellow_('⚠')} ${result.summary}`);\n lines.push('');\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.dir) {\n lines.push(dim_(`dir: ${result.dir}`));\n }\n lines.push('');\n lines.push(\n 'Open migration.ts and replace each `placeholder(...)` call with your actual query.',\n );\n lines.push(`Then run: ${green_(`node ${result.dir ?? '<dir>'}/migration.ts`)}`);\n appendEmittedExtensions();\n return lines.join('\\n');\n }\n\n lines.push(`${green_('✔')} ${result.summary}`);\n lines.push('');\n\n if (result.operations.length > 0) {\n lines.push(dim_('│'));\n for (let i = 0; i < result.operations.length; i++) {\n const op = result.operations[i]!;\n const isLast = i === result.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n // operationClass tag is intentionally NOT inlined per spec:\n // a destructive footer warning still surfaces below this list.\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${yellow_('(destructive)')}` : '';\n lines.push(`${dim_(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = result.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${yellow_('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n lines.push('');\n }\n\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.baselineDir) {\n lines.push(dim_(`Baseline → ${result.baselineDir}`));\n }\n if (result.dir) {\n lines.push(dim_(`App space → ${result.dir}`));\n }\n // Per-space block: surface the extension-space directories materialised\n // alongside the app-space migration. Without this block the cross-space\n // side effect is invisible in the success summary (e2e finding F1).\n for (const entry of result.emittedExtensionDirs) {\n lines.push(\n dim_(`Extension space ${entry.spaceId} → migrations/${entry.spaceId}/${entry.dirName}`),\n );\n }\n\n lines.push('');\n // The \"Next:\" hint always points at the canonical apply path\n // (`prisma-next migrate`) regardless of how many spaces were\n // materialised — `db update` is a dev-time convenience, not the\n // canonical replay step.\n const reviewTarget =\n result.baselineDir !== undefined && result.dir !== undefined\n ? `${result.baselineDir} and ${result.dir}`\n : (result.baselineDir ?? result.dir ?? '<dir>');\n lines.push(\n `Next: review ${green_(reviewTarget)} if needed, then run ${green_('prisma-next migrate')}.`,\n );\n\n if (result.preview && result.preview.statements.length > 0) {\n // The non-empty length is already guaranteed by the surrounding check, so\n // a plain `every` here is equivalent to the helper in formatters/migrations.ts.\n const allSql = result.preview.statements.every((s) => s.language === 'sql');\n lines.push('');\n lines.push(dim_(allSql ? 'DDL preview' : 'Operation preview'));\n lines.push('');\n for (const statement of result.preview.statements) {\n const trimmed = statement.text.trim();\n if (!trimmed) continue;\n const line = statement.language === 'sql' && !trimmed.endsWith(';') ? `${trimmed};` : trimmed;\n lines.push(line);\n }\n }\n\n if (flags.verbose && result.timings) {\n lines.push('');\n lines.push(dim_(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\nexport type PrefixResolutionFailure =\n | { reason: 'ambiguous'; count: number }\n | { reason: 'not-found' };\n\n/**\n * Resolve a migration package by **target contract hash** (`metadata.to`)\n * using exact match or prefix match.\n *\n * Note: matches `metadata.to` (the contract hash this migration produces),\n * not `metadata.migrationHash` (the package's content-addressed identity).\n * Tries exact match first, then prefix match (auto-prepending `sha256:` when\n * the needle omits the scheme). Returns the matched package on success, or a\n * discriminated failure indicating whether the prefix was ambiguous or simply\n * not found.\n *\n * @internal Exported for testing only.\n */\nexport function resolveBundleByPrefix<T extends { metadata: { to: string } }>(\n bundles: readonly T[],\n needle: string,\n): Result<T, PrefixResolutionFailure> {\n const exact = bundles.find((p) => p.metadata.to === needle);\n if (exact) return ok(exact);\n\n const prefixWithScheme = needle.startsWith('sha256:') ? needle : `sha256:${needle}`;\n const candidates = bundles.filter((p) => p.metadata.to.startsWith(prefixWithScheme));\n\n if (candidates.length === 1) return ok(candidates[0]!);\n if (candidates.length > 1) return notOk({ reason: 'ambiguous', count: candidates.length });\n return notOk({ reason: 'not-found' });\n}\n"],"mappings":"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"}
|
|
@@ -2,7 +2,8 @@ import { A as formatStyledHeader, F as CliStructuredError, _ as createTerminalUI
|
|
|
2
2
|
import { t as createControlClient } from "./client-KuBQftxz.mjs";
|
|
3
3
|
import { n as buildReadAggregate, o as refusePackageCorruptionOnAggregate, r as loadContractRawSafely } from "./contract-space-aggregate-loader-D_3VeHVb.mjs";
|
|
4
4
|
import { a as renderMigrationGraphLegend, f as indentMigrationGraphTreeBlock, l as computeGlobalMaxDirNameWidth, p as renderMigrationGraphSpaceTree, u as computeGlobalMaxEdgeTreePrefixWidth } from "./migration-graph-command-render-B83xrnNy.mjs";
|
|
5
|
-
import { c as validateLegendOptions, i as migrationSpaceListEntriesFromAggregate, o as runMigrationList, r as listRefsByContractHash, s as shouldShowLegend } from "./migration-list-
|
|
5
|
+
import { c as validateLegendOptions, i as migrationSpaceListEntriesFromAggregate, o as runMigrationList, r as listRefsByContractHash, s as shouldShowLegend } from "./migration-list-6z6vuXHa.mjs";
|
|
6
|
+
import "./schemas-KhXMzNA_.mjs";
|
|
6
7
|
import { Command } from "commander";
|
|
7
8
|
import { loadConfig } from "@prisma-next/config-loader";
|
|
8
9
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
@@ -443,4 +444,4 @@ function createMigrationStatusCommand() {
|
|
|
443
444
|
//#endregion
|
|
444
445
|
export { formatStatusHumanOutput as a, executeMigrationStatusCommand as i, buildStatusHeadline as n, formatStatusSummary as o, createMigrationStatusCommand as r, buildNoPathSummary as t };
|
|
445
446
|
|
|
446
|
-
//# sourceMappingURL=migration-status-
|
|
447
|
+
//# sourceMappingURL=migration-status-B61YOaMl.mjs.map
|