@prisma-next/cli 0.3.0-pr.99.5 → 0.3.0

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 (257) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +381 -128
  3. package/dist/agent-skill-mongo.md +106 -0
  4. package/dist/agent-skill-postgres.md +106 -0
  5. package/dist/cli-errors-BDCYR5ap.mjs +4 -0
  6. package/dist/cli-errors-DStABy9d.d.mts +3 -0
  7. package/dist/cli.d.mts +1 -0
  8. package/dist/cli.js +1 -2910
  9. package/dist/cli.mjs +261 -0
  10. package/dist/cli.mjs.map +1 -0
  11. package/dist/client-DiUkJAeN.mjs +987 -0
  12. package/dist/client-DiUkJAeN.mjs.map +1 -0
  13. package/dist/commands/contract-emit.d.mts +7 -0
  14. package/dist/commands/contract-emit.d.mts.map +1 -0
  15. package/dist/commands/contract-emit.mjs +9 -0
  16. package/dist/commands/contract-infer.d.mts +7 -0
  17. package/dist/commands/contract-infer.d.mts.map +1 -0
  18. package/dist/commands/contract-infer.mjs +10 -0
  19. package/dist/commands/db-init.d.mts +7 -0
  20. package/dist/commands/db-init.d.mts.map +1 -0
  21. package/dist/commands/db-init.mjs +126 -0
  22. package/dist/commands/db-init.mjs.map +1 -0
  23. package/dist/commands/db-schema.d.mts +7 -0
  24. package/dist/commands/db-schema.d.mts.map +1 -0
  25. package/dist/commands/db-schema.mjs +56 -0
  26. package/dist/commands/db-schema.mjs.map +1 -0
  27. package/dist/commands/db-sign.d.mts +7 -0
  28. package/dist/commands/db-sign.d.mts.map +1 -0
  29. package/dist/commands/db-sign.mjs +137 -0
  30. package/dist/commands/db-sign.mjs.map +1 -0
  31. package/dist/commands/db-update.d.mts +7 -0
  32. package/dist/commands/db-update.d.mts.map +1 -0
  33. package/dist/commands/db-update.mjs +123 -0
  34. package/dist/commands/db-update.mjs.map +1 -0
  35. package/dist/commands/db-verify.d.mts +7 -0
  36. package/dist/commands/db-verify.d.mts.map +1 -0
  37. package/dist/commands/db-verify.mjs +323 -0
  38. package/dist/commands/db-verify.mjs.map +1 -0
  39. package/dist/commands/migration-apply.d.mts +36 -0
  40. package/dist/commands/migration-apply.d.mts.map +1 -0
  41. package/dist/commands/migration-apply.mjs +245 -0
  42. package/dist/commands/migration-apply.mjs.map +1 -0
  43. package/dist/commands/migration-new.d.mts +8 -0
  44. package/dist/commands/migration-new.d.mts.map +1 -0
  45. package/dist/commands/migration-new.mjs +152 -0
  46. package/dist/commands/migration-new.mjs.map +1 -0
  47. package/dist/commands/migration-plan.d.mts +47 -0
  48. package/dist/commands/migration-plan.d.mts.map +1 -0
  49. package/dist/commands/migration-plan.mjs +313 -0
  50. package/dist/commands/migration-plan.mjs.map +1 -0
  51. package/dist/commands/migration-ref.d.mts +43 -0
  52. package/dist/commands/migration-ref.d.mts.map +1 -0
  53. package/dist/commands/migration-ref.mjs +195 -0
  54. package/dist/commands/migration-ref.mjs.map +1 -0
  55. package/dist/commands/migration-show.d.mts +28 -0
  56. package/dist/commands/migration-show.d.mts.map +1 -0
  57. package/dist/commands/migration-show.mjs +140 -0
  58. package/dist/commands/migration-show.mjs.map +1 -0
  59. package/dist/commands/migration-status.d.mts +86 -0
  60. package/dist/commands/migration-status.d.mts.map +1 -0
  61. package/dist/commands/migration-status.mjs +9 -0
  62. package/dist/commands/migration-verify.d.mts +16 -0
  63. package/dist/commands/migration-verify.d.mts.map +1 -0
  64. package/dist/commands/migration-verify.mjs +110 -0
  65. package/dist/commands/migration-verify.mjs.map +1 -0
  66. package/dist/config-loader-C4VXKl8f.mjs +43 -0
  67. package/dist/config-loader-C4VXKl8f.mjs.map +1 -0
  68. package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
  69. package/dist/config-loader.d.mts.map +1 -0
  70. package/dist/config-loader.mjs +3 -0
  71. package/dist/contract-emit-D2wDXfyo.mjs +191 -0
  72. package/dist/contract-emit-D2wDXfyo.mjs.map +1 -0
  73. package/dist/contract-emit-Zm_sd1wQ.mjs +112 -0
  74. package/dist/contract-emit-Zm_sd1wQ.mjs.map +1 -0
  75. package/dist/contract-emit-kN-IkKTE.mjs +6 -0
  76. package/dist/contract-enrichment-CGW6mm-E.mjs +79 -0
  77. package/dist/contract-enrichment-CGW6mm-E.mjs.map +1 -0
  78. package/dist/contract-infer-DozZT511.mjs +90 -0
  79. package/dist/contract-infer-DozZT511.mjs.map +1 -0
  80. package/dist/exports/config-types.d.mts +2 -0
  81. package/dist/exports/config-types.mjs +3 -0
  82. package/dist/exports/control-api.d.mts +624 -0
  83. package/dist/exports/control-api.d.mts.map +1 -0
  84. package/dist/exports/control-api.mjs +8 -0
  85. package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +12 -7
  86. package/dist/exports/index.d.mts.map +1 -0
  87. package/dist/exports/index.mjs +142 -0
  88. package/dist/exports/index.mjs.map +1 -0
  89. package/dist/extract-operation-statements-DZUJNmL3.mjs +13 -0
  90. package/dist/extract-operation-statements-DZUJNmL3.mjs.map +1 -0
  91. package/dist/extract-sql-ddl-DDMX-9mz.mjs +26 -0
  92. package/dist/extract-sql-ddl-DDMX-9mz.mjs.map +1 -0
  93. package/dist/framework-components-BAsliT4V.mjs +59 -0
  94. package/dist/framework-components-BAsliT4V.mjs.map +1 -0
  95. package/dist/init-6Pvm_esG.mjs +430 -0
  96. package/dist/init-6Pvm_esG.mjs.map +1 -0
  97. package/dist/inspect-live-schema-BYnhztxZ.mjs +91 -0
  98. package/dist/inspect-live-schema-BYnhztxZ.mjs.map +1 -0
  99. package/dist/migration-command-scaffold-CntCcntR.mjs +105 -0
  100. package/dist/migration-command-scaffold-CntCcntR.mjs.map +1 -0
  101. package/dist/migration-status-CJANY4yr.mjs +1583 -0
  102. package/dist/migration-status-CJANY4yr.mjs.map +1 -0
  103. package/dist/migrations-DTZBYXm1.mjs +173 -0
  104. package/dist/migrations-DTZBYXm1.mjs.map +1 -0
  105. package/dist/progress-adapter-B-YvmcDu.mjs +43 -0
  106. package/dist/progress-adapter-B-YvmcDu.mjs.map +1 -0
  107. package/dist/quick-reference-mongo.md +93 -0
  108. package/dist/quick-reference-postgres.md +91 -0
  109. package/dist/result-handler-oK_vA-Fn.mjs +697 -0
  110. package/dist/result-handler-oK_vA-Fn.mjs.map +1 -0
  111. package/dist/terminal-ui-C5k88MmW.mjs +274 -0
  112. package/dist/terminal-ui-C5k88MmW.mjs.map +1 -0
  113. package/dist/validate-contract-deps-esa-VQ0h.mjs +37 -0
  114. package/dist/validate-contract-deps-esa-VQ0h.mjs.map +1 -0
  115. package/dist/verify-DlFQ2FOw.mjs +385 -0
  116. package/dist/verify-DlFQ2FOw.mjs.map +1 -0
  117. package/package.json +87 -40
  118. package/src/cli.ts +118 -58
  119. package/src/commands/contract-emit.ts +101 -78
  120. package/src/commands/contract-infer-paths.ts +32 -0
  121. package/src/commands/contract-infer.ts +143 -0
  122. package/src/commands/db-init.ts +97 -219
  123. package/src/commands/db-schema.ts +77 -0
  124. package/src/commands/db-sign.ts +46 -73
  125. package/src/commands/db-update.ts +236 -0
  126. package/src/commands/db-verify.ts +409 -119
  127. package/src/commands/init/detect-package-manager.ts +47 -0
  128. package/src/commands/init/index.ts +21 -0
  129. package/src/commands/init/init.ts +203 -0
  130. package/src/commands/init/templates/agent-skill-mongo.md +106 -0
  131. package/src/commands/init/templates/agent-skill-postgres.md +106 -0
  132. package/src/commands/init/templates/agent-skill.ts +19 -0
  133. package/src/commands/init/templates/code-templates.ts +168 -0
  134. package/src/commands/init/templates/quick-reference-mongo.md +93 -0
  135. package/src/commands/init/templates/quick-reference-postgres.md +91 -0
  136. package/src/commands/init/templates/quick-reference.ts +19 -0
  137. package/src/commands/init/templates/render.ts +20 -0
  138. package/src/commands/init/templates/tsconfig.ts +35 -0
  139. package/src/commands/inspect-live-schema.ts +170 -0
  140. package/src/commands/migration-apply.ts +427 -0
  141. package/src/commands/migration-new.ts +260 -0
  142. package/src/commands/migration-plan.ts +519 -0
  143. package/src/commands/migration-ref.ts +305 -0
  144. package/src/commands/migration-show.ts +246 -0
  145. package/src/commands/migration-status.ts +864 -0
  146. package/src/commands/migration-verify.ts +180 -0
  147. package/src/config-loader.ts +13 -3
  148. package/src/control-api/client.ts +205 -183
  149. package/src/control-api/contract-enrichment.ts +119 -0
  150. package/src/control-api/errors.ts +9 -0
  151. package/src/control-api/operations/contract-emit.ts +181 -0
  152. package/src/control-api/operations/db-init.ts +53 -49
  153. package/src/control-api/operations/db-update.ts +220 -0
  154. package/src/control-api/operations/extract-operation-statements.ts +14 -0
  155. package/src/control-api/operations/extract-sql-ddl.ts +47 -0
  156. package/src/control-api/operations/migration-apply.ts +191 -0
  157. package/src/control-api/operations/migration-helpers.ts +49 -0
  158. package/src/control-api/types.ts +274 -52
  159. package/src/exports/config-types.ts +4 -3
  160. package/src/exports/control-api.ts +15 -5
  161. package/src/load-ts-contract.ts +30 -19
  162. package/src/utils/cli-errors.ts +14 -8
  163. package/src/utils/command-helpers.ts +302 -3
  164. package/src/utils/formatters/emit.ts +67 -0
  165. package/src/utils/formatters/errors.ts +82 -0
  166. package/src/utils/formatters/graph-migration-mapper.ts +240 -0
  167. package/src/utils/formatters/graph-render.ts +1323 -0
  168. package/src/utils/formatters/graph-types.ts +120 -0
  169. package/src/utils/formatters/help.ts +380 -0
  170. package/src/utils/formatters/helpers.ts +28 -0
  171. package/src/utils/formatters/migrations.ts +346 -0
  172. package/src/utils/formatters/styled.ts +212 -0
  173. package/src/utils/formatters/verify.ts +621 -0
  174. package/src/utils/framework-components.ts +13 -10
  175. package/src/utils/global-flags.ts +41 -23
  176. package/src/utils/migration-command-scaffold.ts +184 -0
  177. package/src/utils/migration-types.ts +12 -0
  178. package/src/utils/progress-adapter.ts +18 -29
  179. package/src/utils/result-handler.ts +12 -13
  180. package/src/utils/shutdown.ts +92 -0
  181. package/src/utils/suggest-command.ts +31 -0
  182. package/src/utils/terminal-ui.ts +276 -0
  183. package/src/utils/validate-contract-deps.ts +49 -0
  184. package/dist/chunk-AGOTG4L3.js +0 -965
  185. package/dist/chunk-AGOTG4L3.js.map +0 -1
  186. package/dist/chunk-HLLI4YL7.js +0 -180
  187. package/dist/chunk-HLLI4YL7.js.map +0 -1
  188. package/dist/chunk-HWYQOCAJ.js +0 -47
  189. package/dist/chunk-HWYQOCAJ.js.map +0 -1
  190. package/dist/chunk-VG2R7DGF.js +0 -735
  191. package/dist/chunk-VG2R7DGF.js.map +0 -1
  192. package/dist/cli.d.ts +0 -2
  193. package/dist/cli.d.ts.map +0 -1
  194. package/dist/cli.js.map +0 -1
  195. package/dist/commands/contract-emit.d.ts +0 -3
  196. package/dist/commands/contract-emit.d.ts.map +0 -1
  197. package/dist/commands/contract-emit.js +0 -10
  198. package/dist/commands/contract-emit.js.map +0 -1
  199. package/dist/commands/db-init.d.ts +0 -3
  200. package/dist/commands/db-init.d.ts.map +0 -1
  201. package/dist/commands/db-init.js +0 -257
  202. package/dist/commands/db-init.js.map +0 -1
  203. package/dist/commands/db-introspect.d.ts +0 -3
  204. package/dist/commands/db-introspect.d.ts.map +0 -1
  205. package/dist/commands/db-introspect.js +0 -155
  206. package/dist/commands/db-introspect.js.map +0 -1
  207. package/dist/commands/db-schema-verify.d.ts +0 -3
  208. package/dist/commands/db-schema-verify.d.ts.map +0 -1
  209. package/dist/commands/db-schema-verify.js +0 -171
  210. package/dist/commands/db-schema-verify.js.map +0 -1
  211. package/dist/commands/db-sign.d.ts +0 -3
  212. package/dist/commands/db-sign.d.ts.map +0 -1
  213. package/dist/commands/db-sign.js +0 -195
  214. package/dist/commands/db-sign.js.map +0 -1
  215. package/dist/commands/db-verify.d.ts +0 -3
  216. package/dist/commands/db-verify.d.ts.map +0 -1
  217. package/dist/commands/db-verify.js +0 -193
  218. package/dist/commands/db-verify.js.map +0 -1
  219. package/dist/config-loader.d.ts.map +0 -1
  220. package/dist/config-loader.js +0 -7
  221. package/dist/config-loader.js.map +0 -1
  222. package/dist/control-api/client.d.ts +0 -13
  223. package/dist/control-api/client.d.ts.map +0 -1
  224. package/dist/control-api/operations/db-init.d.ts +0 -29
  225. package/dist/control-api/operations/db-init.d.ts.map +0 -1
  226. package/dist/control-api/types.d.ts +0 -387
  227. package/dist/control-api/types.d.ts.map +0 -1
  228. package/dist/exports/config-types.d.ts +0 -3
  229. package/dist/exports/config-types.d.ts.map +0 -1
  230. package/dist/exports/config-types.js +0 -6
  231. package/dist/exports/config-types.js.map +0 -1
  232. package/dist/exports/control-api.d.ts +0 -13
  233. package/dist/exports/control-api.d.ts.map +0 -1
  234. package/dist/exports/control-api.js +0 -7
  235. package/dist/exports/control-api.js.map +0 -1
  236. package/dist/exports/index.d.ts +0 -4
  237. package/dist/exports/index.d.ts.map +0 -1
  238. package/dist/exports/index.js +0 -176
  239. package/dist/exports/index.js.map +0 -1
  240. package/dist/load-ts-contract.d.ts.map +0 -1
  241. package/dist/utils/cli-errors.d.ts +0 -7
  242. package/dist/utils/cli-errors.d.ts.map +0 -1
  243. package/dist/utils/command-helpers.d.ts +0 -12
  244. package/dist/utils/command-helpers.d.ts.map +0 -1
  245. package/dist/utils/framework-components.d.ts +0 -70
  246. package/dist/utils/framework-components.d.ts.map +0 -1
  247. package/dist/utils/global-flags.d.ts +0 -25
  248. package/dist/utils/global-flags.d.ts.map +0 -1
  249. package/dist/utils/output.d.ts +0 -142
  250. package/dist/utils/output.d.ts.map +0 -1
  251. package/dist/utils/progress-adapter.d.ts +0 -26
  252. package/dist/utils/progress-adapter.d.ts.map +0 -1
  253. package/dist/utils/result-handler.d.ts +0 -15
  254. package/dist/utils/result-handler.d.ts.map +0 -1
  255. package/src/commands/db-introspect.ts +0 -227
  256. package/src/commands/db-schema-verify.ts +0 -238
  257. package/src/utils/output.ts +0 -1471
