prisma-next 0.12.0-dev.39 → 0.12.0-dev.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +12 -12
- package/dist/{client-CcqChq9N.mjs → client-BNdG504y.mjs} +4 -4
- package/dist/{client-CcqChq9N.mjs.map → client-BNdG504y.mjs.map} +1 -1
- package/dist/{command-helpers-DK_5ItoJ.mjs → command-helpers-xvg9oq4T.mjs} +21 -3
- package/dist/command-helpers-xvg9oq4T.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +4 -4
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.mjs +5 -5
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.mjs +5 -6
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +55 -1
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +2 -2
- package/dist/commands/migration-graph.d.mts +13 -1
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +15 -16
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-log.d.mts +18 -1
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -4
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +12 -23
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/commands/ref.mjs +3 -3
- package/dist/commands/telemetry/index.mjs +1 -1
- package/dist/{contract-at-errors-DG3kjgoz.mjs → contract-at-errors-Wj3u4Xco.mjs} +2 -2
- package/dist/{contract-at-errors-DG3kjgoz.mjs.map → contract-at-errors-Wj3u4Xco.mjs.map} +1 -1
- package/dist/{contract-emit-C0Bs0VRj.mjs → contract-emit-COg18szA.mjs} +3 -3
- package/dist/{contract-emit-C0Bs0VRj.mjs.map → contract-emit-COg18szA.mjs.map} +1 -1
- package/dist/{contract-emit-BO0l6fnT.mjs → contract-emit-KyJNQK5-.mjs} +3 -3
- package/dist/{contract-emit-BO0l6fnT.mjs.map → contract-emit-KyJNQK5-.mjs.map} +1 -1
- package/dist/{contract-infer-DaHH7CGX.mjs → contract-infer-IEp0227u.mjs} +3 -3
- package/dist/{contract-infer-DaHH7CGX.mjs.map → contract-infer-IEp0227u.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-Dbr3-jHF.mjs → contract-space-aggregate-loader-BdRPfM3Q.mjs} +62 -4
- package/dist/{contract-space-aggregate-loader-Dbr3-jHF.mjs.map → contract-space-aggregate-loader-BdRPfM3Q.mjs.map} +1 -1
- package/dist/{db-verify-DppLAhYT.mjs → db-verify-C9k5KAyI.mjs} +4 -4
- package/dist/{db-verify-DppLAhYT.mjs.map → db-verify-C9k5KAyI.mjs.map} +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/{framework-components-CxOVKAAh.mjs → framework-components-Be4inY3I.mjs} +2 -2
- package/dist/{framework-components-CxOVKAAh.mjs.map → framework-components-Be4inY3I.mjs.map} +1 -1
- package/dist/{init-R272pxux.mjs → init-BIxw3l7t.mjs} +3 -3
- package/dist/{init-R272pxux.mjs.map → init-BIxw3l7t.mjs.map} +1 -1
- package/dist/{inspect-live-schema-CfOSPCmR.mjs → inspect-live-schema-DXUFGQDe.mjs} +3 -3
- package/dist/{inspect-live-schema-CfOSPCmR.mjs.map → inspect-live-schema-DXUFGQDe.mjs.map} +1 -1
- package/dist/{migration-check-Dc0cOhKH.mjs → migration-check-CUavU7U9.mjs} +236 -88
- package/dist/migration-check-CUavU7U9.mjs.map +1 -0
- package/dist/{migration-command-scaffold-CIxCqBXa.mjs → migration-command-scaffold-omgKpt3K.mjs} +3 -3
- package/dist/{migration-command-scaffold-CIxCqBXa.mjs.map → migration-command-scaffold-omgKpt3K.mjs.map} +1 -1
- package/dist/{migration-graph-space-render-dmLLWift.mjs → migration-graph-space-render-ByJ83gxp.mjs} +2 -2
- package/dist/{migration-graph-space-render-dmLLWift.mjs.map → migration-graph-space-render-ByJ83gxp.mjs.map} +1 -1
- package/dist/{migration-list-C5sXrl0U.mjs → migration-list-jK6QeczE.mjs} +4 -4
- package/dist/{migration-list-C5sXrl0U.mjs.map → migration-list-jK6QeczE.mjs.map} +1 -1
- package/dist/{migration-log-CwP41Cke.mjs → migration-log-CW0EjxSr.mjs} +39 -27
- package/dist/migration-log-CW0EjxSr.mjs.map +1 -0
- package/dist/migration-path-target-DqcrbOis.mjs +24 -0
- package/dist/migration-path-target-DqcrbOis.mjs.map +1 -0
- package/dist/{migration-plan-CeTjQOIG.mjs → migration-plan-NHdlUwPG.mjs} +5 -6
- package/dist/{migration-plan-CeTjQOIG.mjs.map → migration-plan-NHdlUwPG.mjs.map} +1 -1
- package/dist/{migration-status-GMRiiLFP.mjs → migration-status-GZ6XfbWs.mjs} +21 -14
- package/dist/migration-status-GZ6XfbWs.mjs.map +1 -0
- package/dist/{ref-advancement-V1o-9LVK.mjs → ref-advancement-CJY9zOv7.mjs} +1 -1
- package/dist/{ref-advancement-V1o-9LVK.mjs.map → ref-advancement-CJY9zOv7.mjs.map} +1 -1
- package/dist/{telemetry-S-NGi9U6.mjs → telemetry-DQP0BvKv.mjs} +2 -2
- package/dist/{telemetry-S-NGi9U6.mjs.map → telemetry-DQP0BvKv.mjs.map} +1 -1
- package/dist/{verify-BdI-BgYi.mjs → verify-tvHRBBVP.mjs} +2 -2
- package/dist/{verify-BdI-BgYi.mjs.map → verify-tvHRBBVP.mjs.map} +1 -1
- package/package.json +11 -11
- package/dist/command-helpers-DK_5ItoJ.mjs.map +0 -1
- package/dist/extension-pack-inputs-IDvjRCi3.mjs +0 -62
- package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +0 -1
- package/dist/migration-check-Dc0cOhKH.mjs.map +0 -1
- package/dist/migration-log-CwP41Cke.mjs.map +0 -1
- package/dist/migration-status-GMRiiLFP.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import { A as formatStyledHeader, G as errorInvalidSpaceId, K as errorLegendHumanOnly, _ as createTerminalUI, d as setCommandSeeAlso, g as parseGlobalFlagsOrExit, it as errorSpaceNotFound, l as setCommandDescriptions, s as resolveMigrationPaths, t as addGlobalOptions, u as setCommandExamples, y as handleResult } from "./command-helpers-
|
|
3
|
-
import { n as buildReadAggregate } from "./contract-space-aggregate-loader-
|
|
4
|
-
import { a as renderMigrationGraphLegend, c as renderMigrationListWithStyle, o as createAnsiMigrationListStyler } from "./migration-graph-space-render-
|
|
2
|
+
import { A as formatStyledHeader, G as errorInvalidSpaceId, K as errorLegendHumanOnly, _ as createTerminalUI, d as setCommandSeeAlso, g as parseGlobalFlagsOrExit, it as errorSpaceNotFound, l as setCommandDescriptions, s as resolveMigrationPaths, t as addGlobalOptions, u as setCommandExamples, y as handleResult } from "./command-helpers-xvg9oq4T.mjs";
|
|
3
|
+
import { n as buildReadAggregate } from "./contract-space-aggregate-loader-BdRPfM3Q.mjs";
|
|
4
|
+
import { a as renderMigrationGraphLegend, c as renderMigrationListWithStyle, o as createAnsiMigrationListStyler } from "./migration-graph-space-render-ByJ83gxp.mjs";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
7
7
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
@@ -225,4 +225,4 @@ function createMigrationListCommand() {
|
|
|
225
225
|
//#endregion
|
|
226
226
|
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 };
|
|
227
227
|
|
|
228
|
-
//# sourceMappingURL=migration-list-
|
|
228
|
+
//# sourceMappingURL=migration-list-jK6QeczE.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-list-C5sXrl0U.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 type {\n ContractSpaceAggregate,\n ContractSpaceMember,\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 RESERVED_SPACE_SUBDIR_NAMES,\n} from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliStructuredError,\n errorInvalidSpaceId,\n errorSpaceNotFound,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-tree-render';\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.dirName < b.dirName) return 1;\n if (a.dirName > b.dirName) return -1;\n return 0;\n}\n\n/**\n * Ref names decorating a space's destination contract hashes. The\n * tolerant `member.refs` deliberately omits the structural `head.json`;\n * for extension spaces the old enumerator surfaced it as a `head`\n * decoration on the tip migration, so fold `member.headRef` back in to\n * keep that output. The app space synthesises its head, so it carries\n * no on-disk `head` ref to restore.\n */\nexport function listRefsByContractHash(\n member: ContractSpaceMember,\n): ReadonlyMap<string, readonly string[]> {\n const byHash = new Map(refsByContractHash(member.refs));\n if (member.spaceId !== APP_SPACE_ID && member.headRef !== null) {\n const hash = member.headRef.hash;\n const bucket = byHash.get(hash) ?? [];\n if (!bucket.includes(HEAD_REF_NAME)) {\n byHash.set(hash, [...bucket, HEAD_REF_NAME].sort());\n }\n }\n return byHash;\n}\n\nasync function orderedOnDiskSpaceIds(projectMigrationsDir: string): Promise<readonly string[]> {\n const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);\n return candidateDirs\n .filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name))\n .filter(isValidSpaceId)\n .sort(compareSpaceIds);\n}\n\n/**\n * Project the loaded {@link ContractSpaceAggregate} into the render-ready\n * {@link MigrationSpaceListEntry} rows `migration list` displays.\n *\n * Space membership matches the on-disk contract-space directories (not the\n * aggregate's always-present synthesized app member when `migrations/app/`\n * is absent); package and ref data come from `aggregate.space(id)`.\n */\nexport async function migrationSpaceListEntriesFromAggregate(\n aggregate: ContractSpaceAggregate,\n projectMigrationsDir: string,\n): Promise<readonly MigrationSpaceListEntry[]> {\n const spaceIds = await orderedOnDiskSpaceIds(projectMigrationsDir);\n const spaces: MigrationSpaceListEntry[] = [];\n\n for (const spaceId of spaceIds) {\n const member = aggregate.space(spaceId);\n if (member === undefined) {\n continue;\n }\n const refsByHash = listRefsByContractHash(member);\n const migrations: MigrationListEntry[] = member.packages\n .map((pkg) => ({\n dirName: pkg.dirName,\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n operationCount: pkg.ops.length,\n createdAt: pkg.metadata.createdAt,\n refs: refsByHash.get(pkg.metadata.to) ?? [],\n providedInvariants: pkg.metadata.providedInvariants,\n }))\n .sort(compareDirNamesDescending);\n\n spaces.push({ spaceId, migrations });\n }\n\n return spaces;\n}\n\ninterface MigrationListOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n readonly ascii?: boolean;\n 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}\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 });\n}\n\n/**\n * Inputs for {@link runMigrationList} — the policy core of `migration list`\n * that tests exercise directly.\n *\n * The core does not call `loadConfig`, parse CLI flags, render a styled\n * header, or write to any stream. Enumeration is supplied by the caller\n * (the CLI shell builds it from {@link migrationSpaceListEntriesFromAggregate}).\n */\nexport interface RunMigrationListInputs {\n readonly spaces: readonly MigrationSpaceListEntry[];\n readonly spaceFilter?: string;\n}\n\nfunction computeSummary(spaces: readonly MigrationSpaceListEntry[]): string {\n const totalMigrations = spaces.reduce((count, space) => count + space.migrations.length, 0);\n if (spaces.length <= 1) {\n return `${totalMigrations} migration(s) on disk`;\n }\n return `${totalMigrations} migration(s) across ${spaces.length} contract space(s)`;\n}\n\n/**\n * Policy core of `migration list`: validates `--space`, narrows the\n * pre-enumerated spaces, and assembles a {@link MigrationListResult}.\n *\n * - `migrations/` missing or contains no valid space directories →\n * caller passes `spaces: []`; this synthesizes `[{ spaceId: APP_SPACE_ID, migrations: [] }]`.\n * - `--space <id>` on an existing-but-empty space → `{ spaceId, migrations: [] }` in the input.\n * - `--space <id>` on a non-existent (or reserved) space → `SPACE_NOT_FOUND`.\n */\nexport function runMigrationList(\n inputs: RunMigrationListInputs,\n): Result<MigrationListResult, CliStructuredError> {\n const { spaces, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\n }\n\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()));\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n const resultSpaces: readonly MigrationSpaceListEntry[] =\n scopedSpaces.length === 0 ? [{ spaceId: APP_SPACE_ID, migrations: [] }] : scopedSpaces;\n\n return ok({\n ok: true,\n spaces: resultSpaces,\n summary: computeSummary(resultSpaces),\n });\n}\n\n/**\n * CLI shell: loads config, resolves paths, prints the styled header on\n * stderr (interactive mode only), and delegates to {@link runMigrationList}.\n * Kept intentionally thin so the unit-testable surface lives in the core.\n */\nexport async function executeMigrationListCommand(\n options: MigrationListOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<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 }),\n );\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"migration-list-jK6QeczE.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 type {\n ContractSpaceAggregate,\n ContractSpaceMember,\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 RESERVED_SPACE_SUBDIR_NAMES,\n} from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliStructuredError,\n errorInvalidSpaceId,\n errorSpaceNotFound,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { buildReadAggregate } from '../utils/contract-space-aggregate-loader';\nimport { renderMigrationGraphLegend } from '../utils/formatters/migration-graph-tree-render';\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.dirName < b.dirName) return 1;\n if (a.dirName > b.dirName) return -1;\n return 0;\n}\n\n/**\n * Ref names decorating a space's destination contract hashes. The\n * tolerant `member.refs` deliberately omits the structural `head.json`;\n * for extension spaces the old enumerator surfaced it as a `head`\n * decoration on the tip migration, so fold `member.headRef` back in to\n * keep that output. The app space synthesises its head, so it carries\n * no on-disk `head` ref to restore.\n */\nexport function listRefsByContractHash(\n member: ContractSpaceMember,\n): ReadonlyMap<string, readonly string[]> {\n const byHash = new Map(refsByContractHash(member.refs));\n if (member.spaceId !== APP_SPACE_ID && member.headRef !== null) {\n const hash = member.headRef.hash;\n const bucket = byHash.get(hash) ?? [];\n if (!bucket.includes(HEAD_REF_NAME)) {\n byHash.set(hash, [...bucket, HEAD_REF_NAME].sort());\n }\n }\n return byHash;\n}\n\nasync function orderedOnDiskSpaceIds(projectMigrationsDir: string): Promise<readonly string[]> {\n const candidateDirs = await listContractSpaceDirectories(projectMigrationsDir);\n return candidateDirs\n .filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name))\n .filter(isValidSpaceId)\n .sort(compareSpaceIds);\n}\n\n/**\n * Project the loaded {@link ContractSpaceAggregate} into the render-ready\n * {@link MigrationSpaceListEntry} rows `migration list` displays.\n *\n * Space membership matches the on-disk contract-space directories (not the\n * aggregate's always-present synthesized app member when `migrations/app/`\n * is absent); package and ref data come from `aggregate.space(id)`.\n */\nexport async function migrationSpaceListEntriesFromAggregate(\n aggregate: ContractSpaceAggregate,\n projectMigrationsDir: string,\n): Promise<readonly MigrationSpaceListEntry[]> {\n const spaceIds = await orderedOnDiskSpaceIds(projectMigrationsDir);\n const spaces: MigrationSpaceListEntry[] = [];\n\n for (const spaceId of spaceIds) {\n const member = aggregate.space(spaceId);\n if (member === undefined) {\n continue;\n }\n const refsByHash = listRefsByContractHash(member);\n const migrations: MigrationListEntry[] = member.packages\n .map((pkg) => ({\n dirName: pkg.dirName,\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n operationCount: pkg.ops.length,\n createdAt: pkg.metadata.createdAt,\n refs: refsByHash.get(pkg.metadata.to) ?? [],\n providedInvariants: pkg.metadata.providedInvariants,\n }))\n .sort(compareDirNamesDescending);\n\n spaces.push({ spaceId, migrations });\n }\n\n return spaces;\n}\n\ninterface MigrationListOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n readonly ascii?: boolean;\n 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}\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 });\n}\n\n/**\n * Inputs for {@link runMigrationList} — the policy core of `migration list`\n * that tests exercise directly.\n *\n * The core does not call `loadConfig`, parse CLI flags, render a styled\n * header, or write to any stream. Enumeration is supplied by the caller\n * (the CLI shell builds it from {@link migrationSpaceListEntriesFromAggregate}).\n */\nexport interface RunMigrationListInputs {\n readonly spaces: readonly MigrationSpaceListEntry[];\n readonly spaceFilter?: string;\n}\n\nfunction computeSummary(spaces: readonly MigrationSpaceListEntry[]): string {\n const totalMigrations = spaces.reduce((count, space) => count + space.migrations.length, 0);\n if (spaces.length <= 1) {\n return `${totalMigrations} migration(s) on disk`;\n }\n return `${totalMigrations} migration(s) across ${spaces.length} contract space(s)`;\n}\n\n/**\n * Policy core of `migration list`: validates `--space`, narrows the\n * pre-enumerated spaces, and assembles a {@link MigrationListResult}.\n *\n * - `migrations/` missing or contains no valid space directories →\n * caller passes `spaces: []`; this synthesizes `[{ spaceId: APP_SPACE_ID, migrations: [] }]`.\n * - `--space <id>` on an existing-but-empty space → `{ spaceId, migrations: [] }` in the input.\n * - `--space <id>` on a non-existent (or reserved) space → `SPACE_NOT_FOUND`.\n */\nexport function runMigrationList(\n inputs: RunMigrationListInputs,\n): Result<MigrationListResult, CliStructuredError> {\n const { spaces, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\n }\n\n if (spaceFilter !== undefined && !spaces.some((s) => s.spaceId === spaceFilter)) {\n return notOk(errorSpaceNotFound(spaceFilter, spaces.map((s) => s.spaceId).sort()));\n }\n\n const scopedSpaces =\n spaceFilter !== undefined ? spaces.filter((s) => s.spaceId === spaceFilter) : spaces;\n\n const resultSpaces: readonly MigrationSpaceListEntry[] =\n scopedSpaces.length === 0 ? [{ spaceId: APP_SPACE_ID, migrations: [] }] : scopedSpaces;\n\n return ok({\n ok: true,\n spaces: resultSpaces,\n summary: computeSummary(resultSpaces),\n });\n}\n\n/**\n * CLI shell: loads config, resolves paths, prints the styled header on\n * stderr (interactive mode only), and delegates to {@link runMigrationList}.\n * Kept intentionally thin so the unit-testable surface lives in the core.\n */\nexport async function executeMigrationListCommand(\n options: MigrationListOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<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 }),\n );\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import { A as formatStyledHeader,
|
|
3
|
-
import { t as createControlClient } from "./client-
|
|
4
|
-
import { l as abbreviateContractHash, o as createAnsiMigrationListStyler, s as IDENTITY_MIGRATION_LIST_STYLER } from "./migration-graph-space-render-
|
|
2
|
+
import { A as formatStyledHeader, F as CliStructuredError, _ as createTerminalUI, ct as mapMigrationToolsError, d as setCommandSeeAlso, f as targetSupportsMigrations, g as parseGlobalFlagsOrExit, i as maskConnectionUrl, l as setCommandDescriptions, s as resolveMigrationPaths, st as errorUnexpected, t as addGlobalOptions, u as setCommandExamples, ut as requireLiveDatabase, y as handleResult } from "./command-helpers-xvg9oq4T.mjs";
|
|
3
|
+
import { t as createControlClient } from "./client-BNdG504y.mjs";
|
|
4
|
+
import { d as migrationListForwardArrow, l as abbreviateContractHash, o as createAnsiMigrationListStyler, s as IDENTITY_MIGRATION_LIST_STYLER, u as migrationListEmptySource } from "./migration-graph-space-render-ByJ83gxp.mjs";
|
|
5
5
|
import { Command } from "commander";
|
|
6
|
+
import { ifDefined } from "@prisma-next/utils/defined";
|
|
6
7
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
8
|
import stringWidth from "string-width";
|
|
8
9
|
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
@@ -14,6 +15,7 @@ const HEADING_CHANGE = "Change";
|
|
|
14
15
|
const HEADING_OPS = "Ops";
|
|
15
16
|
const COLUMN_SEPARATOR = " ";
|
|
16
17
|
const DIVIDER_CHAR = "─";
|
|
18
|
+
const ASCII_DIVIDER_CHAR = "-";
|
|
17
19
|
function sortLedgerEntries(entries) {
|
|
18
20
|
return [...entries].sort((left, right) => {
|
|
19
21
|
const timeDiff = left.appliedAt.getTime() - right.appliedAt.getTime();
|
|
@@ -36,15 +38,15 @@ function formatLedgerAppliedAt(date, mode) {
|
|
|
36
38
|
const offsetMins = pad2(absoluteOffset % 60);
|
|
37
39
|
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())} ${sign}${offsetHours}:${offsetMins}`;
|
|
38
40
|
}
|
|
39
|
-
function formatHashEndpoint(hash) {
|
|
40
|
-
if (hash === null) return
|
|
41
|
+
function formatHashEndpoint(hash, glyphMode = "unicode") {
|
|
42
|
+
if (hash === null) return migrationListEmptySource(glyphMode);
|
|
41
43
|
return abbreviateContractHash(hash);
|
|
42
44
|
}
|
|
43
|
-
function formatHashTransition(from, to) {
|
|
44
|
-
return `${formatHashEndpoint(from)}
|
|
45
|
+
function formatHashTransition(from, to, glyphMode = "unicode") {
|
|
46
|
+
return `${formatHashEndpoint(from, glyphMode)} ${migrationListForwardArrow(glyphMode)} ${abbreviateContractHash(to)}`;
|
|
45
47
|
}
|
|
46
|
-
function styleHashTransition(from, to, styler) {
|
|
47
|
-
return `${from === null ? styler.glyph(
|
|
48
|
+
function styleHashTransition(from, to, styler, glyphMode = "unicode") {
|
|
49
|
+
return `${from === null ? styler.glyph(migrationListEmptySource(glyphMode)) : styler.sourceHash(abbreviateContractHash(from))} ${styler.glyph(migrationListForwardArrow(glyphMode))} ${styler.destHash(abbreviateContractHash(to))}`;
|
|
48
50
|
}
|
|
49
51
|
function padVisible(text, targetWidth) {
|
|
50
52
|
const padding = Math.max(0, targetWidth - stringWidth(text));
|
|
@@ -53,8 +55,8 @@ function padVisible(text, targetWidth) {
|
|
|
53
55
|
function columnWidth(values) {
|
|
54
56
|
return values.reduce((max, value) => Math.max(max, stringWidth(value)), 0);
|
|
55
57
|
}
|
|
56
|
-
function padDividerCell(valueWidth) {
|
|
57
|
-
return
|
|
58
|
+
function padDividerCell(valueWidth, dividerChar) {
|
|
59
|
+
return dividerChar.repeat(valueWidth + 2);
|
|
58
60
|
}
|
|
59
61
|
function padTextCell(value, valueWidth) {
|
|
60
62
|
return ` ${padVisible(value, valueWidth)} `;
|
|
@@ -67,13 +69,15 @@ function renderMigrationLogTable(entries, options = {}) {
|
|
|
67
69
|
const sorted = sortLedgerEntries(entries);
|
|
68
70
|
if (sorted.length === 0) return "";
|
|
69
71
|
const styler = options.styler ?? IDENTITY_MIGRATION_LIST_STYLER;
|
|
72
|
+
const glyphMode = options.glyphMode ?? "unicode";
|
|
73
|
+
const dividerChar = glyphMode === "ascii" ? ASCII_DIVIDER_CHAR : DIVIDER_CHAR;
|
|
70
74
|
const showSpace = new Set(sorted.map((entry) => entry.space)).size > 1;
|
|
71
75
|
const timestampMode = options.utc ? "utc" : "local";
|
|
72
76
|
const rows = sorted.map((entry) => ({
|
|
73
77
|
appliedAt: formatLedgerAppliedAt(entry.appliedAt, timestampMode),
|
|
74
78
|
space: entry.space,
|
|
75
79
|
migrationName: entry.migrationName,
|
|
76
|
-
transition: formatHashTransition(entry.from, entry.to),
|
|
80
|
+
transition: formatHashTransition(entry.from, entry.to, glyphMode),
|
|
77
81
|
ops: `${entry.operationCount} ops`,
|
|
78
82
|
from: entry.from,
|
|
79
83
|
to: entry.to
|
|
@@ -87,16 +91,16 @@ function renderMigrationLogTable(entries, options = {}) {
|
|
|
87
91
|
if (showSpace) headingParts.push(padTextCell(HEADING_SPACE, spaceWidth));
|
|
88
92
|
headingParts.push(padTextCell(HEADING_MIGRATION, nameWidth), padTextCell(HEADING_CHANGE, transitionWidth), padOpsCell(HEADING_OPS, opsWidth));
|
|
89
93
|
const heading = headingParts.join(COLUMN_SEPARATOR);
|
|
90
|
-
const dividerParts = [padDividerCell(appliedAtWidth)];
|
|
91
|
-
if (showSpace) dividerParts.push(padDividerCell(spaceWidth));
|
|
92
|
-
dividerParts.push(padDividerCell(nameWidth), padDividerCell(transitionWidth), padDividerCell(opsWidth));
|
|
94
|
+
const dividerParts = [padDividerCell(appliedAtWidth, dividerChar)];
|
|
95
|
+
if (showSpace) dividerParts.push(padDividerCell(spaceWidth, dividerChar));
|
|
96
|
+
dividerParts.push(padDividerCell(nameWidth, dividerChar), padDividerCell(transitionWidth, dividerChar), padDividerCell(opsWidth, dividerChar));
|
|
93
97
|
return [
|
|
94
98
|
heading,
|
|
95
99
|
dividerParts.map((cell) => styler.summary(cell)).join(COLUMN_SEPARATOR),
|
|
96
100
|
...rows.map((row) => {
|
|
97
101
|
const parts = [padTextCell(row.appliedAt, appliedAtWidth)];
|
|
98
102
|
if (showSpace) parts.push(padTextCell(row.space, spaceWidth));
|
|
99
|
-
parts.push(padTextCell(styler.dirName(row.migrationName), nameWidth), padTextCell(styleHashTransition(row.from, row.to, styler), transitionWidth), padOpsCell(row.ops, opsWidth));
|
|
103
|
+
parts.push(padTextCell(styler.dirName(row.migrationName), nameWidth), padTextCell(styleHashTransition(row.from, row.to, styler, glyphMode), transitionWidth), padOpsCell(row.ops, opsWidth));
|
|
100
104
|
return parts.join(COLUMN_SEPARATOR);
|
|
101
105
|
})
|
|
102
106
|
].join("\n");
|
|
@@ -114,11 +118,13 @@ async function executeMigrationLogCommand(options, flags, ui) {
|
|
|
114
118
|
const config = await loadConfig(options.config);
|
|
115
119
|
const { configPath } = resolveMigrationPaths(options.config, config);
|
|
116
120
|
const dbConnection = options.db ?? config.db?.connection;
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
const missingDb = requireLiveDatabase({
|
|
122
|
+
dbConnection,
|
|
123
|
+
hasDriver: !!config.driver,
|
|
124
|
+
why: `migration log needs a database connection and driver to read the ledger (set db.connection in ${configPath}, or pass --db <url>)`,
|
|
119
125
|
commandName: "migration log"
|
|
120
|
-
})
|
|
121
|
-
if (
|
|
126
|
+
});
|
|
127
|
+
if (missingDb) return notOk(missingDb);
|
|
122
128
|
if (!targetSupportsMigrations(config.target)) return notOk(errorUnexpected("Target does not support migrations"));
|
|
123
129
|
if (!flags.json && !flags.quiet) {
|
|
124
130
|
const header = formatStyledHeader({
|
|
@@ -139,7 +145,7 @@ async function executeMigrationLogCommand(options, flags, ui) {
|
|
|
139
145
|
family: config.family,
|
|
140
146
|
target: config.target,
|
|
141
147
|
adapter: config.adapter,
|
|
142
|
-
driver
|
|
148
|
+
...ifDefined("driver", config.driver),
|
|
143
149
|
extensionPacks: config.extensionPacks ?? []
|
|
144
150
|
});
|
|
145
151
|
try {
|
|
@@ -155,7 +161,7 @@ async function executeMigrationLogCommand(options, flags, ui) {
|
|
|
155
161
|
}
|
|
156
162
|
function createMigrationLogCommand() {
|
|
157
163
|
const command = new Command("log");
|
|
158
|
-
setCommandDescriptions(command, "Show executed migration history", "Reads the database ledger and displays every applied migration edge\nin chronological order, including rollbacks and re-applies.");
|
|
164
|
+
setCommandDescriptions(command, "Show executed migration history", "Reads the database ledger and displays every applied migration edge\nin chronological order, including rollbacks and re-applies, merged\nacross all contract spaces. Requires a database connection.");
|
|
159
165
|
setCommandExamples(command, [
|
|
160
166
|
"prisma-next migration log --db $DATABASE_URL",
|
|
161
167
|
"prisma-next migration log --utc --db $DATABASE_URL",
|
|
@@ -179,17 +185,23 @@ function createMigrationLogCommand() {
|
|
|
179
185
|
oneLiner: "Display migration package contents"
|
|
180
186
|
}
|
|
181
187
|
]);
|
|
182
|
-
addGlobalOptions(command).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--utc", "Render human timestamps in UTC instead of local time").action(async (options) => {
|
|
188
|
+
addGlobalOptions(command).option("--db <url>", "Database connection string").option("--config <path>", "Path to prisma-next.config.ts").option("--utc", "Render human timestamps in UTC instead of local time").option("--ascii", "Use ASCII glyphs (pipe-friendly)").action(async (options) => {
|
|
183
189
|
const flags = parseGlobalFlagsOrExit(options);
|
|
184
190
|
const ui = createTerminalUI(flags);
|
|
185
191
|
const exitCode = handleResult(await executeMigrationLogCommand(options, flags, ui), flags, ui, (entries) => {
|
|
186
|
-
if (flags.json)
|
|
187
|
-
|
|
192
|
+
if (flags.json) {
|
|
193
|
+
const result = {
|
|
194
|
+
ok: true,
|
|
195
|
+
entries: serializeLedgerEntriesForJson(entries)
|
|
196
|
+
};
|
|
197
|
+
ui.output(JSON.stringify(result, null, 2));
|
|
198
|
+
} else if (!flags.quiet) if (entries.length === 0) ui.output(MIGRATION_LOG_EMPTY_MESSAGE);
|
|
188
199
|
else {
|
|
189
200
|
const styler = createAnsiMigrationListStyler({ useColor: ui.useColor });
|
|
190
201
|
ui.output(renderMigrationLogTable(entries, {
|
|
191
202
|
utc: options.utc === true,
|
|
192
|
-
styler
|
|
203
|
+
styler,
|
|
204
|
+
glyphMode: ui.resolveGlyphMode(options.ascii === true)
|
|
193
205
|
}));
|
|
194
206
|
}
|
|
195
207
|
});
|
|
@@ -200,4 +212,4 @@ function createMigrationLogCommand() {
|
|
|
200
212
|
//#endregion
|
|
201
213
|
export { executeMigrationLogCommand as n, createMigrationLogCommand as t };
|
|
202
214
|
|
|
203
|
-
//# sourceMappingURL=migration-log-
|
|
215
|
+
//# sourceMappingURL=migration-log-CW0EjxSr.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-log-CW0EjxSr.mjs","names":[],"sources":["../src/utils/formatters/migration-log-table.ts","../src/commands/migration-log.ts"],"sourcesContent":["import type { LedgerEntryRecord } from '@prisma-next/contract/types';\nimport stringWidth from 'string-width';\nimport type { GlyphMode } from '../glyph-mode';\nimport {\n abbreviateContractHash,\n migrationListEmptySource,\n migrationListForwardArrow,\n} from './migration-list-data-column';\nimport { IDENTITY_MIGRATION_LIST_STYLER, type MigrationListStyler } from './migration-list-render';\n\nexport type LedgerTimestampMode = 'local' | 'utc' | 'iso';\n\nexport interface RenderMigrationLogTableOptions {\n readonly utc?: boolean;\n readonly styler?: MigrationListStyler;\n readonly glyphMode?: GlyphMode;\n}\n\nexport interface SerializedLedgerEntryRecord {\n readonly space: string;\n readonly migrationName: string;\n readonly migrationHash: string;\n readonly from: string | null;\n readonly to: string;\n readonly appliedAt: string;\n readonly operationCount: number;\n}\n\nconst HEADING_APPLIED_AT = 'Applied at';\nconst HEADING_SPACE = 'Space';\nconst HEADING_MIGRATION = 'Migration';\nconst HEADING_CHANGE = 'Change';\nconst HEADING_OPS = 'Ops';\nconst COLUMN_SEPARATOR = ' ';\nconst DIVIDER_CHAR = '─';\nconst ASCII_DIVIDER_CHAR = '-';\n\nexport function sortLedgerEntries(entries: readonly LedgerEntryRecord[]): LedgerEntryRecord[] {\n return [...entries].sort((left, right) => {\n const timeDiff = left.appliedAt.getTime() - right.appliedAt.getTime();\n if (timeDiff !== 0) {\n return timeDiff;\n }\n const spaceDiff = left.space.localeCompare(right.space);\n if (spaceDiff !== 0) {\n return spaceDiff;\n }\n return left.migrationName.localeCompare(right.migrationName);\n });\n}\n\nfunction pad2(value: number): string {\n return String(value).padStart(2, '0');\n}\n\nexport function formatLedgerAppliedAt(date: Date, mode: LedgerTimestampMode): string {\n if (mode === 'iso') {\n return date.toISOString();\n }\n if (mode === 'utc') {\n return `${date.getUTCFullYear()}-${pad2(date.getUTCMonth() + 1)}-${pad2(date.getUTCDate())} ${pad2(date.getUTCHours())}:${pad2(date.getUTCMinutes())}:${pad2(date.getUTCSeconds())}Z`;\n }\n const offsetMinutes = -date.getTimezoneOffset();\n const sign = offsetMinutes >= 0 ? '+' : '-';\n const absoluteOffset = Math.abs(offsetMinutes);\n const offsetHours = pad2(Math.floor(absoluteOffset / 60));\n const offsetMins = pad2(absoluteOffset % 60);\n return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())} ${sign}${offsetHours}:${offsetMins}`;\n}\n\nexport function formatHashEndpoint(hash: string | null, glyphMode: GlyphMode = 'unicode'): string {\n if (hash === null) {\n return migrationListEmptySource(glyphMode);\n }\n return abbreviateContractHash(hash);\n}\n\nexport function formatHashTransition(\n from: string | null,\n to: string,\n glyphMode: GlyphMode = 'unicode',\n): string {\n return `${formatHashEndpoint(from, glyphMode)} ${migrationListForwardArrow(glyphMode)} ${abbreviateContractHash(to)}`;\n}\n\nexport function styleHashTransition(\n from: string | null,\n to: string,\n styler: MigrationListStyler,\n glyphMode: GlyphMode = 'unicode',\n): string {\n const fromPart =\n from === null\n ? styler.glyph(migrationListEmptySource(glyphMode))\n : styler.sourceHash(abbreviateContractHash(from));\n const arrow = styler.glyph(migrationListForwardArrow(glyphMode));\n const dest = styler.destHash(abbreviateContractHash(to));\n return `${fromPart} ${arrow} ${dest}`;\n}\n\nfunction padVisible(text: string, targetWidth: number): string {\n const padding = Math.max(0, targetWidth - stringWidth(text));\n return text + ' '.repeat(padding);\n}\n\nfunction columnWidth(values: readonly string[]): number {\n return values.reduce((max, value) => Math.max(max, stringWidth(value)), 0);\n}\n\nfunction padDividerCell(valueWidth: number, dividerChar: string): string {\n return dividerChar.repeat(valueWidth + 2);\n}\n\nfunction padTextCell(value: string, valueWidth: number): string {\n return ` ${padVisible(value, valueWidth)} `;\n}\n\nfunction padOpsCell(value: string, valueWidth: number): string {\n const padding = Math.max(0, valueWidth - stringWidth(value));\n return ` ${' '.repeat(padding)}${value} `;\n}\n\nexport function renderMigrationLogTable(\n entries: readonly LedgerEntryRecord[],\n options: RenderMigrationLogTableOptions = {},\n): string {\n const sorted = sortLedgerEntries(entries);\n if (sorted.length === 0) {\n return '';\n }\n\n const styler = options.styler ?? IDENTITY_MIGRATION_LIST_STYLER;\n const glyphMode = options.glyphMode ?? 'unicode';\n const dividerChar = glyphMode === 'ascii' ? ASCII_DIVIDER_CHAR : DIVIDER_CHAR;\n const showSpace = new Set(sorted.map((entry) => entry.space)).size > 1;\n const timestampMode: LedgerTimestampMode = options.utc ? 'utc' : 'local';\n const rows = sorted.map((entry) => ({\n appliedAt: formatLedgerAppliedAt(entry.appliedAt, timestampMode),\n space: entry.space,\n migrationName: entry.migrationName,\n transition: formatHashTransition(entry.from, entry.to, glyphMode),\n ops: `${entry.operationCount} ops`,\n from: entry.from,\n to: entry.to,\n }));\n\n const appliedAtWidth = columnWidth([HEADING_APPLIED_AT, ...rows.map((row) => row.appliedAt)]);\n const spaceWidth = showSpace ? columnWidth([HEADING_SPACE, ...rows.map((row) => row.space)]) : 0;\n const nameWidth = columnWidth([HEADING_MIGRATION, ...rows.map((row) => row.migrationName)]);\n const transitionWidth = columnWidth([HEADING_CHANGE, ...rows.map((row) => row.transition)]);\n const opsWidth = columnWidth([HEADING_OPS, ...rows.map((row) => row.ops)]);\n\n const headingParts = [padTextCell(HEADING_APPLIED_AT, appliedAtWidth)];\n if (showSpace) {\n headingParts.push(padTextCell(HEADING_SPACE, spaceWidth));\n }\n headingParts.push(\n padTextCell(HEADING_MIGRATION, nameWidth),\n padTextCell(HEADING_CHANGE, transitionWidth),\n padOpsCell(HEADING_OPS, opsWidth),\n );\n const heading = headingParts.join(COLUMN_SEPARATOR);\n\n const dividerParts = [padDividerCell(appliedAtWidth, dividerChar)];\n if (showSpace) {\n dividerParts.push(padDividerCell(spaceWidth, dividerChar));\n }\n dividerParts.push(\n padDividerCell(nameWidth, dividerChar),\n padDividerCell(transitionWidth, dividerChar),\n padDividerCell(opsWidth, dividerChar),\n );\n const divider = dividerParts.map((cell) => styler.summary(cell)).join(COLUMN_SEPARATOR);\n\n const dataRows = rows.map((row) => {\n const parts = [padTextCell(row.appliedAt, appliedAtWidth)];\n if (showSpace) {\n parts.push(padTextCell(row.space, spaceWidth));\n }\n parts.push(\n padTextCell(styler.dirName(row.migrationName), nameWidth),\n padTextCell(styleHashTransition(row.from, row.to, styler, glyphMode), transitionWidth),\n padOpsCell(row.ops, opsWidth),\n );\n return parts.join(COLUMN_SEPARATOR);\n });\n\n return [heading, divider, ...dataRows].join('\\n');\n}\n\nexport function serializeLedgerEntriesForJson(\n entries: readonly LedgerEntryRecord[],\n): SerializedLedgerEntryRecord[] {\n return sortLedgerEntries(entries).map(({ appliedAt, ...rest }) => ({\n ...rest,\n appliedAt: formatLedgerAppliedAt(appliedAt, 'iso'),\n }));\n}\n\nexport const MIGRATION_LOG_EMPTY_MESSAGE = 'No migrations have been applied to this database.';\n","import type { LedgerEntryRecord } from '@prisma-next/contract/types';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorUnexpected,\n mapMigrationToolsError,\n requireLiveDatabase,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n maskConnectionUrl,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n targetSupportsMigrations,\n} from '../utils/command-helpers';\nimport { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';\nimport {\n MIGRATION_LOG_EMPTY_MESSAGE,\n renderMigrationLogTable,\n type SerializedLedgerEntryRecord,\n serializeLedgerEntriesForJson,\n} from '../utils/formatters/migration-log-table';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationLogOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n readonly utc?: boolean;\n readonly ascii?: boolean;\n}\n\nexport interface MigrationLogResult {\n readonly ok: true;\n readonly entries: readonly SerializedLedgerEntryRecord[];\n}\n\nexport async function executeMigrationLogCommand(\n options: MigrationLogOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<readonly LedgerEntryRecord[], CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath } = resolveMigrationPaths(options.config, config);\n\n const dbConnection = options.db ?? config.db?.connection;\n const missingDb = requireLiveDatabase({\n dbConnection,\n hasDriver: !!config.driver,\n why: `migration log needs a database connection and driver to read the ledger (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: 'migration log',\n });\n if (missingDb) {\n return notOk(missingDb);\n }\n if (!targetSupportsMigrations(config.target)) {\n return notOk(errorUnexpected('Target does not support migrations'));\n }\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration log',\n description: 'Show executed migration history from the database ledger',\n details: [\n { label: 'config', value: configPath },\n ...(typeof dbConnection === 'string'\n ? [{ label: 'database', value: maskConnectionUrl(dbConnection) }]\n : []),\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n ...ifDefined('driver', config.driver),\n extensionPacks: config.extensionPacks ?? [],\n });\n\n try {\n await client.connect(dbConnection);\n const ledger = await client.readLedger();\n return ok(ledger);\n } catch (error) {\n if (CliStructuredError.is(error)) return notOk(error);\n if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration log: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n\nexport function createMigrationLogCommand(): Command {\n const command = new Command('log');\n setCommandDescriptions(\n command,\n 'Show executed migration history',\n 'Reads the database ledger and displays every applied migration edge\\n' +\n 'in chronological order, including rollbacks and re-applies, merged\\n' +\n 'across all contract spaces. Requires a database connection.',\n );\n setCommandExamples(command, [\n 'prisma-next migration log --db $DATABASE_URL',\n 'prisma-next migration log --utc --db $DATABASE_URL',\n 'prisma-next migration log --json --db $DATABASE_URL',\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 addGlobalOptions(command)\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--utc', 'Render human timestamps in UTC instead of local time')\n .option('--ascii', 'Use ASCII glyphs (pipe-friendly)')\n .action(async (options: MigrationLogOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const result = await executeMigrationLogCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (entries) => {\n if (flags.json) {\n const result: MigrationLogResult = {\n ok: true,\n entries: serializeLedgerEntriesForJson(entries),\n };\n ui.output(JSON.stringify(result, null, 2));\n } else if (!flags.quiet) {\n if (entries.length === 0) {\n ui.output(MIGRATION_LOG_EMPTY_MESSAGE);\n } else {\n const styler = createAnsiMigrationListStyler({ useColor: ui.useColor });\n ui.output(\n renderMigrationLogTable(entries, {\n utc: options.utc === true,\n styler,\n glyphMode: ui.resolveGlyphMode(options.ascii === true),\n }),\n );\n }\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { nt as errorRuntime } from "./command-helpers-xvg9oq4T.mjs";
|
|
2
|
+
import { notOk, ok } from "@prisma-next/utils/result";
|
|
3
|
+
import { isAbsolute, relative, resolve } from "pathe";
|
|
4
|
+
//#region src/utils/migration-path-target.ts
|
|
5
|
+
function looksLikePath(target) {
|
|
6
|
+
return target.includes("/") || target.includes("\\");
|
|
7
|
+
}
|
|
8
|
+
function resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative) {
|
|
9
|
+
const targetPath = resolve(target);
|
|
10
|
+
const relativeToApp = relative(appMigrationsDir, targetPath);
|
|
11
|
+
if (relativeToApp === "" || relativeToApp === "." || relativeToApp.startsWith("..") || isAbsolute(relativeToApp)) return notOk(errorRuntime("Target must point to an app-space migration", {
|
|
12
|
+
why: `Expected a path under ${appMigrationsRelative}, got ${target}`,
|
|
13
|
+
fix: "Pass an app-space migration directory or use a hash prefix."
|
|
14
|
+
}));
|
|
15
|
+
return ok(targetPath);
|
|
16
|
+
}
|
|
17
|
+
function findPackageByDirPath(packages, resolvedDirPath) {
|
|
18
|
+
const normalized = resolve(resolvedDirPath);
|
|
19
|
+
return packages.find((p) => resolve(p.dirPath) === normalized);
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { looksLikePath as n, resolveAppTargetPath as r, findPackageByDirPath as t };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=migration-path-target-DqcrbOis.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-path-target-DqcrbOis.mjs","names":[],"sources":["../src/utils/migration-path-target.ts"],"sourcesContent":["import type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { isAbsolute, relative, resolve } from 'pathe';\nimport { type CliStructuredError, errorRuntime } from './cli-errors';\n\nexport function looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\nexport function resolveAppTargetPath(\n target: string,\n appMigrationsDir: string,\n appMigrationsRelative: string,\n): Result<string, CliStructuredError> {\n const targetPath = resolve(target);\n const relativeToApp = relative(appMigrationsDir, targetPath);\n const isOutsideAppDir =\n relativeToApp === '' ||\n relativeToApp === '.' ||\n relativeToApp.startsWith('..') ||\n isAbsolute(relativeToApp);\n if (isOutsideAppDir) {\n return notOk(\n errorRuntime('Target must point to an app-space migration', {\n why: `Expected a path under ${appMigrationsRelative}, got ${target}`,\n fix: 'Pass an app-space migration directory or use a hash prefix.',\n }),\n );\n }\n return ok(targetPath);\n}\n\nexport function findPackageByDirPath(\n packages: readonly OnDiskMigrationPackage[],\n resolvedDirPath: string,\n): OnDiskMigrationPackage | undefined {\n const normalized = resolve(resolvedDirPath);\n return packages.find((p) => resolve(p.dirPath) === normalized);\n}\n"],"mappings":";;;;AAKA,SAAgB,cAAc,QAAyB;CACrD,OAAO,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,IAAI;AACrD;AAEA,SAAgB,qBACd,QACA,kBACA,uBACoC;CACpC,MAAM,aAAa,QAAQ,MAAM;CACjC,MAAM,gBAAgB,SAAS,kBAAkB,UAAU;CAM3D,IAJE,kBAAkB,MAClB,kBAAkB,OAClB,cAAc,WAAW,IAAI,KAC7B,WAAW,aAAa,GAExB,OAAO,MACL,aAAa,+CAA+C;EAC1D,KAAK,yBAAyB,sBAAsB,QAAQ;EAC5D,KAAK;CACP,CAAC,CACH;CAEF,OAAO,GAAG,UAAU;AACtB;AAEA,SAAgB,qBACd,UACA,iBACoC;CACpC,MAAM,aAAa,QAAQ,eAAe;CAC1C,OAAO,SAAS,MAAM,MAAM,QAAQ,EAAE,OAAO,MAAM,UAAU;AAC/D"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import { A as formatStyledHeader, F as CliStructuredError, U as errorFileNotFound, Y as errorMigrationPlanningFailed, Z as errorPlanForgotTheFlag, _ as createTerminalUI, at as errorTargetMigrationNotSupported, ct as mapMigrationToolsError, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, lt as mapRefResolutionError, o as resolveContractPath, r as getTargetMigrations, rt as errorSnapshotMissing, s as resolveMigrationPaths, st as errorUnexpected, t as addGlobalOptions, u as setCommandExamples, y as handleResult, z as errorContractValidationFailed } from "./command-helpers-
|
|
3
|
-
import { t as assertFrameworkComponentsCompatible } from "./framework-components-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { t as mapContractAtError } from "./contract-at-errors-DG3kjgoz.mjs";
|
|
2
|
+
import { A as formatStyledHeader, F as CliStructuredError, U as errorFileNotFound, Y as errorMigrationPlanningFailed, Z as errorPlanForgotTheFlag, _ as createTerminalUI, at as errorTargetMigrationNotSupported, ct as mapMigrationToolsError, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, lt as mapRefResolutionError, o as resolveContractPath, r as getTargetMigrations, rt as errorSnapshotMissing, s as resolveMigrationPaths, st as errorUnexpected, t as addGlobalOptions, u as setCommandExamples, y as handleResult, z as errorContractValidationFailed } from "./command-helpers-xvg9oq4T.mjs";
|
|
3
|
+
import { t as assertFrameworkComponentsCompatible } from "./framework-components-Be4inY3I.mjs";
|
|
4
|
+
import { c as toExtensionInputs, i as loadContractSpaceAggregateForCli, t as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-BdRPfM3Q.mjs";
|
|
5
|
+
import { t as mapContractAtError } from "./contract-at-errors-Wj3u4Xco.mjs";
|
|
7
6
|
import { Command } from "commander";
|
|
8
7
|
import { getEmittedArtifactPaths } from "@prisma-next/emitter";
|
|
9
8
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
@@ -765,4 +764,4 @@ function resolveBundleByPrefix(bundles, needle) {
|
|
|
765
764
|
//#endregion
|
|
766
765
|
export { formatMigrationPlanOutput as n, resolveBundleByPrefix as r, createMigrationPlanCommand as t };
|
|
767
766
|
|
|
768
|
-
//# sourceMappingURL=migration-plan-
|
|
767
|
+
//# sourceMappingURL=migration-plan-NHdlUwPG.mjs.map
|