@prisma-next/cli 0.3.0-dev.11 → 0.3.0-dev.114
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/LICENSE +201 -0
- package/README.md +470 -134
- package/dist/cli-errors-ByGuoqNj.mjs +3 -0
- package/dist/cli-errors-D6HxRn3A.d.mts +2 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.js +1 -2350
- package/dist/cli.mjs +235 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/client-612RJJD_.mjs +1069 -0
- package/dist/client-612RJJD_.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts +7 -0
- package/dist/commands/contract-emit.d.mts.map +1 -0
- package/dist/commands/contract-emit.mjs +4 -0
- package/dist/commands/contract-infer.d.mts +7 -0
- package/dist/commands/contract-infer.d.mts.map +1 -0
- package/dist/commands/contract-infer.mjs +4 -0
- package/dist/commands/db-init.d.mts +7 -0
- package/dist/commands/db-init.d.mts.map +1 -0
- package/dist/commands/db-init.mjs +124 -0
- package/dist/commands/db-init.mjs.map +1 -0
- package/dist/commands/db-schema.d.mts +7 -0
- package/dist/commands/db-schema.d.mts.map +1 -0
- package/dist/commands/db-schema.mjs +52 -0
- package/dist/commands/db-schema.mjs.map +1 -0
- package/dist/commands/db-sign.d.mts +7 -0
- package/dist/commands/db-sign.d.mts.map +1 -0
- package/dist/commands/db-sign.mjs +135 -0
- package/dist/commands/db-sign.mjs.map +1 -0
- package/dist/commands/db-update.d.mts +7 -0
- package/dist/commands/db-update.d.mts.map +1 -0
- package/dist/commands/db-update.mjs +121 -0
- package/dist/commands/db-update.mjs.map +1 -0
- package/dist/commands/db-verify.d.mts +7 -0
- package/dist/commands/db-verify.d.mts.map +1 -0
- package/dist/commands/db-verify.mjs +310 -0
- package/dist/commands/db-verify.mjs.map +1 -0
- package/dist/commands/migration-apply.d.mts +36 -0
- package/dist/commands/migration-apply.d.mts.map +1 -0
- package/dist/commands/migration-apply.mjs +240 -0
- package/dist/commands/migration-apply.mjs.map +1 -0
- package/dist/commands/migration-plan.d.mts +47 -0
- package/dist/commands/migration-plan.d.mts.map +1 -0
- package/dist/commands/migration-plan.mjs +288 -0
- package/dist/commands/migration-plan.mjs.map +1 -0
- package/dist/commands/migration-ref.d.mts +43 -0
- package/dist/commands/migration-ref.d.mts.map +1 -0
- package/dist/commands/migration-ref.mjs +194 -0
- package/dist/commands/migration-ref.mjs.map +1 -0
- package/dist/commands/migration-show.d.mts +28 -0
- package/dist/commands/migration-show.d.mts.map +1 -0
- package/dist/commands/migration-show.mjs +139 -0
- package/dist/commands/migration-show.mjs.map +1 -0
- package/dist/commands/migration-status.d.mts +85 -0
- package/dist/commands/migration-status.d.mts.map +1 -0
- package/dist/commands/migration-status.mjs +4 -0
- package/dist/commands/migration-verify.d.mts +16 -0
- package/dist/commands/migration-verify.d.mts.map +1 -0
- package/dist/commands/migration-verify.mjs +87 -0
- package/dist/commands/migration-verify.mjs.map +1 -0
- package/dist/config-loader-d_KF19Tw.mjs +43 -0
- package/dist/config-loader-d_KF19Tw.mjs.map +1 -0
- package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
- package/dist/config-loader.d.mts.map +1 -0
- package/dist/config-loader.mjs +3 -0
- package/dist/contract-emit-CVv7dbQ9.mjs +187 -0
- package/dist/contract-emit-CVv7dbQ9.mjs.map +1 -0
- package/dist/contract-infer-Bvw8u8Eu.mjs +83 -0
- package/dist/contract-infer-Bvw8u8Eu.mjs.map +1 -0
- package/dist/exports/config-types.d.mts +2 -0
- package/dist/exports/config-types.mjs +3 -0
- package/dist/exports/control-api.d.mts +626 -0
- package/dist/exports/control-api.d.mts.map +1 -0
- package/dist/exports/control-api.mjs +107 -0
- package/dist/exports/control-api.mjs.map +1 -0
- package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +10 -5
- package/dist/exports/index.d.mts.map +1 -0
- package/dist/exports/index.mjs +130 -0
- package/dist/exports/index.mjs.map +1 -0
- package/dist/extract-sql-ddl-Jf5blEO0.mjs +26 -0
- package/dist/extract-sql-ddl-Jf5blEO0.mjs.map +1 -0
- package/dist/framework-components-M2j-qPfr.mjs +59 -0
- package/dist/framework-components-M2j-qPfr.mjs.map +1 -0
- package/dist/inspect-live-schema-BQe5i4YE.mjs +90 -0
- package/dist/inspect-live-schema-BQe5i4YE.mjs.map +1 -0
- package/dist/migration-command-scaffold-SLrjcKXS.mjs +104 -0
- package/dist/migration-command-scaffold-SLrjcKXS.mjs.map +1 -0
- package/dist/migration-status-B7OVZ-Ka.mjs +1576 -0
- package/dist/migration-status-B7OVZ-Ka.mjs.map +1 -0
- package/dist/migrations-Db_ea9eE.mjs +173 -0
- package/dist/migrations-Db_ea9eE.mjs.map +1 -0
- package/dist/progress-adapter-DRNe2idZ.mjs +43 -0
- package/dist/progress-adapter-DRNe2idZ.mjs.map +1 -0
- package/dist/terminal-ui-DAcMBRKf.mjs +980 -0
- package/dist/terminal-ui-DAcMBRKf.mjs.map +1 -0
- package/dist/verify-DXKxBFvU.mjs +385 -0
- package/dist/verify-DXKxBFvU.mjs.map +1 -0
- package/package.json +88 -43
- package/src/cli.ts +109 -58
- package/src/commands/contract-emit.ts +236 -143
- package/src/commands/contract-infer-paths.ts +32 -0
- package/src/commands/contract-infer.ts +131 -0
- package/src/commands/db-init.ts +211 -425
- package/src/commands/db-schema.ts +77 -0
- package/src/commands/db-sign.ts +207 -228
- package/src/commands/db-update.ts +236 -0
- package/src/commands/db-verify.ts +484 -186
- package/src/commands/inspect-live-schema.ts +171 -0
- package/src/commands/migration-apply.ts +416 -0
- package/src/commands/migration-plan.ts +451 -0
- package/src/commands/migration-ref.ts +305 -0
- package/src/commands/migration-show.ts +246 -0
- package/src/commands/migration-status.ts +838 -0
- package/src/commands/migration-verify.ts +134 -0
- package/src/config-loader.ts +13 -3
- package/src/control-api/client.ts +614 -0
- package/src/control-api/contract-enrichment.ts +135 -0
- package/src/control-api/errors.ts +9 -0
- package/src/control-api/operations/contract-emit.ts +173 -0
- package/src/control-api/operations/db-init.ts +286 -0
- package/src/control-api/operations/db-update.ts +221 -0
- package/src/control-api/operations/extract-sql-ddl.ts +47 -0
- package/src/control-api/operations/migration-apply.ts +194 -0
- package/src/control-api/operations/migration-helpers.ts +49 -0
- package/src/control-api/types.ts +683 -0
- package/src/exports/config-types.ts +4 -3
- package/src/exports/control-api.ts +56 -0
- package/src/load-ts-contract.ts +16 -11
- package/src/utils/cli-errors.ts +5 -2
- package/src/utils/command-helpers.ts +293 -3
- package/src/utils/formatters/emit.ts +67 -0
- package/src/utils/formatters/errors.ts +82 -0
- package/src/utils/formatters/graph-migration-mapper.ts +220 -0
- package/src/utils/formatters/graph-render.ts +1317 -0
- package/src/utils/formatters/graph-types.ts +114 -0
- package/src/utils/formatters/help.ts +380 -0
- package/src/utils/formatters/helpers.ts +28 -0
- package/src/utils/formatters/migrations.ts +346 -0
- package/src/utils/formatters/styled.ts +212 -0
- package/src/utils/formatters/verify.ts +620 -0
- package/src/utils/global-flags.ts +41 -23
- package/src/utils/migration-command-scaffold.ts +187 -0
- package/src/utils/migration-types.ts +12 -0
- package/src/utils/progress-adapter.ts +75 -0
- package/src/utils/result-handler.ts +12 -13
- package/src/utils/shutdown.ts +92 -0
- package/src/utils/suggest-command.ts +31 -0
- package/src/utils/terminal-ui.ts +276 -0
- package/dist/chunk-BZMBKEEQ.js +0 -997
- package/dist/chunk-BZMBKEEQ.js.map +0 -1
- package/dist/chunk-CVNWLFXO.js +0 -91
- package/dist/chunk-CVNWLFXO.js.map +0 -1
- package/dist/chunk-HWYQOCAJ.js +0 -47
- package/dist/chunk-HWYQOCAJ.js.map +0 -1
- package/dist/chunk-QUPBU4KV.js +0 -131
- package/dist/chunk-QUPBU4KV.js.map +0 -1
- package/dist/cli.d.ts +0 -2
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/contract-emit.d.ts +0 -3
- package/dist/commands/contract-emit.d.ts.map +0 -1
- package/dist/commands/contract-emit.js +0 -9
- package/dist/commands/contract-emit.js.map +0 -1
- package/dist/commands/db-init.d.ts +0 -3
- package/dist/commands/db-init.d.ts.map +0 -1
- package/dist/commands/db-init.js +0 -337
- package/dist/commands/db-init.js.map +0 -1
- package/dist/commands/db-introspect.d.ts +0 -3
- package/dist/commands/db-introspect.d.ts.map +0 -1
- package/dist/commands/db-introspect.js +0 -186
- package/dist/commands/db-introspect.js.map +0 -1
- package/dist/commands/db-schema-verify.d.ts +0 -3
- package/dist/commands/db-schema-verify.d.ts.map +0 -1
- package/dist/commands/db-schema-verify.js +0 -160
- package/dist/commands/db-schema-verify.js.map +0 -1
- package/dist/commands/db-sign.d.ts +0 -3
- package/dist/commands/db-sign.d.ts.map +0 -1
- package/dist/commands/db-sign.js +0 -195
- package/dist/commands/db-sign.js.map +0 -1
- package/dist/commands/db-verify.d.ts +0 -3
- package/dist/commands/db-verify.d.ts.map +0 -1
- package/dist/commands/db-verify.js +0 -169
- package/dist/commands/db-verify.js.map +0 -1
- package/dist/config-loader.d.ts.map +0 -1
- package/dist/config-loader.js +0 -7
- package/dist/config-loader.js.map +0 -1
- package/dist/exports/config-types.d.ts +0 -3
- package/dist/exports/config-types.d.ts.map +0 -1
- package/dist/exports/config-types.js +0 -6
- package/dist/exports/config-types.js.map +0 -1
- package/dist/exports/index.d.ts +0 -4
- package/dist/exports/index.d.ts.map +0 -1
- package/dist/exports/index.js +0 -175
- package/dist/exports/index.js.map +0 -1
- package/dist/load-ts-contract.d.ts.map +0 -1
- package/dist/utils/action.d.ts +0 -16
- package/dist/utils/action.d.ts.map +0 -1
- package/dist/utils/cli-errors.d.ts +0 -7
- package/dist/utils/cli-errors.d.ts.map +0 -1
- package/dist/utils/command-helpers.d.ts +0 -12
- package/dist/utils/command-helpers.d.ts.map +0 -1
- package/dist/utils/framework-components.d.ts +0 -70
- package/dist/utils/framework-components.d.ts.map +0 -1
- package/dist/utils/global-flags.d.ts +0 -25
- package/dist/utils/global-flags.d.ts.map +0 -1
- package/dist/utils/output.d.ts +0 -142
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/result-handler.d.ts +0 -15
- package/dist/utils/result-handler.d.ts.map +0 -1
- package/dist/utils/spinner.d.ts +0 -29
- package/dist/utils/spinner.d.ts.map +0 -1
- package/src/commands/db-introspect.ts +0 -256
- package/src/commands/db-schema-verify.ts +0 -232
- package/src/utils/action.ts +0 -43
- package/src/utils/output.ts +0 -1471
- package/src/utils/spinner.ts +0 -67
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-plan.mjs","names":["details: Array<{ label: string; value: string }>","contractJsonContent: string","toContractJson: ContractIR","fromContract: ContractIR | null","fromHash: string","manifest: MigrationManifest","lines: string[]"],"sources":["../../src/commands/migration-plan.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport { EMPTY_CONTRACT_HASH } from '@prisma-next/core-control-plane/constants';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/stack';\nimport { attestMigration } from '@prisma-next/migration-tools/attestation';\nimport { findLatestMigration } from '@prisma-next/migration-tools/dag';\nimport { formatMigrationDirName, writeMigrationPackage } from '@prisma-next/migration-tools/io';\nimport { type MigrationManifest, MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractSqlDdl } from '../control-api/operations/extract-sql-ddl';\nimport {\n type CliErrorConflict,\n type CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorMigrationPlanningFailed,\n errorRuntime,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\n loadMigrationBundles,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationPlanOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly name?: string;\n readonly from?: string;\n}\n\nexport interface MigrationPlanResult {\n readonly ok: boolean;\n readonly noOp: boolean;\n readonly from: string;\n readonly to: string;\n readonly migrationId?: string;\n readonly dir?: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql?: readonly string[];\n readonly summary: string;\n readonly timings: {\n readonly total: number;\n };\n}\n\nfunction mapMigrationToolsError(error: unknown): CliStructuredError {\n if (MigrationToolsError.is(error)) {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n }\n return errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Unexpected error during migration plan: ${error instanceof Error ? error.message : String(error)}`,\n });\n}\n\nasync function executeMigrationPlanCommand(\n options: MigrationPlanOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationPlanResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'migrations', value: migrationsRelative },\n ];\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (options.name) {\n details.push({ label: 'name', value: options.name });\n }\n const header = formatStyledHeader({\n command: 'migration plan',\n description: 'Plan a migration from contract changes',\n url: 'https://pris.ly/migration-plan',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file (the \"to\" contract)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n let toContractJson: ContractIR;\n try {\n toContractJson = JSON.parse(contractJsonContent) as ContractIR;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n const toStorageHash = (toContractJson as unknown as Record<string, unknown>)['storageHash'] as\n | string\n | undefined;\n if (!toStorageHash) {\n return notOk(\n errorContractValidationFailed('Contract is missing storageHash', {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n\n // Read existing migrations and determine \"from\" contract\n let fromContract: ContractIR | null = null;\n let fromHash: string = EMPTY_CONTRACT_HASH;\n\n try {\n const { bundles, graph } = await loadMigrationBundles(migrationsDir);\n\n if (options.from) {\n const resolved = resolveBundleByPrefix(bundles, options.from);\n if (!resolved.ok) {\n const f = resolved.failure;\n return notOk(\n f.reason === 'ambiguous'\n ? errorRuntime('Multiple matching migrations found', {\n why: `Prefix \"${options.from}\" matches ${f.count} migrations in ${migrationsRelative}`,\n fix: 'Provide a longer prefix to disambiguate, or omit --from to use the latest migration target.',\n })\n : errorRuntime('Starting contract not found', {\n why: `No migration with to hash matching \"${options.from}\" exists in ${migrationsRelative}`,\n fix: 'Check that the --from hash matches a known migration target hash, or omit --from to use the latest migration target.',\n }),\n );\n }\n fromHash = resolved.value.manifest.to;\n fromContract = resolved.value.manifest.toContract;\n } else {\n const latestMigration = findLatestMigration(graph);\n if (latestMigration) {\n fromHash = latestMigration.to;\n const leafPkg = bundles.find((p) => p.manifest.migrationId === latestMigration.migrationId);\n if (leafPkg) {\n fromContract = leafPkg.manifest.toContract;\n }\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n throw error;\n }\n\n // Check for no-op (same hash means no changes)\n if (fromHash === toStorageHash) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: true,\n from: fromHash,\n to: toStorageHash,\n operations: [],\n summary: 'No changes detected between contracts',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n // Check target supports migrations\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n const stack = createControlPlaneStack({\n target: config.target,\n adapter: config.adapter,\n extensionPacks: config.extensionPacks ?? [],\n });\n const familyInstance = config.family.create(stack);\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n [config.target, config.adapter, ...(config.extensionPacks ?? [])],\n );\n const planner = migrations.createPlanner(familyInstance);\n const fromSchemaIR = migrations.contractToSchema(fromContract, frameworkComponents);\n const plannerResult = planner.plan({\n contract: toContractJson,\n schema: fromSchemaIR,\n policy: { allowedOperationClasses: ['additive', 'widening', 'destructive'] },\n frameworkComponents,\n });\n\n if (plannerResult.kind === 'failure') {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: plannerResult.conflicts as readonly CliErrorConflict[],\n }),\n );\n }\n\n if (plannerResult.plan.operations.length === 0) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: [\n {\n kind: 'unsupportedChange',\n summary:\n 'Contract changed but planner produced no operations. ' +\n 'This indicates unsupported or ignored changes (e.g. removals, type changes, or a planner/contract mismatch).',\n },\n ],\n }),\n );\n }\n\n // Build manifest and write migration package\n const timestamp = new Date();\n const slug = options.name ?? 'migration';\n const dirName = formatMigrationDirName(timestamp, slug);\n const packageDir = join(migrationsDir, dirName);\n\n const manifest: MigrationManifest = {\n from: fromHash,\n to: toStorageHash,\n migrationId: null,\n kind: 'regular',\n fromContract,\n toContract: toContractJson,\n hints: {\n used: [],\n applied: [],\n plannerVersion: '1.0.0',\n planningStrategy: 'diff',\n },\n labels: [],\n createdAt: timestamp.toISOString(),\n };\n\n try {\n await writeMigrationPackage(packageDir, manifest, plannerResult.plan.operations);\n const migrationId = await attestMigration(packageDir);\n\n const sql = extractSqlDdl(plannerResult.plan.operations);\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n migrationId,\n dir: relative(process.cwd(), packageDir),\n operations: plannerResult.plan.operations.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `Planned ${plannerResult.plan.operations.length} operation(s)`,\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n } catch (error) {\n return notOk(mapMigrationToolsError(error));\n }\n}\n\nexport function createMigrationPlanCommand(): Command {\n const command = new Command('plan');\n setCommandDescriptions(\n command,\n 'Plan a migration from contract changes',\n 'Compares the emitted contract against the latest on-disk migration state and\\n' +\n 'produces a new migration package with the required operations. No database\\n' +\n 'connection is needed — this is a fully offline operation.',\n );\n setCommandExamples(command, [\n 'prisma-next migration plan',\n 'prisma-next migration plan --name add-users-table',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--name <slug>', 'Name slug for the migration directory', 'migration')\n .option('--from <hash>', 'Explicit starting contract hash (overrides latest migration target)')\n .action(async (options: MigrationPlanOptions) => {\n const flags = parseGlobalFlags(options);\n const startTime = Date.now();\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeMigrationPlanCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (planResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(planResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationPlanOutput(planResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n\nfunction formatMigrationPlanOutput(result: MigrationPlanResult, flags: GlobalFlags): string {\n const lines: string[] = [];\n const useColor = flags.color !== false;\n\n const green_ = useColor ? (s: string) => `\\x1b[32m${s}\\x1b[0m` : (s: string) => s;\n const yellow_ = useColor ? (s: string) => `\\x1b[33m${s}\\x1b[0m` : (s: string) => s;\n const dim_ = useColor ? (s: string) => `\\x1b[2m${s}\\x1b[0m` : (s: string) => s;\n\n if (result.noOp) {\n lines.push(`${green_('✔')} No changes detected`);\n lines.push(dim_(` from: ${result.from}`));\n lines.push(dim_(` to: ${result.to}`));\n return lines.join('\\n');\n }\n\n lines.push(`${green_('✔')} ${result.summary}`);\n lines.push('');\n\n if (result.operations.length > 0) {\n lines.push(dim_('│'));\n for (let i = 0; i < result.operations.length; i++) {\n const op = result.operations[i]!;\n const isLast = i === result.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const opClassLabel =\n op.operationClass === 'destructive'\n ? yellow_(`[${op.operationClass}]`)\n : dim_(`[${op.operationClass}]`);\n lines.push(`${dim_(treeChar)}─ ${op.label} ${opClassLabel}`);\n }\n\n const hasDestructive = result.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${yellow_('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n lines.push('');\n }\n\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.migrationId) {\n lines.push(dim_(`migrationId: ${result.migrationId}`));\n }\n if (result.dir) {\n lines.push(dim_(`dir: ${result.dir}`));\n }\n\n if (result.sql && result.sql.length > 0) {\n lines.push('');\n lines.push(dim_('DDL preview'));\n lines.push('');\n for (const statement of result.sql) {\n const trimmed = statement.trim();\n if (!trimmed) continue;\n const line = trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n lines.push(line);\n }\n }\n\n if (flags.verbose && result.timings) {\n lines.push('');\n lines.push(dim_(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\nexport type PrefixResolutionFailure =\n | { reason: 'ambiguous'; count: number }\n | { reason: 'not-found' };\n\n/**\n * Resolve a migration bundle by exact hash or prefix match.\n *\n * Tries exact match first, then prefix match (auto-prepending `sha256:` when\n * the needle omits the scheme). Returns the matched bundle on success, or a\n * discriminated failure indicating whether the prefix was ambiguous or simply\n * not found.\n *\n * @internal Exported for testing only.\n */\nexport function resolveBundleByPrefix<T extends { manifest: { to: string } }>(\n bundles: readonly T[],\n needle: string,\n): Result<T, PrefixResolutionFailure> {\n const exact = bundles.find((p) => p.manifest.to === needle);\n if (exact) return ok(exact);\n\n const prefixWithScheme = needle.startsWith('sha256:') ? needle : `sha256:${needle}`;\n const candidates = bundles.filter((p) => p.manifest.to.startsWith(prefixWithScheme));\n\n if (candidates.length === 1) return ok(candidates[0]!);\n if (candidates.length > 1) return notOk({ reason: 'ambiguous', count: candidates.length });\n return notOk({ reason: 'not-found' });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { t as CliStructuredError } from "../cli-errors-D6HxRn3A.mjs";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { Result } from "@prisma-next/utils/result";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/migration-ref.d.ts
|
|
6
|
+
interface RefSetResult {
|
|
7
|
+
readonly ok: true;
|
|
8
|
+
readonly ref: string;
|
|
9
|
+
readonly hash: string;
|
|
10
|
+
}
|
|
11
|
+
interface RefGetResult {
|
|
12
|
+
readonly ok: true;
|
|
13
|
+
readonly ref: string;
|
|
14
|
+
readonly hash: string;
|
|
15
|
+
}
|
|
16
|
+
interface RefDeleteResult {
|
|
17
|
+
readonly ok: true;
|
|
18
|
+
readonly ref: string;
|
|
19
|
+
readonly deleted: true;
|
|
20
|
+
}
|
|
21
|
+
interface RefListResult {
|
|
22
|
+
readonly ok: true;
|
|
23
|
+
readonly refs: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
declare function cliErrorInvalidRefName(name: string): CliStructuredError;
|
|
26
|
+
declare function cliErrorInvalidRefValue(hash: string): CliStructuredError;
|
|
27
|
+
declare function errorRefNotFound(name: string): CliStructuredError;
|
|
28
|
+
declare function executeRefSetCommand(name: string, hash: string, options: {
|
|
29
|
+
config?: string;
|
|
30
|
+
}): Promise<Result<RefSetResult, CliStructuredError>>;
|
|
31
|
+
declare function executeRefGetCommand(name: string, options: {
|
|
32
|
+
config?: string;
|
|
33
|
+
}): Promise<Result<RefGetResult, CliStructuredError>>;
|
|
34
|
+
declare function executeRefDeleteCommand(name: string, options: {
|
|
35
|
+
config?: string;
|
|
36
|
+
}): Promise<Result<RefDeleteResult, CliStructuredError>>;
|
|
37
|
+
declare function executeRefListCommand(options: {
|
|
38
|
+
config?: string;
|
|
39
|
+
}): Promise<Result<RefListResult, CliStructuredError>>;
|
|
40
|
+
declare function createMigrationRefCommand(): Command;
|
|
41
|
+
//#endregion
|
|
42
|
+
export { cliErrorInvalidRefName, cliErrorInvalidRefValue, createMigrationRefCommand, errorRefNotFound, executeRefDeleteCommand, executeRefGetCommand, executeRefListCommand, executeRefSetCommand };
|
|
43
|
+
//# sourceMappingURL=migration-ref.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-ref.d.mts","names":[],"sources":["../../src/commands/migration-ref.ts"],"sourcesContent":[],"mappings":";;;;;UAmBU,YAAA;;EAAA,SAAA,GAAA,EAAA,MAAY;EAMZ,SAAA,IAAA,EAAY,MAAA;AAAA;AAMG,UANf,YAAA,CAYa;EAqBd,SAAA,EAAA,EAAA,IAAA;EAOA,SAAA,GAAA,EAAA,MAAA;EAOA,SAAA,IAAA,EAAA,MAAgB;AAAkC;UAzCjD,eAAA,CAoDQ;EAAc,SAAA,EAAA,EAAA,IAAA;EAArB,SAAA,GAAA,EAAA,MAAA;EAAR,SAAA,OAAA,EAAA,IAAA;;AAAO,UA9CA,aAAA,CAmEK;EAGG,SAAA,EAAA,EAAA,IAAA;EAAc,SAAA,IAAA,EApEf,MAoEe,CAAA,MAAA,EAAA,MAAA,CAAA;;iBAjDvB,sBAAA,CAiDN,IAAA,EAAA,MAAA,CAAA,EAjD4C,kBAiD5C;iBA1CM,uBAAA,CA0CC,IAAA,EAAA,MAAA,CAAA,EA1CsC,kBA0CtC;AAAA,iBAnCD,gBAAA,CAgD6B,IAAA,EAAA,MAAA,CAAA,EAhDG,kBAgDH;iBAzCvB,oBAAA,CA4CG,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA;EAAiB,MAAA,CAAA,EAAA,MAAA;CAAxB,CAAA,EAxCR,OAwCQ,CAxCA,MAwCA,CAxCO,YAwCP,EAxCqB,kBAwCrB,CAAA,CAAA;iBAnBI,oBAAA,CAmBZ,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA;EAAO,MAAA,CAAA,EAAA,MAAA;AAAA,CAAA,CAAA,EAhBP,OAiCY,CAjCJ,MAiCI,CAjCG,YAiCkB,EAjCJ,kBAiCI,CAAA,CAAA;iBApBrB,uBAAA,CAsBI,IAAA,EAAA,MAAA,EAAA,OAAA,EAAA;EAAe,MAAA,CAAA,EAAA,MAAA;CAAtB,CAAA,EAnBT,OAmBS,CAnBD,MAmBC,CAnBM,eAmBN,EAnBuB,kBAmBvB,CAAA,CAAA;iBAFG,qBAAA,CAEX,OAAA,EAAA;EAAO,MAAA,CAAA,EAAA,MAAA;AAiJX,CAAA,CAAA,EAjJI,OAiJY,CAjJJ,MAiJI,CAjJG,aAiJsB,EAjJP,kBAiJkB,CAAA,CAAA;iBAApC,yBAAA,CAAA,GAA6B"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { t as loadConfig } from "../config-loader-d_KF19Tw.mjs";
|
|
2
|
+
import { _ as errorUnexpected, m as errorRuntime, t as CliStructuredError } from "../cli-errors-ByGuoqNj.mjs";
|
|
3
|
+
import { _ as formatCommandHelp, f as setCommandDescriptions, g as parseGlobalFlags, i as addGlobalOptions, r as handleResult, t as TerminalUI } from "../terminal-ui-DAcMBRKf.mjs";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
6
|
+
import { resolve } from "pathe";
|
|
7
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/types";
|
|
8
|
+
import { readRefs, resolveRef, validateRefName, validateRefValue, writeRefs } from "@prisma-next/migration-tools/refs";
|
|
9
|
+
|
|
10
|
+
//#region src/commands/migration-ref.ts
|
|
11
|
+
function resolveRefsPath(configPath, config) {
|
|
12
|
+
return resolve(configPath ? resolve(configPath, "..") : process.cwd(), config?.migrations?.dir ?? "migrations", "refs.json");
|
|
13
|
+
}
|
|
14
|
+
function mapError(error) {
|
|
15
|
+
if (MigrationToolsError.is(error)) return errorRuntime(error.message, {
|
|
16
|
+
why: error.why,
|
|
17
|
+
fix: error.fix,
|
|
18
|
+
meta: { code: error.code }
|
|
19
|
+
});
|
|
20
|
+
return errorUnexpected(error instanceof Error ? error.message : String(error));
|
|
21
|
+
}
|
|
22
|
+
function cliErrorInvalidRefName(name) {
|
|
23
|
+
return errorRuntime(`Invalid ref name "${name}"`, {
|
|
24
|
+
why: `Ref name "${name}" does not match the required format`,
|
|
25
|
+
fix: "Ref names must be lowercase alphanumeric with hyphens or forward slashes, no `.` or `..` segments"
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function cliErrorInvalidRefValue(hash) {
|
|
29
|
+
return errorRuntime(`Invalid contract hash "${hash}"`, {
|
|
30
|
+
why: `"${hash}" is not a valid contract hash`,
|
|
31
|
+
fix: "Contract hashes must match the format \"sha256:<64 hex chars>\". Copy the hash from `prisma-next contract emit` or `migration status --json`."
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function errorRefNotFound(name) {
|
|
35
|
+
return errorRuntime(`Ref "${name}" does not exist`, {
|
|
36
|
+
why: `No ref named "${name}" found in refs.json`,
|
|
37
|
+
fix: `Run \`prisma-next migration ref list\` to see available refs, or \`prisma-next migration ref set ${name} <hash>\` to create it`
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async function executeRefSetCommand(name, hash, options) {
|
|
41
|
+
if (!validateRefName(name)) return notOk(cliErrorInvalidRefName(name));
|
|
42
|
+
if (!validateRefValue(hash)) return notOk(cliErrorInvalidRefValue(hash));
|
|
43
|
+
try {
|
|
44
|
+
const config = await loadConfig(options.config);
|
|
45
|
+
const refsPath = resolveRefsPath(options.config, config);
|
|
46
|
+
await writeRefs(refsPath, {
|
|
47
|
+
...await readRefs(refsPath),
|
|
48
|
+
[name]: hash
|
|
49
|
+
});
|
|
50
|
+
return ok({
|
|
51
|
+
ok: true,
|
|
52
|
+
ref: name,
|
|
53
|
+
hash
|
|
54
|
+
});
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error instanceof CliStructuredError) return notOk(error);
|
|
57
|
+
return notOk(mapError(error));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function executeRefGetCommand(name, options) {
|
|
61
|
+
try {
|
|
62
|
+
const config = await loadConfig(options.config);
|
|
63
|
+
return ok({
|
|
64
|
+
ok: true,
|
|
65
|
+
ref: name,
|
|
66
|
+
hash: resolveRef(await readRefs(resolveRefsPath(options.config, config)), name)
|
|
67
|
+
});
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error instanceof CliStructuredError) return notOk(error);
|
|
70
|
+
return notOk(mapError(error));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function executeRefDeleteCommand(name, options) {
|
|
74
|
+
try {
|
|
75
|
+
const config = await loadConfig(options.config);
|
|
76
|
+
const refsPath = resolveRefsPath(options.config, config);
|
|
77
|
+
const refs = await readRefs(refsPath);
|
|
78
|
+
if (!Object.hasOwn(refs, name)) return notOk(errorRefNotFound(name));
|
|
79
|
+
const { [name]: _, ...remaining } = refs;
|
|
80
|
+
await writeRefs(refsPath, remaining);
|
|
81
|
+
return ok({
|
|
82
|
+
ok: true,
|
|
83
|
+
ref: name,
|
|
84
|
+
deleted: true
|
|
85
|
+
});
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (error instanceof CliStructuredError) return notOk(error);
|
|
88
|
+
return notOk(mapError(error));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function executeRefListCommand(options) {
|
|
92
|
+
try {
|
|
93
|
+
const config = await loadConfig(options.config);
|
|
94
|
+
return ok({
|
|
95
|
+
ok: true,
|
|
96
|
+
refs: await readRefs(resolveRefsPath(options.config, config))
|
|
97
|
+
});
|
|
98
|
+
} catch (error) {
|
|
99
|
+
if (error instanceof CliStructuredError) return notOk(error);
|
|
100
|
+
return notOk(mapError(error));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function createRefSetCommand() {
|
|
104
|
+
const command = new Command("set");
|
|
105
|
+
setCommandDescriptions(command, "Set a ref to a contract hash", "Sets a named ref to point to a contract hash in migrations/refs.json.");
|
|
106
|
+
addGlobalOptions(command).argument("<name>", "Ref name (e.g., staging, production)").argument("<hash>", "Contract hash to point to").option("--config <path>", "Path to prisma-next.config.ts").action(async (name, hash, options) => {
|
|
107
|
+
const flags = parseGlobalFlags(options);
|
|
108
|
+
const ui = new TerminalUI({
|
|
109
|
+
color: flags.color,
|
|
110
|
+
interactive: flags.interactive
|
|
111
|
+
});
|
|
112
|
+
const exitCode = handleResult(await executeRefSetCommand(name, hash, options), flags, ui, (value) => {
|
|
113
|
+
if (flags.json) ui.output(JSON.stringify(value));
|
|
114
|
+
else if (!flags.quiet) ui.output(`Set ref "${value.ref}" → ${value.hash}`);
|
|
115
|
+
});
|
|
116
|
+
process.exit(exitCode);
|
|
117
|
+
});
|
|
118
|
+
return command;
|
|
119
|
+
}
|
|
120
|
+
function createRefGetCommand() {
|
|
121
|
+
const command = new Command("get");
|
|
122
|
+
setCommandDescriptions(command, "Get the hash for a ref", "Reads a named ref from migrations/refs.json and prints its contract hash.");
|
|
123
|
+
addGlobalOptions(command).argument("<name>", "Ref name to look up").option("--config <path>", "Path to prisma-next.config.ts").action(async (name, options) => {
|
|
124
|
+
const flags = parseGlobalFlags(options);
|
|
125
|
+
const ui = new TerminalUI({
|
|
126
|
+
color: flags.color,
|
|
127
|
+
interactive: flags.interactive
|
|
128
|
+
});
|
|
129
|
+
const exitCode = handleResult(await executeRefGetCommand(name, options), flags, ui, (value) => {
|
|
130
|
+
if (flags.json) ui.output(JSON.stringify(value));
|
|
131
|
+
else ui.output(value.hash);
|
|
132
|
+
});
|
|
133
|
+
process.exit(exitCode);
|
|
134
|
+
});
|
|
135
|
+
return command;
|
|
136
|
+
}
|
|
137
|
+
function createRefDeleteCommand() {
|
|
138
|
+
const command = new Command("delete");
|
|
139
|
+
setCommandDescriptions(command, "Delete a ref", "Removes a named ref from migrations/refs.json.");
|
|
140
|
+
addGlobalOptions(command).argument("<name>", "Ref name to delete").option("--config <path>", "Path to prisma-next.config.ts").action(async (name, options) => {
|
|
141
|
+
const flags = parseGlobalFlags(options);
|
|
142
|
+
const ui = new TerminalUI({
|
|
143
|
+
color: flags.color,
|
|
144
|
+
interactive: flags.interactive
|
|
145
|
+
});
|
|
146
|
+
const exitCode = handleResult(await executeRefDeleteCommand(name, options), flags, ui, (value) => {
|
|
147
|
+
if (flags.json) ui.output(JSON.stringify(value));
|
|
148
|
+
else if (!flags.quiet) ui.output(`Deleted ref "${value.ref}"`);
|
|
149
|
+
});
|
|
150
|
+
process.exit(exitCode);
|
|
151
|
+
});
|
|
152
|
+
return command;
|
|
153
|
+
}
|
|
154
|
+
function createRefListCommand() {
|
|
155
|
+
const command = new Command("list");
|
|
156
|
+
setCommandDescriptions(command, "List all refs", "Lists all named refs from migrations/refs.json.");
|
|
157
|
+
addGlobalOptions(command).option("--config <path>", "Path to prisma-next.config.ts").action(async (options) => {
|
|
158
|
+
const flags = parseGlobalFlags(options);
|
|
159
|
+
const ui = new TerminalUI({
|
|
160
|
+
color: flags.color,
|
|
161
|
+
interactive: flags.interactive
|
|
162
|
+
});
|
|
163
|
+
const exitCode = handleResult(await executeRefListCommand(options), flags, ui, (value) => {
|
|
164
|
+
if (flags.json) ui.output(JSON.stringify(value));
|
|
165
|
+
else if (!flags.quiet) {
|
|
166
|
+
const entries = Object.entries(value.refs);
|
|
167
|
+
if (entries.length === 0) ui.output("No refs defined");
|
|
168
|
+
else for (const [refName, hash] of entries) ui.output(`${refName} → ${hash}`);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
process.exit(exitCode);
|
|
172
|
+
});
|
|
173
|
+
return command;
|
|
174
|
+
}
|
|
175
|
+
function createMigrationRefCommand() {
|
|
176
|
+
const command = new Command("ref");
|
|
177
|
+
setCommandDescriptions(command, "Manage migration refs", "Manage named refs in migrations/refs.json. Refs map logical environment\nnames (e.g., staging, production) to contract hashes.");
|
|
178
|
+
addGlobalOptions(command).configureHelp({
|
|
179
|
+
formatHelp: (cmd) => formatCommandHelp({
|
|
180
|
+
command: cmd,
|
|
181
|
+
flags: parseGlobalFlags({})
|
|
182
|
+
}),
|
|
183
|
+
subcommandDescription: () => ""
|
|
184
|
+
});
|
|
185
|
+
command.addCommand(createRefSetCommand());
|
|
186
|
+
command.addCommand(createRefGetCommand());
|
|
187
|
+
command.addCommand(createRefDeleteCommand());
|
|
188
|
+
command.addCommand(createRefListCommand());
|
|
189
|
+
return command;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//#endregion
|
|
193
|
+
export { cliErrorInvalidRefName, cliErrorInvalidRefValue, createMigrationRefCommand, errorRefNotFound, executeRefDeleteCommand, executeRefGetCommand, executeRefListCommand, executeRefSetCommand };
|
|
194
|
+
//# sourceMappingURL=migration-ref.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-ref.mjs","names":[],"sources":["../../src/commands/migration-ref.ts"],"sourcesContent":["import {\n readRefs,\n resolveRef,\n validateRefName,\n validateRefValue,\n writeRefs,\n} from '@prisma-next/migration-tools/refs';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport { addGlobalOptions, setCommandDescriptions } from '../utils/command-helpers';\nimport { formatCommandHelp } from '../utils/formatters/help';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface RefSetResult {\n readonly ok: true;\n readonly ref: string;\n readonly hash: string;\n}\n\ninterface RefGetResult {\n readonly ok: true;\n readonly ref: string;\n readonly hash: string;\n}\n\ninterface RefDeleteResult {\n readonly ok: true;\n readonly ref: string;\n readonly deleted: true;\n}\n\ninterface RefListResult {\n readonly ok: true;\n readonly refs: Record<string, string>;\n}\n\nfunction resolveRefsPath(configPath?: string, config?: { migrations?: { dir?: string } }): string {\n const base = configPath ? resolve(configPath, '..') : process.cwd();\n return resolve(base, config?.migrations?.dir ?? 'migrations', 'refs.json');\n}\n\nfunction mapError(error: unknown): CliStructuredError {\n if (MigrationToolsError.is(error)) {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code },\n });\n }\n return errorUnexpected(error instanceof Error ? error.message : String(error));\n}\n\nfunction cliErrorInvalidRefName(name: string): CliStructuredError {\n return errorRuntime(`Invalid ref name \"${name}\"`, {\n why: `Ref name \"${name}\" does not match the required format`,\n fix: 'Ref names must be lowercase alphanumeric with hyphens or forward slashes, no `.` or `..` segments',\n });\n}\n\nfunction cliErrorInvalidRefValue(hash: string): CliStructuredError {\n return errorRuntime(`Invalid contract hash \"${hash}\"`, {\n why: `\"${hash}\" is not a valid contract hash`,\n fix: 'Contract hashes must match the format \"sha256:<64 hex chars>\". Copy the hash from `prisma-next contract emit` or `migration status --json`.',\n });\n}\n\nfunction errorRefNotFound(name: string): CliStructuredError {\n return errorRuntime(`Ref \"${name}\" does not exist`, {\n why: `No ref named \"${name}\" found in refs.json`,\n fix: `Run \\`prisma-next migration ref list\\` to see available refs, or \\`prisma-next migration ref set ${name} <hash>\\` to create it`,\n });\n}\n\nasync function executeRefSetCommand(\n name: string,\n hash: string,\n options: { config?: string },\n): Promise<Result<RefSetResult, CliStructuredError>> {\n if (!validateRefName(name)) {\n return notOk(cliErrorInvalidRefName(name));\n }\n if (!validateRefValue(hash)) {\n return notOk(cliErrorInvalidRefValue(hash));\n }\n\n try {\n const config = await loadConfig(options.config);\n const refsPath = resolveRefsPath(options.config, config);\n const refs = await readRefs(refsPath);\n const updated = { ...refs, [name]: hash };\n await writeRefs(refsPath, updated);\n return ok({ ok: true as const, ref: name, hash });\n } catch (error) {\n if (error instanceof CliStructuredError) return notOk(error);\n return notOk(mapError(error));\n }\n}\n\nasync function executeRefGetCommand(\n name: string,\n options: { config?: string },\n): Promise<Result<RefGetResult, CliStructuredError>> {\n try {\n const config = await loadConfig(options.config);\n const refsPath = resolveRefsPath(options.config, config);\n const refs = await readRefs(refsPath);\n const hash = resolveRef(refs, name);\n return ok({ ok: true as const, ref: name, hash });\n } catch (error) {\n if (error instanceof CliStructuredError) return notOk(error);\n return notOk(mapError(error));\n }\n}\n\nasync function executeRefDeleteCommand(\n name: string,\n options: { config?: string },\n): Promise<Result<RefDeleteResult, CliStructuredError>> {\n try {\n const config = await loadConfig(options.config);\n const refsPath = resolveRefsPath(options.config, config);\n const refs = await readRefs(refsPath);\n if (!Object.hasOwn(refs, name)) {\n return notOk(errorRefNotFound(name));\n }\n const { [name]: _, ...remaining } = refs;\n await writeRefs(refsPath, remaining);\n return ok({ ok: true as const, ref: name, deleted: true as const });\n } catch (error) {\n if (error instanceof CliStructuredError) return notOk(error);\n return notOk(mapError(error));\n }\n}\n\nasync function executeRefListCommand(options: {\n config?: string;\n}): Promise<Result<RefListResult, CliStructuredError>> {\n try {\n const config = await loadConfig(options.config);\n const refsPath = resolveRefsPath(options.config, config);\n const refs = await readRefs(refsPath);\n return ok({ ok: true as const, refs });\n } catch (error) {\n if (error instanceof CliStructuredError) return notOk(error);\n return notOk(mapError(error));\n }\n}\n\nfunction createRefSetCommand(): Command {\n const command = new Command('set');\n setCommandDescriptions(\n command,\n 'Set a ref to a contract hash',\n 'Sets a named ref to point to a contract hash in migrations/refs.json.',\n );\n addGlobalOptions(command)\n .argument('<name>', 'Ref name (e.g., staging, production)')\n .argument('<hash>', 'Contract hash to point to')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(\n async (\n name: string,\n hash: string,\n options: { config?: string; json?: string | boolean; quiet?: boolean },\n ) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeRefSetCommand(name, hash, options);\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value));\n } else if (!flags.quiet) {\n ui.output(`Set ref \"${value.ref}\" → ${value.hash}`);\n }\n });\n process.exit(exitCode);\n },\n );\n return command;\n}\n\nfunction createRefGetCommand(): Command {\n const command = new Command('get');\n setCommandDescriptions(\n command,\n 'Get the hash for a ref',\n 'Reads a named ref from migrations/refs.json and prints its contract hash.',\n );\n addGlobalOptions(command)\n .argument('<name>', 'Ref name to look up')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(\n async (\n name: string,\n options: { config?: string; json?: string | boolean; quiet?: boolean },\n ) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeRefGetCommand(name, options);\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value));\n } else {\n ui.output(value.hash);\n }\n });\n process.exit(exitCode);\n },\n );\n return command;\n}\n\nfunction createRefDeleteCommand(): Command {\n const command = new Command('delete');\n setCommandDescriptions(command, 'Delete a ref', 'Removes a named ref from migrations/refs.json.');\n addGlobalOptions(command)\n .argument('<name>', 'Ref name to delete')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(\n async (\n name: string,\n options: { config?: string; json?: string | boolean; quiet?: boolean },\n ) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeRefDeleteCommand(name, options);\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value));\n } else if (!flags.quiet) {\n ui.output(`Deleted ref \"${value.ref}\"`);\n }\n });\n process.exit(exitCode);\n },\n );\n return command;\n}\n\nfunction createRefListCommand(): Command {\n const command = new Command('list');\n setCommandDescriptions(\n command,\n 'List all refs',\n 'Lists all named refs from migrations/refs.json.',\n );\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: { config?: string; json?: string | boolean; quiet?: boolean }) => {\n const flags = parseGlobalFlags(options);\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n const result = await executeRefListCommand(options);\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value));\n } else if (!flags.quiet) {\n const entries = Object.entries(value.refs);\n if (entries.length === 0) {\n ui.output('No refs defined');\n } else {\n for (const [refName, hash] of entries) {\n ui.output(`${refName} → ${hash}`);\n }\n }\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n\nexport {\n executeRefSetCommand,\n executeRefGetCommand,\n executeRefDeleteCommand,\n executeRefListCommand,\n cliErrorInvalidRefName,\n cliErrorInvalidRefValue,\n errorRefNotFound,\n};\n\nexport function createMigrationRefCommand(): Command {\n const command = new Command('ref');\n setCommandDescriptions(\n command,\n 'Manage migration refs',\n 'Manage named refs in migrations/refs.json. Refs map logical environment\\n' +\n 'names (e.g., staging, production) to contract hashes.',\n );\n addGlobalOptions(command).configureHelp({\n formatHelp: (cmd) => formatCommandHelp({ command: cmd, flags: parseGlobalFlags({}) }),\n subcommandDescription: () => '',\n });\n command.addCommand(createRefSetCommand());\n command.addCommand(createRefGetCommand());\n command.addCommand(createRefDeleteCommand());\n command.addCommand(createRefListCommand());\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { t as CliStructuredError } from "../cli-errors-D6HxRn3A.mjs";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { Result } from "@prisma-next/utils/result";
|
|
4
|
+
import { MigrationBundle } from "@prisma-next/migration-tools/types";
|
|
5
|
+
|
|
6
|
+
//#region src/commands/migration-show.d.ts
|
|
7
|
+
interface MigrationShowResult {
|
|
8
|
+
readonly ok: true;
|
|
9
|
+
readonly dirName: string;
|
|
10
|
+
readonly dirPath: string;
|
|
11
|
+
readonly from: string;
|
|
12
|
+
readonly to: string;
|
|
13
|
+
readonly migrationId: string | null;
|
|
14
|
+
readonly kind: string;
|
|
15
|
+
readonly createdAt: string;
|
|
16
|
+
readonly operations: readonly {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly label: string;
|
|
19
|
+
readonly operationClass: string;
|
|
20
|
+
}[];
|
|
21
|
+
readonly sql: readonly string[];
|
|
22
|
+
readonly summary: string;
|
|
23
|
+
}
|
|
24
|
+
declare function resolveByHashPrefix(packages: readonly MigrationBundle[], prefix: string): Result<MigrationBundle, CliStructuredError>;
|
|
25
|
+
declare function createMigrationShowCommand(): Command;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { MigrationShowResult, createMigrationShowCommand, resolveByHashPrefix };
|
|
28
|
+
//# sourceMappingURL=migration-show.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":[],"mappings":";;;;;;UA2BiB,mBAAA;;EAAA,SAAA,OAAA,EAAA,MAAmB;EAsBpB,SAAA,OAAA,EAAA,MAAmB;EACd,SAAA,IAAA,EAAA,MAAA;EAEX,SAAA,EAAA,EAAA,MAAA;EAAiB,SAAA,WAAA,EAAA,MAAA,GAAA,IAAA;EAAxB,SAAA,IAAA,EAAA,MAAA;EAAM,SAAA,SAAA,EAAA,MAAA;EA2JO,SAAA,UAAA,EAAA,SAA0B;;;;;;;;iBA9J1B,mBAAA,oBACK,oCAElB,OAAO,iBAAiB;iBA2JX,0BAAA,CAAA,GAA8B"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { t as loadConfig } from "../config-loader-d_KF19Tw.mjs";
|
|
2
|
+
import { _ as errorUnexpected, m as errorRuntime } from "../cli-errors-ByGuoqNj.mjs";
|
|
3
|
+
import { t as extractSqlDdl } from "../extract-sql-ddl-Jf5blEO0.mjs";
|
|
4
|
+
import { f as setCommandDescriptions, g as parseGlobalFlags, i as addGlobalOptions, p as setCommandExamples, r as handleResult, t as TerminalUI, y as formatStyledHeader } from "../terminal-ui-DAcMBRKf.mjs";
|
|
5
|
+
import { a as formatMigrationShowOutput } from "../migrations-Db_ea9eE.mjs";
|
|
6
|
+
import { Command } from "commander";
|
|
7
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
8
|
+
import { relative, resolve } from "pathe";
|
|
9
|
+
import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/dag";
|
|
10
|
+
import { readMigrationPackage, readMigrationsDir } from "@prisma-next/migration-tools/io";
|
|
11
|
+
import { MigrationToolsError, isAttested } from "@prisma-next/migration-tools/types";
|
|
12
|
+
|
|
13
|
+
//#region src/commands/migration-show.ts
|
|
14
|
+
function looksLikePath(target) {
|
|
15
|
+
return target.includes("/") || target.includes("\\");
|
|
16
|
+
}
|
|
17
|
+
function resolveByHashPrefix(packages, prefix) {
|
|
18
|
+
const normalizedPrefix = prefix.startsWith("sha256:") ? prefix : `sha256:${prefix}`;
|
|
19
|
+
const matches = packages.filter((p) => typeof p.manifest.migrationId === "string").filter((p) => p.manifest.migrationId.startsWith(normalizedPrefix));
|
|
20
|
+
if (matches.length === 1) return ok(matches[0]);
|
|
21
|
+
if (matches.length === 0) return notOk(errorRuntime("No migration found matching prefix", {
|
|
22
|
+
why: `No attested migration has a migrationId starting with "${normalizedPrefix}"`,
|
|
23
|
+
fix: "Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages."
|
|
24
|
+
}));
|
|
25
|
+
return notOk(errorRuntime("Ambiguous hash prefix", {
|
|
26
|
+
why: `Multiple migrations match prefix "${normalizedPrefix}":\n${matches.map((p) => ` ${p.dirName} ${p.manifest.migrationId}`).join("\n")}`,
|
|
27
|
+
fix: "Provide a longer prefix to uniquely identify the migration."
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
async function executeMigrationShowCommand(target, options, flags, ui) {
|
|
31
|
+
const config = await loadConfig(options.config);
|
|
32
|
+
const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
|
|
33
|
+
const migrationsDir = resolve(options.config ? resolve(options.config, "..") : process.cwd(), config.migrations?.dir ?? "migrations");
|
|
34
|
+
const migrationsRelative = relative(process.cwd(), migrationsDir);
|
|
35
|
+
if (!flags.json && !flags.quiet) {
|
|
36
|
+
const details = [{
|
|
37
|
+
label: "config",
|
|
38
|
+
value: configPath
|
|
39
|
+
}, {
|
|
40
|
+
label: "migrations",
|
|
41
|
+
value: migrationsRelative
|
|
42
|
+
}];
|
|
43
|
+
if (target) details.push({
|
|
44
|
+
label: "target",
|
|
45
|
+
value: target
|
|
46
|
+
});
|
|
47
|
+
const header = formatStyledHeader({
|
|
48
|
+
command: "migration show",
|
|
49
|
+
description: "Display migration package contents",
|
|
50
|
+
details,
|
|
51
|
+
flags
|
|
52
|
+
});
|
|
53
|
+
ui.stderr(header);
|
|
54
|
+
}
|
|
55
|
+
let pkg;
|
|
56
|
+
try {
|
|
57
|
+
if (target && looksLikePath(target)) pkg = await readMigrationPackage(resolve(target));
|
|
58
|
+
else {
|
|
59
|
+
const allPackages = await readMigrationsDir(migrationsDir);
|
|
60
|
+
if (allPackages.length === 0) return notOk(errorRuntime("No migrations found", {
|
|
61
|
+
why: `No migration packages found in ${migrationsRelative}`,
|
|
62
|
+
fix: "Run `prisma-next migration plan` to create a migration first."
|
|
63
|
+
}));
|
|
64
|
+
if (target) {
|
|
65
|
+
const resolved = resolveByHashPrefix(allPackages, target);
|
|
66
|
+
if (!resolved.ok) return resolved;
|
|
67
|
+
pkg = resolved.value;
|
|
68
|
+
} else {
|
|
69
|
+
const attested = allPackages.filter(isAttested);
|
|
70
|
+
if (attested.length === 0) return notOk(errorRuntime("No attested migrations found", {
|
|
71
|
+
why: `All migrations in ${migrationsRelative} are drafts (migrationId: null)`,
|
|
72
|
+
fix: "Run `prisma-next migration verify --dir <path>` to attest a draft migration."
|
|
73
|
+
}));
|
|
74
|
+
const latestMigration = findLatestMigration(reconstructGraph(attested));
|
|
75
|
+
if (!latestMigration) return notOk(errorRuntime("Could not resolve latest migration", {
|
|
76
|
+
why: "No latest migration found in the migration history",
|
|
77
|
+
fix: "The migrations directory may be corrupted. Inspect the migration.json files."
|
|
78
|
+
}));
|
|
79
|
+
const leafPkg = attested.find((p) => p.manifest.migrationId === latestMigration.migrationId);
|
|
80
|
+
if (!leafPkg) return notOk(errorRuntime("Could not resolve latest migration", {
|
|
81
|
+
why: `Latest migration ${latestMigration.dirName} does not match any package`,
|
|
82
|
+
fix: "The migrations directory may be corrupted. Inspect the migration.json files."
|
|
83
|
+
}));
|
|
84
|
+
pkg = leafPkg;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
} catch (error) {
|
|
88
|
+
if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
|
|
89
|
+
why: error.why,
|
|
90
|
+
fix: error.fix,
|
|
91
|
+
meta: {
|
|
92
|
+
code: error.code,
|
|
93
|
+
...error.details ?? {}
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}` }));
|
|
97
|
+
}
|
|
98
|
+
const ops = pkg.ops;
|
|
99
|
+
const sql = extractSqlDdl(ops);
|
|
100
|
+
return ok({
|
|
101
|
+
ok: true,
|
|
102
|
+
dirName: pkg.dirName,
|
|
103
|
+
dirPath: relative(process.cwd(), pkg.dirPath),
|
|
104
|
+
from: pkg.manifest.from,
|
|
105
|
+
to: pkg.manifest.to,
|
|
106
|
+
migrationId: pkg.manifest.migrationId,
|
|
107
|
+
kind: pkg.manifest.kind,
|
|
108
|
+
createdAt: pkg.manifest.createdAt,
|
|
109
|
+
operations: ops.map((op) => ({
|
|
110
|
+
id: op.id,
|
|
111
|
+
label: op.label,
|
|
112
|
+
operationClass: op.operationClass
|
|
113
|
+
})),
|
|
114
|
+
sql,
|
|
115
|
+
summary: `${ops.length} operation(s)`
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function createMigrationShowCommand() {
|
|
119
|
+
const command = new Command("show");
|
|
120
|
+
setCommandDescriptions(command, "Display migration package contents", "Shows the operations, DDL preview, and metadata for a migration package.\nAccepts a directory path, a hash prefix (git-style), or defaults to the\nlatest migration.");
|
|
121
|
+
setCommandExamples(command, ["prisma-next migration show", "prisma-next migration show sha256:a1b2c3"]);
|
|
122
|
+
addGlobalOptions(command).argument("[target]", "Migration directory path or migrationId hash prefix (defaults to latest)").option("--config <path>", "Path to prisma-next.config.ts").action(async (target, options) => {
|
|
123
|
+
const flags = parseGlobalFlags(options);
|
|
124
|
+
const ui = new TerminalUI({
|
|
125
|
+
color: flags.color,
|
|
126
|
+
interactive: flags.interactive
|
|
127
|
+
});
|
|
128
|
+
const exitCode = handleResult(await executeMigrationShowCommand(target, options, flags, ui), flags, ui, (showResult) => {
|
|
129
|
+
if (flags.json) ui.output(JSON.stringify(showResult, null, 2));
|
|
130
|
+
else if (!flags.quiet) ui.log(formatMigrationShowOutput(showResult, flags));
|
|
131
|
+
});
|
|
132
|
+
process.exit(exitCode);
|
|
133
|
+
});
|
|
134
|
+
return command;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
//#endregion
|
|
138
|
+
export { createMigrationShowCommand, resolveByHashPrefix };
|
|
139
|
+
//# sourceMappingURL=migration-show.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-show.mjs","names":["details: Array<{ label: string; value: string }>","pkg: MigrationBundle"],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import type { MigrationPlanOperation } from '@prisma-next/core-control-plane/types';\nimport { findLatestMigration, reconstructGraph } from '@prisma-next/migration-tools/dag';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport type { MigrationBundle } from '@prisma-next/migration-tools/types';\nimport { isAttested, MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractSqlDdl } from '../control-api/operations/extract-sql-ddl';\nimport { type CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport interface MigrationShowResult {\n readonly ok: true;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string;\n readonly to: string;\n readonly migrationId: string | null;\n readonly kind: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql: readonly string[];\n readonly summary: string;\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\nexport function resolveByHashPrefix(\n packages: readonly MigrationBundle[],\n prefix: string,\n): Result<MigrationBundle, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const attested = packages.filter((p) => typeof p.manifest.migrationId === 'string');\n const matches = attested.filter((p) => p.manifest.migrationId!.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No attested migration has a migrationId starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.manifest.migrationId}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n const migrationsDir = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let pkg: MigrationBundle;\n\n try {\n if (target && looksLikePath(target)) {\n pkg = await readMigrationPackage(resolve(target));\n } else {\n const allPackages = await readMigrationsDir(migrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${migrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n pkg = resolved.value;\n } else {\n const attested = allPackages.filter(isAttested);\n if (attested.length === 0) {\n return notOk(\n errorRuntime('No attested migrations found', {\n why: `All migrations in ${migrationsRelative} are drafts (migrationId: null)`,\n fix: 'Run `prisma-next migration verify --dir <path>` to attest a draft migration.',\n }),\n );\n }\n const graph = reconstructGraph(attested);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = attested.find(\n (p) => p.manifest.migrationId === latestMigration.migrationId,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n pkg = leafPkg;\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n const sql = extractSqlDdl(ops);\n\n const result: MigrationShowResult = {\n ok: true,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.manifest.from,\n to: pkg.manifest.to,\n migrationId: pkg.manifest.migrationId,\n kind: pkg.manifest.kind,\n createdAt: pkg.manifest.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `${ops.length} operation(s)`,\n };\n return ok(result);\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, DDL preview, and metadata for a migration package.\\n' +\n 'Accepts a directory path, a hash prefix (git-style), or defaults to the\\n' +\n 'latest migration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument(\n '[target]',\n 'Migration directory path or migrationId hash prefix (defaults to latest)',\n )\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { MigrationBundle, MigrationGraph } from "@prisma-next/migration-tools/types";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/migration-types.d.ts
|
|
5
|
+
interface StatusRef {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly hash: string;
|
|
8
|
+
readonly active: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface StatusDiagnostic {
|
|
11
|
+
readonly code: string;
|
|
12
|
+
readonly severity: 'warn' | 'info';
|
|
13
|
+
readonly message: string;
|
|
14
|
+
readonly hints: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/utils/formatters/graph-migration-mapper.d.ts
|
|
18
|
+
type EdgeStatusKind = 'applied' | 'pending' | 'unreachable';
|
|
19
|
+
/** Minimal per-edge status from the CLI's status result. */
|
|
20
|
+
interface EdgeStatus {
|
|
21
|
+
readonly dirName: string;
|
|
22
|
+
readonly status: EdgeStatusKind;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/commands/migration-status.d.ts
|
|
26
|
+
interface MigrationStatusEntry {
|
|
27
|
+
readonly dirName: string;
|
|
28
|
+
readonly from: string;
|
|
29
|
+
readonly to: string;
|
|
30
|
+
readonly migrationId: string | null;
|
|
31
|
+
readonly operationCount: number;
|
|
32
|
+
readonly operationSummary: string;
|
|
33
|
+
readonly hasDestructive: boolean;
|
|
34
|
+
readonly status: EdgeStatusKind | 'unknown';
|
|
35
|
+
}
|
|
36
|
+
interface MigrationStatusResult {
|
|
37
|
+
readonly ok: true;
|
|
38
|
+
readonly mode: 'online' | 'offline';
|
|
39
|
+
readonly migrations: readonly MigrationStatusEntry[];
|
|
40
|
+
readonly markerHash?: string;
|
|
41
|
+
readonly targetHash: string;
|
|
42
|
+
readonly contractHash: string;
|
|
43
|
+
readonly refs?: readonly StatusRef[];
|
|
44
|
+
readonly pathDecision?: {
|
|
45
|
+
readonly fromHash: string;
|
|
46
|
+
readonly toHash: string;
|
|
47
|
+
readonly alternativeCount: number;
|
|
48
|
+
readonly tieBreakReasons: readonly string[];
|
|
49
|
+
readonly refName?: string;
|
|
50
|
+
readonly selectedPath: readonly {
|
|
51
|
+
readonly dirName: string;
|
|
52
|
+
readonly migrationId: string | null;
|
|
53
|
+
readonly from: string;
|
|
54
|
+
readonly to: string;
|
|
55
|
+
}[];
|
|
56
|
+
};
|
|
57
|
+
readonly summary: string;
|
|
58
|
+
readonly diagnostics: readonly StatusDiagnostic[];
|
|
59
|
+
readonly graph?: MigrationGraph;
|
|
60
|
+
readonly bundles?: readonly MigrationBundle[];
|
|
61
|
+
readonly edgeStatuses?: readonly EdgeStatus[];
|
|
62
|
+
readonly activeRefHash?: string;
|
|
63
|
+
readonly activeRefName?: string;
|
|
64
|
+
readonly diverged?: boolean;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Derive per-edge status across the full graph using path analysis.
|
|
68
|
+
*
|
|
69
|
+
* - **applied**: edge is on the path from root to the DB marker
|
|
70
|
+
* - **pending**: edge is on the path from the DB marker to the target
|
|
71
|
+
* (and the marker is reachable from root, i.e. it's on the same branch)
|
|
72
|
+
* - **unreachable**: edge is on the path from root to the target but the DB
|
|
73
|
+
* marker is on a different branch — `apply` can't reach these edges
|
|
74
|
+
* without the DB first moving to this branch
|
|
75
|
+
*
|
|
76
|
+
* Returns statuses only for edges that have a known status (skips offline
|
|
77
|
+
* and edges not on any relevant path).
|
|
78
|
+
*
|
|
79
|
+
* @internal Exported for testing only.
|
|
80
|
+
*/
|
|
81
|
+
declare function deriveEdgeStatuses(graph: MigrationGraph, targetHash: string, contractHash: string, markerHash: string | undefined, mode: 'online' | 'offline'): EdgeStatus[];
|
|
82
|
+
declare function createMigrationStatusCommand(): Command;
|
|
83
|
+
//#endregion
|
|
84
|
+
export { MigrationStatusEntry, MigrationStatusResult, type StatusDiagnostic, type StatusRef, createMigrationStatusCommand, deriveEdgeStatuses };
|
|
85
|
+
//# sourceMappingURL=migration-status.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"sourcesContent":[],"mappings":";;;;UAAiB,SAAA;;;;AAAjB;AAMiB,UAAA,gBAAA,CAAgB;;;;ECWrB,SAAA,KAAA,EAAA,SAAc,MAAA,EAAA;AAmB1B;;;KAnBY,cAAA;ADjBZ;AAMiB,UC8BA,UAAA,CD9BgB;;mBCgCd;;;;ADtCF,UE2DA,oBAAA,CF3DS;EAMT,SAAA,OAAA,EAAA,MAAgB;;;;ECWrB,SAAA,cAAc,EAAA,MAAA;EAmBT,SAAA,gBAEE,EAAA,MAAA;;mBC6BA;;AAKF,UAAA,qBAAA,CAAqB;EAGN,SAAA,EAAA,EAAA,IAAA;EAIL,SAAA,IAAA,EAAA,QAAA,GAAA,SAAA;EAeM,SAAA,UAAA,EAAA,SAnBD,oBAmBC,EAAA;EACd,SAAA,UAAA,CAAA,EAAA,MAAA;EACW,SAAA,UAAA,EAAA,MAAA;EACK,SAAA,YAAA,EAAA,MAAA;EAAU,SAAA,IAAA,CAAA,EAAA,SAlBlB,SAkBkB,EAAA;EAkD7B,SAAA,YAAkB,CAAA,EAAA;IAuiBlB,SAAA,QAAA,EAAA,MAAA;;;;;;;;;;;;;iCA5lBiB;mBACd;8BACW;mCACK;;;;;;;;;;;;;;;;;;;;iBAkDnB,kBAAA,QACP,uHAKN;iBAiiBa,4BAAA,CAAA,GAAgC"}
|