@@ -0,0 +1,191 @@
1
+ import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
2
+ import type {
3
+ ControlDriverInstance,
4
+ ControlFamilyInstance,
5
+ MigrationRunnerResult,
6
+ TargetMigrationsCapability,
7
+ } from '@prisma-next/framework-components/control';
8
+ import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
9
+ import { notOk, ok } from '@prisma-next/utils/result';
10
+ import type {
11
+ MigrationApplyAppliedEntry,
12
+ MigrationApplyResult,
13
+ MigrationApplyStep,
14
+ OnControlProgress,
15
+ } from '../types';
16
+
17
+ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetId extends string> {
18
+ readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
19
+ readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
20
+ readonly originHash: string;
21
+ readonly destinationHash: string;
22
+ readonly pendingMigrations: readonly MigrationApplyStep[];
23
+ readonly migrations: TargetMigrationsCapability<
24
+ TFamilyId,
25
+ TTargetId,
26
+ ControlFamilyInstance<TFamilyId, unknown>
27
+ >;
28
+ readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
29
+ readonly targetId: string;
30
+ readonly onProgress?: OnControlProgress;
31
+ }
32
+
33
+ export async function executeMigrationApply<TFamilyId extends string, TTargetId extends string>(
34
+ options: ExecuteMigrationApplyOptions<TFamilyId, TTargetId>,
35
+ ): Promise<MigrationApplyResult> {
36
+ const {
37
+ driver,
38
+ familyInstance,
39
+ originHash,
40
+ destinationHash,
41
+ pendingMigrations,
42
+ migrations,
43
+ frameworkComponents,
44
+ targetId,
45
+ onProgress,
46
+ } = options;
47
+
48
+ if (pendingMigrations.length === 0) {
49
+ if (originHash !== destinationHash) {
50
+ return notOk({
51
+ code: 'MIGRATION_PATH_NOT_FOUND' as const,
52
+ summary: 'No migrations provided for requested origin and destination',
53
+ why: `Requested ${originHash} -> ${destinationHash} but pendingMigrations is empty`,
54
+ meta: { originHash, destinationHash },
55
+ });
56
+ }
57
+ return ok({
58
+ migrationsApplied: 0,
59
+ markerHash: originHash,
60
+ applied: [],
61
+ summary: 'Already up to date',
62
+ });
63
+ }
64
+
65
+ const firstMigration = pendingMigrations[0]!;
66
+ const lastMigration = pendingMigrations[pendingMigrations.length - 1]!;
67
+ if (firstMigration.from !== originHash || lastMigration.to !== destinationHash) {
68
+ return notOk({
69
+ code: 'MIGRATION_PATH_NOT_FOUND' as const,
70
+ summary: 'Migration apply path does not match requested origin and destination',
71
+ why: `Path resolved as ${firstMigration.from} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,
72
+ meta: {
73
+ originHash,
74
+ destinationHash,
75
+ pathOrigin: firstMigration.from,
76
+ pathDestination: lastMigration.to,
77
+ },
78
+ });
79
+ }
80
+
81
+ for (let i = 1; i < pendingMigrations.length; i++) {
82
+ const previous = pendingMigrations[i - 1]!;
83
+ const current = pendingMigrations[i]!;
84
+ if (previous.to !== current.from) {
85
+ return notOk({
86
+ code: 'MIGRATION_PATH_NOT_FOUND' as const,
87
+ summary: 'Migration apply path contains a discontinuity between adjacent migrations',
88
+ why: `Migration "${previous.dirName}" ends at ${previous.to}, but next migration "${current.dirName}" starts at ${current.from}`,
89
+ meta: {
90
+ originHash,
91
+ destinationHash,
92
+ previousDirName: previous.dirName,
93
+ previousTo: previous.to,
94
+ currentDirName: current.dirName,
95
+ currentFrom: current.from,
96
+ discontinuityIndex: i,
97
+ },
98
+ });
99
+ }
100
+ }
101
+
102
+ const runner = migrations.createRunner(familyInstance);
103
+ const applied: MigrationApplyAppliedEntry[] = [];
104
+
105
+ for (const migration of pendingMigrations) {
106
+ const migrationSpanId = `migration:${migration.dirName}`;
107
+ onProgress?.({
108
+ action: 'migrationApply',
109
+ kind: 'spanStart',
110
+ spanId: migrationSpanId,
111
+ label: `Applying ${migration.dirName}`,
112
+ });
113
+
114
+ const { operations } = migration;
115
+
116
+ // Allow all operation classes. The policy gate belongs at plan time, not
117
+ // apply time — the planner already decided what to emit. Restricting here
118
+ // would be a tautology (the allowed set would just mirror what's in ops).
119
+ const policy = {
120
+ allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] as const,
121
+ };
122
+
123
+ // EMPTY_CONTRACT_HASH means "no prior state" — the runner expects origin: null
124
+ // for a fresh database (no marker present).
125
+ const plan = {
126
+ targetId,
127
+ origin: migration.from === EMPTY_CONTRACT_HASH ? null : { storageHash: migration.from },
128
+ destination: { storageHash: migration.to },
129
+ operations,
130
+ };
131
+
132
+ const destinationContract = familyInstance.validateContract(migration.toContract);
133
+
134
+ const runnerResult: MigrationRunnerResult = await runner.execute({
135
+ plan,
136
+ driver,
137
+ destinationContract,
138
+ policy,
139
+ executionChecks: {
140
+ prechecks: true,
141
+ postchecks: true,
142
+ idempotencyChecks: true,
143
+ },
144
+ frameworkComponents,
145
+ });
146
+
147
+ if (!runnerResult.ok) {
148
+ onProgress?.({
149
+ action: 'migrationApply',
150
+ kind: 'spanEnd',
151
+ spanId: migrationSpanId,
152
+ outcome: 'error',
153
+ });
154
+ return notOk({
155
+ code: 'RUNNER_FAILED' as const,
156
+ summary: runnerResult.failure.summary,
157
+ why: runnerResult.failure.why,
158
+ meta: {
159
+ migration: migration.dirName,
160
+ from: migration.from,
161
+ to: migration.to,
162
+ ...(runnerResult.failure.meta ?? {}),
163
+ },
164
+ });
165
+ }
166
+
167
+ onProgress?.({
168
+ action: 'migrationApply',
169
+ kind: 'spanEnd',
170
+ spanId: migrationSpanId,
171
+ outcome: 'ok',
172
+ });
173
+
174
+ applied.push({
175
+ dirName: migration.dirName,
176
+ from: migration.from,
177
+ to: migration.to,
178
+ operationsExecuted: runnerResult.value.operationsExecuted,
179
+ });
180
+ }
181
+
182
+ const finalHash = pendingMigrations[pendingMigrations.length - 1]!.to;
183
+ const totalOps = applied.reduce((sum, a) => sum + a.operationsExecuted, 0);
184
+
185
+ return ok({
186
+ migrationsApplied: applied.length,
187
+ markerHash: finalHash,
188
+ applied,
189
+ summary: `Applied ${applied.length} migration(s) (${totalOps} operation(s)), marker at ${finalHash}`,
190
+ });
191
+ }
@@ -0,0 +1,49 @@
1
+ import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';
2
+ import type { ControlActionName, OnControlProgress } from '../types';
3
+
4
+ /**
5
+ * Strips operation objects to their public shape (id, label, operationClass).
6
+ * Used at the API boundary to avoid leaking internal fields (precheck, execute, postcheck, etc.).
7
+ */
8
+ export function stripOperations(
9
+ operations: readonly MigrationPlanOperation[],
10
+ ): ReadonlyArray<{ readonly id: string; readonly label: string; readonly operationClass: string }> {
11
+ return operations.map((op) => ({
12
+ id: op.id,
13
+ label: op.label,
14
+ operationClass: op.operationClass,
15
+ }));
16
+ }
17
+
18
+ /**
19
+ * Creates per-operation progress callbacks for the runner.
20
+ * Returns undefined when no onProgress callback is provided.
21
+ */
22
+ export function createOperationCallbacks(
23
+ onProgress: OnControlProgress | undefined,
24
+ action: ControlActionName,
25
+ parentSpanId: string,
26
+ ) {
27
+ if (!onProgress) {
28
+ return undefined;
29
+ }
30
+ return {
31
+ onOperationStart: (op: MigrationPlanOperation) => {
32
+ onProgress({
33
+ action,
34
+ kind: 'spanStart',
35
+ spanId: `operation:${op.id}`,
36
+ parentSpanId,
37
+ label: op.label,
38
+ });
39
+ },
40
+ onOperationComplete: (op: MigrationPlanOperation) => {
41
+ onProgress({
42
+ action,
43
+ kind: 'spanEnd',
44
+ spanId: `operation:${op.id}`,
45
+ outcome: 'ok',
46
+ });
47
+ },
48
+ };
49
+ }