@prisma-next/cli 0.11.0-dev.7 → 0.11.0-dev.71

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.
Files changed (187) hide show
  1. package/README.md +13 -9
  2. package/dist/cli.mjs +9 -10
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/{client-oXO2WCPD.mjs → client-KgJorIvG.mjs} +72 -60
  5. package/dist/client-KgJorIvG.mjs.map +1 -0
  6. package/dist/{command-helpers-DtavI0wJ.mjs → command-helpers-Bbw1GbwL.mjs} +642 -45
  7. package/dist/command-helpers-Bbw1GbwL.mjs.map +1 -0
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +1 -1
  10. package/dist/commands/contract-infer.d.mts.map +1 -1
  11. package/dist/commands/contract-infer.mjs +1 -1
  12. package/dist/commands/db-init.d.mts.map +1 -1
  13. package/dist/commands/db-init.mjs +32 -7
  14. package/dist/commands/db-init.mjs.map +1 -1
  15. package/dist/commands/db-schema.d.mts.map +1 -1
  16. package/dist/commands/db-schema.mjs +3 -4
  17. package/dist/commands/db-schema.mjs.map +1 -1
  18. package/dist/commands/db-sign.d.mts.map +1 -1
  19. package/dist/commands/db-sign.mjs +12 -10
  20. package/dist/commands/db-sign.mjs.map +1 -1
  21. package/dist/commands/db-update.d.mts.map +1 -1
  22. package/dist/commands/db-update.mjs +41 -11
  23. package/dist/commands/db-update.mjs.map +1 -1
  24. package/dist/commands/db-verify.d.mts.map +1 -1
  25. package/dist/commands/db-verify.mjs +1 -1
  26. package/dist/commands/migrate.d.mts +6 -2
  27. package/dist/commands/migrate.d.mts.map +1 -1
  28. package/dist/commands/migrate.mjs +75 -40
  29. package/dist/commands/migrate.mjs.map +1 -1
  30. package/dist/commands/migration-check.d.mts +4 -3
  31. package/dist/commands/migration-check.d.mts.map +1 -1
  32. package/dist/commands/migration-check.mjs +1 -280
  33. package/dist/commands/migration-graph.d.mts +13 -2
  34. package/dist/commands/migration-graph.d.mts.map +1 -1
  35. package/dist/commands/migration-graph.mjs +2 -137
  36. package/dist/commands/migration-list.d.mts +64 -4
  37. package/dist/commands/migration-list.d.mts.map +1 -1
  38. package/dist/commands/migration-list.mjs +143 -56
  39. package/dist/commands/migration-list.mjs.map +1 -1
  40. package/dist/commands/migration-log.d.mts +10 -1
  41. package/dist/commands/migration-log.d.mts.map +1 -1
  42. package/dist/commands/migration-log.mjs +10 -15
  43. package/dist/commands/migration-log.mjs.map +1 -1
  44. package/dist/commands/migration-new.d.mts.map +1 -1
  45. package/dist/commands/migration-new.mjs +32 -38
  46. package/dist/commands/migration-new.mjs.map +1 -1
  47. package/dist/commands/migration-plan.d.mts +3 -2
  48. package/dist/commands/migration-plan.d.mts.map +1 -1
  49. package/dist/commands/migration-plan.mjs +1 -1
  50. package/dist/commands/migration-show.d.mts +4 -55
  51. package/dist/commands/migration-show.d.mts.map +1 -1
  52. package/dist/commands/migration-show.mjs +61 -153
  53. package/dist/commands/migration-show.mjs.map +1 -1
  54. package/dist/commands/migration-status.d.mts +12 -49
  55. package/dist/commands/migration-status.d.mts.map +1 -1
  56. package/dist/commands/migration-status.mjs +85 -81
  57. package/dist/commands/migration-status.mjs.map +1 -1
  58. package/dist/commands/ref.d.mts +1 -1
  59. package/dist/commands/ref.d.mts.map +1 -1
  60. package/dist/commands/ref.mjs +38 -10
  61. package/dist/commands/ref.mjs.map +1 -1
  62. package/dist/config-loader-B6sJjXTv.mjs.map +1 -1
  63. package/dist/config-loader.d.mts.map +1 -1
  64. package/dist/contract-at-errors-BxP-TOMl.mjs +42 -0
  65. package/dist/contract-at-errors-BxP-TOMl.mjs.map +1 -0
  66. package/dist/{contract-emit-o-8VmdQX.mjs → contract-emit-D-4jrNve.mjs} +21 -7
  67. package/dist/{contract-emit-o-8VmdQX.mjs.map → contract-emit-D-4jrNve.mjs.map} +1 -1
  68. package/dist/{contract-emit-CmsklifJ.mjs → contract-emit-DxcGl4Uq.mjs} +4 -6
  69. package/dist/{contract-emit-CmsklifJ.mjs.map → contract-emit-DxcGl4Uq.mjs.map} +1 -1
  70. package/dist/{contract-enrichment-Dani0mMW.mjs → contract-enrichment-a0V5Y_mL.mjs} +4 -25
  71. package/dist/contract-enrichment-a0V5Y_mL.mjs.map +1 -0
  72. package/dist/{contract-infer-pKkiCt7C.mjs → contract-infer-D8uEbJuu.mjs} +3 -4
  73. package/dist/{contract-infer-pKkiCt7C.mjs.map → contract-infer-D8uEbJuu.mjs.map} +1 -1
  74. package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs +247 -0
  75. package/dist/contract-space-aggregate-loader-DvZwdkrr.mjs.map +1 -0
  76. package/dist/{db-verify-AoIUriL4.mjs → db-verify-v_vUKXTU.mjs} +5 -7
  77. package/dist/{db-verify-AoIUriL4.mjs.map → db-verify-v_vUKXTU.mjs.map} +1 -1
  78. package/dist/exports/control-api.d.mts +3 -3
  79. package/dist/exports/control-api.d.mts.map +1 -1
  80. package/dist/exports/control-api.mjs +3 -3
  81. package/dist/exports/index.d.mts.map +1 -1
  82. package/dist/exports/index.mjs +1 -1
  83. package/dist/exports/index.mjs.map +1 -1
  84. package/dist/exports/init-output.d.mts.map +1 -1
  85. package/dist/exports/init-output.mjs +1 -1
  86. package/dist/extension-pack-inputs-IDvjRCi3.mjs +62 -0
  87. package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +1 -0
  88. package/dist/{framework-components-65gOHkHB.mjs → framework-components-fYXjz_in.mjs} +2 -2
  89. package/dist/{framework-components-65gOHkHB.mjs.map → framework-components-fYXjz_in.mjs.map} +1 -1
  90. package/dist/global-flags-DEHjV8_s.d.mts +34 -0
  91. package/dist/global-flags-DEHjV8_s.d.mts.map +1 -0
  92. package/dist/{graph-render-DJVv0_uf.mjs → graph-render-rFAqZujX.mjs} +2 -2
  93. package/dist/{graph-render-DJVv0_uf.mjs.map → graph-render-rFAqZujX.mjs.map} +1 -1
  94. package/dist/{init-Db5Itt5r.mjs → init-Dzi4_BFb.mjs} +4 -5
  95. package/dist/{init-Db5Itt5r.mjs.map → init-Dzi4_BFb.mjs.map} +1 -1
  96. package/dist/{inspect-live-schema-LeWvkZVz.mjs → inspect-live-schema-C6ohV_oQ.mjs} +4 -5
  97. package/dist/{inspect-live-schema-LeWvkZVz.mjs.map → inspect-live-schema-C6ohV_oQ.mjs.map} +1 -1
  98. package/dist/migration-check-BiBJoYYW.mjs +341 -0
  99. package/dist/migration-check-BiBJoYYW.mjs.map +1 -0
  100. package/dist/migration-cli.d.mts.map +1 -1
  101. package/dist/migration-cli.mjs +4 -4
  102. package/dist/migration-cli.mjs.map +1 -1
  103. package/dist/{migration-command-scaffold-BtkunvFQ.mjs → migration-command-scaffold-CjvwO6at.mjs} +4 -5
  104. package/dist/{migration-command-scaffold-BtkunvFQ.mjs.map → migration-command-scaffold-CjvwO6at.mjs.map} +1 -1
  105. package/dist/migration-graph-D7DVUElV.mjs +1232 -0
  106. package/dist/migration-graph-D7DVUElV.mjs.map +1 -0
  107. package/dist/migration-list-styler-BRwF4-gy.mjs +399 -0
  108. package/dist/migration-list-styler-BRwF4-gy.mjs.map +1 -0
  109. package/dist/{migration-plan-C2jeH1J5.mjs → migration-plan-9DJ7q7_z.mjs} +372 -133
  110. package/dist/migration-plan-9DJ7q7_z.mjs.map +1 -0
  111. package/dist/{migration-types-BXWvz12q.d.mts → migration-types-D2FW63pr.d.mts} +1 -1
  112. package/dist/{migration-types-BXWvz12q.d.mts.map → migration-types-D2FW63pr.d.mts.map} +1 -1
  113. package/dist/{migrations-CwZMa1Ck.mjs → migrations-Cv2jxNNK.mjs} +12 -13
  114. package/dist/migrations-Cv2jxNNK.mjs.map +1 -0
  115. package/dist/{output-BlsrGMEF.mjs → output-B60Gw5fu.mjs} +1 -1
  116. package/dist/{output-BlsrGMEF.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
  117. package/dist/{progress-adapter-DFfvZcYL.mjs → progress-adapter-C644QK8l.mjs} +1 -1
  118. package/dist/{progress-adapter-DFfvZcYL.mjs.map → progress-adapter-C644QK8l.mjs.map} +1 -1
  119. package/dist/ref-advancement-DUZqsue6.mjs +50 -0
  120. package/dist/ref-advancement-DUZqsue6.mjs.map +1 -0
  121. package/dist/terminal-ui-5Y6mrg93.d.mts +133 -0
  122. package/dist/terminal-ui-5Y6mrg93.d.mts.map +1 -0
  123. package/dist/{types-C9FfXb1l.d.mts → types-Dt_SfqFm.d.mts} +21 -28
  124. package/dist/types-Dt_SfqFm.d.mts.map +1 -0
  125. package/dist/{verify-Bom75OYI.mjs → verify-DCA9Sldu.mjs} +2 -2
  126. package/dist/{verify-Bom75OYI.mjs.map → verify-DCA9Sldu.mjs.map} +1 -1
  127. package/package.json +19 -19
  128. package/src/commands/db-init.ts +48 -2
  129. package/src/commands/db-sign.ts +9 -5
  130. package/src/commands/db-update.ts +54 -8
  131. package/src/commands/migrate.ts +125 -44
  132. package/src/commands/migration-check.ts +43 -83
  133. package/src/commands/migration-graph.ts +75 -60
  134. package/src/commands/migration-list.ts +220 -74
  135. package/src/commands/migration-log.ts +8 -14
  136. package/src/commands/migration-new.ts +44 -48
  137. package/src/commands/migration-plan.ts +412 -197
  138. package/src/commands/migration-show.ts +65 -284
  139. package/src/commands/migration-status.ts +127 -124
  140. package/src/commands/ref.ts +53 -8
  141. package/src/control-api/client.ts +0 -1
  142. package/src/control-api/contract-enrichment.ts +6 -42
  143. package/src/control-api/operations/{apply-aggregate.ts → apply.ts} +44 -75
  144. package/src/control-api/operations/contract-emit.ts +7 -2
  145. package/src/control-api/operations/{db-apply-aggregate.ts → db-apply.ts} +19 -19
  146. package/src/control-api/operations/db-init.ts +4 -4
  147. package/src/control-api/operations/db-update.ts +4 -4
  148. package/src/control-api/operations/db-verify.ts +15 -11
  149. package/src/control-api/operations/migration-apply.ts +56 -47
  150. package/src/control-api/types.ts +19 -27
  151. package/src/migration-cli.ts +4 -4
  152. package/src/utils/cli-errors.ts +234 -0
  153. package/src/utils/command-helpers.ts +1 -20
  154. package/src/utils/contract-at-errors.ts +96 -0
  155. package/src/utils/contract-space-aggregate-loader.ts +336 -117
  156. package/src/utils/formatters/migration-graph-layout.ts +1119 -0
  157. package/src/utils/formatters/migration-graph-rows.ts +336 -0
  158. package/src/utils/formatters/migration-graph-tree-render.ts +459 -0
  159. package/src/utils/formatters/migration-list-data-column.ts +115 -0
  160. package/src/utils/formatters/migration-list-graph-topology.ts +368 -0
  161. package/src/utils/formatters/migration-list-render.ts +191 -0
  162. package/src/utils/formatters/migration-list-styler.ts +63 -0
  163. package/src/utils/formatters/migration-list-types.ts +21 -0
  164. package/src/utils/formatters/migrations.ts +37 -46
  165. package/src/utils/glyph-mode.ts +22 -0
  166. package/src/utils/integrity-violation-to-check-failure.ts +130 -0
  167. package/src/utils/plan-resolution.ts +258 -0
  168. package/src/utils/ref-advancement.ts +68 -0
  169. package/src/utils/terminal-ui.ts +42 -1
  170. package/dist/cli-errors-Czmx92Zy.d.mts +0 -3
  171. package/dist/cli-errors-Djtz98Vm.mjs +0 -71
  172. package/dist/cli-errors-Djtz98Vm.mjs.map +0 -1
  173. package/dist/client-oXO2WCPD.mjs.map +0 -1
  174. package/dist/command-helpers-DtavI0wJ.mjs.map +0 -1
  175. package/dist/commands/migration-check.mjs.map +0 -1
  176. package/dist/commands/migration-graph.mjs.map +0 -1
  177. package/dist/contract-enrichment-Dani0mMW.mjs.map +0 -1
  178. package/dist/contract-space-aggregate-loader-BmNQwlws.mjs +0 -160
  179. package/dist/contract-space-aggregate-loader-BmNQwlws.mjs.map +0 -1
  180. package/dist/global-flags-CdE7M0d9.d.mts +0 -15
  181. package/dist/global-flags-CdE7M0d9.d.mts.map +0 -1
  182. package/dist/migration-plan-C2jeH1J5.mjs.map +0 -1
  183. package/dist/migrations-CwZMa1Ck.mjs.map +0 -1
  184. package/dist/rolldown-runtime-twds-ZHy.mjs +0 -14
  185. package/dist/terminal-ui-BiB_8KNo.mjs +0 -379
  186. package/dist/terminal-ui-BiB_8KNo.mjs.map +0 -1
  187. package/dist/types-C9FfXb1l.d.mts.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration-check.mjs","names":[],"sources":["../../src/commands/migration-check.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { verifyMigrationHash } from '@prisma-next/migration-tools/hash';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { parseMigrationRef } from '@prisma-next/migration-tools/ref-resolution';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport {\n addGlobalOptions,\n loadMigrationPackages,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\nimport { INTEGRITY_FAILED, OK, PRECONDITION } from './migration-check/exit-codes';\n\ninterface MigrationCheckOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport interface CheckFailure {\n readonly pnCode: string;\n readonly where: string;\n readonly why: string;\n readonly fix: string;\n}\n\nexport interface MigrationCheckResult {\n readonly ok: boolean;\n readonly failures: readonly CheckFailure[];\n readonly summary: string;\n}\n\n/**\n * Canonical user-facing locator for a check failure: the cwd-relative path\n * to the migration package directory. Surfacing the same shape across every\n * PN code means `--json` consumers can branch uniformly on `where`.\n */\nfunction migrationPathRelative(dirPath: string): string {\n return relative(process.cwd(), dirPath);\n}\n\nfunction migrationFileRelative(dirPath: string, fileName: string): string {\n return join(migrationPathRelative(dirPath), fileName);\n}\n\nfunction checkFileExists(dirPath: string, dirName: string, fileName: string): CheckFailure | null {\n if (!existsSync(join(dirPath, fileName))) {\n return {\n pnCode: 'PN-MIG-CHECK-002',\n where: migrationFileRelative(dirPath, fileName),\n why: `${fileName} is missing from ${dirName}`,\n fix: 'Re-emit the migration package or restore from version control.',\n };\n }\n return null;\n}\n\n/**\n * Within-migration snapshot-consistency check (PN-MIG-CHECK-005).\n *\n * Compares the migration's stored `metadata.to` against the `storageHash`\n * recorded in its on-disk `end-contract.json` snapshot. The two values are\n * independent on-disk records of the same fact (the migration's destination\n * contract); drift between them indicates the package is internally\n * corrupt. Cross-migration consistency (one migration's end-contract.json\n * agreeing with the next migration's start-contract.json) is a separate\n * check that requires shadow execution and is deferred to\n * `migration preflight`.\n *\n * Shared between the graph-wide and per-migration code paths so both report\n * the same failure for the same on-disk state.\n */\nfunction checkSnapshotConsistency(pkg: OnDiskMigrationPackage): CheckFailure | null {\n const endContractPath = join(pkg.dirPath, 'end-contract.json');\n if (!existsSync(endContractPath)) return null;\n try {\n const raw = JSON.parse(readFileSync(endContractPath, 'utf-8')) as Record<string, unknown>;\n const storage = raw['storage'] as Record<string, unknown> | undefined;\n const snapshotHash = storage?.['storageHash'];\n if (typeof snapshotHash === 'string' && snapshotHash !== pkg.metadata.to) {\n return {\n pnCode: 'PN-MIG-CHECK-005',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" declares to=${pkg.metadata.to} but end-contract.json has storageHash=${snapshotHash}`,\n fix: 'Re-emit the migration package so migration.json and end-contract.json agree.',\n };\n }\n } catch {\n return {\n pnCode: 'PN-MIG-CHECK-006',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" has an unparseable end-contract.json.`,\n fix: 'Re-emit the migration package to repair the snapshot file.',\n };\n }\n return null;\n}\n\nasync function executeMigrationCheckCommand(\n target: string | undefined,\n options: MigrationCheckOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<{ result: MigrationCheckResult; exitCode: number }> {\n const config = await loadConfig(options.config);\n const { configPath, appMigrationsDir, appMigrationsRelative, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration check',\n description: 'Verify artifact and graph integrity',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n const failures: CheckFailure[] = [];\n\n let bundles: Awaited<ReturnType<typeof loadMigrationPackages>>['bundles'];\n let graph: Awaited<ReturnType<typeof loadMigrationPackages>>['graph'];\n try {\n const loaded = await loadMigrationPackages(appMigrationsDir);\n bundles = loaded.bundles;\n graph = loaded.graph;\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n const pnCode =\n error.code === 'MIGRATION.HASH_MISMATCH' ? 'PN-MIG-CHECK-001' : 'PN-MIG-CHECK-002';\n // Normalise to a cwd-relative path. `error.details.dir` is absolute\n // (the migration-tools layer doesn't know the caller's cwd); the\n // `filePath` fallback is also absolute. Surfacing the relative form\n // matches the rest of the command's `where` shape and keeps `--json`\n // consumers from having to special-case the bootstrap-failure path.\n const rawWhere =\n (error.details?.['dir'] as string) ?? (error.details?.['filePath'] as string) ?? null;\n const where = rawWhere ? relative(process.cwd(), rawWhere) : 'unknown';\n failures.push({\n pnCode,\n where,\n why: error.why,\n fix: error.fix,\n });\n return {\n result: { ok: false, failures, summary: `${failures.length} integrity failure(s)` },\n exitCode: INTEGRITY_FAILED,\n };\n }\n throw error;\n }\n\n if (existsSync(appMigrationsDir)) {\n const loadedDirNames = new Set(bundles.map((p) => p.dirName));\n try {\n const entries = readdirSync(appMigrationsDir);\n for (const entry of entries) {\n if (entry.startsWith('.') || entry.startsWith('_') || entry === 'refs') continue;\n const entryPath = join(appMigrationsDir, entry);\n try {\n if (!statSync(entryPath).isDirectory()) continue;\n } catch {\n continue;\n }\n if (!loadedDirNames.has(entry)) {\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(entryPath, entry, f);\n if (fail) failures.push(fail);\n }\n }\n }\n } catch {\n // migrations dir unreadable — skip\n }\n }\n\n if (target) {\n const refs = await readRefs(refsDir);\n const migResult = parseMigrationRef(target, { graph, refs });\n if (!migResult.ok) {\n const msg =\n migResult.failure.kind === 'not-found'\n ? `Migration \"${target}\" does not exist`\n : migResult.failure.kind === 'wrong-grammar'\n ? migResult.failure.message\n : `Invalid migration reference: \"${target}\"`;\n return {\n result: { ok: false, failures: [], summary: msg },\n exitCode: PRECONDITION,\n };\n }\n\n const matchedPkg = bundles.find(\n (p) => p.metadata.migrationHash === migResult.value.migrationHash,\n );\n if (!matchedPkg) {\n return {\n result: {\n ok: false,\n failures: [],\n summary: `Migration package for \"${target}\" not found on disk`,\n },\n exitCode: PRECONDITION,\n };\n }\n\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(matchedPkg.dirPath, matchedPkg.dirName, f);\n if (fail) failures.push(fail);\n }\n\n const verification = verifyMigrationHash(matchedPkg);\n if (!verification.ok) {\n failures.push({\n pnCode: 'PN-MIG-CHECK-001',\n where: migrationFileRelative(matchedPkg.dirPath, 'migration.json'),\n why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,\n fix: 'Re-emit the migration package or restore from version control.',\n });\n }\n\n // PN-MIG-CHECK-005 must fire per-migration as well as graph-wide; both\n // call sites delegate to the shared helper so the same on-disk drift\n // produces the same failure regardless of how the user invoked check.\n const snapshotFailure = checkSnapshotConsistency(matchedPkg);\n if (snapshotFailure) failures.push(snapshotFailure);\n } else {\n for (const pkg of bundles) {\n for (const f of ['migration.json', 'ops.json']) {\n const fail = checkFileExists(pkg.dirPath, pkg.dirName, f);\n if (fail) failures.push(fail);\n }\n\n const verification = verifyMigrationHash(pkg);\n if (!verification.ok) {\n failures.push({\n pnCode: 'PN-MIG-CHECK-001',\n where: migrationFileRelative(pkg.dirPath, 'migration.json'),\n why: `Stored hash ${verification.storedHash} does not match recomputed hash ${verification.computedHash}`,\n fix: 'Re-emit the migration package or restore from version control.',\n });\n }\n }\n\n for (const pkg of bundles) {\n const snapshotFailure = checkSnapshotConsistency(pkg);\n if (snapshotFailure) failures.push(snapshotFailure);\n }\n\n const allToHashes = new Set(bundles.map((p) => p.metadata.to));\n for (const pkg of bundles) {\n const isReachable =\n pkg.metadata.from === null ||\n allToHashes.has(pkg.metadata.from) ||\n pkg.metadata.from === 'sha256:empty';\n if (!isReachable) {\n failures.push({\n pnCode: 'PN-MIG-CHECK-003',\n where: migrationPathRelative(pkg.dirPath),\n why: `Migration \"${pkg.dirName}\" starts from ${pkg.metadata.from} which no other migration produces`,\n fix: 'This migration is unreachable in the graph. Delete it or re-emit a connecting migration.',\n });\n }\n }\n\n try {\n const refs = await readRefs(refsDir);\n for (const [name, entry] of Object.entries(refs)) {\n if (!graph.nodes.has(entry.hash)) {\n failures.push({\n pnCode: 'PN-MIG-CHECK-004',\n where: relative(process.cwd(), join(refsDir, `${name}.json`)),\n why: `Ref \"${name}\" points at ${entry.hash} which does not exist in the migration graph`,\n fix: `Update the ref with \\`prisma-next ref set ${name} <valid-hash>\\` or delete it.`,\n });\n }\n }\n } catch {\n // Refs unreadable — skip ref checks\n }\n }\n\n if (failures.length === 0) {\n return {\n result: { ok: true, failures: [], summary: 'All checks passed' },\n exitCode: OK,\n };\n }\n\n return {\n result: { ok: false, failures, summary: `${failures.length} integrity failure(s)` },\n exitCode: INTEGRITY_FAILED,\n };\n}\n\nexport function createMigrationCheckCommand(): Command {\n const command = new Command('check');\n setCommandDescriptions(\n command,\n 'Verify artifact and graph integrity',\n 'Validates that on-disk migration packages are internally consistent\\n' +\n '(hashes match, manifests are complete) and that the graph is well-formed\\n' +\n '(edges connect, refs point at valid nodes). Offline — does not consult\\n' +\n 'the database.',\n );\n setCommandExamples(command, [\n 'prisma-next migration check',\n 'prisma-next migration check 20260101-add-users',\n 'prisma-next migration check --json',\n ]);\n setCommandSeeAlso(command, [\n { verb: 'migration status', oneLiner: 'Show migration path and pending status' },\n { verb: 'migration list', oneLiner: 'List on-disk migrations' },\n { verb: 'migration graph', oneLiner: 'Show the migration graph topology' },\n ]);\n command.exitOverride();\n addGlobalOptions(command)\n .argument('[migration]', 'Migration reference (directory name or hash) to check')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationCheckOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n let result: MigrationCheckResult;\n let exitCode: number;\n try {\n ({ result, exitCode } = await executeMigrationCheckCommand(target, options, flags, ui));\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n result = { ok: false, failures: [], summary: msg };\n exitCode = PRECONDITION;\n }\n\n if (flags.json) {\n ui.output(JSON.stringify(result, null, 2));\n } else if (!flags.quiet) {\n if (result.ok) {\n ui.log(`✔ ${result.summary}`);\n } else {\n for (const f of result.failures) {\n ui.log(`✗ [${f.pnCode}] ${f.where}: ${f.why}`);\n ui.log(` fix: ${f.fix}`);\n }\n ui.log(`\\n${result.summary}`);\n }\n }\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration-graph.mjs","names":[],"sources":["../../src/commands/migration-graph.ts"],"sourcesContent":["import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport type { MigrationGraph } from '@prisma-next/migration-tools/graph';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliStructuredError,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n loadMigrationPackages,\n readContractEnvelope,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n setCommandSeeAlso,\n} from '../utils/command-helpers';\nimport { migrationGraphToRenderInput } from '../utils/formatters/graph-migration-mapper';\nimport { graphRenderer } from '../utils/formatters/graph-render';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport type { StatusRef } from '../utils/migration-types';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationGraphOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly dot?: boolean;\n}\n\nexport interface MigrationGraphResult {\n readonly ok: true;\n readonly graph: MigrationGraph;\n readonly contractHash: string | null;\n readonly refs: readonly StatusRef[];\n readonly summary: string;\n}\n\nasync function executeMigrationGraphCommand(\n options: MigrationGraphOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationGraphResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, appMigrationsDir, appMigrationsRelative, refsDir } = resolveMigrationPaths(\n options.config,\n config,\n );\n\n if (!flags.json && !flags.quiet) {\n const header = formatStyledHeader({\n command: 'migration graph',\n description: 'Show the migration graph topology',\n details: [\n { label: 'config', value: configPath },\n { label: 'migrations', value: appMigrationsRelative },\n ],\n flags,\n });\n ui.stderr(header);\n }\n\n let graph: MigrationGraph;\n try {\n ({ graph } = await loadMigrationPackages(appMigrationsDir));\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 read migrations: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n let contractHash: string | null = null;\n try {\n const envelope = await readContractEnvelope(config);\n contractHash = envelope.storageHash;\n } catch {\n // Contract unreadable — render graph without contract marker\n }\n\n let refs: readonly StatusRef[] = [];\n try {\n const allRefs = await readRefs(refsDir);\n refs = Object.entries(allRefs).map(([name, entry]) => ({\n name,\n hash: entry.hash,\n active: false,\n }));\n } catch {\n // Refs unreadable — render graph without ref markers\n }\n\n return ok({\n ok: true,\n graph,\n contractHash,\n refs,\n summary: `${graph.nodes.size} node(s), ${graph.migrationByHash.size} edge(s)`,\n });\n}\n\nexport function createMigrationGraphCommand(): Command {\n const command = new Command('graph');\n setCommandDescriptions(\n command,\n 'Show the migration graph topology',\n 'Renders the migration graph as an ASCII tree. Offline — does not\\n' +\n 'consult the database. Use --json for machine-readable output or\\n' +\n '--dot for Graphviz DOT format.',\n );\n setCommandExamples(command, [\n 'prisma-next migration graph',\n 'prisma-next migration graph --json',\n 'prisma-next migration graph --dot',\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 list', oneLiner: 'List on-disk migrations' },\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('--dot', 'Output in Graphviz DOT format')\n .action(async (options: MigrationGraphOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n const result = await executeMigrationGraphCommand(options, flags, ui);\n const exitCode = handleResult(result, flags, ui, (graphResult) => {\n // Explicit format flags win over the auto-JSON default. `flags.json`\n // is auto-enabled when stdout is non-TTY (per CLI Style Guide §\n // JSON Semantics); without this ordering, `migration graph --dot |\n // dot -Tsvg` pipes JSON into the GraphViz binary, which then\n // errors. `--dot` is the more specific instruction; honour it.\n if (options.dot) {\n const lines = ['digraph migrations {'];\n for (const edge of graphResult.graph.migrationByHash.values()) {\n const from = edge.from.slice(0, 12);\n const to = edge.to.slice(0, 12);\n lines.push(` \"${from}\" -> \"${to}\" [label=\"${edge.dirName}\"];`);\n }\n lines.push('}');\n ui.output(lines.join('\\n'));\n } else if (flags.json) {\n const nodes = [...graphResult.graph.nodes];\n const edges = [...graphResult.graph.migrationByHash.values()].map((e) => ({\n dirName: e.dirName,\n from: e.from,\n to: e.to,\n migrationHash: e.migrationHash,\n }));\n ui.output(\n JSON.stringify({ ok: true, nodes, edges, summary: graphResult.summary }, null, 2),\n );\n } else if (!flags.quiet) {\n const renderInput = migrationGraphToRenderInput({\n graph: graphResult.graph,\n mode: 'offline',\n markerHash: undefined,\n contractHash: graphResult.contractHash ?? EMPTY_CONTRACT_HASH,\n refs: graphResult.refs,\n activeRefHash: undefined,\n activeRefName: undefined,\n edgeStatuses: [],\n });\n const graphOutput = graphRenderer.render(renderInput.graph, {\n ...renderInput.options,\n colorize: flags.color !== false,\n });\n ui.log(graphOutput);\n ui.log(`\\n${graphResult.summary}`);\n }\n });\n process.exit(exitCode);\n });\n return command;\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-enrichment-Dani0mMW.mjs","names":[],"sources":["../src/control-api/contract-enrichment.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\n\ntype CapabilityMatrix = Record<string, Record<string, boolean>>;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction sortDeep(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map(sortDeep);\n }\n if (!isPlainObject(value)) {\n return value;\n }\n const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));\n const next: Record<string, unknown> = {};\n for (const [key, child] of entries) {\n next[key] = sortDeep(child);\n }\n return next;\n}\n\nfunction sortDeepTyped<T>(value: T): T {\n return sortDeep(value) as T;\n}\n\nfunction extractCapabilityMatrix(value: unknown): CapabilityMatrix {\n if (!isPlainObject(value)) return {};\n\n const out: CapabilityMatrix = {};\n for (const [namespace, maybeCaps] of Object.entries(value)) {\n if (!isPlainObject(maybeCaps)) continue;\n const caps: Record<string, boolean> = {};\n for (const [key, flag] of Object.entries(maybeCaps)) {\n if (typeof flag === 'boolean') {\n caps[key] = flag;\n }\n }\n if (Object.keys(caps).length > 0) {\n out[namespace] = caps;\n }\n }\n\n return out;\n}\n\nfunction mergeCapabilities(left: CapabilityMatrix, right: CapabilityMatrix): CapabilityMatrix {\n const next: CapabilityMatrix = { ...left };\n for (const [namespace, capabilities] of Object.entries(right)) {\n next[namespace] = {\n ...(left[namespace] ?? {}),\n ...capabilities,\n };\n }\n return next;\n}\n\nfunction extractExtensionPackMeta(\n component: TargetBoundComponentDescriptor<string, string>,\n): Record<string, unknown> {\n const { kind, id, version, capabilities, types } = component;\n const base: Record<string, unknown> = {\n kind,\n id,\n familyId: component.familyId,\n targetId: component.targetId,\n version,\n };\n if (capabilities) {\n base['capabilities'] = capabilities;\n }\n if (types) {\n if (types.codecTypes) {\n const {\n controlPlaneHooks: _,\n codecDescriptors: _cd,\n ...cleanedCodecTypes\n } = types.codecTypes;\n base['types'] = { ...types, codecTypes: cleanedCodecTypes };\n } else {\n base['types'] = types;\n }\n }\n return base;\n}\n\n/**\n * Enriches a raw contract with framework-derived metadata: capabilities from all component descriptors and extension pack metadata from extension descriptors. Produces deterministically sorted output.\n */\nexport function enrichContract(\n ir: Contract,\n components: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>,\n): Contract {\n let mergedCapabilities = ir.capabilities;\n const extensionPacksMeta: Record<string, unknown> = {};\n\n for (const component of components) {\n if (component.capabilities) {\n mergedCapabilities = mergeCapabilities(\n mergedCapabilities,\n extractCapabilityMatrix(component.capabilities),\n );\n }\n if (component.kind === 'extension') {\n extensionPacksMeta[component.id] = extractExtensionPackMeta(component);\n }\n }\n\n const extensionPacks =\n Object.keys(extensionPacksMeta).length > 0\n ? { ...ir.extensionPacks, ...extensionPacksMeta }\n : ir.extensionPacks;\n\n return {\n ...ir,\n capabilities: sortDeepTyped(mergedCapabilities),\n extensionPacks: sortDeepTyped(extensionPacks),\n };\n}\n"],"mappings":";AAKA,SAAS,cAAc,OAAkD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,SAAS,SAAS,OAAyB;CACzC,IAAI,MAAM,QAAQ,MAAM,EACtB,OAAO,MAAM,IAAI,SAAS;CAE5B,IAAI,CAAC,cAAc,MAAM,EACvB,OAAO;CAET,MAAM,UAAU,OAAO,QAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;CAC5E,MAAM,OAAgC,EAAE;CACxC,KAAK,MAAM,CAAC,KAAK,UAAU,SACzB,KAAK,OAAO,SAAS,MAAM;CAE7B,OAAO;;AAGT,SAAS,cAAiB,OAAa;CACrC,OAAO,SAAS,MAAM;;AAGxB,SAAS,wBAAwB,OAAkC;CACjE,IAAI,CAAC,cAAc,MAAM,EAAE,OAAO,EAAE;CAEpC,MAAM,MAAwB,EAAE;CAChC,KAAK,MAAM,CAAC,WAAW,cAAc,OAAO,QAAQ,MAAM,EAAE;EAC1D,IAAI,CAAC,cAAc,UAAU,EAAE;EAC/B,MAAM,OAAgC,EAAE;EACxC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,UAAU,EACjD,IAAI,OAAO,SAAS,WAClB,KAAK,OAAO;EAGhB,IAAI,OAAO,KAAK,KAAK,CAAC,SAAS,GAC7B,IAAI,aAAa;;CAIrB,OAAO;;AAGT,SAAS,kBAAkB,MAAwB,OAA2C;CAC5F,MAAM,OAAyB,EAAE,GAAG,MAAM;CAC1C,KAAK,MAAM,CAAC,WAAW,iBAAiB,OAAO,QAAQ,MAAM,EAC3D,KAAK,aAAa;EAChB,GAAI,KAAK,cAAc,EAAE;EACzB,GAAG;EACJ;CAEH,OAAO;;AAGT,SAAS,yBACP,WACyB;CACzB,MAAM,EAAE,MAAM,IAAI,SAAS,cAAc,UAAU;CACnD,MAAM,OAAgC;EACpC;EACA;EACA,UAAU,UAAU;EACpB,UAAU,UAAU;EACpB;EACD;CACD,IAAI,cACF,KAAK,kBAAkB;CAEzB,IAAI,OACF,IAAI,MAAM,YAAY;EACpB,MAAM,EACJ,mBAAmB,GACnB,kBAAkB,KAClB,GAAG,sBACD,MAAM;EACV,KAAK,WAAW;GAAE,GAAG;GAAO,YAAY;GAAmB;QAE3D,KAAK,WAAW;CAGpB,OAAO;;;;;AAMT,SAAgB,eACd,IACA,YACU;CACV,IAAI,qBAAqB,GAAG;CAC5B,MAAM,qBAA8C,EAAE;CAEtD,KAAK,MAAM,aAAa,YAAY;EAClC,IAAI,UAAU,cACZ,qBAAqB,kBACnB,oBACA,wBAAwB,UAAU,aAAa,CAChD;EAEH,IAAI,UAAU,SAAS,aACrB,mBAAmB,UAAU,MAAM,yBAAyB,UAAU;;CAI1E,MAAM,iBACJ,OAAO,KAAK,mBAAmB,CAAC,SAAS,IACrC;EAAE,GAAG,GAAG;EAAgB,GAAG;EAAoB,GAC/C,GAAG;CAET,OAAO;EACL,GAAG;EACH,cAAc,cAAc,mBAAmB;EAC/C,gBAAgB,cAAc,eAAe;EAC9C"}
@@ -1,160 +0,0 @@
1
- import { t as CliStructuredError } from "./cli-errors-Djtz98Vm.mjs";
2
- import { notOk, ok } from "@prisma-next/utils/result";
3
- import { loadContractSpaceAggregate } from "@prisma-next/migration-tools/aggregate";
4
- //#region src/utils/extension-pack-inputs.ts
5
- /**
6
- * Project the CLI's `Config.extensionPacks` array into the canonical
7
- * {@link ExtensionPackInput} shape. The single `as ExtensionPackLike`
8
- * structural cast in the CLI lives inside this function.
9
- */
10
- function toExtensionInputs(extensionPacks) {
11
- return extensionPacks.map((raw) => {
12
- const pack = raw;
13
- if (pack.contractSpace === void 0) return {
14
- id: pack.id,
15
- targetId: pack.targetId
16
- };
17
- return {
18
- id: pack.id,
19
- targetId: pack.targetId,
20
- contractSpace: {
21
- contractJson: pack.contractSpace.contractJson,
22
- headRef: pack.contractSpace.headRef,
23
- migrations: pack.contractSpace.migrations ?? []
24
- }
25
- };
26
- });
27
- }
28
- /**
29
- * Minimal aggregate-loader projection that extracts `id` + `targetId`
30
- * from raw extension pack descriptors **without invoking any
31
- * `contractSpace` accessor**. Inspects the own-property descriptor so
32
- * that getter-backed `contractSpace` declarations are detected but
33
- * never called.
34
- *
35
- * Inclusion semantics match {@link toDeclaredExtensions}: a data
36
- * property whose value is explicitly `undefined` is treated as "no
37
- * contract-space declaration" and skipped, mirroring the
38
- * `pack.contractSpace === undefined` check used on canonicalised
39
- * inputs. Prototype-chain `contractSpace` properties (no own
40
- * descriptor) are also skipped.
41
- *
42
- * This variant must be used by `buildContractSpaceAggregate` so that
43
- * the aggregate path (including `db verify`) never reads
44
- * `contractSpace.contractJson` from extension descriptors — the loader
45
- * always reads the contract from on-disk artefacts instead.
46
- */
47
- function toDeclaredExtensionsFromRaw(extensionPacks) {
48
- const entries = [];
49
- for (const raw of extensionPacks) {
50
- if (typeof raw !== "object" || raw === null) continue;
51
- const descriptor = Object.getOwnPropertyDescriptor(raw, "contractSpace");
52
- if (descriptor === void 0) continue;
53
- if ("value" in descriptor && descriptor.value === void 0) continue;
54
- const pack = raw;
55
- entries.push({
56
- id: pack.id,
57
- targetId: pack.targetId
58
- });
59
- }
60
- return entries;
61
- }
62
- //#endregion
63
- //#region src/utils/contract-space-aggregate-loader.ts
64
- /**
65
- * Render a {@link LoadAggregateError} into a CLI structured-error
66
- * envelope. Preserves error codes `5001` (layout) and `5002` (marker /
67
- * disjointness / etc.) so existing integration tests and downstream
68
- * tooling continue to assert on the same `meta.violations[]` shape
69
- * they did under the old precheck/marker-check helpers.
70
- */
71
- function mapLoadAggregateError(error) {
72
- if (error.kind === "layoutViolation") {
73
- const lines = error.violations.map((v) => `- [${v.kind}] ${v.spaceId}`);
74
- return new CliStructuredError("5001", error.violations.length === 1 ? "Contract-space layout violation detected" : `Contract-space layout violations detected (${error.violations.length})`, {
75
- domain: "MIG",
76
- why: `The on-disk \`migrations/\` directory and your \`extensionPacks\` declaration are not in agreement.\n${lines.join("\n")}`,
77
- fix: "Run `prisma-next migrate` to materialise on-disk artefacts for declared extensions, or remove the orphan directory.",
78
- docsUrl: "https://pris.ly/contract-spaces",
79
- meta: { violations: error.violations.map((v) => ({
80
- kind: v.kind,
81
- spaceId: v.spaceId
82
- })) }
83
- });
84
- }
85
- if (error.kind === "disjointnessViolation") return new CliStructuredError("5002", `Contract-space disjointness violation: storage element "${error.element}" claimed by multiple spaces`, {
86
- domain: "MIG",
87
- why: `Spaces ${error.claimedBy.map((s) => `"${s}"`).join(", ")} all claim the storage element "${error.element}". Each storage element must be owned by exactly one contract space.`,
88
- fix: "Update the conflicting contracts so each storage element is claimed by exactly one space.",
89
- docsUrl: "https://pris.ly/contract-spaces",
90
- meta: { violations: [{
91
- kind: "disjointness",
92
- spaceId: error.claimedBy.join(","),
93
- element: error.element,
94
- claimedBy: error.claimedBy
95
- }] }
96
- });
97
- if (error.kind === "integrityFailure") return new CliStructuredError("5002", `Contract-space integrity failure for "${error.spaceId}"`, {
98
- domain: "MIG",
99
- why: error.detail,
100
- fix: "Run `prisma-next migrate` to refresh on-disk artefacts, or restore the on-disk `migrations/` directory from version control.",
101
- docsUrl: "https://pris.ly/contract-spaces",
102
- meta: { violations: [{
103
- kind: "integrity",
104
- spaceId: error.spaceId,
105
- detail: error.detail
106
- }] }
107
- });
108
- if (error.kind === "validationFailure") return new CliStructuredError("5002", `Contract-space contract validation failed for "${error.spaceId}"`, {
109
- domain: "MIG",
110
- why: error.detail,
111
- fix: "Run `prisma-next migrate` to refresh on-disk artefacts, or fix the extension descriptor producing the invalid contract.",
112
- meta: { violations: [{
113
- kind: "validation",
114
- spaceId: error.spaceId,
115
- detail: error.detail
116
- }] }
117
- });
118
- return new CliStructuredError("5002", `Contract-space target mismatch for "${error.spaceId}"`, {
119
- domain: "MIG",
120
- why: `Space "${error.spaceId}" targets "${error.actual}" but the project's adapter targets "${error.expected}".`,
121
- fix: "Update the extension descriptor to target the configured database, or change the project adapter.",
122
- meta: { violations: [{
123
- kind: "targetMismatch",
124
- spaceId: error.spaceId,
125
- expected: error.expected,
126
- actual: error.actual
127
- }] }
128
- });
129
- }
130
- /**
131
- * Run the aggregate loader at the CLI surface, mapping any
132
- * {@link LoadAggregateError} into a {@link CliStructuredError} envelope.
133
- *
134
- * App-side migration packages flow through `inputs.appMigrationPackages`
135
- * (defaulting to `[]`). `db init` / `db update` leave it empty: the
136
- * planner's `synth` strategy is used for the app member (driven by
137
- * `callerPolicy.ignoreGraphFor`), so the app's authored `migrations/`
138
- * graph does not need to be walked. `migrate` threads the
139
- * already-loaded app-space packages through so the graph-walk strategy
140
- * can plot a path through them — replay forbids synth.
141
- *
142
- * @see specs/contract-space-aggregate-spec.md § Loader.
143
- */
144
- async function buildContractSpaceAggregate(inputs) {
145
- const declaredExtensions = toDeclaredExtensionsFromRaw(inputs.extensionPacks);
146
- const result = await loadContractSpaceAggregate({
147
- targetId: inputs.targetId,
148
- migrationsDir: inputs.migrationsDir,
149
- appContract: inputs.appContract,
150
- declaredExtensions,
151
- deserializeContract: inputs.deserializeContract,
152
- appMigrationPackages: inputs.appMigrationPackages ?? []
153
- });
154
- if (!result.ok) return notOk(mapLoadAggregateError(result.failure));
155
- return ok(result.value.aggregate);
156
- }
157
- //#endregion
158
- export { toExtensionInputs as n, buildContractSpaceAggregate as t };
159
-
160
- //# sourceMappingURL=contract-space-aggregate-loader-BmNQwlws.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract-space-aggregate-loader-BmNQwlws.mjs","names":[],"sources":["../src/utils/extension-pack-inputs.ts","../src/utils/contract-space-aggregate-loader.ts"],"sourcesContent":["/**\n * Single descriptor-import boundary for CLI consumers of `Config.extensionPacks`.\n *\n * Every CLI command / utility that reads an extension descriptor's\n * `contractSpace` projection (loader, migrate-pass, extension-migrations\n * pass, migration commands) goes through {@link toExtensionInputs}. The\n * structural cast `pack as { contractSpace?: ... }` lives **only** here —\n * downstream code consumes the canonical shape and maps it to its own\n * narrower shape via the per-consumer adapters below.\n *\n * The CLI receives extension descriptors typed against the SQL family\n * (or any other family in the future); this helper only depends on the\n * structural shape of `contractSpace`. SQL-family callers pass the same\n * `contractJson` / `headRef.hash` value through unchanged.\n */\nimport type { DeclaredExtensionEntry } from '@prisma-next/migration-tools/aggregate';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport type { MigrationOps } from '@prisma-next/migration-tools/package';\n\n/**\n * In-memory authored migration package shipped by an extension descriptor.\n * Mirrors the `MigrationPackage` shape from\n * `@prisma-next/framework-components/control` minus `dirPath`; redeclared\n * structurally here so the helper does not couple to the SQL family's\n * `ExtensionMigrationPackage` type.\n */\nexport interface DescriptorMigrationPackage {\n readonly dirName: string;\n readonly metadata: MigrationMetadata;\n readonly ops: MigrationOps;\n}\n\n/**\n * The most-general projection of a single declared extension pack\n * needed by the CLI's descriptor-import boundary.\n *\n * - `id` / `targetId` are always present.\n * - `contractSpace` is present only when the extension declares one.\n * When present, it carries the canonical inputs every downstream\n * consumer needs — `contractJson`, `headRef`, and the descriptor's\n * pre-built migration packages.\n */\nexport interface ExtensionPackInput {\n readonly id: string;\n readonly targetId: string;\n readonly contractSpace?: {\n readonly contractJson: unknown;\n readonly headRef: {\n readonly hash: string;\n readonly invariants: readonly string[];\n };\n readonly migrations: readonly DescriptorMigrationPackage[];\n };\n}\n\n/**\n * Structural shape we read off each `Config.extensionPacks` entry.\n *\n * The CLI is the descriptor-import boundary; `extensionPacks` is the only\n * surface where the SQL-family-typed `ControlExtensionDescriptor` flows\n * into framework-neutral helpers. The structural cast lives here, and\n * here alone — every other CLI consumer reads the canonical\n * {@link ExtensionPackInput} shape produced by {@link toExtensionInputs}.\n */\ntype ExtensionPackLike = {\n readonly id: string;\n readonly targetId: string;\n readonly contractSpace?: {\n readonly contractJson: unknown;\n readonly headRef: {\n readonly hash: string;\n readonly invariants: readonly string[];\n };\n readonly migrations?: readonly DescriptorMigrationPackage[];\n };\n};\n\n/**\n * Project the CLI's `Config.extensionPacks` array into the canonical\n * {@link ExtensionPackInput} shape. The single `as ExtensionPackLike`\n * structural cast in the CLI lives inside this function.\n */\nexport function toExtensionInputs(\n extensionPacks: ReadonlyArray<unknown>,\n): readonly ExtensionPackInput[] {\n return extensionPacks.map((raw) => {\n const pack = raw as ExtensionPackLike;\n if (pack.contractSpace === undefined) {\n return { id: pack.id, targetId: pack.targetId };\n }\n return {\n id: pack.id,\n targetId: pack.targetId,\n contractSpace: {\n contractJson: pack.contractSpace.contractJson,\n headRef: pack.contractSpace.headRef,\n migrations: pack.contractSpace.migrations ?? [],\n },\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Per-consumer adapters: take the canonical `ExtensionPackInput[]` and\n// project to whatever narrower shape the downstream primitive needs.\n// ---------------------------------------------------------------------------\n\n/**\n * Aggregate-loader projection. Surfaces `id` + `targetId` per\n * contract-space-bearing extension to\n * {@link import('./contract-space-aggregate-loader').buildContractSpaceAggregate}.\n *\n * Codec-only extensions (no `contractSpace` declaration) are filtered\n * out: they are not contract-space members, so the aggregate loader\n * has nothing to do with them. Filtering happens at this descriptor-\n * import boundary so the loader stays oblivious to that distinction —\n * every entry it sees expects an on-disk `migrations/<id>/` directory.\n */\nexport function toDeclaredExtensions(\n inputs: ReadonlyArray<ExtensionPackInput>,\n): readonly DeclaredExtensionEntry[] {\n const entries: DeclaredExtensionEntry[] = [];\n for (const pack of inputs) {\n if (pack.contractSpace === undefined) continue;\n entries.push({ id: pack.id, targetId: pack.targetId });\n }\n return entries;\n}\n\n/**\n * Minimal aggregate-loader projection that extracts `id` + `targetId`\n * from raw extension pack descriptors **without invoking any\n * `contractSpace` accessor**. Inspects the own-property descriptor so\n * that getter-backed `contractSpace` declarations are detected but\n * never called.\n *\n * Inclusion semantics match {@link toDeclaredExtensions}: a data\n * property whose value is explicitly `undefined` is treated as \"no\n * contract-space declaration\" and skipped, mirroring the\n * `pack.contractSpace === undefined` check used on canonicalised\n * inputs. Prototype-chain `contractSpace` properties (no own\n * descriptor) are also skipped.\n *\n * This variant must be used by `buildContractSpaceAggregate` so that\n * the aggregate path (including `db verify`) never reads\n * `contractSpace.contractJson` from extension descriptors — the loader\n * always reads the contract from on-disk artefacts instead.\n */\nexport function toDeclaredExtensionsFromRaw(\n extensionPacks: ReadonlyArray<unknown>,\n): readonly DeclaredExtensionEntry[] {\n const entries: DeclaredExtensionEntry[] = [];\n for (const raw of extensionPacks) {\n if (typeof raw !== 'object' || raw === null) continue;\n const descriptor = Object.getOwnPropertyDescriptor(raw, 'contractSpace');\n if (descriptor === undefined) continue;\n if ('value' in descriptor && descriptor.value === undefined) continue;\n const pack = raw as { readonly id: string; readonly targetId: string };\n entries.push({ id: pack.id, targetId: pack.targetId });\n }\n return entries;\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport type { ControlExtensionDescriptor } from '@prisma-next/framework-components/control';\nimport type {\n ContractSpaceAggregate,\n LoadAggregateError,\n LoadAggregateInput,\n LoadAggregateOutput,\n} from '@prisma-next/migration-tools/aggregate';\nimport { loadContractSpaceAggregate } from '@prisma-next/migration-tools/aggregate';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { CliStructuredError } from './cli-errors';\nimport { toDeclaredExtensionsFromRaw } from './extension-pack-inputs';\n\n/**\n * Render a {@link LoadAggregateError} into a CLI structured-error\n * envelope. Preserves error codes `5001` (layout) and `5002` (marker /\n * disjointness / etc.) so existing integration tests and downstream\n * tooling continue to assert on the same `meta.violations[]` shape\n * they did under the old precheck/marker-check helpers.\n */\nexport function mapLoadAggregateError(error: LoadAggregateError): CliStructuredError {\n if (error.kind === 'layoutViolation') {\n const lines = error.violations.map((v) => `- [${v.kind}] ${v.spaceId}`);\n const summary =\n error.violations.length === 1\n ? 'Contract-space layout violation detected'\n : `Contract-space layout violations detected (${error.violations.length})`;\n return new CliStructuredError('5001', summary, {\n domain: 'MIG',\n why: `The on-disk \\`migrations/\\` directory and your \\`extensionPacks\\` declaration are not in agreement.\\n${lines.join('\\n')}`,\n fix: 'Run `prisma-next migrate` to materialise on-disk artefacts for declared extensions, or remove the orphan directory.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: error.violations.map((v) => ({\n kind: v.kind,\n spaceId: v.spaceId,\n })),\n },\n });\n }\n if (error.kind === 'disjointnessViolation') {\n return new CliStructuredError(\n '5002',\n `Contract-space disjointness violation: storage element \"${error.element}\" claimed by multiple spaces`,\n {\n domain: 'MIG',\n why: `Spaces ${error.claimedBy.map((s) => `\"${s}\"`).join(', ')} all claim the storage element \"${error.element}\". Each storage element must be owned by exactly one contract space.`,\n fix: 'Update the conflicting contracts so each storage element is claimed by exactly one space.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: [\n {\n kind: 'disjointness',\n spaceId: error.claimedBy.join(','),\n element: error.element,\n claimedBy: error.claimedBy,\n },\n ],\n },\n },\n );\n }\n if (error.kind === 'integrityFailure') {\n return new CliStructuredError(\n '5002',\n `Contract-space integrity failure for \"${error.spaceId}\"`,\n {\n domain: 'MIG',\n why: error.detail,\n fix: 'Run `prisma-next migrate` to refresh on-disk artefacts, or restore the on-disk `migrations/` directory from version control.',\n docsUrl: 'https://pris.ly/contract-spaces',\n meta: {\n violations: [{ kind: 'integrity', spaceId: error.spaceId, detail: error.detail }],\n },\n },\n );\n }\n if (error.kind === 'validationFailure') {\n return new CliStructuredError(\n '5002',\n `Contract-space contract validation failed for \"${error.spaceId}\"`,\n {\n domain: 'MIG',\n why: error.detail,\n fix: 'Run `prisma-next migrate` to refresh on-disk artefacts, or fix the extension descriptor producing the invalid contract.',\n meta: {\n violations: [{ kind: 'validation', spaceId: error.spaceId, detail: error.detail }],\n },\n },\n );\n }\n // targetMismatch\n return new CliStructuredError('5002', `Contract-space target mismatch for \"${error.spaceId}\"`, {\n domain: 'MIG',\n why: `Space \"${error.spaceId}\" targets \"${error.actual}\" but the project's adapter targets \"${error.expected}\".`,\n fix: 'Update the extension descriptor to target the configured database, or change the project adapter.',\n meta: {\n violations: [\n {\n kind: 'targetMismatch',\n spaceId: error.spaceId,\n expected: error.expected,\n actual: error.actual,\n },\n ],\n },\n });\n}\n\n/**\n * Inputs needed to compose the aggregate loader at the CLI surface.\n *\n * Keeps the loader framework-neutral (no `Config` import) by accepting\n * already-resolved structural inputs: validated app contract, target\n * id, migrations root directory, and the set of extension descriptors.\n */\nexport interface BuildAggregateInputs<TFamilyId extends string, TTargetId extends string> {\n readonly targetId: TTargetId;\n readonly migrationsDir: string;\n readonly appContract: Contract;\n readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;\n readonly deserializeContract: (contractJson: unknown) => Contract;\n /**\n * App-space migration packages to hydrate the app member's\n * migration graph with. Defaults to `[]` (matches the `db init` /\n * `db update` daily-driver behaviour, where the app's authored\n * `migrations/` graph is not walked — the planner uses the synth\n * strategy for the app member instead).\n *\n * `migrate` callers thread the user's authored app-space\n * packages (loaded via `loadMigrationPackages(appMigrationsDir)`)\n * through here so the graph-walk strategy can plot a path through\n * them — the prod-time replay path explicitly forbids synth.\n */\n readonly appMigrationPackages?: ReadonlyArray<OnDiskMigrationPackage>;\n}\n\n/**\n * Run the aggregate loader at the CLI surface, mapping any\n * {@link LoadAggregateError} into a {@link CliStructuredError} envelope.\n *\n * App-side migration packages flow through `inputs.appMigrationPackages`\n * (defaulting to `[]`). `db init` / `db update` leave it empty: the\n * planner's `synth` strategy is used for the app member (driven by\n * `callerPolicy.ignoreGraphFor`), so the app's authored `migrations/`\n * graph does not need to be walked. `migrate` threads the\n * already-loaded app-space packages through so the graph-walk strategy\n * can plot a path through them — replay forbids synth.\n *\n * @see specs/contract-space-aggregate-spec.md § Loader.\n */\nexport async function buildContractSpaceAggregate<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n inputs: BuildAggregateInputs<TFamilyId, TTargetId>,\n): Promise<Result<ContractSpaceAggregate, CliStructuredError>> {\n const declaredExtensions = toDeclaredExtensionsFromRaw(\n inputs.extensionPacks as ReadonlyArray<unknown>,\n );\n\n const loadInput: LoadAggregateInput = {\n targetId: inputs.targetId,\n migrationsDir: inputs.migrationsDir,\n appContract: inputs.appContract,\n declaredExtensions,\n deserializeContract: inputs.deserializeContract,\n appMigrationPackages: inputs.appMigrationPackages ?? [],\n };\n\n const result: LoadAggregateOutput = await loadContractSpaceAggregate(loadInput);\n if (!result.ok) {\n return notOk(mapLoadAggregateError(result.failure));\n }\n return ok(result.value.aggregate);\n}\n"],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- //#region src/utils/global-flags.d.ts
2
- type OutputFormat = 'pretty' | 'json';
3
- interface GlobalFlags {
4
- readonly format: OutputFormat;
5
- readonly explicitFormat: boolean;
6
- readonly json?: boolean;
7
- readonly quiet?: boolean;
8
- readonly verbose?: number;
9
- readonly color?: boolean;
10
- readonly interactive?: boolean;
11
- readonly yes?: boolean;
12
- }
13
- //#endregion
14
- export { GlobalFlags as t };
15
- //# sourceMappingURL=global-flags-CdE7M0d9.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"global-flags-CdE7M0d9.d.mts","names":[],"sources":["../src/utils/global-flags.ts"],"mappings":";KAMY,YAAA;AAAA,UAEK,WAAA;EAAA,SACN,MAAA,EAAQ,YAAA;EAAA,SACR,cAAA;EAAA,SACA,IAAA;EAAA,SACA,KAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA;EAAA,SACA,WAAA;EAAA,SACA,GAAA;AAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration-plan-C2jeH1J5.mjs","names":[],"sources":["../src/utils/contract-space-seed-phase.ts","../src/commands/migration-plan.ts"],"sourcesContent":["import { materialiseExtensionMigrationPackageIfMissing } from '@prisma-next/migration-tools/io';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport type { MigrationOps } from '@prisma-next/migration-tools/package';\nimport {\n emitContractSpaceArtefacts,\n planAllSpaces,\n readContractSpaceHeadRef,\n type SpacePlanOutput,\n spaceMigrationDirectory,\n} from '@prisma-next/migration-tools/spaces';\n\n/**\n * In-memory authored migration package shipped by an extension descriptor.\n * Mirrors `MigrationPackage` from `@prisma-next/migration-tools/io` (the\n * on-disk shape minus `dirPath`); redeclared structurally here so the\n * CLI helper does not couple to any family's `ExtensionMigrationPackage`\n * type — any family that ships pre-built migration packages can pass\n * them through unchanged.\n */\nexport interface DescriptorMigrationPackage {\n readonly dirName: string;\n readonly metadata: MigrationMetadata;\n readonly ops: MigrationOps;\n}\n\n/**\n * Minimal descriptor view consumed by the seed phase. Mirrors the shape\n * the SQL family ships on each declared extension entry; only the fields\n * the seed phase needs are surfaced.\n */\nexport interface SeedPhaseExtensionInput {\n readonly id: string;\n readonly contractSpace?: {\n readonly contractJson: unknown;\n readonly headRef: { readonly hash: string; readonly invariants: readonly string[] };\n readonly migrations: readonly DescriptorMigrationPackage[];\n };\n}\n\nexport interface ContractSpaceSeedPhaseInputs {\n readonly migrationsDir: string;\n readonly extensionPacks: ReadonlyArray<SeedPhaseExtensionInput>;\n}\n\n/**\n * One per-space record describing what the seed phase did for an\n * extension contract space. Surfaced verbatim by the caller (typically\n * `migration plan`) so users see a single line per touched extension.\n *\n * - `action: 'updated'` — either the on-disk head pointer changed, or\n * one or more new descriptor-shipped migration packages were\n * materialised into `migrations/<spaceId>/<dirName>/`.\n * - `action: 'unchanged'` — the on-disk head already matched the\n * descriptor and no new migration packages needed to be written.\n *\n * Either way, the artefacts (`contract.json`, `contract.d.ts`,\n * `refs/head.json`) are re-emitted: the framework owns those files and\n * makes the re-emit observably idempotent at the byte level.\n */\nexport interface ContractSpaceSeedPhaseRecord {\n readonly spaceId: string;\n readonly action: 'updated' | 'unchanged';\n readonly priorHash: string | null;\n readonly newHash: string;\n readonly newMigrationDirs: readonly string[];\n}\n\nexport interface ContractSpaceSeedPhaseResult {\n readonly seeded: readonly ContractSpaceSeedPhaseRecord[];\n}\n\n/**\n * Phase-1 of the two-phase `migration plan` pipeline (sub-spec § 4).\n *\n * For every extension that exposes a `contractSpace`:\n *\n * 1. Read the on-disk head ref (returns `null` on first emit).\n * 2. Re-emit `contract.json` / `contract.d.ts` / `refs/head.json`\n * unconditionally via {@link emitContractSpaceArtefacts}. The\n * framework owns these files; re-emit is the contract.\n * 3. Materialise any descriptor-shipped migration packages not yet on\n * disk via {@link materialiseExtensionMigrationPackageIfMissing}.\n * Existing packages are left untouched (by-existence skip).\n *\n * The return value lets the caller render a per-space status line and\n * lets the phase-2 aggregate loader run on a now-consistent disk state\n * (every loaded extension is guaranteed to have its head ref pinned\n * to the descriptor's hash and to ship every package the descriptor\n * declares).\n *\n * Output ordering is deterministic and alphabetical by spaceId (via\n * {@link planAllSpaces}, which also detects duplicate spaceIds). This\n * matches the canonical sort order used by every other aggregate\n * surface (`migrate`, `migration status`, the runner).\n */\nexport async function runContractSpaceSeedPhase(\n inputs: ContractSpaceSeedPhaseInputs,\n): Promise<ContractSpaceSeedPhaseResult> {\n const planInputs = inputs.extensionPacks\n .filter(\n (\n pack,\n ): pack is SeedPhaseExtensionInput & {\n contractSpace: NonNullable<SeedPhaseExtensionInput['contractSpace']>;\n } => pack.contractSpace !== undefined,\n )\n .map((pack) => ({\n spaceId: pack.id,\n priorContract: null,\n newContract: pack.contractSpace.contractJson,\n __pack: pack.contractSpace,\n }));\n\n // `planAllSpaces` brings deterministic alphabetical ordering and\n // duplicate-spaceId detection. The \"planner\" callback is a no-op\n // pass-through that simply returns the descriptor's pre-built\n // migration packages.\n const planned: readonly SpacePlanOutput<DescriptorMigrationPackage>[] = planAllSpaces(\n planInputs,\n (input) =>\n (\n input as typeof input & {\n readonly __pack: NonNullable<SeedPhaseExtensionInput['contractSpace']>;\n }\n ).__pack.migrations,\n );\n\n // Reassemble a spaceId → descriptor lookup so the loop below can read\n // the contractJson / headRef without leaking the typed-cast back into\n // `planAllSpaces`'s output shape.\n const descriptorBySpace = new Map<\n string,\n NonNullable<SeedPhaseExtensionInput['contractSpace']>\n >();\n for (const pack of inputs.extensionPacks) {\n if (pack.contractSpace !== undefined) descriptorBySpace.set(pack.id, pack.contractSpace);\n }\n\n const seeded: ContractSpaceSeedPhaseRecord[] = [];\n for (const space of planned) {\n const descriptor = descriptorBySpace.get(space.spaceId);\n if (descriptor === undefined) continue;\n\n const onDiskHeadRef = await readContractSpaceHeadRef(inputs.migrationsDir, space.spaceId);\n const priorHash = onDiskHeadRef?.hash ?? null;\n\n await emitContractSpaceArtefacts(inputs.migrationsDir, space.spaceId, {\n contract: descriptor.contractJson,\n contractDts: buildPlaceholderContractDts(space.spaceId),\n headRef: { hash: descriptor.headRef.hash, invariants: descriptor.headRef.invariants },\n });\n\n const spaceDir = spaceMigrationDirectory(inputs.migrationsDir, space.spaceId);\n const newMigrationDirs: string[] = [];\n for (const pkg of space.migrationPackages) {\n const { written } = await materialiseExtensionMigrationPackageIfMissing(spaceDir, pkg);\n if (written) newMigrationDirs.push(pkg.dirName);\n }\n\n const action: ContractSpaceSeedPhaseRecord['action'] =\n priorHash !== descriptor.headRef.hash || newMigrationDirs.length > 0\n ? 'updated'\n : 'unchanged';\n\n seeded.push({\n spaceId: space.spaceId,\n action,\n priorHash,\n newHash: descriptor.headRef.hash,\n newMigrationDirs,\n });\n }\n\n return { seeded };\n}\n\n/**\n * Placeholder `.d.ts` content for an extension space's on-disk mirror.\n *\n * Rendering a fully-typed `.d.ts` for an extension contract requires\n * the SQL-family renderer with the codec / typemap registry threaded\n * through; until that integration ships, the on-disk `.d.ts` is a\n * stub `export {};` module that documents how consumers should\n * validate the sibling `contract.json`. The stub typechecks on its\n * own and does not need any TypeScript suppressions.\n */\nfunction buildPlaceholderContractDts(spaceId: string): string {\n return [\n '/**',\n ` * Placeholder \\`.d.ts\\` for extension space \"${spaceId}\".`,\n ' *',\n ' * The framework re-emits this file on every `migration plan` run',\n ' * alongside `contract.json` and `refs/head.json`. A typed `.d.ts`',\n ' * rendering pass for extension contracts is tracked separately;',\n ' * until that ships, consumers should import `contract.json`',\n ' * and pass it through the target descriptor’s `contractSerializer`.',\n ' */',\n 'export {};',\n '',\n ].join('\\n');\n}\n","import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport {\n type ControlFamilyInstance,\n createControlStack,\n hasOperationPreview,\n type MigrationPlanOperation,\n type OperationPreview,\n} from '@prisma-next/framework-components/control';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { computeMigrationHash } from '@prisma-next/migration-tools/hash';\nimport { deriveProvidedInvariants } from '@prisma-next/migration-tools/invariants';\nimport {\n copyFilesWithRename,\n formatMigrationDirName,\n writeMigrationPackage,\n} from '@prisma-next/migration-tools/io';\nimport type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';\nimport { findLatestMigration } from '@prisma-next/migration-tools/migration-graph';\nimport { writeMigrationTs } from '@prisma-next/migration-tools/migration-ts';\nimport { parseContractRef } from '@prisma-next/migration-tools/ref-resolution';\nimport { readRefs } from '@prisma-next/migration-tools/refs';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { join, relative } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport {\n type CliErrorConflict,\n CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorMigrationPlanningFailed,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n mapMigrationToolsError,\n mapRefResolutionError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n getTargetMigrations,\n loadMigrationPackages,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { buildContractSpaceAggregate } from '../utils/contract-space-aggregate-loader';\nimport { runContractSpaceSeedPhase } from '../utils/contract-space-seed-phase';\nimport { toExtensionInputs } from '../utils/extension-pack-inputs';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport { assertFrameworkComponentsCompatible } from '../utils/framework-components';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI, type TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationPlanOptions extends CommonCommandOptions {\n readonly config?: string;\n readonly name?: string;\n readonly from?: string;\n}\n\n/**\n * Load a predecessor migration's destination contract from its sibling\n * `end-contract.json` on disk and route it through the family's\n * `ContractSerializer` (via `deserializeContract`) so the in-memory shape\n * is the hydrated `Contract` every other caller sees. Bypassing this\n * seam was the root cause of TML-2536: a raw `JSON.parse(...) as Contract`\n * here let polymorphic `storage.types` entries reach the planner without\n * the `kind` discriminator the planner dispatches on.\n *\n * Throws `CliStructuredError` with:\n * - `errorFileNotFound` when the sibling file is missing — the user\n * has likely deleted or never authored the snapshot, and the\n * message names the file and points them at re-emitting from the\n * source.\n * - `errorContractValidationFailed` when the JSON parses but the\n * family deserializer rejects it (legacy untagged shape, structural\n * mismatch, etc.) — the message names the predecessor's path so\n * the operator can locate the bad snapshot.\n */\nasync function readPredecessorEndContract(\n migrationDir: string,\n familyInstance: ControlFamilyInstance<string, unknown>,\n): Promise<Contract> {\n const path = join(migrationDir, 'end-contract.json');\n let raw: string;\n try {\n raw = await readFile(path, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n throw errorFileNotFound(path, {\n why: `Predecessor migration is missing its destination contract snapshot at ${path}`,\n fix: 'Re-emit the predecessor migration (`prisma-next migration plan` from its source) so its sibling `end-contract.json` is restored, then re-run this command.',\n });\n }\n throw error;\n }\n try {\n return familyInstance.deserializeContract(JSON.parse(raw) as unknown);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n throw error;\n }\n throw errorContractValidationFailed(\n `Predecessor contract at ${path} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path } },\n );\n }\n}\n\nexport interface MigrationPlanResult {\n readonly ok: boolean;\n readonly noOp: boolean;\n readonly from: string | null;\n readonly to: string;\n readonly dir?: string;\n /**\n * Extension-space migration packages materialised onto disk during this\n * `plan` run. Each entry names a `migrations/<spaceId>/<dirName>/`\n * tree the framework wrote alongside the app-space migration directory.\n * Empty when the project has no extension packs declaring a contract\n * space, or when every extension-space package is already on disk.\n *\n * Surfacing these in the result (rather than only via `ui.step` log\n * lines) makes the cross-space side effect explicit to JSON consumers\n * and the success-summary renderer — the same multi-space side effect\n * that `migrate` will replay.\n */\n readonly emittedExtensionDirs: readonly { readonly spaceId: string; readonly dirName: string }[];\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the migration plan operations.\n * Replaces the previous `sql?: readonly string[]` field; consumers should\n * read `result.preview?.statements`.\n */\n readonly preview?: OperationPreview;\n readonly summary: string;\n /**\n * When true, `migration.ts` was written but contains unfilled\n * `placeholder(...)` calls. The user must edit the file and then run\n * `node migration.ts` to self-emit `ops.json` / `migration.json`.\n */\n readonly pendingPlaceholders?: boolean;\n readonly timings: {\n readonly total: number;\n };\n}\n\nasync function executeMigrationPlanCommand(\n options: MigrationPlanOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n): Promise<Result<MigrationPlanResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } =\n resolveMigrationPaths(options.config, config);\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (options.from) {\n details.push({ label: 'from', value: options.from });\n }\n if (options.name) {\n details.push({ label: 'name', value: options.name });\n }\n const header = formatStyledHeader({\n command: 'migration plan',\n description: 'Plan a migration from contract changes',\n url: 'https://pris.ly/migration-plan',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file (the \"to\" contract)\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Construct the family instance up-front so on-disk reads (the app\n // contract here + every `readPredecessorEndContract` below) cross the\n // serializer seam at the read site, not after the planner has already\n // started dispatching on raw shapes. See TML-2536.\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n\n let toContract: Contract;\n try {\n toContract = familyInstance.deserializeContract(JSON.parse(contractJsonContent) as unknown);\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract at ${contractPathAbsolute} failed to deserialize: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n const rawStorageHash = toContract.storage?.storageHash;\n if (typeof rawStorageHash !== 'string') {\n return notOk(\n errorContractValidationFailed('Contract is missing storageHash', {\n where: { path: contractPathAbsolute },\n }),\n );\n }\n const toStorageHash = rawStorageHash;\n\n // Read existing migrations and determine \"from\" contract\n let fromContract: Contract | null = null;\n let fromHash: string | null = null;\n let fromContractSourceDir: string | null = null;\n\n try {\n const { bundles, graph } = await loadMigrationPackages(appMigrationsDir);\n\n if (options.from) {\n const refs = await readRefs(resolveMigrationPaths(options.config, config).refsDir);\n const refResult = parseContractRef(options.from, { graph, refs });\n if (!refResult.ok) {\n return notOk(mapRefResolutionError(refResult.failure));\n }\n fromHash = refResult.value.hash;\n const matchingBundle = bundles.find((p) => p.metadata.to === fromHash);\n if (!matchingBundle) {\n return notOk(\n errorUnexpected(\n `No migration bundle found for --from \"${options.from}\" (resolved hash: ${fromHash})`,\n {\n why: `The ref resolved successfully but no on-disk migration package has an end-contract hash matching ${fromHash}.`,\n fix: 'Provide a ref or hash that corresponds to an existing migration package, or run `migration list` to see available migrations.',\n },\n ),\n );\n }\n fromContractSourceDir = matchingBundle.dirPath;\n fromContract = await readPredecessorEndContract(fromContractSourceDir, familyInstance);\n } else {\n const latestMigration = findLatestMigration(graph);\n if (latestMigration) {\n fromHash = latestMigration.to;\n const leafPkg = bundles.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n if (leafPkg) {\n fromContractSourceDir = leafPkg.dirPath;\n fromContract = await readPredecessorEndContract(fromContractSourceDir, familyInstance);\n }\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n // `readPredecessorEndContract` raises a `CliStructuredError` directly\n // for the missing-snapshot case so the operator gets a precise\n // why/fix; pass it through unchanged rather than re-wrapping.\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n // Wrap unexpected (non-MigrationToolsError) failures from the migration\n // load phase in a structured CLI envelope. Letting them throw would\n // bypass `handleResult()` and crash the command — see CLI structured-\n // errors guideline (CliStructuredError + Result pattern).\n const message = error instanceof Error ? error.message : String(error);\n return notOk(\n errorUnexpected(message, {\n why: `Unexpected error while loading migrations: ${message}`,\n }),\n );\n }\n\n // Phase 1 — seed: unconditionally re-emit per-space pinned artefacts\n // (contract.json / contract.d.ts / refs/head.json) and materialise any\n // descriptor-shipped migration packages not yet on disk. Runs before\n // the no-op check so that an extension bump alone (with no structural\n // app-space change) still re-pins extension artefacts on disk.\n const canonicalExtensionInputs = toExtensionInputs(config.extensionPacks ?? []);\n const seedResult = await runContractSpaceSeedPhase({\n migrationsDir,\n extensionPacks: canonicalExtensionInputs,\n });\n if (!flags.json && !flags.quiet) {\n for (const record of seedResult.seeded) {\n if (record.action === 'updated') {\n const pkgSuffix =\n record.newMigrationDirs.length > 0\n ? `; ${record.newMigrationDirs.length} new migration package(s) materialised`\n : '';\n ui.step(`Updated ${record.spaceId} to ${record.newHash}${pkgSuffix}`);\n }\n }\n }\n const emittedExtensionDirs = seedResult.seeded.flatMap((r) =>\n r.newMigrationDirs.map((dirName) => ({ spaceId: r.spaceId, dirName })),\n );\n\n // Check for no-op (same hash means no changes)\n if (fromHash === toStorageHash) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: true,\n from: fromHash,\n to: toStorageHash,\n operations: [],\n emittedExtensionDirs,\n summary: 'No changes detected between contracts',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n // Check target supports migrations\n const migrations = getTargetMigrations(config.target);\n if (!migrations) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n // Phase 2 — load: build the aggregate against the now-consistent disk\n // state that phase 1 just seeded. The seed phase guarantees every\n // declared extension has its head ref pinned, so the loader's\n // declaredButUnmigrated precheck always passes here. The app contract\n // was already routed through `familyInstance.deserializeContract` at the\n // read site above (see TML-2536), so it's the hydrated `Contract`\n // here — no second validation pass needed.\n const aggregateResult = await buildContractSpaceAggregate({\n targetId: config.target.targetId,\n migrationsDir,\n appContract: toContract,\n extensionPacks: config.extensionPacks ?? [],\n deserializeContract: (json: unknown) => familyInstance.deserializeContract(json),\n });\n if (!aggregateResult.ok) {\n return notOk(aggregateResult.failure);\n }\n const aggregate = aggregateResult.value;\n\n const frameworkComponents = assertFrameworkComponentsCompatible(\n config.family.familyId,\n config.target.targetId,\n [config.target, config.adapter, ...(config.extensionPacks ?? [])],\n );\n\n // Build manifest and write migration package\n const timestamp = new Date();\n const slug = options.name ?? 'migration';\n const dirName = formatMigrationDirName(timestamp, slug);\n const packageDir = join(appMigrationsDir, dirName);\n\n const baseMetadata: Omit<MigrationMetadata, 'migrationHash' | 'providedInvariants'> = {\n from: fromHash,\n to: toStorageHash,\n hints: {\n used: [],\n applied: [],\n plannerVersion: '2.0.0',\n },\n labels: [],\n createdAt: timestamp.toISOString(),\n };\n\n try {\n const planner = migrations.createPlanner(familyInstance);\n const fromSchema = migrations.contractToSchema(fromContract, frameworkComponents);\n const plannerResult = planner.plan({\n contract: aggregate.app.contract,\n schema: fromSchema,\n policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },\n fromContract,\n frameworkComponents,\n spaceId: aggregate.app.spaceId,\n });\n if (plannerResult.kind === 'failure') {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: plannerResult.conflicts as readonly CliErrorConflict[],\n }),\n );\n }\n\n // Accessing .operations triggers toOp() on each call. If any call\n // is a DataTransformCall with an unfilled placeholder stub, toOp()\n // throws PN-MIG-2001. We catch that here so the migration can still\n // be scaffolded with `ops: []`; the user fills the placeholder, then\n // re-runs `node migration.ts` to attest with the real ops.\n let plannedOps: readonly MigrationPlanOperation[] = [];\n let hasPlaceholders = false;\n try {\n plannedOps = plannerResult.plan.operations;\n if (plannedOps.length === 0) {\n return notOk(\n errorMigrationPlanningFailed({\n conflicts: [\n {\n kind: 'unsupportedChange',\n summary:\n 'Contract changed but planner produced no operations. ' +\n 'This indicates unsupported or ignored changes.',\n },\n ],\n }),\n );\n }\n } catch (e) {\n if (CliStructuredError.is(e) && e.domain === 'MIG' && e.code === '2001') {\n hasPlaceholders = true;\n } else {\n throw e;\n }\n }\n\n const migrationTsContent = plannerResult.plan.renderTypeScript();\n\n // Always-attest: compute migrationHash over (metadata, ops). When\n // placeholders blocked lowering, ops is `[]` and the hash is computed\n // over the empty list — re-emitting after the user fills the placeholder\n // produces a different hash (over the real ops). This is intentional;\n // there is no on-disk \"draft\" state.\n const opsForWrite = hasPlaceholders ? [] : plannedOps;\n const metadataWithInvariants: Omit<MigrationMetadata, 'migrationHash'> = {\n ...baseMetadata,\n providedInvariants: deriveProvidedInvariants(opsForWrite),\n };\n const metadata: MigrationMetadata = {\n ...metadataWithInvariants,\n migrationHash: computeMigrationHash(metadataWithInvariants, opsForWrite),\n };\n\n await writeMigrationPackage(packageDir, metadata, opsForWrite);\n const destinationArtifacts = getEmittedArtifactPaths(contractPathAbsolute);\n await copyFilesWithRename(packageDir, [\n { sourcePath: destinationArtifacts.jsonPath, destName: 'end-contract.json' },\n { sourcePath: destinationArtifacts.dtsPath, destName: 'end-contract.d.ts' },\n ]);\n if (fromContractSourceDir !== null) {\n const sourceArtifacts = getEmittedArtifactPaths(\n join(fromContractSourceDir, 'end-contract.json'),\n );\n await copyFilesWithRename(packageDir, [\n { sourcePath: sourceArtifacts.jsonPath, destName: 'start-contract.json' },\n { sourcePath: sourceArtifacts.dtsPath, destName: 'start-contract.d.ts' },\n ]);\n }\n await writeMigrationTs(packageDir, migrationTsContent);\n\n if (hasPlaceholders) {\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), packageDir),\n operations: [],\n emittedExtensionDirs,\n pendingPlaceholders: true,\n summary:\n 'Planned migration with placeholder(s) — edit migration.ts then run `node migration.ts` to self-emit',\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n }\n\n const preview = hasOperationPreview(familyInstance)\n ? familyInstance.toOperationPreview(plannedOps)\n : undefined;\n const result: MigrationPlanResult = {\n ok: true,\n noOp: false,\n from: fromHash,\n to: toStorageHash,\n dir: relative(process.cwd(), packageDir),\n operations: plannedOps.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n emittedExtensionDirs,\n ...(preview !== undefined ? { preview } : {}),\n summary: buildPlanSummary(plannedOps.length, emittedExtensionDirs.length),\n timings: { total: Date.now() - startTime },\n };\n return ok(result);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n const message = error instanceof Error ? error.message : String(error);\n return notOk(\n errorUnexpected(message, {\n why: `Unexpected error during migration plan: ${message}`,\n }),\n );\n }\n}\n\nexport function createMigrationPlanCommand(): Command {\n const command = new Command('plan');\n setCommandDescriptions(\n command,\n 'Plan a migration from contract changes',\n 'Compares the emitted contract against the latest on-disk migration state and\\n' +\n 'produces a new migration package with the required operations. No database\\n' +\n 'connection is needed — this is a fully offline operation.',\n );\n setCommandExamples(command, [\n 'prisma-next migration plan',\n 'prisma-next migration plan --name add-users-table',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--name <slug>', 'Name slug for the migration directory', 'migration')\n .option(\n '--from <contract>',\n 'Starting contract reference (hash, prefix, ref name, migration dir name, <dir>^, or ./path)',\n )\n .action(async (options: MigrationPlanOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const startTime = Date.now();\n\n const ui = createTerminalUI(flags);\n const result = await executeMigrationPlanCommand(options, flags, ui, startTime);\n\n const exitCode = handleResult(result, flags, ui, (planResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(planResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationPlanOutput(planResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n\n/**\n * Compose the success-line summary so the cross-space side effect\n * (extension-space migration packages materialised on disk during\n * this `plan` run) is visible in the top line — not just in the\n * step log above it.\n *\n * Example outputs:\n * - `Planned 3 operation(s)` (app-space-only project)\n * - `Planned 3 operation(s); materialised 1 extension-space migration` (one extension)\n * - `Planned 3 operation(s); materialised 2 extension-space migrations` (two extensions)\n *\n * Locks AC3 at the summary-line level: a reader of the success line\n * can tell that something happened beyond the app space.\n */\nfunction buildPlanSummary(plannedOpsCount: number, emittedExtensionDirsCount: number): string {\n const base = `Planned ${plannedOpsCount} operation(s)`;\n if (emittedExtensionDirsCount === 0) return base;\n const noun =\n emittedExtensionDirsCount === 1 ? 'extension-space migration' : 'extension-space migrations';\n return `${base}; materialised ${emittedExtensionDirsCount} ${noun}`;\n}\n\nexport function formatMigrationPlanOutput(result: MigrationPlanResult, flags: GlobalFlags): string {\n const lines: string[] = [];\n const useColor = flags.color !== false;\n\n const green_ = useColor ? (s: string) => `\\x1b[32m${s}\\x1b[0m` : (s: string) => s;\n const yellow_ = useColor ? (s: string) => `\\x1b[33m${s}\\x1b[0m` : (s: string) => s;\n const dim_ = useColor ? (s: string) => `\\x1b[2m${s}\\x1b[0m` : (s: string) => s;\n\n // Renders the extension-space materialisation block + canonical apply-step\n // hint shared by the no-op, placeholder, and full-plan branches. The app\n // space short-circuits do not skip it: an extension-only bump emits new\n // `migrations/<spaceId>/<dirName>/` directories on disk that the user\n // still has to apply, so the success line must surface them.\n function appendEmittedExtensions(): void {\n if (result.emittedExtensionDirs.length === 0) return;\n lines.push('');\n lines.push(dim_('Emitted extension migrations:'));\n for (const entry of result.emittedExtensionDirs) {\n lines.push(dim_(` ${entry.spaceId} → migrations/${entry.spaceId}/${entry.dirName}`));\n }\n lines.push('');\n lines.push(\n `Next: review the extension migrations above, then run ${green_('prisma-next migrate')}.`,\n );\n }\n\n if (result.noOp) {\n lines.push(`${green_('✔')} No changes detected`);\n lines.push(dim_(` from: ${result.from}`));\n lines.push(dim_(` to: ${result.to}`));\n appendEmittedExtensions();\n return lines.join('\\n');\n }\n\n if (result.pendingPlaceholders) {\n lines.push(`${yellow_('⚠')} ${result.summary}`);\n lines.push('');\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.dir) {\n lines.push(dim_(`dir: ${result.dir}`));\n }\n lines.push('');\n lines.push(\n 'Open migration.ts and replace each `placeholder(...)` call with your actual query.',\n );\n lines.push(`Then run: ${green_(`node ${result.dir ?? '<dir>'}/migration.ts`)}`);\n appendEmittedExtensions();\n return lines.join('\\n');\n }\n\n lines.push(`${green_('✔')} ${result.summary}`);\n lines.push('');\n\n if (result.operations.length > 0) {\n lines.push(dim_('│'));\n for (let i = 0; i < result.operations.length; i++) {\n const op = result.operations[i]!;\n const isLast = i === result.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n // operationClass tag is intentionally NOT inlined per spec:\n // a destructive footer warning still surfaces below this list.\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${yellow_('(destructive)')}` : '';\n lines.push(`${dim_(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = result.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${yellow_('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n lines.push('');\n }\n\n lines.push(dim_(`from: ${result.from}`));\n lines.push(dim_(`to: ${result.to}`));\n if (result.dir) {\n lines.push(dim_(`App space → ${result.dir}`));\n }\n // Per-space block: surface the extension-space directories materialised\n // alongside the app-space migration. Without this block the cross-space\n // side effect is invisible in the success summary (e2e finding F1).\n for (const entry of result.emittedExtensionDirs) {\n lines.push(\n dim_(`Extension space ${entry.spaceId} → migrations/${entry.spaceId}/${entry.dirName}`),\n );\n }\n\n lines.push('');\n // The \"Next:\" hint always points at the canonical apply path\n // (`prisma-next migrate`) regardless of how many spaces were\n // materialised — `db update` is a dev-time convenience, not the\n // canonical replay step.\n lines.push(\n `Next: review ${green_(result.dir ?? '<dir>')} if needed, then run ${green_('prisma-next migrate')}.`,\n );\n\n if (result.preview && result.preview.statements.length > 0) {\n // The non-empty length is already guaranteed by the surrounding check, so\n // a plain `every` here is equivalent to the helper in formatters/migrations.ts.\n const allSql = result.preview.statements.every((s) => s.language === 'sql');\n lines.push('');\n lines.push(dim_(allSql ? 'DDL preview' : 'Operation preview'));\n lines.push('');\n for (const statement of result.preview.statements) {\n const trimmed = statement.text.trim();\n if (!trimmed) continue;\n const line = statement.language === 'sql' && !trimmed.endsWith(';') ? `${trimmed};` : trimmed;\n lines.push(line);\n }\n }\n\n if (flags.verbose && result.timings) {\n lines.push('');\n lines.push(dim_(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\nexport type PrefixResolutionFailure =\n | { reason: 'ambiguous'; count: number }\n | { reason: 'not-found' };\n\n/**\n * Resolve a migration package by **target contract hash** (`metadata.to`)\n * using exact match or prefix match.\n *\n * Note: matches `metadata.to` (the contract hash this migration produces),\n * not `metadata.migrationHash` (the package's content-addressed identity).\n * Tries exact match first, then prefix match (auto-prepending `sha256:` when\n * the needle omits the scheme). Returns the matched package on success, or a\n * discriminated failure indicating whether the prefix was ambiguous or simply\n * not found.\n *\n * @internal Exported for testing only.\n */\nexport function resolveBundleByPrefix<T extends { metadata: { to: string } }>(\n bundles: readonly T[],\n needle: string,\n): Result<T, PrefixResolutionFailure> {\n const exact = bundles.find((p) => p.metadata.to === needle);\n if (exact) return ok(exact);\n\n const prefixWithScheme = needle.startsWith('sha256:') ? needle : `sha256:${needle}`;\n const candidates = bundles.filter((p) => p.metadata.to.startsWith(prefixWithScheme));\n\n if (candidates.length === 1) return ok(candidates[0]!);\n if (candidates.length > 1) return notOk({ reason: 'ambiguous', count: candidates.length });\n return notOk({ reason: 'not-found' });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+FA,eAAsB,0BACpB,QACuC;CAoBvC,MAAM,UAAkE,cAnBrD,OAAO,eACvB,QAEG,SAGG,KAAK,kBAAkB,KAAA,EAC7B,CACA,KAAK,UAAU;EACd,SAAS,KAAK;EACd,eAAe;EACf,aAAa,KAAK,cAAc;EAChC,QAAQ,KAAK;EACd,EAOS,GACT,UAEG,MAGA,OAAO,WACZ;CAKD,MAAM,oCAAoB,IAAI,KAG3B;CACH,KAAK,MAAM,QAAQ,OAAO,gBACxB,IAAI,KAAK,kBAAkB,KAAA,GAAW,kBAAkB,IAAI,KAAK,IAAI,KAAK,cAAc;CAG1F,MAAM,SAAyC,EAAE;CACjD,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,aAAa,kBAAkB,IAAI,MAAM,QAAQ;EACvD,IAAI,eAAe,KAAA,GAAW;EAG9B,MAAM,aAAY,MADU,yBAAyB,OAAO,eAAe,MAAM,QAAQ,GACxD,QAAQ;EAEzC,MAAM,2BAA2B,OAAO,eAAe,MAAM,SAAS;GACpE,UAAU,WAAW;GACrB,aAAa,4BAA4B,MAAM,QAAQ;GACvD,SAAS;IAAE,MAAM,WAAW,QAAQ;IAAM,YAAY,WAAW,QAAQ;IAAY;GACtF,CAAC;EAEF,MAAM,WAAW,wBAAwB,OAAO,eAAe,MAAM,QAAQ;EAC7E,MAAM,mBAA6B,EAAE;EACrC,KAAK,MAAM,OAAO,MAAM,mBAAmB;GACzC,MAAM,EAAE,YAAY,MAAM,8CAA8C,UAAU,IAAI;GACtF,IAAI,SAAS,iBAAiB,KAAK,IAAI,QAAQ;;EAGjD,MAAM,SACJ,cAAc,WAAW,QAAQ,QAAQ,iBAAiB,SAAS,IAC/D,YACA;EAEN,OAAO,KAAK;GACV,SAAS,MAAM;GACf;GACA;GACA,SAAS,WAAW,QAAQ;GAC5B;GACD,CAAC;;CAGJ,OAAO,EAAE,QAAQ;;;;;;;;;;;;AAanB,SAAS,4BAA4B,SAAyB;CAC5D,OAAO;EACL;EACA,iDAAiD,QAAQ;EACzD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;;;;ACrHd,eAAe,2BACb,cACA,gBACmB;CACnB,MAAM,OAAO,KAAK,cAAc,oBAAoB;CACpD,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,MAAM,QAAQ;UAC5B,OAAO;EACd,IAAI,iBAAiB,SAAU,MAA4B,SAAS,UAClE,MAAM,kBAAkB,MAAM;GAC5B,KAAK,yEAAyE;GAC9E,KAAK;GACN,CAAC;EAEJ,MAAM;;CAER,IAAI;EACF,OAAO,eAAe,oBAAoB,KAAK,MAAM,IAAI,CAAY;UAC9D,OAAO;EACd,IAAI,mBAAmB,GAAG,MAAM,EAC9B,MAAM;EAER,MAAM,8BACJ,2BAA2B,KAAK,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAChH,EAAE,OAAO,EAAE,MAAM,EAAE,CACpB;;;AA8CL,eAAe,4BACb,SACA,OACA,IACA,WAC0D;CAC1D,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,EAAE,YAAY,eAAe,kBAAkB,0BACnD,sBAAsB,QAAQ,QAAQ,OAAO;CAE/C,MAAM,uBAAuB,oBAAoB,OAAO;CACxD,MAAM,eAAe,SAAS,QAAQ,KAAK,EAAE,qBAAqB;CAElE,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAM,UAAmD;GACvD;IAAE,OAAO;IAAU,OAAO;IAAY;GACtC;IAAE,OAAO;IAAY,OAAO;IAAc;GAC1C;IAAE,OAAO;IAAc,OAAO;IAAuB;GACtD;EACD,IAAI,QAAQ,MACV,QAAQ,KAAK;GAAE,OAAO;GAAQ,OAAO,QAAQ;GAAM,CAAC;EAEtD,IAAI,QAAQ,MACV,QAAQ,KAAK;GAAE,OAAO;GAAQ,OAAO,QAAQ;GAAM,CAAC;EAEtD,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb,KAAK;GACL;GACA;GACD,CAAC;EACF,GAAG,OAAO,OAAO;;CAInB,IAAI;CACJ,IAAI;EACF,sBAAsB,MAAM,SAAS,sBAAsB,QAAQ;UAC5D,OAAO;EACd,IAAI,iBAAiB,SAAU,MAA4B,SAAS,UAClE,OAAO,MACL,kBAAkB,sBAAsB;GACtC,KAAK,8BAA8B;GACnC,KAAK,iDAAiD,aAAa,4CAA4C;GAChH,CAAC,CACH;EAEH,OAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC7F,CAAC,CACH;;CAOH,MAAM,QAAQ,mBAAmB,OAAO;CACxC,MAAM,iBAAiB,OAAO,OAAO,OAAO,MAAM;CAElD,IAAI;CACJ,IAAI;EACF,aAAa,eAAe,oBAAoB,KAAK,MAAM,oBAAoB,CAAY;UACpF,OAAO;EACd,OAAO,MACL,8BACE,eAAe,qBAAqB,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACpH,EAAE,OAAO,EAAE,MAAM,sBAAsB,EAAE,CAC1C,CACF;;CAGH,MAAM,iBAAiB,WAAW,SAAS;CAC3C,IAAI,OAAO,mBAAmB,UAC5B,OAAO,MACL,8BAA8B,mCAAmC,EAC/D,OAAO,EAAE,MAAM,sBAAsB,EACtC,CAAC,CACH;CAEH,MAAM,gBAAgB;CAGtB,IAAI,eAAgC;CACpC,IAAI,WAA0B;CAC9B,IAAI,wBAAuC;CAE3C,IAAI;EACF,MAAM,EAAE,SAAS,UAAU,MAAM,sBAAsB,iBAAiB;EAExE,IAAI,QAAQ,MAAM;GAChB,MAAM,OAAO,MAAM,SAAS,sBAAsB,QAAQ,QAAQ,OAAO,CAAC,QAAQ;GAClF,MAAM,YAAY,iBAAiB,QAAQ,MAAM;IAAE;IAAO;IAAM,CAAC;GACjE,IAAI,CAAC,UAAU,IACb,OAAO,MAAM,sBAAsB,UAAU,QAAQ,CAAC;GAExD,WAAW,UAAU,MAAM;GAC3B,MAAM,iBAAiB,QAAQ,MAAM,MAAM,EAAE,SAAS,OAAO,SAAS;GACtE,IAAI,CAAC,gBACH,OAAO,MACL,gBACE,yCAAyC,QAAQ,KAAK,oBAAoB,SAAS,IACnF;IACE,KAAK,oGAAoG,SAAS;IAClH,KAAK;IACN,CACF,CACF;GAEH,wBAAwB,eAAe;GACvC,eAAe,MAAM,2BAA2B,uBAAuB,eAAe;SACjF;GACL,MAAM,kBAAkB,oBAAoB,MAAM;GAClD,IAAI,iBAAiB;IACnB,WAAW,gBAAgB;IAC3B,MAAM,UAAU,QAAQ,MACrB,MAAM,EAAE,SAAS,kBAAkB,gBAAgB,cACrD;IACD,IAAI,SAAS;KACX,wBAAwB,QAAQ;KAChC,eAAe,MAAM,2BAA2B,uBAAuB,eAAe;;;;UAIrF,OAAO;EACd,IAAI,oBAAoB,GAAG,MAAM,EAC/B,OAAO,MAAM,uBAAuB,MAAM,CAAC;EAK7C,IAAI,mBAAmB,GAAG,MAAM,EAC9B,OAAO,MAAM,MAAM;EAMrB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;EACtE,OAAO,MACL,gBAAgB,SAAS,EACvB,KAAK,8CAA8C,WACpD,CAAC,CACH;;CASH,MAAM,aAAa,MAAM,0BAA0B;EACjD;EACA,gBAH+B,kBAAkB,OAAO,kBAAkB,EAAE,CAGpC;EACzC,CAAC;CACF,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM;OACnB,MAAM,UAAU,WAAW,QAC9B,IAAI,OAAO,WAAW,WAAW;GAC/B,MAAM,YACJ,OAAO,iBAAiB,SAAS,IAC7B,KAAK,OAAO,iBAAiB,OAAO,0CACpC;GACN,GAAG,KAAK,WAAW,OAAO,QAAQ,MAAM,OAAO,UAAU,YAAY;;;CAI3E,MAAM,uBAAuB,WAAW,OAAO,SAAS,MACtD,EAAE,iBAAiB,KAAK,aAAa;EAAE,SAAS,EAAE;EAAS;EAAS,EAAE,CACvE;CAGD,IAAI,aAAa,eAWf,OAAO,GAAG;EATR,IAAI;EACJ,MAAM;EACN,MAAM;EACN,IAAI;EACJ,YAAY,EAAE;EACd;EACA,SAAS;EACT,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;EAE5B,CAAC;CAInB,MAAM,aAAa,oBAAoB,OAAO,OAAO;CACrD,IAAI,CAAC,YACH,OAAO,MACL,iCAAiC,EAC/B,KAAK,WAAW,OAAO,OAAO,GAAG,gCAClC,CAAC,CACH;CAUH,MAAM,kBAAkB,MAAM,4BAA4B;EACxD,UAAU,OAAO,OAAO;EACxB;EACA,aAAa;EACb,gBAAgB,OAAO,kBAAkB,EAAE;EAC3C,sBAAsB,SAAkB,eAAe,oBAAoB,KAAK;EACjF,CAAC;CACF,IAAI,CAAC,gBAAgB,IACnB,OAAO,MAAM,gBAAgB,QAAQ;CAEvC,MAAM,YAAY,gBAAgB;CAElC,MAAM,sBAAsB,oCAC1B,OAAO,OAAO,UACd,OAAO,OAAO,UACd;EAAC,OAAO;EAAQ,OAAO;EAAS,GAAI,OAAO,kBAAkB,EAAE;EAAE,CAClE;CAGD,MAAM,4BAAY,IAAI,MAAM;CAG5B,MAAM,aAAa,KAAK,kBADR,uBAAuB,WAD1B,QAAQ,QAAQ,YAEoB,CAAC;CAElD,MAAM,eAAgF;EACpF,MAAM;EACN,IAAI;EACJ,OAAO;GACL,MAAM,EAAE;GACR,SAAS,EAAE;GACX,gBAAgB;GACjB;EACD,QAAQ,EAAE;EACV,WAAW,UAAU,aAAa;EACnC;CAED,IAAI;EACF,MAAM,UAAU,WAAW,cAAc,eAAe;EACxD,MAAM,aAAa,WAAW,iBAAiB,cAAc,oBAAoB;EACjF,MAAM,gBAAgB,QAAQ,KAAK;GACjC,UAAU,UAAU,IAAI;GACxB,QAAQ;GACR,QAAQ,EAAE,yBAAyB;IAAC;IAAY;IAAY;IAAe;IAAO,EAAE;GACpF;GACA;GACA,SAAS,UAAU,IAAI;GACxB,CAAC;EACF,IAAI,cAAc,SAAS,WACzB,OAAO,MACL,6BAA6B,EAC3B,WAAW,cAAc,WAC1B,CAAC,CACH;EAQH,IAAI,aAAgD,EAAE;EACtD,IAAI,kBAAkB;EACtB,IAAI;GACF,aAAa,cAAc,KAAK;GAChC,IAAI,WAAW,WAAW,GACxB,OAAO,MACL,6BAA6B,EAC3B,WAAW,CACT;IACE,MAAM;IACN,SACE;IAEH,CACF,EACF,CAAC,CACH;WAEI,GAAG;GACV,IAAI,mBAAmB,GAAG,EAAE,IAAI,EAAE,WAAW,SAAS,EAAE,SAAS,QAC/D,kBAAkB;QAElB,MAAM;;EAIV,MAAM,qBAAqB,cAAc,KAAK,kBAAkB;EAOhE,MAAM,cAAc,kBAAkB,EAAE,GAAG;EAC3C,MAAM,yBAAmE;GACvE,GAAG;GACH,oBAAoB,yBAAyB,YAAY;GAC1D;EAMD,MAAM,sBAAsB,YAAY;GAJtC,GAAG;GACH,eAAe,qBAAqB,wBAAwB,YAAY;GAG1B,EAAE,YAAY;EAC9D,MAAM,uBAAuB,wBAAwB,qBAAqB;EAC1E,MAAM,oBAAoB,YAAY,CACpC;GAAE,YAAY,qBAAqB;GAAU,UAAU;GAAqB,EAC5E;GAAE,YAAY,qBAAqB;GAAS,UAAU;GAAqB,CAC5E,CAAC;EACF,IAAI,0BAA0B,MAAM;GAClC,MAAM,kBAAkB,wBACtB,KAAK,uBAAuB,oBAAoB,CACjD;GACD,MAAM,oBAAoB,YAAY,CACpC;IAAE,YAAY,gBAAgB;IAAU,UAAU;IAAuB,EACzE;IAAE,YAAY,gBAAgB;IAAS,UAAU;IAAuB,CACzE,CAAC;;EAEJ,MAAM,iBAAiB,YAAY,mBAAmB;EAEtD,IAAI,iBAcF,OAAO,GAAG;GAZR,IAAI;GACJ,MAAM;GACN,MAAM;GACN,IAAI;GACJ,KAAK,SAAS,QAAQ,KAAK,EAAE,WAAW;GACxC,YAAY,EAAE;GACd;GACA,qBAAqB;GACrB,SACE;GACF,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAE5B,CAAC;EAGnB,MAAM,UAAU,oBAAoB,eAAe,GAC/C,eAAe,mBAAmB,WAAW,GAC7C,KAAA;EAiBJ,OAAO,GAAG;GAfR,IAAI;GACJ,MAAM;GACN,MAAM;GACN,IAAI;GACJ,KAAK,SAAS,QAAQ,KAAK,EAAE,WAAW;GACxC,YAAY,WAAW,KAAK,QAAQ;IAClC,IAAI,GAAG;IACP,OAAO,GAAG;IACV,gBAAgB,GAAG;IACpB,EAAE;GACH;GACA,GAAI,YAAY,KAAA,IAAY,EAAE,SAAS,GAAG,EAAE;GAC5C,SAAS,iBAAiB,WAAW,QAAQ,qBAAqB,OAAO;GACzE,SAAS,EAAE,OAAO,KAAK,KAAK,GAAG,WAAW;GAE5B,CAAC;UACV,OAAO;EACd,IAAI,mBAAmB,GAAG,MAAM,EAC9B,OAAO,MAAM,MAAM;EAErB,IAAI,oBAAoB,GAAG,MAAM,EAC/B,OAAO,MAAM,uBAAuB,MAAM,CAAC;EAE7C,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;EACtE,OAAO,MACL,gBAAgB,SAAS,EACvB,KAAK,2CAA2C,WACjD,CAAC,CACH;;;AAIL,SAAgB,6BAAsC;CACpD,MAAM,UAAU,IAAI,QAAQ,OAAO;CACnC,uBACE,SACA,0CACA,sNAGD;CACD,mBAAmB,SAAS,CAC1B,8BACA,oDACD,CAAC;CACF,iBAAiB,QAAQ,CACtB,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,iBAAiB,yCAAyC,YAAY,CAC7E,OACC,qBACA,8FACD,CACA,OAAO,OAAO,YAAkC;EAC/C,MAAM,QAAQ,uBAAuB,QAAQ;EAC7C,MAAM,YAAY,KAAK,KAAK;EAE5B,MAAM,KAAK,iBAAiB,MAAM;EAGlC,MAAM,WAAW,aAAa,MAFT,4BAA4B,SAAS,OAAO,IAAI,UAAU,EAEzC,OAAO,KAAK,eAAe;GAC/D,IAAI,MAAM,MACR,GAAG,OAAO,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM,OAChB,GAAG,IAAI,0BAA0B,YAAY,MAAM,CAAC;IAEtD;EAEF,QAAQ,KAAK,SAAS;GACtB;CAEJ,OAAO;;;;;;;;;;;;;;;;AAiBT,SAAS,iBAAiB,iBAAyB,2BAA2C;CAC5F,MAAM,OAAO,WAAW,gBAAgB;CACxC,IAAI,8BAA8B,GAAG,OAAO;CAG5C,OAAO,GAAG,KAAK,iBAAiB,0BAA0B,GADxD,8BAA8B,IAAI,8BAA8B;;AAIpE,SAAgB,0BAA0B,QAA6B,OAA4B;CACjG,MAAM,QAAkB,EAAE;CAC1B,MAAM,WAAW,MAAM,UAAU;CAEjC,MAAM,SAAS,YAAY,MAAc,WAAW,EAAE,YAAY,MAAc;CAChF,MAAM,UAAU,YAAY,MAAc,WAAW,EAAE,YAAY,MAAc;CACjF,MAAM,OAAO,YAAY,MAAc,UAAU,EAAE,YAAY,MAAc;CAO7E,SAAS,0BAAgC;EACvC,IAAI,OAAO,qBAAqB,WAAW,GAAG;EAC9C,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,KAAK,gCAAgC,CAAC;EACjD,KAAK,MAAM,SAAS,OAAO,sBACzB,MAAM,KAAK,KAAK,KAAK,MAAM,QAAQ,gBAAgB,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC;EAEvF,MAAM,KAAK,GAAG;EACd,MAAM,KACJ,yDAAyD,OAAO,sBAAsB,CAAC,GACxF;;CAGH,IAAI,OAAO,MAAM;EACf,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,sBAAsB;EAChD,MAAM,KAAK,KAAK,WAAW,OAAO,OAAO,CAAC;EAC1C,MAAM,KAAK,KAAK,WAAW,OAAO,KAAK,CAAC;EACxC,yBAAyB;EACzB,OAAO,MAAM,KAAK,KAAK;;CAGzB,IAAI,OAAO,qBAAqB;EAC9B,MAAM,KAAK,GAAG,QAAQ,IAAI,CAAC,GAAG,OAAO,UAAU;EAC/C,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,KAAK,SAAS,OAAO,OAAO,CAAC;EACxC,MAAM,KAAK,KAAK,SAAS,OAAO,KAAK,CAAC;EACtC,IAAI,OAAO,KACT,MAAM,KAAK,KAAK,SAAS,OAAO,MAAM,CAAC;EAEzC,MAAM,KAAK,GAAG;EACd,MAAM,KACJ,qFACD;EACD,MAAM,KAAK,aAAa,OAAO,QAAQ,OAAO,OAAO,QAAQ,eAAe,GAAG;EAC/E,yBAAyB;EACzB,OAAO,MAAM,KAAK,KAAK;;CAGzB,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,GAAG,OAAO,UAAU;CAC9C,MAAM,KAAK,GAAG;CAEd,IAAI,OAAO,WAAW,SAAS,GAAG;EAChC,MAAM,KAAK,KAAK,IAAI,CAAC;EACrB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,WAAW,QAAQ,KAAK;GACjD,MAAM,KAAK,OAAO,WAAW;GAE7B,MAAM,WADS,MAAM,OAAO,WAAW,SAAS,IACtB,MAAM;GAGhC,MAAM,oBACJ,GAAG,mBAAmB,gBAAgB,IAAI,QAAQ,gBAAgB,KAAK;GACzE,MAAM,KAAK,GAAG,KAAK,SAAS,CAAC,IAAI,GAAG,QAAQ,oBAAoB;;EAIlE,IADuB,OAAO,WAAW,MAAM,OAAO,GAAG,mBAAmB,cAC1D,EAAE;GAClB,MAAM,KAAK,GAAG;GACd,MAAM,KACJ,GAAG,QAAQ,IAAI,CAAC,2EACjB;;EAEH,MAAM,KAAK,GAAG;;CAGhB,MAAM,KAAK,KAAK,WAAW,OAAO,OAAO,CAAC;CAC1C,MAAM,KAAK,KAAK,WAAW,OAAO,KAAK,CAAC;CACxC,IAAI,OAAO,KACT,MAAM,KAAK,KAAK,eAAe,OAAO,MAAM,CAAC;CAK/C,KAAK,MAAM,SAAS,OAAO,sBACzB,MAAM,KACJ,KAAK,mBAAmB,MAAM,QAAQ,gBAAgB,MAAM,QAAQ,GAAG,MAAM,UAAU,CACxF;CAGH,MAAM,KAAK,GAAG;CAKd,MAAM,KACJ,gBAAgB,OAAO,OAAO,OAAO,QAAQ,CAAC,uBAAuB,OAAO,sBAAsB,CAAC,GACpG;CAED,IAAI,OAAO,WAAW,OAAO,QAAQ,WAAW,SAAS,GAAG;EAG1D,MAAM,SAAS,OAAO,QAAQ,WAAW,OAAO,MAAM,EAAE,aAAa,MAAM;EAC3E,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,KAAK,SAAS,gBAAgB,oBAAoB,CAAC;EAC9D,MAAM,KAAK,GAAG;EACd,KAAK,MAAM,aAAa,OAAO,QAAQ,YAAY;GACjD,MAAM,UAAU,UAAU,KAAK,MAAM;GACrC,IAAI,CAAC,SAAS;GACd,MAAM,OAAO,UAAU,aAAa,SAAS,CAAC,QAAQ,SAAS,IAAI,GAAG,GAAG,QAAQ,KAAK;GACtF,MAAM,KAAK,KAAK;;;CAIpB,IAAI,MAAM,WAAW,OAAO,SAAS;EACnC,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,KAAK,eAAe,OAAO,QAAQ,MAAM,IAAI,CAAC;;CAG3D,OAAO,MAAM,KAAK,KAAK;;;;;;;;;;;;;;;AAoBzB,SAAgB,sBACd,SACA,QACoC;CACpC,MAAM,QAAQ,QAAQ,MAAM,MAAM,EAAE,SAAS,OAAO,OAAO;CAC3D,IAAI,OAAO,OAAO,GAAG,MAAM;CAE3B,MAAM,mBAAmB,OAAO,WAAW,UAAU,GAAG,SAAS,UAAU;CAC3E,MAAM,aAAa,QAAQ,QAAQ,MAAM,EAAE,SAAS,GAAG,WAAW,iBAAiB,CAAC;CAEpF,IAAI,WAAW,WAAW,GAAG,OAAO,GAAG,WAAW,GAAI;CACtD,IAAI,WAAW,SAAS,GAAG,OAAO,MAAM;EAAE,QAAQ;EAAa,OAAO,WAAW;EAAQ,CAAC;CAC1F,OAAO,MAAM,EAAE,QAAQ,aAAa,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"migrations-CwZMa1Ck.mjs","names":[],"sources":["../src/utils/formatters/migrations.ts"],"sourcesContent":["import type { OperationPreview } from '@prisma-next/framework-components/control';\nimport { cyan, green, yellow } from 'colorette';\n\nimport type { AggregatePerSpaceExecutionEntry } from '../../control-api/types';\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim, isVerbose } from './helpers';\n\n/**\n * Render a single statement of an `OperationPreview` for the human-readable\n * preview block. SQL statements get a trailing `;` if missing so the rendered\n * preview is byte-identical to the legacy `string[]`-based renderer for SQL\n * targets. Other languages (`'mongodb-shell'`) render verbatim.\n */\nfunction renderPreviewStatement(text: string, language: string): string | undefined {\n const trimmed = text.trim();\n if (!trimmed) return undefined;\n if (language === 'sql') {\n return trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n }\n return trimmed;\n}\n\n/**\n * Choose the header label for a preview block. SQL-only previews keep the\n * legacy `DDL preview` label so the rendered output is byte-identical to the\n * pre-aggregate SQL CLI; previews from any other family — or a mix that\n * includes any non-SQL language — use the family-agnostic `Operation preview`\n * label.\n *\n * An empty `statements` array deliberately renders as `Operation preview`\n * rather than `DDL preview`: `Array.prototype.every` is vacuously true for\n * empty arrays, but we have no evidence the preview is SQL-only when no\n * statements are present, so the family-agnostic label is the safer default.\n */\nexport function previewBlockHeader(preview: OperationPreview): string {\n const allSql =\n preview.statements.length > 0 && preview.statements.every((s) => s.language === 'sql');\n return allSql ? 'DDL preview' : 'Operation preview';\n}\n\n// ============================================================================\n// Migration Command Output Formatters (shared by db init and db update)\n// ============================================================================\n\n/**\n * Shared CLI output type for migration commands (db init, db update).\n */\nexport interface MigrationCommandResult {\n readonly ok: true;\n readonly mode: 'plan' | 'apply';\n readonly plan: {\n readonly targetId: string;\n readonly destination: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the planned operations. Replaces the\n * previous `sql?: readonly string[]`. Consumers should read\n * `plan.preview?.statements`.\n */\n readonly preview?: OperationPreview;\n };\n readonly execution?: {\n readonly operationsPlanned: number;\n readonly operationsExecuted: number;\n };\n readonly marker?: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n /**\n * Per-space execution breakdown in canonical schedule order\n * (extensions alphabetically, then app). Surfaces per-space markers\n * and the ops grouped by space, so the CLI summary can name which\n * space each op and marker belongs to instead of flattening them\n * into a single ambiguous list. See {@link AggregatePerSpaceExecutionEntry}.\n */\n readonly perSpace?: ReadonlyArray<AggregatePerSpaceExecutionEntry>;\n readonly summary: string;\n readonly timings: {\n readonly total: number;\n };\n}\n\n/**\n * Render the shared per-space execution block consumed by the `db init`\n * / `db update` / `migrate` summaries. Always shows: space\n * label (`Extension space: <id>` or `App space`) → per-op lines under\n * each space → per-space marker hash (when known).\n *\n * `mode` controls the marker label phrasing — `'apply'` shows\n * `marker → <hash>` (post-apply), `'plan'` omits the marker line\n * entirely (no marker has been written yet).\n */\nexport function formatPerSpaceBlock(\n perSpace: ReadonlyArray<AggregatePerSpaceExecutionEntry>,\n mode: 'plan' | 'apply',\n useColor: boolean,\n): readonly string[] {\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatCyan = createColorFormatter(useColor, cyan);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n for (let s = 0; s < perSpace.length; s++) {\n const space = perSpace[s]!;\n if (s > 0) lines.push('');\n const header =\n space.kind === 'app'\n ? formatCyan('App space')\n : formatCyan(`Extension space: ${space.spaceId}`);\n lines.push(header);\n if (space.operations.length === 0) {\n lines.push(` ${formatDimText('(no operations)')}`);\n } else {\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(` ${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n }\n if (mode === 'apply' && space.marker) {\n lines.push(` ${formatDimText(`marker: ${space.marker.storageHash}`)}`);\n }\n }\n return lines;\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in plan mode.\n */\nexport function formatMigrationPlanOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Plan summary\n const operationCount = result.plan?.operations.length ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Planned ${operationCount} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Planned ${operationCount} operation(s)`);\n }\n\n const formatYellow = createColorFormatter(useColor, yellow);\n\n // Per-space breakdown takes precedence over the flat ops tree when\n // the aggregate flow surfaced one.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'plan', useColor));\n const hasDestructive = result.perSpace.some((s) =>\n s.operations.some((op) => op.operationClass === 'destructive'),\n );\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n } else if (result.plan?.operations && result.plan.operations.length > 0) {\n // Single-space fallback (no aggregate breakdown). Same flat tree\n // we've always rendered.\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < result.plan.operations.length; i++) {\n const op = result.plan.operations[i];\n if (!op) continue;\n const isLast = i === result.plan.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = result.plan.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n // Destination hash\n if (result.plan?.destination) {\n lines.push('');\n lines.push(`${formatDimText(`Destination hash: ${result.plan.destination.storageHash}`)}`);\n }\n\n // Statement preview (any family that implements OperationPreviewCapable)\n const preview = result.plan?.preview;\n if (preview) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(preview))}`);\n if (preview.statements.length === 0) {\n lines.push(`${formatDimText('No operations.')}`);\n } else {\n lines.push('');\n for (const statement of preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(`Total time: ${result.timings.total}ms`)}`);\n }\n\n // Note about dry run\n lines.push('');\n lines.push(`${formatDimText('This is a dry run. No changes were applied.')}`);\n lines.push(`${formatDimText('Run without --dry-run to apply changes.')}`);\n\n return lines.join('\\n');\n}\n\nexport interface MigrationApplyCommandOutputResult {\n readonly migrationsApplied: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly spaceId: string;\n readonly dirName?: string;\n readonly migrationHash?: string;\n readonly from?: string;\n readonly to?: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n /**\n * Per-space breakdown in canonical schedule order (extensions\n * alphabetically, then app). Always present for the aggregate-walking\n * `migrate` command.\n */\n readonly perSpace: readonly AggregatePerSpaceExecutionEntry[];\n readonly timings?: {\n readonly total: number;\n };\n}\n\nexport function formatMigrationApplyCommandOutput(\n result: MigrationApplyCommandOutputResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n lines.push(`${formatGreen('✔')} ${result.summary}`);\n\n if (result.perSpace.length > 0) {\n lines.push('');\n for (const line of formatPerSpaceBlock(result.perSpace, 'apply', useColor)) {\n lines.push(line);\n }\n }\n\n lines.push('');\n lines.push(formatDimText('Next: prisma-next migration status'));\n\n if (isVerbose(flags, 1) && result.timings) {\n lines.push('');\n lines.push(formatDimText(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\ninterface MigrationShowSpacePresent {\n readonly kind: 'present';\n readonly spaceId: string;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\ninterface MigrationShowSpaceMissing {\n readonly kind: 'missing';\n readonly spaceId: string;\n readonly summary: string;\n}\n\ntype MigrationShowSpaceResult = MigrationShowSpacePresent | MigrationShowSpaceMissing;\n\ninterface MigrationShowResult {\n readonly spaces: readonly MigrationShowSpaceResult[];\n}\n\nfunction formatSpaceShowBlock(\n space: MigrationShowSpacePresent,\n useColor: boolean,\n): readonly string[] {\n const formatGreen = createColorFormatter(useColor, green);\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n lines.push(`${formatGreen('✔')} ${space.dirName}`);\n lines.push(`${formatDimText(` from: ${space.from ?? '(baseline)'}`)}`);\n lines.push(`${formatDimText(` to: ${space.to}`)}`);\n lines.push(`${formatDimText(` migrationHash: ${space.migrationHash}`)}`);\n lines.push(`${formatDimText(` created: ${space.createdAt}`)}`);\n\n lines.push('');\n lines.push(`${space.operations.length} operation(s)`);\n\n if (space.operations.length > 0) {\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = space.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n if (space.preview.statements.length > 0) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(space.preview))}`);\n lines.push('');\n for (const statement of space.preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n\n return lines;\n}\n\nexport function formatMigrationShowOutput(result: MigrationShowResult, flags: GlobalFlags): string {\n if (flags.quiet) {\n return '';\n }\n\n const useColor = flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n const multipleSpaces = result.spaces.length > 1;\n const lines: string[] = [];\n\n for (let i = 0; i < result.spaces.length; i++) {\n const space = result.spaces[i]!;\n if (multipleSpaces) {\n lines.push(formatDimText(`── ${space.spaceId} ──`));\n }\n if (space.kind === 'missing') {\n lines.push(formatDimText(` ${space.summary}`));\n } else {\n for (const line of formatSpaceShowBlock(space, useColor)) {\n lines.push(line);\n }\n }\n if (i < result.spaces.length - 1) {\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in apply mode.\n */\nexport function formatMigrationApplyOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n if (result.ok) {\n // Success summary\n const executed = result.execution?.operationsExecuted ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n\n if (executed === 0) {\n const acrossClause =\n spaceCount > 0 ? ` across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}` : '';\n lines.push(`${formatGreen('✔')} Database already matches contract${acrossClause}`);\n } else if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Applied ${executed} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Applied ${executed} operation(s)`);\n }\n\n // Per-space breakdown — replaces the single ambiguous `Signature:`\n // line with a per-space marker + ops listing.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'apply', useColor));\n lines.push('');\n lines.push(\n formatDimText(\n `Run 'prisma-next migration status' to confirm ${\n spaceCount === 1 ? 'the space is' : 'all spaces are'\n } up to date.`,\n ),\n );\n } else if (result.marker) {\n // Single-space fallback (no aggregate breakdown surfaced — e.g.\n // older callers / non-aggregate code paths). The label is\n // `App-space marker` (not `Signature`) so that when only one\n // marker is observable we still name what it covers explicitly.\n lines.push(`${formatDimText(` App-space marker: ${result.marker.storageHash}`)}`);\n if (result.marker.profileHash) {\n lines.push(`${formatDimText(` Profile hash: ${result.marker.profileHash}`)}`);\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(` Total time: ${result.timings.total}ms`)}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats JSON output for migration commands (db init, db update).\n */\nexport function formatMigrationJson(result: MigrationCommandResult): string {\n return JSON.stringify(result, null, 2);\n}\n"],"mappings":";;;;;;;;;AAaA,SAAS,uBAAuB,MAAc,UAAsC;CAClF,MAAM,UAAU,KAAK,MAAM;CAC3B,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,IAAI,aAAa,OACf,OAAO,QAAQ,SAAS,IAAI,GAAG,UAAU,GAAG,QAAQ;CAEtD,OAAO;;;;;;;;;;;;;;AAeT,SAAgB,mBAAmB,SAAmC;CAGpE,OADE,QAAQ,WAAW,SAAS,KAAK,QAAQ,WAAW,OAAO,MAAM,EAAE,aAAa,MAAM,GACxE,gBAAgB;;;;;;;;;;;;AA+DlC,SAAgB,oBACd,UACA,MACA,UACmB;CACnB,MAAM,eAAe,qBAAqB,UAAU,OAAO;CAC3D,MAAM,aAAa,qBAAqB,UAAU,KAAK;CACvD,MAAM,iBAAiB,SAAiB,UAAU,UAAU,KAAK;CAEjE,MAAM,QAAkB,EAAE;CAC1B,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,QAAQ,SAAS;EACvB,IAAI,IAAI,GAAG,MAAM,KAAK,GAAG;EACzB,MAAM,SACJ,MAAM,SAAS,QACX,WAAW,YAAY,GACvB,WAAW,oBAAoB,MAAM,UAAU;EACrD,MAAM,KAAK,OAAO;EAClB,IAAI,MAAM,WAAW,WAAW,GAC9B,MAAM,KAAK,KAAK,cAAc,kBAAkB,GAAG;OAEnD,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,WAAW,QAAQ,KAAK;GAChD,MAAM,KAAK,MAAM,WAAW;GAE5B,MAAM,WADS,MAAM,MAAM,WAAW,SAAS,IACrB,MAAM;GAChC,MAAM,oBACJ,GAAG,mBAAmB,gBAAgB,IAAI,aAAa,gBAAgB,KAAK;GAC9E,MAAM,KAAK,KAAK,cAAc,SAAS,CAAC,IAAI,GAAG,QAAQ,oBAAoB;;EAG/E,IAAI,SAAS,WAAW,MAAM,QAC5B,MAAM,KAAK,KAAK,cAAc,WAAW,MAAM,OAAO,cAAc,GAAG;;CAG3E,OAAO;;;;;AAMT,SAAgB,0BACd,QACA,OACQ;CACR,IAAI,MAAM,OACR,OAAO;CAGT,MAAM,QAAkB,EAAE;CAE1B,MAAM,WAAW,MAAM,UAAU;CACjC,MAAM,cAAc,qBAAqB,UAAU,MAAM;CACzD,MAAM,iBAAiB,SAAiB,UAAU,UAAU,KAAK;CAGjE,MAAM,iBAAiB,OAAO,MAAM,WAAW,UAAU;CACzD,MAAM,aAAa,OAAO,UAAU,UAAU;CAC9C,IAAI,aAAa,GACf,MAAM,KACJ,GAAG,YAAY,IAAI,CAAC,WAAW,eAAe,uBAAuB,WAAW,iBAAiB,eAAe,IAAI,KAAK,MAC1H;MAED,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,WAAW,eAAe,eAAe;CAG1E,MAAM,eAAe,qBAAqB,UAAU,OAAO;CAI3D,IAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;EACjD,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,GAAG,oBAAoB,OAAO,UAAU,QAAQ,SAAS,CAAC;EAIrE,IAHuB,OAAO,SAAS,MAAM,MAC3C,EAAE,WAAW,MAAM,OAAO,GAAG,mBAAmB,cAAc,CAE9C,EAAE;GAClB,MAAM,KAAK,GAAG;GACd,MAAM,KACJ,GAAG,aAAa,IAAI,CAAC,2EACtB;;QAEE,IAAI,OAAO,MAAM,cAAc,OAAO,KAAK,WAAW,SAAS,GAAG;EAGvE,MAAM,KAAK,GAAG,cAAc,IAAI,GAAG;EACnC,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,WAAW,QAAQ,KAAK;GACtD,MAAM,KAAK,OAAO,KAAK,WAAW;GAClC,IAAI,CAAC,IAAI;GAET,MAAM,WADS,MAAM,OAAO,KAAK,WAAW,SAAS,IAC3B,MAAM;GAChC,MAAM,oBACJ,GAAG,mBAAmB,gBAAgB,IAAI,aAAa,gBAAgB,KAAK;GAC9E,MAAM,KAAK,GAAG,cAAc,SAAS,CAAC,IAAI,GAAG,QAAQ,oBAAoB;;EAI3E,IADuB,OAAO,KAAK,WAAW,MAAM,OAAO,GAAG,mBAAmB,cAC/D,EAAE;GAClB,MAAM,KAAK,GAAG;GACd,MAAM,KACJ,GAAG,aAAa,IAAI,CAAC,2EACtB;;;CAKL,IAAI,OAAO,MAAM,aAAa;EAC5B,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,GAAG,cAAc,qBAAqB,OAAO,KAAK,YAAY,cAAc,GAAG;;CAI5F,MAAM,UAAU,OAAO,MAAM;CAC7B,IAAI,SAAS;EACX,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,GAAG,cAAc,mBAAmB,QAAQ,CAAC,GAAG;EAC3D,IAAI,QAAQ,WAAW,WAAW,GAChC,MAAM,KAAK,GAAG,cAAc,iBAAiB,GAAG;OAC3C;GACL,MAAM,KAAK,GAAG;GACd,KAAK,MAAM,aAAa,QAAQ,YAAY;IAC1C,MAAM,WAAW,uBAAuB,UAAU,MAAM,UAAU,SAAS;IAC3E,IAAI,UACF,MAAM,KAAK,SAAS;;;;CAO5B,IAAI,UAAU,OAAO,EAAE,EACrB,MAAM,KAAK,GAAG,cAAc,eAAe,OAAO,QAAQ,MAAM,IAAI,GAAG;CAIzE,MAAM,KAAK,GAAG;CACd,MAAM,KAAK,GAAG,cAAc,8CAA8C,GAAG;CAC7E,MAAM,KAAK,GAAG,cAAc,0CAA0C,GAAG;CAEzE,OAAO,MAAM,KAAK,KAAK;;AA0BzB,SAAgB,kCACd,QACA,OACQ;CACR,IAAI,MAAM,OACR,OAAO;CAGT,MAAM,QAAkB,EAAE;CAC1B,MAAM,WAAW,MAAM,UAAU;CACjC,MAAM,cAAc,qBAAqB,UAAU,MAAM;CACzD,MAAM,iBAAiB,SAAiB,UAAU,UAAU,KAAK;CAEjE,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,GAAG,OAAO,UAAU;CAEnD,IAAI,OAAO,SAAS,SAAS,GAAG;EAC9B,MAAM,KAAK,GAAG;EACd,KAAK,MAAM,QAAQ,oBAAoB,OAAO,UAAU,SAAS,SAAS,EACxE,MAAM,KAAK,KAAK;;CAIpB,MAAM,KAAK,GAAG;CACd,MAAM,KAAK,cAAc,qCAAqC,CAAC;CAE/D,IAAI,UAAU,OAAO,EAAE,IAAI,OAAO,SAAS;EACzC,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,cAAc,eAAe,OAAO,QAAQ,MAAM,IAAI,CAAC;;CAGpE,OAAO,MAAM,KAAK,KAAK;;AAiCzB,SAAS,qBACP,OACA,UACmB;CACnB,MAAM,cAAc,qBAAqB,UAAU,MAAM;CACzD,MAAM,eAAe,qBAAqB,UAAU,OAAO;CAC3D,MAAM,iBAAiB,SAAiB,UAAU,UAAU,KAAK;CAEjE,MAAM,QAAkB,EAAE;CAC1B,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,GAAG,MAAM,UAAU;CAClD,MAAM,KAAK,GAAG,cAAc,WAAW,MAAM,QAAQ,eAAe,GAAG;CACvE,MAAM,KAAK,GAAG,cAAc,WAAW,MAAM,KAAK,GAAG;CACrD,MAAM,KAAK,GAAG,cAAc,oBAAoB,MAAM,gBAAgB,GAAG;CACzE,MAAM,KAAK,GAAG,cAAc,cAAc,MAAM,YAAY,GAAG;CAE/D,MAAM,KAAK,GAAG;CACd,MAAM,KAAK,GAAG,MAAM,WAAW,OAAO,eAAe;CAErD,IAAI,MAAM,WAAW,SAAS,GAAG;EAC/B,MAAM,KAAK,GAAG,cAAc,IAAI,GAAG;EACnC,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,WAAW,QAAQ,KAAK;GAChD,MAAM,KAAK,MAAM,WAAW;GAE5B,MAAM,WADS,MAAM,MAAM,WAAW,SAAS,IACrB,MAAM;GAChC,MAAM,oBACJ,GAAG,mBAAmB,gBAAgB,IAAI,aAAa,gBAAgB,KAAK;GAC9E,MAAM,KAAK,GAAG,cAAc,SAAS,CAAC,IAAI,GAAG,QAAQ,oBAAoB;;EAI3E,IADuB,MAAM,WAAW,MAAM,OAAO,GAAG,mBAAmB,cACzD,EAAE;GAClB,MAAM,KAAK,GAAG;GACd,MAAM,KACJ,GAAG,aAAa,IAAI,CAAC,2EACtB;;;CAIL,IAAI,MAAM,QAAQ,WAAW,SAAS,GAAG;EACvC,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,GAAG,cAAc,mBAAmB,MAAM,QAAQ,CAAC,GAAG;EACjE,MAAM,KAAK,GAAG;EACd,KAAK,MAAM,aAAa,MAAM,QAAQ,YAAY;GAChD,MAAM,WAAW,uBAAuB,UAAU,MAAM,UAAU,SAAS;GAC3E,IAAI,UACF,MAAM,KAAK,SAAS;;;CAK1B,OAAO;;AAGT,SAAgB,0BAA0B,QAA6B,OAA4B;CACjG,IAAI,MAAM,OACR,OAAO;CAGT,MAAM,WAAW,MAAM,UAAU;CACjC,MAAM,iBAAiB,SAAiB,UAAU,UAAU,KAAK;CACjE,MAAM,iBAAiB,OAAO,OAAO,SAAS;CAC9C,MAAM,QAAkB,EAAE;CAE1B,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,OAAO,QAAQ,KAAK;EAC7C,MAAM,QAAQ,OAAO,OAAO;EAC5B,IAAI,gBACF,MAAM,KAAK,cAAc,MAAM,MAAM,QAAQ,KAAK,CAAC;EAErD,IAAI,MAAM,SAAS,WACjB,MAAM,KAAK,cAAc,KAAK,MAAM,UAAU,CAAC;OAE/C,KAAK,MAAM,QAAQ,qBAAqB,OAAO,SAAS,EACtD,MAAM,KAAK,KAAK;EAGpB,IAAI,IAAI,OAAO,OAAO,SAAS,GAC7B,MAAM,KAAK,GAAG;;CAIlB,OAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,2BACd,QACA,OACQ;CACR,IAAI,MAAM,OACR,OAAO;CAGT,MAAM,QAAkB,EAAE;CAE1B,MAAM,WAAW,MAAM,UAAU;CACjC,MAAM,cAAc,qBAAqB,UAAU,MAAM;CACzD,MAAM,iBAAiB,SAAiB,UAAU,UAAU,KAAK;CAEjE,IAAI,OAAO,IAAI;EAEb,MAAM,WAAW,OAAO,WAAW,sBAAsB;EACzD,MAAM,aAAa,OAAO,UAAU,UAAU;EAE9C,IAAI,aAAa,GAAG;GAClB,MAAM,eACJ,aAAa,IAAI,WAAW,WAAW,iBAAiB,eAAe,IAAI,KAAK,QAAQ;GAC1F,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,oCAAoC,eAAe;SAC7E,IAAI,aAAa,GACtB,MAAM,KACJ,GAAG,YAAY,IAAI,CAAC,WAAW,SAAS,uBAAuB,WAAW,iBAAiB,eAAe,IAAI,KAAK,MACpH;OAED,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,WAAW,SAAS,eAAe;EAKpE,IAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;GACjD,MAAM,KAAK,GAAG;GACd,MAAM,KAAK,GAAG,oBAAoB,OAAO,UAAU,SAAS,SAAS,CAAC;GACtE,MAAM,KAAK,GAAG;GACd,MAAM,KACJ,cACE,iDACE,eAAe,IAAI,iBAAiB,iBACrC,cACF,CACF;SACI,IAAI,OAAO,QAAQ;GAKxB,MAAM,KAAK,GAAG,cAAc,uBAAuB,OAAO,OAAO,cAAc,GAAG;GAClF,IAAI,OAAO,OAAO,aAChB,MAAM,KAAK,GAAG,cAAc,mBAAmB,OAAO,OAAO,cAAc,GAAG;;EAKlF,IAAI,UAAU,OAAO,EAAE,EACrB,MAAM,KAAK,GAAG,cAAc,iBAAiB,OAAO,QAAQ,MAAM,IAAI,GAAG;;CAI7E,OAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,oBAAoB,QAAwC;CAC1E,OAAO,KAAK,UAAU,QAAQ,MAAM,EAAE"}
@@ -1,14 +0,0 @@
1
- import "node:module";
2
- //#region \0rolldown/runtime.js
3
- var __defProp = Object.defineProperty;
4
- var __exportAll = (all, no_symbols) => {
5
- let target = {};
6
- for (var name in all) __defProp(target, name, {
7
- get: all[name],
8
- enumerable: true
9
- });
10
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
11
- return target;
12
- };
13
- //#endregion
14
- export { __exportAll as t };