prisma-next 0.11.0-dev.4 → 0.11.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-errors-DFF1LlfU.mjs +215 -0
- package/dist/cli-errors-DFF1LlfU.mjs.map +1 -0
- package/dist/cli.mjs +8 -9
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-oXO2WCPD.mjs → client-a5NJce0-.mjs} +5 -5
- package/dist/{client-oXO2WCPD.mjs.map → client-a5NJce0-.mjs.map} +1 -1
- package/dist/{command-helpers-DtavI0wJ.mjs → command-helpers-BnqwTptC.mjs} +380 -6
- package/dist/command-helpers-BnqwTptC.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +33 -7
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +3 -4
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +6 -7
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +36 -8
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +5 -1
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +44 -9
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +2 -3
- package/dist/commands/migration-check.mjs.map +1 -1
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +2 -3
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +57 -13
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +2 -103
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +3 -4
- package/dist/commands/migration-log.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +3 -10
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +1 -0
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -1
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +6 -7
- 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 +6 -7
- package/dist/commands/migration-status.mjs.map +1 -1
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +34 -9
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/config-loader-B6sJjXTv.mjs.map +1 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/{contract-emit-bcrpT-wD.mjs → contract-emit-DYBHfZqL.mjs} +8 -7
- package/dist/contract-emit-DYBHfZqL.mjs.map +1 -0
- package/dist/{contract-emit-uwT-Mj8-.mjs → contract-emit-aFcOi3aw.mjs} +20 -14
- package/dist/contract-emit-aFcOi3aw.mjs.map +1 -0
- package/dist/{contract-enrichment-Dani0mMW.mjs → contract-enrichment-XmUPhmsS.mjs} +4 -25
- package/dist/contract-enrichment-XmUPhmsS.mjs.map +1 -0
- package/dist/{contract-infer-pKkiCt7C.mjs → contract-infer-BpJeg-Eu.mjs} +3 -4
- package/dist/{contract-infer-pKkiCt7C.mjs.map → contract-infer-BpJeg-Eu.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-BmNQwlws.mjs → contract-space-aggregate-loader-EVU3n9YE.mjs} +2 -2
- package/dist/{contract-space-aggregate-loader-BmNQwlws.mjs.map → contract-space-aggregate-loader-EVU3n9YE.mjs.map} +1 -1
- package/dist/{db-verify-AoIUriL4.mjs → db-verify-CxtdGiL3.mjs} +6 -7
- package/dist/{db-verify-AoIUriL4.mjs.map → db-verify-CxtdGiL3.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -3
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-65gOHkHB.mjs → framework-components-DTcjouhS.mjs} +2 -2
- package/dist/{framework-components-65gOHkHB.mjs.map → framework-components-DTcjouhS.mjs.map} +1 -1
- package/dist/global-flags-CdE7M0d9.d.mts.map +1 -1
- package/dist/graph-render-DJVv0_uf.mjs.map +1 -1
- package/dist/{init-YX6lCJpG.mjs → init-eGkSo7hi.mjs} +5 -5
- package/dist/{init-YX6lCJpG.mjs.map → init-eGkSo7hi.mjs.map} +1 -1
- package/dist/{inspect-live-schema-LeWvkZVz.mjs → inspect-live-schema-B1GCyjAJ.mjs} +5 -5
- package/dist/{inspect-live-schema-LeWvkZVz.mjs.map → inspect-live-schema-B1GCyjAJ.mjs.map} +1 -1
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +4 -4
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-BtkunvFQ.mjs → migration-command-scaffold-CNdZl60X.mjs} +5 -5
- package/dist/{migration-command-scaffold-BtkunvFQ.mjs.map → migration-command-scaffold-CNdZl60X.mjs.map} +1 -1
- package/dist/migration-list-CnYiHrNV.mjs +288 -0
- package/dist/migration-list-CnYiHrNV.mjs.map +1 -0
- package/dist/{migration-plan-C2jeH1J5.mjs → migration-plan-ulpJu26J.mjs} +340 -88
- package/dist/migration-plan-ulpJu26J.mjs.map +1 -0
- package/dist/{migrations-CwZMa1Ck.mjs → migrations-C7YTBnLy.mjs} +11 -2
- package/dist/migrations-C7YTBnLy.mjs.map +1 -0
- package/dist/{output-BlsrGMEF.mjs → output-CUIdfYo5.mjs} +1 -1
- package/dist/{output-BlsrGMEF.mjs.map → output-CUIdfYo5.mjs.map} +1 -1
- package/dist/{progress-adapter-DFfvZcYL.mjs → progress-adapter-xASh41wr.mjs} +1 -1
- package/dist/{progress-adapter-DFfvZcYL.mjs.map → progress-adapter-xASh41wr.mjs.map} +1 -1
- package/dist/ref-advancement-CHJ_8HxQ.mjs +50 -0
- package/dist/ref-advancement-CHJ_8HxQ.mjs.map +1 -0
- package/dist/{types--CqjMdk0.d.mts → types-UWB2-rrw.d.mts} +12 -4
- package/dist/types-UWB2-rrw.d.mts.map +1 -0
- package/dist/{verify-Bom75OYI.mjs → verify-DX4RQwq4.mjs} +2 -2
- package/dist/{verify-Bom75OYI.mjs.map → verify-DX4RQwq4.mjs.map} +1 -1
- package/package.json +12 -12
- package/dist/cli-errors-Czmx92Zy.d.mts +0 -3
- package/dist/cli-errors-Djtz98Vm.mjs +0 -71
- package/dist/cli-errors-Djtz98Vm.mjs.map +0 -1
- package/dist/command-helpers-DtavI0wJ.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/contract-emit-bcrpT-wD.mjs.map +0 -1
- package/dist/contract-emit-uwT-Mj8-.mjs.map +0 -1
- package/dist/contract-enrichment-Dani0mMW.mjs.map +0 -1
- package/dist/migration-plan-C2jeH1J5.mjs.map +0 -1
- package/dist/migrations-CwZMa1Ck.mjs.map +0 -1
- package/dist/terminal-ui-BiB_8KNo.mjs +0 -379
- package/dist/terminal-ui-BiB_8KNo.mjs.map +0 -1
- package/dist/types--CqjMdk0.d.mts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-list-CnYiHrNV.mjs","names":[],"sources":["../src/utils/formatters/migration-list-render.ts","../src/utils/formatters/migration-list-styler.ts","../src/commands/migration-list.ts"],"sourcesContent":["import type {\n MigrationListEntry,\n MigrationListResult,\n} from '@prisma-next/migration-tools/migration-list-types';\n\nexport type {\n MigrationListEntry,\n MigrationListResult,\n MigrationSpaceListEntry,\n} from '@prisma-next/migration-tools/migration-list-types';\n\nconst HASH_WIDTH = 7;\nconst EMPTY_SOURCE = '∅';\nconst SELF_EDGE_GLYPH = '⟲';\nconst FORWARD_EDGE_GLYPH = '→';\nconst DECORATION_PREFIX = ' ';\n\n/**\n * Semantic styler for `migration list` output tokens. Token-typed so\n * the renderer composes presentation-neutral fragments and the styler\n * decides how each token kind is decorated (ANSI codes, plain text,\n * etc.). The renderer pads with raw spaces *outside* styled tokens so\n * visible column widths stay stable regardless of what the styler\n * emits — adding ANSI escape sequences never disturbs alignment.\n *\n * `invariants` and `refs` receive the underlying string arrays rather\n * than a pre-joined string so per-element styling (e.g. distinguishing\n * the live-DB `db` marker from user-named refs) is possible without\n * having to re-parse a joined block.\n */\nexport interface MigrationListStyler {\n dirName(text: string): string;\n sourceHash(text: string): string;\n destHash(text: string): string;\n glyph(text: string): string;\n invariants(ids: readonly string[]): string;\n refs(names: readonly string[]): string;\n spaceHeading(text: string): string;\n summary(text: string): string;\n emptyState(text: string): string;\n}\n\nexport const IDENTITY_MIGRATION_LIST_STYLER: MigrationListStyler = {\n dirName: (text) => text,\n sourceHash: (text) => text,\n destHash: (text) => text,\n glyph: (text) => text,\n invariants: (ids) => `{${ids.join(', ')}}`,\n refs: (names) => `(${names.join(', ')})`,\n spaceHeading: (text) => text,\n summary: (text) => text,\n emptyState: (text) => text,\n};\n\nfunction abbreviateContractHash(hash: string): string {\n const stripped = hash.startsWith('sha256:') ? hash.slice(7) : hash;\n return stripped.slice(0, HASH_WIDTH);\n}\n\nfunction formatSourceColumn(from: string | null, style: MigrationListStyler): string {\n if (from === null) {\n return style.glyph(EMPTY_SOURCE) + ' '.repeat(HASH_WIDTH - EMPTY_SOURCE.length);\n }\n return style.sourceHash(abbreviateContractHash(from));\n}\n\nfunction formatDestColumn(from: string | null, to: string, style: MigrationListStyler): string {\n if (from !== null && from === to) {\n return ' '.repeat(HASH_WIDTH);\n }\n return style.destHash(abbreviateContractHash(to));\n}\n\nfunction formatArrowGlyph(from: string | null, to: string, style: MigrationListStyler): string {\n return style.glyph(from !== null && from === to ? SELF_EDGE_GLYPH : FORWARD_EDGE_GLYPH);\n}\n\nfunction formatDecorations(\n providedInvariants: readonly string[],\n refs: readonly string[],\n style: MigrationListStyler,\n): string {\n const blocks: string[] = [];\n if (providedInvariants.length > 0) {\n blocks.push(style.invariants(providedInvariants));\n }\n if (refs.length > 0) {\n blocks.push(style.refs(refs));\n }\n if (blocks.length === 0) return '';\n return `${DECORATION_PREFIX}${blocks.join(' ')}`;\n}\n\nfunction formatMigrationRow(\n migration: MigrationListEntry,\n dirNameWidth: number,\n style: MigrationListStyler,\n): string {\n const dirNamePadding = ' '.repeat(Math.max(0, dirNameWidth - migration.dirName.length));\n const dirName = `${style.dirName(migration.dirName)}${dirNamePadding}`;\n const source = formatSourceColumn(migration.from, style);\n const arrow = formatArrowGlyph(migration.from, migration.to, style);\n const dest = formatDestColumn(migration.from, migration.to, style);\n const decorations = formatDecorations(migration.providedInvariants, migration.refs, style);\n return `${dirName}${source} ${arrow} ${dest}${decorations}`;\n}\n\nfunction formatEmptyStateLine(spaceId: string, style: MigrationListStyler): string {\n return style.emptyState(`There are no migrations in migrations/${spaceId}/ yet`);\n}\n\nfunction renderSpaceBlock(\n spaceId: string,\n migrations: readonly MigrationListEntry[],\n multiSpace: boolean,\n style: MigrationListStyler,\n): readonly string[] {\n if (migrations.length === 0) {\n const emptyLine = formatEmptyStateLine(spaceId, style);\n if (!multiSpace) {\n return [emptyLine];\n }\n return [style.spaceHeading(`${spaceId}:`), ` ${emptyLine}`];\n }\n\n const dirNameWidth = Math.max(...migrations.map((entry) => entry.dirName.length)) + 2;\n const rows = migrations.map((entry) => formatMigrationRow(entry, dirNameWidth, style));\n if (!multiSpace) {\n return rows;\n }\n return [style.spaceHeading(`${spaceId}:`), ...rows.map((row) => ` ${row}`)];\n}\n\n/**\n * Compose the styled `migration list` output. The renderer is\n * presentation-neutral — every token passes through `style` before\n * landing in the output, so the same composition serves the pure-text\n * path ({@link renderMigrationList} via\n * {@link IDENTITY_MIGRATION_LIST_STYLER}) and the ANSI-styled CLI path\n * (via the ANSI styler the CLI shell wires up).\n */\nexport function renderMigrationListWithStyle(\n result: MigrationListResult,\n style: MigrationListStyler,\n): string {\n const multiSpace = result.spaces.length > 1;\n const lines: string[] = [];\n\n for (let index = 0; index < result.spaces.length; index++) {\n const space = result.spaces[index]!;\n if (index > 0) {\n lines.push('');\n }\n lines.push(...renderSpaceBlock(space.spaceId, space.migrations, multiSpace, style));\n }\n\n const totalMigrations = result.spaces.reduce(\n (count, space) => count + space.migrations.length,\n 0,\n );\n if (totalMigrations > 0) {\n lines.push('');\n lines.push(style.summary(result.summary));\n }\n\n return lines.join('\\n');\n}\n\nexport function renderMigrationList(result: MigrationListResult): string {\n return renderMigrationListWithStyle(result, IDENTITY_MIGRATION_LIST_STYLER);\n}\n","import { bold, cyan, cyanBright, dim, green, greenBright, yellow } from 'colorette';\nimport { IDENTITY_MIGRATION_LIST_STYLER, type MigrationListStyler } from './migration-list-render';\n\n/**\n * The reserved ref name for the live-database marker. Treated as a\n * structurally distinct token from user-named refs so the styler can\n * make it visually pop in `(refs)` decorations.\n */\nconst DB_REF_NAME = 'db';\n\nfunction styleRefName(name: string): string {\n return name === DB_REF_NAME ? bold(greenBright(name)) : green(name);\n}\n\n/**\n * Build a {@link MigrationListStyler} that decorates `migration list`\n * tokens with ANSI SGR codes. When `useColor` is `false` (non-TTY,\n * `--no-color`, `NO_COLOR=1`, piped output) the function returns the\n * shared identity styler so callers get plain text with zero ANSI\n * bytes — pipe-friendly by construction.\n *\n * Palette:\n *\n * - `dirName`: bold\n * - `sourceHash`: dim cyan\n * - `destHash`: bright cyan\n * - `glyph` (`→` / `⟲` / `∅`): dim\n * - `invariants` (`{...}`): yellow\n * - `refs` (`(...)`): green; the live-DB `db` marker inside is green-bold\n * - `spaceHeading` (`<spaceId>:`): bold\n * - `summary`: dim\n * - `emptyState`: dim\n */\nexport function createAnsiMigrationListStyler(opts: {\n readonly useColor: boolean;\n}): MigrationListStyler {\n if (!opts.useColor) {\n return IDENTITY_MIGRATION_LIST_STYLER;\n }\n return {\n dirName: (text) => bold(text),\n sourceHash: (text) => dim(cyan(text)),\n destHash: (text) => cyanBright(text),\n glyph: (text) => dim(text),\n invariants: (ids) => yellow(`{${ids.join(', ')}}`),\n refs: (names) => {\n const open = green('(');\n const close = green(')');\n const separator = green(', ');\n return open + names.map(styleRefName).join(separator) + close;\n },\n spaceHeading: (text) => bold(text),\n summary: (text) => dim(text),\n emptyState: (text) => dim(text),\n };\n}\n","import { enumerateMigrationSpaces } from '@prisma-next/migration-tools/enumerate-migration-spaces';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport type {\n MigrationListResult,\n MigrationSpaceListEntry,\n} from '@prisma-next/migration-tools/migration-list-types';\nimport { APP_SPACE_ID, isValidSpaceId } 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 errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { renderMigrationListWithStyle } from '../utils/formatters/migration-list-render';\nimport { createAnsiMigrationListStyler } from '../utils/formatters/migration-list-styler';\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 MigrationListOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly space?: string;\n}\n\n/**\n * Inputs for {@link runMigrationList} — the pure-ish data-and-policy core\n * of `migration list` that tests exercise directly.\n *\n * The core depends only on the filesystem rooted at `migrationsDir`. It\n * does NOT call `loadConfig`, parse CLI flags, render a styled header,\n * or write to any stream. Output rendering is the caller's concern (the\n * CLI shell renders via {@link renderMigrationList}; JSON callers\n * serialize the {@link MigrationListResult} directly).\n */\nexport interface RunMigrationListInputs {\n /** Absolute path to the project's `migrations/` directory. */\n readonly migrationsDir: string;\n /**\n * Optional contract-space id to narrow the result to a single space.\n * Same validation rules as {@link isValidSpaceId}. When absent, every\n * on-disk space contributes.\n */\n readonly spaceFilter?: string;\n}\n\n/**\n * Compute the trailing one-line summary appended below the migration\n * rows. Wording follows the existing CLI's pluralization style (\"N\n * migration(s) on disk\" for the common single-space path; multi-space\n * adds \"across K contract space(s)\" so consumers can see the spread).\n *\n * The renderer suppresses the summary line when `totalMigrations === 0`\n * — the empty-state line carries enough information on its own — so\n * this function always returns a string even for the empty-state.\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 * The unit-testable core of `migration list`. Given an absolute\n * `migrationsDir` and an optional `spaceFilter`, enumerates every\n * on-disk migration (via {@link enumerateMigrationSpaces}), narrows to\n * the requested space if any, and assembles a {@link MigrationListResult}\n * ready for the renderer or JSON serializer.\n *\n * The enumerator is the single source of truth for \"what is a contract\n * space\": existence, the `--space` candidate-suggestion list, and\n * scoping are all derived from one {@link enumerateMigrationSpaces}\n * traversal. This means the reserved-name exclusion the enumerator\n * applies (e.g. the per-space `refs/` subdirectory) is honoured here for\n * free — a `--space refs` request resolves to `SPACE_NOT_FOUND`, not a\n * synthesized empty-state.\n *\n * Distinct empty-state paths:\n *\n * - `migrations/` missing or contains no valid space directories →\n * synthesizes `[{ spaceId: APP_SPACE_ID, migrations: [] }]` so the\n * renderer's empty-state path can name a directory (spec § Empty-state +\n * the `migrations/` missing edge case).\n * - `--space <id>` on an existing-but-empty space dir → the enumerator\n * surfaces `{ spaceId, migrations: [] }`; `<id>` is in the set, so it\n * scopes to that entry and renders the empty-state the same way.\n * - `--space <id>` on a non-existent (or reserved) space → structured\n * `MIGRATION.SPACE_NOT_FOUND` error (NOT empty-state).\n *\n * Errors caught here:\n *\n * - {@link MigrationToolsError} from the enumerator → mapped through\n * {@link mapMigrationToolsError} so callers see the catalogue code.\n * - Anything else (filesystem etc.) → wrapped via {@link errorUnexpected}.\n */\nexport async function runMigrationList(\n inputs: RunMigrationListInputs,\n): Promise<Result<MigrationListResult, CliStructuredError>> {\n const { migrationsDir, spaceFilter } = inputs;\n\n if (spaceFilter !== undefined && !isValidSpaceId(spaceFilter)) {\n return notOk(errorInvalidSpaceId(spaceFilter));\n }\n\n let spaces: readonly MigrationSpaceListEntry[];\n try {\n spaces = await enumerateMigrationSpaces({ projectMigrationsDir: migrationsDir });\n } catch (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 enumerate migrations: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\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 */\nasync function executeMigrationListCommand(\n options: MigrationListOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationListResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, migrationsRelative } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration list',\n description: 'List on-disk migrations, latest first, per contract space',\n details: [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ...(options.space !== undefined ? [{ label: 'space', value: options.space }] : []),\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n return runMigrationList({\n migrationsDir,\n ...ifDefined('spaceFilter', options.space),\n });\n}\n\nexport function createMigrationListCommand(): Command {\n const command = new Command('list');\n setCommandDescriptions(\n command,\n 'List on-disk migrations, latest first, per contract space',\n 'Enumerates every on-disk migration under migrations/<space>/ for every\\n' +\n 'contract space found on disk, latest first. Offline — does not consult\\n' +\n 'the database. Each row shows source → destination contract hashes\\n' +\n '(7-char git-style), the self-edge marker (⟲), any provided invariants\\n' +\n '({...}), and refs landing on the destination ((production, db)). Pass\\n' +\n '--space <id> to narrow to a single contract space.',\n );\n setCommandExamples(command, [\n 'prisma-next migration list',\n 'prisma-next migration list --space app',\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 .action(async (options: MigrationListOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const result = await executeMigrationListCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (listResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(listResult, null, 2));\n } else if (!flags.quiet) {\n const styler = createAnsiMigrationListStyler({ useColor: ui.useColor });\n ui.output(renderMigrationListWithStyle(listResult, styler));\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-B6sJjXTv.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as assertFrameworkComponentsCompatible } from "./framework-components-
|
|
4
|
-
import { t as createTerminalUI } from "./
|
|
5
|
-
import {
|
|
6
|
-
import { n as toExtensionInputs, t as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-BmNQwlws.mjs";
|
|
2
|
+
import { A as mapRefResolutionError, E as errorTargetMigrationNotSupported, O as errorUnexpected, a as errorContractValidationFailed, h as errorMigrationPlanningFailed, k as mapMigrationToolsError, l as errorFileNotFound, t as CliStructuredError, v as errorPlanForgotTheFlag, w as errorSnapshotMissing } from "./cli-errors-DFF1LlfU.mjs";
|
|
3
|
+
import { t as assertFrameworkComponentsCompatible } from "./framework-components-DTcjouhS.mjs";
|
|
4
|
+
import { D as formatStyledHeader, a as loadMigrationPackages, c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, i as getTargetMigrations, l as resolveMigrationPaths, t as addGlobalOptions, v as parseGlobalFlagsOrExit, x as handleResult, y as createTerminalUI } from "./command-helpers-BnqwTptC.mjs";
|
|
5
|
+
import { n as toExtensionInputs, t as buildContractSpaceAggregate } from "./contract-space-aggregate-loader-EVU3n9YE.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";
|
|
10
9
|
import { join, relative } from "pathe";
|
|
11
|
-
import { readFile } from "node:fs/promises";
|
|
10
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
12
11
|
import { createControlStack, hasOperationPreview } from "@prisma-next/framework-components/control";
|
|
13
12
|
import { copyFilesWithRename, formatMigrationDirName, materialiseExtensionMigrationPackageIfMissing, writeMigrationPackage } from "@prisma-next/migration-tools/io";
|
|
14
|
-
import { findLatestMigration } from "@prisma-next/migration-tools/migration-graph";
|
|
13
|
+
import { assertHashIsGraphNode, findLatestMigration, isGraphNode } from "@prisma-next/migration-tools/migration-graph";
|
|
15
14
|
import { emitContractSpaceArtefacts, planAllSpaces, readContractSpaceHeadRef, spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
|
|
16
15
|
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
16
|
+
import { readRefSnapshot, readRefs } from "@prisma-next/migration-tools/refs";
|
|
17
17
|
import { parseContractRef } from "@prisma-next/migration-tools/ref-resolution";
|
|
18
|
-
import { readRefs } from "@prisma-next/migration-tools/refs";
|
|
19
18
|
import { computeMigrationHash } from "@prisma-next/migration-tools/hash";
|
|
20
19
|
import { writeMigrationTs } from "@prisma-next/migration-tools/migration-ts";
|
|
20
|
+
import { canonicalizeJson } from "@prisma-next/framework-components/utils";
|
|
21
21
|
import { deriveProvidedInvariants } from "@prisma-next/migration-tools/invariants";
|
|
22
22
|
//#region src/utils/contract-space-seed-phase.ts
|
|
23
23
|
/**
|
|
@@ -109,6 +109,135 @@ function buildPlaceholderContractDts(spaceId) {
|
|
|
109
109
|
].join("\n");
|
|
110
110
|
}
|
|
111
111
|
//#endregion
|
|
112
|
+
//#region src/utils/plan-resolution.ts
|
|
113
|
+
const FULL_HASH_PATTERN = /^sha256:([0-9a-f]{64}|empty)$/;
|
|
114
|
+
function looksLikeFullHash(input) {
|
|
115
|
+
return FULL_HASH_PATTERN.test(input);
|
|
116
|
+
}
|
|
117
|
+
function graphIsEmpty(bundles) {
|
|
118
|
+
return bundles.length === 0;
|
|
119
|
+
}
|
|
120
|
+
function getReachableRefs(refs, graph) {
|
|
121
|
+
return Object.entries(refs).flatMap(([name, entry]) => entry && isGraphNode(entry.hash, graph) ? [{
|
|
122
|
+
name,
|
|
123
|
+
hash: entry.hash
|
|
124
|
+
}] : []).sort((a, b) => a.name.localeCompare(b.name));
|
|
125
|
+
}
|
|
126
|
+
function assertFromIsGraphNode(fromHash, graph, refs, graphTipHash) {
|
|
127
|
+
try {
|
|
128
|
+
assertHashIsGraphNode(fromHash, graph);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
if (MigrationToolsError.is(error) && error.code === "MIGRATION.HASH_NOT_IN_GRAPH") throw errorPlanForgotTheFlag(fromHash, getReachableRefs(refs, graph), graphTipHash);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function deserializeSnapshotContract(familyInstance, contract) {
|
|
135
|
+
try {
|
|
136
|
+
return ok(familyInstance.deserializeContract(contract));
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (CliStructuredError.is(error)) return notOk(error);
|
|
139
|
+
return notOk(errorContractValidationFailed(`Ref snapshot contract failed to deserialize: ${error instanceof Error ? error.message : String(error)}`, { where: { path: "ref-snapshot" } }));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function resolveGraphNodeFromBundle(fromHash, bundles, readBundleEndContract, explicitFromLabel) {
|
|
143
|
+
const matchingBundle = bundles.find((pkg) => pkg.metadata.to === fromHash);
|
|
144
|
+
if (!matchingBundle) return notOk(errorUnexpected(explicitFromLabel ? `No migration bundle found for --from "${explicitFromLabel}" (resolved hash: ${fromHash})` : `No migration bundle found for graph node ${fromHash}`, {
|
|
145
|
+
why: `The hash ${fromHash} is a graph node but no on-disk migration package has an end-contract hash matching it.`,
|
|
146
|
+
fix: "Provide a ref or hash that corresponds to an existing migration package, or run `migration list` to see available migrations."
|
|
147
|
+
}));
|
|
148
|
+
try {
|
|
149
|
+
return ok({
|
|
150
|
+
kind: "graph-node",
|
|
151
|
+
fromHash,
|
|
152
|
+
fromContract: await readBundleEndContract(matchingBundle.dirPath),
|
|
153
|
+
sourceDir: matchingBundle.dirPath
|
|
154
|
+
});
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (CliStructuredError.is(error)) return notOk(error);
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function resolveFromRefName(refName, fromHash, input, refs) {
|
|
161
|
+
const { refsDir, bundles, graph, familyInstance, readBundleEndContract } = input;
|
|
162
|
+
const empty = graphIsEmpty(bundles);
|
|
163
|
+
const graphTip = findLatestMigration(graph)?.to ?? null;
|
|
164
|
+
let snapshot;
|
|
165
|
+
try {
|
|
166
|
+
snapshot = await readRefSnapshot(refsDir, refName);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
if (snapshot) {
|
|
172
|
+
const contractResult = await deserializeSnapshotContract(familyInstance, snapshot.contract);
|
|
173
|
+
if (!contractResult.ok) return contractResult;
|
|
174
|
+
const fromContract = contractResult.value;
|
|
175
|
+
const { contractDts, contract: contractJson } = snapshot;
|
|
176
|
+
if (empty) return ok({
|
|
177
|
+
kind: "auto-baseline",
|
|
178
|
+
fromHash,
|
|
179
|
+
fromContract,
|
|
180
|
+
contractDts,
|
|
181
|
+
contractJson
|
|
182
|
+
});
|
|
183
|
+
try {
|
|
184
|
+
assertFromIsGraphNode(fromHash, graph, refs, graphTip);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
if (CliStructuredError.is(error)) return notOk(error);
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
return ok({
|
|
190
|
+
kind: "snapshot",
|
|
191
|
+
fromHash,
|
|
192
|
+
fromContract,
|
|
193
|
+
contractDts,
|
|
194
|
+
contractJson
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
if (isGraphNode(fromHash, graph)) return resolveGraphNodeFromBundle(fromHash, bundles, readBundleEndContract);
|
|
198
|
+
return notOk(errorSnapshotMissing(refName));
|
|
199
|
+
}
|
|
200
|
+
async function resolveFromHashProvenance(fromHash, input, _refs, explicitFromLabel) {
|
|
201
|
+
const { bundles, graph } = input;
|
|
202
|
+
if (isGraphNode(fromHash, graph)) return resolveGraphNodeFromBundle(fromHash, bundles, input.readBundleEndContract, explicitFromLabel);
|
|
203
|
+
throw new Error(`resolveFromHashProvenance: non-graph-node hash ${fromHash} should be refused via looksLikeFullHash before this helper is called`);
|
|
204
|
+
}
|
|
205
|
+
async function resolveFromForPlan(input) {
|
|
206
|
+
const { optionsFrom, refsDir, graph } = input;
|
|
207
|
+
let refs;
|
|
208
|
+
try {
|
|
209
|
+
refs = await readRefs(refsDir);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
if (optionsFrom === void 0) {
|
|
215
|
+
const dbRef = refs["db"];
|
|
216
|
+
if (!dbRef) return ok({
|
|
217
|
+
kind: "greenfield",
|
|
218
|
+
fromHash: null,
|
|
219
|
+
fromContract: null
|
|
220
|
+
});
|
|
221
|
+
return resolveFromRefName("db", dbRef.hash, input, refs);
|
|
222
|
+
}
|
|
223
|
+
const refResult = parseContractRef(optionsFrom, {
|
|
224
|
+
graph,
|
|
225
|
+
refs
|
|
226
|
+
});
|
|
227
|
+
if (!refResult.ok) {
|
|
228
|
+
if (looksLikeFullHash(optionsFrom)) {
|
|
229
|
+
const empty = graphIsEmpty(input.bundles);
|
|
230
|
+
const graphTip = findLatestMigration(graph)?.to ?? null;
|
|
231
|
+
if (empty) return notOk(errorSnapshotMissing(optionsFrom, { viaRef: false }));
|
|
232
|
+
return notOk(errorPlanForgotTheFlag(optionsFrom, getReachableRefs(refs, graph), graphTip));
|
|
233
|
+
}
|
|
234
|
+
return notOk(mapRefResolutionError(refResult.failure));
|
|
235
|
+
}
|
|
236
|
+
const { hash: fromHash, provenance } = refResult.value;
|
|
237
|
+
if (provenance.kind === "ref") return resolveFromRefName(provenance.refName, fromHash, input, refs);
|
|
238
|
+
return resolveFromHashProvenance(fromHash, input, refs, optionsFrom);
|
|
239
|
+
}
|
|
240
|
+
//#endregion
|
|
112
241
|
//#region src/commands/migration-plan.ts
|
|
113
242
|
/**
|
|
114
243
|
* Load a predecessor migration's destination contract from its sibling
|
|
@@ -148,6 +277,64 @@ async function readPredecessorEndContract(migrationDir, familyInstance) {
|
|
|
148
277
|
throw errorContractValidationFailed(`Predecessor contract at ${path} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`, { where: { path } });
|
|
149
278
|
}
|
|
150
279
|
}
|
|
280
|
+
async function writeSnapshotContractArtifacts(packageDir, contractJson, contractDts, artifactBasename) {
|
|
281
|
+
await mkdir(packageDir, { recursive: true });
|
|
282
|
+
const jsonContent = `${canonicalizeJson(contractJson)}\n`;
|
|
283
|
+
const dtsContent = contractDts.endsWith("\n") ? contractDts : `${contractDts}\n`;
|
|
284
|
+
await writeFile(join(packageDir, `${artifactBasename}.json`), jsonContent);
|
|
285
|
+
await writeFile(join(packageDir, `${artifactBasename}.d.ts`), dtsContent);
|
|
286
|
+
}
|
|
287
|
+
async function writeSnapshotStartContract(packageDir, contractJson, contractDts) {
|
|
288
|
+
await writeSnapshotContractArtifacts(packageDir, contractJson, contractDts, "start-contract");
|
|
289
|
+
}
|
|
290
|
+
async function runPlannerLeg(planner, migrations, frameworkComponents, contract, fromContract, spaceId) {
|
|
291
|
+
const fromSchema = migrations.contractToSchema(fromContract, frameworkComponents);
|
|
292
|
+
const plannerResult = planner.plan({
|
|
293
|
+
contract,
|
|
294
|
+
schema: fromSchema,
|
|
295
|
+
policy: { allowedOperationClasses: [
|
|
296
|
+
"additive",
|
|
297
|
+
"widening",
|
|
298
|
+
"destructive",
|
|
299
|
+
"data"
|
|
300
|
+
] },
|
|
301
|
+
fromContract,
|
|
302
|
+
frameworkComponents,
|
|
303
|
+
spaceId
|
|
304
|
+
});
|
|
305
|
+
if (plannerResult.kind === "failure") return notOk(errorMigrationPlanningFailed({ conflicts: plannerResult.conflicts }));
|
|
306
|
+
let plannedOps = [];
|
|
307
|
+
let hasPlaceholders = false;
|
|
308
|
+
try {
|
|
309
|
+
plannedOps = plannerResult.plan.operations;
|
|
310
|
+
if (plannedOps.length === 0) return notOk(errorMigrationPlanningFailed({ conflicts: [{
|
|
311
|
+
kind: "unsupportedChange",
|
|
312
|
+
summary: "Contract changed but planner produced no operations. This indicates unsupported or ignored changes."
|
|
313
|
+
}] }));
|
|
314
|
+
} catch (e) {
|
|
315
|
+
if (CliStructuredError.is(e) && e.domain === "MIG" && e.code === "2001") hasPlaceholders = true;
|
|
316
|
+
else throw e;
|
|
317
|
+
}
|
|
318
|
+
return ok({
|
|
319
|
+
plannedOps,
|
|
320
|
+
migrationTsContent: plannerResult.plan.renderTypeScript(),
|
|
321
|
+
hasPlaceholders
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
async function writePlannedMigrationPackage(packageDir, fromHash, toHash, createdAt, leg) {
|
|
325
|
+
const opsForWrite = leg.hasPlaceholders ? [] : leg.plannedOps;
|
|
326
|
+
const metadataWithInvariants = {
|
|
327
|
+
from: fromHash,
|
|
328
|
+
to: toHash,
|
|
329
|
+
providedInvariants: deriveProvidedInvariants(opsForWrite),
|
|
330
|
+
createdAt: createdAt.toISOString()
|
|
331
|
+
};
|
|
332
|
+
await writeMigrationPackage(packageDir, {
|
|
333
|
+
...metadataWithInvariants,
|
|
334
|
+
migrationHash: computeMigrationHash(metadataWithInvariants, opsForWrite)
|
|
335
|
+
}, opsForWrite);
|
|
336
|
+
await writeMigrationTs(packageDir, leg.migrationTsContent);
|
|
337
|
+
}
|
|
151
338
|
async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
152
339
|
const config = await loadConfig(options.config);
|
|
153
340
|
const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } = resolveMigrationPaths(options.config, config);
|
|
@@ -206,36 +393,47 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
206
393
|
const rawStorageHash = toContract.storage?.storageHash;
|
|
207
394
|
if (typeof rawStorageHash !== "string") return notOk(errorContractValidationFailed("Contract is missing storageHash", { where: { path: contractPathAbsolute } }));
|
|
208
395
|
const toStorageHash = rawStorageHash;
|
|
396
|
+
const { refsDir } = resolveMigrationPaths(options.config, config);
|
|
209
397
|
let fromContract = null;
|
|
210
398
|
let fromHash = null;
|
|
211
399
|
let fromContractSourceDir = null;
|
|
400
|
+
let snapshotStartContract = null;
|
|
401
|
+
let isAutoBaseline = false;
|
|
212
402
|
try {
|
|
213
403
|
const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
404
|
+
const resolutionResult = await resolveFromForPlan({
|
|
405
|
+
optionsFrom: options.from,
|
|
406
|
+
refsDir,
|
|
407
|
+
bundles,
|
|
408
|
+
graph,
|
|
409
|
+
familyInstance,
|
|
410
|
+
readBundleEndContract: (migrationDir) => readPredecessorEndContract(migrationDir, familyInstance)
|
|
411
|
+
});
|
|
412
|
+
if (!resolutionResult.ok) return notOk(resolutionResult.failure);
|
|
413
|
+
switch (resolutionResult.value.kind) {
|
|
414
|
+
case "greenfield": break;
|
|
415
|
+
case "graph-node":
|
|
416
|
+
fromHash = resolutionResult.value.fromHash;
|
|
417
|
+
fromContract = resolutionResult.value.fromContract;
|
|
418
|
+
fromContractSourceDir = resolutionResult.value.sourceDir;
|
|
419
|
+
break;
|
|
420
|
+
case "snapshot":
|
|
421
|
+
fromHash = resolutionResult.value.fromHash;
|
|
422
|
+
fromContract = resolutionResult.value.fromContract;
|
|
423
|
+
snapshotStartContract = {
|
|
424
|
+
contractJson: resolutionResult.value.contractJson,
|
|
425
|
+
contractDts: resolutionResult.value.contractDts
|
|
426
|
+
};
|
|
427
|
+
break;
|
|
428
|
+
case "auto-baseline":
|
|
429
|
+
fromHash = resolutionResult.value.fromHash;
|
|
430
|
+
fromContract = resolutionResult.value.fromContract;
|
|
431
|
+
snapshotStartContract = {
|
|
432
|
+
contractJson: resolutionResult.value.contractJson,
|
|
433
|
+
contractDts: resolutionResult.value.contractDts
|
|
434
|
+
};
|
|
435
|
+
isAutoBaseline = true;
|
|
436
|
+
break;
|
|
239
437
|
}
|
|
240
438
|
} catch (error) {
|
|
241
439
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
@@ -257,7 +455,7 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
257
455
|
spaceId: r.spaceId,
|
|
258
456
|
dirName
|
|
259
457
|
})));
|
|
260
|
-
if (fromHash === toStorageHash) return ok({
|
|
458
|
+
if (fromHash === toStorageHash && !isAutoBaseline) return ok({
|
|
261
459
|
ok: true,
|
|
262
460
|
noOp: true,
|
|
263
461
|
from: fromHash,
|
|
@@ -283,58 +481,105 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
283
481
|
config.adapter,
|
|
284
482
|
...config.extensionPacks ?? []
|
|
285
483
|
]);
|
|
286
|
-
const timestamp = /* @__PURE__ */ new Date();
|
|
287
|
-
const packageDir = join(appMigrationsDir, formatMigrationDirName(timestamp, options.name ?? "migration"));
|
|
288
|
-
const baseMetadata = {
|
|
289
|
-
from: fromHash,
|
|
290
|
-
to: toStorageHash,
|
|
291
|
-
hints: {
|
|
292
|
-
used: [],
|
|
293
|
-
applied: [],
|
|
294
|
-
plannerVersion: "2.0.0"
|
|
295
|
-
},
|
|
296
|
-
labels: [],
|
|
297
|
-
createdAt: timestamp.toISOString()
|
|
298
|
-
};
|
|
299
484
|
try {
|
|
300
485
|
const planner = migrations.createPlanner(familyInstance);
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
486
|
+
if (isAutoBaseline && fromHash !== null && fromContract !== null && snapshotStartContract !== null) {
|
|
487
|
+
const baselineTimestamp = /* @__PURE__ */ new Date();
|
|
488
|
+
const deltaTimestamp = new Date(baselineTimestamp.getTime() + 6e4);
|
|
489
|
+
const baselineDirName = formatMigrationDirName(baselineTimestamp, "baseline");
|
|
490
|
+
const deltaDirName = formatMigrationDirName(deltaTimestamp, options.name ?? "migration");
|
|
491
|
+
const baselinePackageDir = join(appMigrationsDir, baselineDirName);
|
|
492
|
+
const deltaPackageDir = join(appMigrationsDir, deltaDirName);
|
|
493
|
+
const baselineLeg = await runPlannerLeg(planner, migrations, frameworkComponents, fromContract, null, aggregate.app.spaceId);
|
|
494
|
+
if (!baselineLeg.ok) return notOk(baselineLeg.failure);
|
|
495
|
+
await writePlannedMigrationPackage(baselinePackageDir, null, fromHash, baselineTimestamp, baselineLeg.value);
|
|
496
|
+
await writeSnapshotContractArtifacts(baselinePackageDir, snapshotStartContract.contractJson, snapshotStartContract.contractDts, "end-contract");
|
|
497
|
+
if (fromHash === toStorageHash) {
|
|
498
|
+
const baselineOps = baselineLeg.value.hasPlaceholders ? [] : baselineLeg.value.plannedOps;
|
|
499
|
+
if (baselineLeg.value.hasPlaceholders) {
|
|
500
|
+
const baselineDir = relative(process.cwd(), baselinePackageDir);
|
|
501
|
+
return ok({
|
|
502
|
+
ok: true,
|
|
503
|
+
noOp: false,
|
|
504
|
+
from: fromHash,
|
|
505
|
+
to: toStorageHash,
|
|
506
|
+
dir: baselineDir,
|
|
507
|
+
baselineDir,
|
|
508
|
+
operations: [],
|
|
509
|
+
emittedExtensionDirs,
|
|
510
|
+
pendingPlaceholders: true,
|
|
511
|
+
summary: "Planned baseline with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit",
|
|
512
|
+
timings: { total: Date.now() - startTime }
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
const preview = hasOperationPreview(familyInstance) ? familyInstance.toOperationPreview(baselineOps) : void 0;
|
|
516
|
+
return ok({
|
|
517
|
+
ok: true,
|
|
518
|
+
noOp: false,
|
|
519
|
+
from: fromHash,
|
|
520
|
+
to: toStorageHash,
|
|
521
|
+
baselineDir: relative(process.cwd(), baselinePackageDir),
|
|
522
|
+
operations: baselineOps.map((op) => ({
|
|
523
|
+
id: op.id,
|
|
524
|
+
label: op.label,
|
|
525
|
+
operationClass: op.operationClass
|
|
526
|
+
})),
|
|
527
|
+
emittedExtensionDirs,
|
|
528
|
+
...preview !== void 0 ? { preview } : {},
|
|
529
|
+
summary: buildAutoBaselinePlanSummary(0, emittedExtensionDirs.length),
|
|
530
|
+
timings: { total: Date.now() - startTime }
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract, fromContract, aggregate.app.spaceId);
|
|
534
|
+
if (!deltaLeg.ok) return notOk(deltaLeg.failure);
|
|
535
|
+
await writePlannedMigrationPackage(deltaPackageDir, fromHash, toStorageHash, deltaTimestamp, deltaLeg.value);
|
|
536
|
+
const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);
|
|
537
|
+
await copyFilesWithRename(deltaPackageDir, [{
|
|
538
|
+
sourcePath: destinationArtifacts.jsonPath,
|
|
539
|
+
destName: "end-contract.json"
|
|
540
|
+
}, {
|
|
541
|
+
sourcePath: destinationArtifacts.dtsPath,
|
|
542
|
+
destName: "end-contract.d.ts"
|
|
543
|
+
}]);
|
|
544
|
+
await writeSnapshotStartContract(deltaPackageDir, snapshotStartContract.contractJson, snapshotStartContract.contractDts);
|
|
545
|
+
const deltaOps = deltaLeg.value.hasPlaceholders ? [] : deltaLeg.value.plannedOps;
|
|
546
|
+
if (deltaLeg.value.hasPlaceholders) return ok({
|
|
547
|
+
ok: true,
|
|
548
|
+
noOp: false,
|
|
549
|
+
from: fromHash,
|
|
550
|
+
to: toStorageHash,
|
|
551
|
+
dir: relative(process.cwd(), deltaPackageDir),
|
|
552
|
+
baselineDir: relative(process.cwd(), baselinePackageDir),
|
|
553
|
+
operations: [],
|
|
554
|
+
emittedExtensionDirs,
|
|
555
|
+
pendingPlaceholders: true,
|
|
556
|
+
summary: "Planned baseline + migration with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit",
|
|
557
|
+
timings: { total: Date.now() - startTime }
|
|
558
|
+
});
|
|
559
|
+
const preview = hasOperationPreview(familyInstance) ? familyInstance.toOperationPreview(deltaOps) : void 0;
|
|
560
|
+
return ok({
|
|
561
|
+
ok: true,
|
|
562
|
+
noOp: false,
|
|
563
|
+
from: fromHash,
|
|
564
|
+
to: toStorageHash,
|
|
565
|
+
dir: relative(process.cwd(), deltaPackageDir),
|
|
566
|
+
baselineDir: relative(process.cwd(), baselinePackageDir),
|
|
567
|
+
operations: deltaOps.map((op) => ({
|
|
568
|
+
id: op.id,
|
|
569
|
+
label: op.label,
|
|
570
|
+
operationClass: op.operationClass
|
|
571
|
+
})),
|
|
572
|
+
emittedExtensionDirs,
|
|
573
|
+
...preview !== void 0 ? { preview } : {},
|
|
574
|
+
summary: buildAutoBaselinePlanSummary(deltaOps.length, emittedExtensionDirs.length),
|
|
575
|
+
timings: { total: Date.now() - startTime }
|
|
576
|
+
});
|
|
327
577
|
}
|
|
328
|
-
const
|
|
329
|
-
const
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
};
|
|
334
|
-
await writeMigrationPackage(packageDir, {
|
|
335
|
-
...metadataWithInvariants,
|
|
336
|
-
migrationHash: computeMigrationHash(metadataWithInvariants, opsForWrite)
|
|
337
|
-
}, opsForWrite);
|
|
578
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
579
|
+
const packageDir = join(appMigrationsDir, formatMigrationDirName(timestamp, options.name ?? "migration"));
|
|
580
|
+
const deltaLeg = await runPlannerLeg(planner, migrations, frameworkComponents, aggregate.app.contract, fromContract, aggregate.app.spaceId);
|
|
581
|
+
if (!deltaLeg.ok) return notOk(deltaLeg.failure);
|
|
582
|
+
await writePlannedMigrationPackage(packageDir, fromHash, toStorageHash, timestamp, deltaLeg.value);
|
|
338
583
|
const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);
|
|
339
584
|
await copyFilesWithRename(packageDir, [{
|
|
340
585
|
sourcePath: destinationArtifacts.jsonPath,
|
|
@@ -352,9 +597,8 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
352
597
|
sourcePath: sourceArtifacts.dtsPath,
|
|
353
598
|
destName: "start-contract.d.ts"
|
|
354
599
|
}]);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (hasPlaceholders) return ok({
|
|
600
|
+
} else if (snapshotStartContract !== null) await writeSnapshotStartContract(packageDir, snapshotStartContract.contractJson, snapshotStartContract.contractDts);
|
|
601
|
+
if (deltaLeg.value.hasPlaceholders) return ok({
|
|
358
602
|
ok: true,
|
|
359
603
|
noOp: false,
|
|
360
604
|
from: fromHash,
|
|
@@ -366,6 +610,7 @@ async function executeMigrationPlanCommand(options, flags, ui, startTime) {
|
|
|
366
610
|
summary: "Planned migration with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit",
|
|
367
611
|
timings: { total: Date.now() - startTime }
|
|
368
612
|
});
|
|
613
|
+
const plannedOps = deltaLeg.value.plannedOps;
|
|
369
614
|
const preview = hasOperationPreview(familyInstance) ? familyInstance.toOperationPreview(plannedOps) : void 0;
|
|
370
615
|
return ok({
|
|
371
616
|
ok: true,
|
|
@@ -425,6 +670,11 @@ function buildPlanSummary(plannedOpsCount, emittedExtensionDirsCount) {
|
|
|
425
670
|
if (emittedExtensionDirsCount === 0) return base;
|
|
426
671
|
return `${base}; materialised ${emittedExtensionDirsCount} ${emittedExtensionDirsCount === 1 ? "extension-space migration" : "extension-space migrations"}`;
|
|
427
672
|
}
|
|
673
|
+
function buildAutoBaselinePlanSummary(deltaOpsCount, emittedExtensionDirsCount) {
|
|
674
|
+
const base = `Planned baseline + ${deltaOpsCount} operation(s)`;
|
|
675
|
+
if (emittedExtensionDirsCount === 0) return base;
|
|
676
|
+
return `${base}; materialised ${emittedExtensionDirsCount} ${emittedExtensionDirsCount === 1 ? "extension-space migration" : "extension-space migrations"}`;
|
|
677
|
+
}
|
|
428
678
|
function formatMigrationPlanOutput(result, flags) {
|
|
429
679
|
const lines = [];
|
|
430
680
|
const useColor = flags.color !== false;
|
|
@@ -476,10 +726,12 @@ function formatMigrationPlanOutput(result, flags) {
|
|
|
476
726
|
}
|
|
477
727
|
lines.push(dim_(`from: ${result.from}`));
|
|
478
728
|
lines.push(dim_(`to: ${result.to}`));
|
|
729
|
+
if (result.baselineDir) lines.push(dim_(`Baseline → ${result.baselineDir}`));
|
|
479
730
|
if (result.dir) lines.push(dim_(`App space → ${result.dir}`));
|
|
480
731
|
for (const entry of result.emittedExtensionDirs) lines.push(dim_(`Extension space ${entry.spaceId} → migrations/${entry.spaceId}/${entry.dirName}`));
|
|
481
732
|
lines.push("");
|
|
482
|
-
|
|
733
|
+
const reviewTarget = result.baselineDir !== void 0 && result.dir !== void 0 ? `${result.baselineDir} and ${result.dir}` : result.baselineDir ?? result.dir ?? "<dir>";
|
|
734
|
+
lines.push(`Next: review ${green_(reviewTarget)} if needed, then run ${green_("prisma-next migrate")}.`);
|
|
483
735
|
if (result.preview && result.preview.statements.length > 0) {
|
|
484
736
|
const allSql = result.preview.statements.every((s) => s.language === "sql");
|
|
485
737
|
lines.push("");
|
|
@@ -526,4 +778,4 @@ function resolveBundleByPrefix(bundles, needle) {
|
|
|
526
778
|
//#endregion
|
|
527
779
|
export { formatMigrationPlanOutput as n, resolveBundleByPrefix as r, createMigrationPlanCommand as t };
|
|
528
780
|
|
|
529
|
-
//# sourceMappingURL=migration-plan-
|
|
781
|
+
//# sourceMappingURL=migration-plan-ulpJu26J.mjs.map
|