@platforma-sdk/model 1.58.3 → 1.58.9

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 (366) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +43 -0
  2. package/dist/_virtual/_rolldown/runtime.js +18 -0
  3. package/dist/annotations/converter.cjs +15 -20
  4. package/dist/annotations/converter.cjs.map +1 -1
  5. package/dist/annotations/converter.d.ts +6 -2
  6. package/dist/annotations/converter.js +14 -18
  7. package/dist/annotations/converter.js.map +1 -1
  8. package/dist/annotations/index.cjs +1 -0
  9. package/dist/annotations/index.d.ts +2 -3
  10. package/dist/annotations/index.js +1 -0
  11. package/dist/annotations/types.d.ts +21 -16
  12. package/dist/bconfig/index.cjs +2 -0
  13. package/dist/bconfig/index.d.ts +5 -6
  14. package/dist/bconfig/index.js +2 -0
  15. package/dist/bconfig/lambdas.d.ts +52 -52
  16. package/dist/bconfig/normalization.cjs +13 -18
  17. package/dist/bconfig/normalization.cjs.map +1 -1
  18. package/dist/bconfig/normalization.d.ts +10 -6
  19. package/dist/bconfig/normalization.js +12 -16
  20. package/dist/bconfig/normalization.js.map +1 -1
  21. package/dist/bconfig/types.cjs +4 -3
  22. package/dist/bconfig/types.cjs.map +1 -1
  23. package/dist/bconfig/types.d.ts +10 -5
  24. package/dist/bconfig/types.js +4 -2
  25. package/dist/bconfig/types.js.map +1 -1
  26. package/dist/bconfig/util.d.ts +7 -4
  27. package/dist/bconfig/v3.d.ts +10 -6
  28. package/dist/block_api_v1.d.ts +62 -58
  29. package/dist/block_api_v2.d.ts +51 -47
  30. package/dist/block_api_v3.d.ts +33 -29
  31. package/dist/block_migrations.cjs +481 -413
  32. package/dist/block_migrations.cjs.map +1 -1
  33. package/dist/block_migrations.d.ts +258 -204
  34. package/dist/block_migrations.js +482 -408
  35. package/dist/block_migrations.js.map +1 -1
  36. package/dist/block_model.cjs +312 -343
  37. package/dist/block_model.cjs.map +1 -1
  38. package/dist/block_model.d.ts +143 -147
  39. package/dist/block_model.js +312 -341
  40. package/dist/block_model.js.map +1 -1
  41. package/dist/block_model_legacy.cjs +231 -255
  42. package/dist/block_model_legacy.cjs.map +1 -1
  43. package/dist/block_model_legacy.d.ts +108 -106
  44. package/dist/block_model_legacy.js +231 -253
  45. package/dist/block_model_legacy.js.map +1 -1
  46. package/dist/block_state_patch.d.ts +10 -10
  47. package/dist/block_state_util.cjs +15 -19
  48. package/dist/block_state_util.cjs.map +1 -1
  49. package/dist/block_state_util.d.ts +14 -13
  50. package/dist/block_state_util.js +15 -18
  51. package/dist/block_state_util.js.map +1 -1
  52. package/dist/block_storage.cjs +233 -238
  53. package/dist/block_storage.cjs.map +1 -1
  54. package/dist/block_storage.d.ts +62 -78
  55. package/dist/block_storage.js +234 -237
  56. package/dist/block_storage.js.map +1 -1
  57. package/dist/block_storage_callbacks.cjs +156 -195
  58. package/dist/block_storage_callbacks.cjs.map +1 -1
  59. package/dist/block_storage_callbacks.js +156 -192
  60. package/dist/block_storage_callbacks.js.map +1 -1
  61. package/dist/block_storage_facade.cjs +29 -85
  62. package/dist/block_storage_facade.cjs.map +1 -1
  63. package/dist/block_storage_facade.d.ts +83 -126
  64. package/dist/block_storage_facade.js +29 -83
  65. package/dist/block_storage_facade.js.map +1 -1
  66. package/dist/components/PFrameForGraphs.cjs +26 -24
  67. package/dist/components/PFrameForGraphs.cjs.map +1 -1
  68. package/dist/components/PFrameForGraphs.d.ts +12 -7
  69. package/dist/components/PFrameForGraphs.js +25 -22
  70. package/dist/components/PFrameForGraphs.js.map +1 -1
  71. package/dist/components/PlAnnotations/filter.d.ts +62 -79
  72. package/dist/components/PlAnnotations/filters_ui.cjs +135 -171
  73. package/dist/components/PlAnnotations/filters_ui.cjs.map +1 -1
  74. package/dist/components/PlAnnotations/filters_ui.d.ts +48 -46
  75. package/dist/components/PlAnnotations/filters_ui.js +135 -170
  76. package/dist/components/PlAnnotations/filters_ui.js.map +1 -1
  77. package/dist/components/PlAnnotations/index.d.ts +2 -3
  78. package/dist/components/PlDataTable/index.cjs +2 -0
  79. package/dist/components/PlDataTable/index.d.ts +3 -5
  80. package/dist/components/PlDataTable/index.js +2 -0
  81. package/dist/components/PlDataTable/labels.cjs +59 -81
  82. package/dist/components/PlDataTable/labels.cjs.map +1 -1
  83. package/dist/components/PlDataTable/labels.js +58 -79
  84. package/dist/components/PlDataTable/labels.js.map +1 -1
  85. package/dist/components/PlDataTable/state-migration.cjs +186 -144
  86. package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
  87. package/dist/components/PlDataTable/state-migration.d.ts +85 -82
  88. package/dist/components/PlDataTable/state-migration.js +185 -142
  89. package/dist/components/PlDataTable/state-migration.js.map +1 -1
  90. package/dist/components/PlDataTable/table.cjs +172 -194
  91. package/dist/components/PlDataTable/table.cjs.map +1 -1
  92. package/dist/components/PlDataTable/table.d.ts +16 -12
  93. package/dist/components/PlDataTable/table.js +171 -192
  94. package/dist/components/PlDataTable/table.js.map +1 -1
  95. package/dist/components/PlDataTable/v4.d.ts +84 -119
  96. package/dist/components/PlDataTable/v5.d.ts +80 -103
  97. package/dist/components/PlMultiSequenceAlignment.cjs +27 -29
  98. package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
  99. package/dist/components/PlMultiSequenceAlignment.d.ts +36 -27
  100. package/dist/components/PlMultiSequenceAlignment.js +26 -27
  101. package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
  102. package/dist/components/PlSelectionModel.cjs +7 -6
  103. package/dist/components/PlSelectionModel.cjs.map +1 -1
  104. package/dist/components/PlSelectionModel.d.ts +10 -8
  105. package/dist/components/PlSelectionModel.js +7 -5
  106. package/dist/components/PlSelectionModel.js.map +1 -1
  107. package/dist/components/index.cjs +8 -0
  108. package/dist/components/index.d.ts +11 -6
  109. package/dist/components/index.js +8 -0
  110. package/dist/config/actions.cjs +138 -171
  111. package/dist/config/actions.cjs.map +1 -1
  112. package/dist/config/actions.d.ts +47 -47
  113. package/dist/config/actions.js +146 -178
  114. package/dist/config/actions.js.map +1 -1
  115. package/dist/config/actions_kinds.d.ts +114 -121
  116. package/dist/config/index.cjs +1 -0
  117. package/dist/config/index.d.ts +6 -7
  118. package/dist/config/index.js +1 -0
  119. package/dist/config/model.d.ts +131 -127
  120. package/dist/config/model_meta.d.ts +4 -1
  121. package/dist/config/type_engine.d.ts +22 -21
  122. package/dist/config/type_util.d.ts +12 -10
  123. package/dist/env_value.cjs +5 -6
  124. package/dist/env_value.cjs.map +1 -1
  125. package/dist/env_value.d.ts +4 -1
  126. package/dist/env_value.js +5 -5
  127. package/dist/env_value.js.map +1 -1
  128. package/dist/filters/converters/filterToQuery.cjs +273 -239
  129. package/dist/filters/converters/filterToQuery.cjs.map +1 -1
  130. package/dist/filters/converters/filterToQuery.d.ts +6 -2
  131. package/dist/filters/converters/filterToQuery.js +272 -237
  132. package/dist/filters/converters/filterToQuery.js.map +1 -1
  133. package/dist/filters/converters/filterUiToExpressionImpl.cjs +56 -85
  134. package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -1
  135. package/dist/filters/converters/filterUiToExpressionImpl.d.ts +8 -4
  136. package/dist/filters/converters/filterUiToExpressionImpl.js +55 -83
  137. package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -1
  138. package/dist/filters/converters/index.cjs +2 -0
  139. package/dist/filters/converters/index.d.ts +2 -3
  140. package/dist/filters/converters/index.js +2 -0
  141. package/dist/filters/distill.cjs +59 -50
  142. package/dist/filters/distill.cjs.map +1 -1
  143. package/dist/filters/distill.d.ts +6 -3
  144. package/dist/filters/distill.js +58 -48
  145. package/dist/filters/distill.js.map +1 -1
  146. package/dist/filters/index.cjs +4 -0
  147. package/dist/filters/index.d.ts +5 -4
  148. package/dist/filters/index.js +4 -0
  149. package/dist/filters/traverse.cjs +31 -40
  150. package/dist/filters/traverse.cjs.map +1 -1
  151. package/dist/filters/traverse.js +31 -39
  152. package/dist/filters/traverse.js.map +1 -1
  153. package/dist/filters/types.d.ts +10 -7
  154. package/dist/index.cjs +193 -187
  155. package/dist/index.d.ts +61 -28
  156. package/dist/index.js +49 -41
  157. package/dist/internal.cjs +48 -62
  158. package/dist/internal.cjs.map +1 -1
  159. package/dist/internal.js +49 -60
  160. package/dist/internal.js.map +1 -1
  161. package/dist/package.cjs +12 -0
  162. package/dist/package.cjs.map +1 -0
  163. package/dist/package.js +6 -0
  164. package/dist/package.js.map +1 -0
  165. package/dist/pframe.cjs +32 -37
  166. package/dist/pframe.cjs.map +1 -1
  167. package/dist/pframe.d.ts +14 -10
  168. package/dist/pframe.js +32 -35
  169. package/dist/pframe.js.map +1 -1
  170. package/dist/pframe_utils/axes.cjs +81 -114
  171. package/dist/pframe_utils/axes.cjs.map +1 -1
  172. package/dist/pframe_utils/axes.d.ts +10 -13
  173. package/dist/pframe_utils/axes.js +80 -112
  174. package/dist/pframe_utils/axes.js.map +1 -1
  175. package/dist/pframe_utils/columns.cjs +61 -81
  176. package/dist/pframe_utils/columns.cjs.map +1 -1
  177. package/dist/pframe_utils/columns.d.ts +15 -6
  178. package/dist/pframe_utils/columns.js +60 -79
  179. package/dist/pframe_utils/columns.js.map +1 -1
  180. package/dist/pframe_utils/index.cjs +232 -253
  181. package/dist/pframe_utils/index.cjs.map +1 -1
  182. package/dist/pframe_utils/index.d.ts +39 -35
  183. package/dist/pframe_utils/index.js +231 -251
  184. package/dist/pframe_utils/index.js.map +1 -1
  185. package/dist/platforma.d.ts +48 -46
  186. package/dist/plugin_handle.cjs +6 -14
  187. package/dist/plugin_handle.cjs.map +1 -1
  188. package/dist/plugin_handle.d.ts +20 -25
  189. package/dist/plugin_handle.js +6 -13
  190. package/dist/plugin_handle.js.map +1 -1
  191. package/dist/plugin_model.cjs +364 -163
  192. package/dist/plugin_model.cjs.map +1 -1
  193. package/dist/plugin_model.d.ts +280 -129
  194. package/dist/plugin_model.js +362 -163
  195. package/dist/plugin_model.js.map +1 -1
  196. package/dist/raw_globals.cjs +10 -22
  197. package/dist/raw_globals.cjs.map +1 -1
  198. package/dist/raw_globals.d.ts +8 -5
  199. package/dist/raw_globals.js +10 -20
  200. package/dist/raw_globals.js.map +1 -1
  201. package/dist/ref_util.cjs +14 -13
  202. package/dist/ref_util.cjs.map +1 -1
  203. package/dist/ref_util.d.ts +18 -12
  204. package/dist/ref_util.js +14 -11
  205. package/dist/ref_util.js.map +1 -1
  206. package/dist/render/accessor.cjs +213 -226
  207. package/dist/render/accessor.cjs.map +1 -1
  208. package/dist/render/accessor.d.ts +115 -120
  209. package/dist/render/accessor.js +212 -224
  210. package/dist/render/accessor.js.map +1 -1
  211. package/dist/render/api.cjs +478 -580
  212. package/dist/render/api.cjs.map +1 -1
  213. package/dist/render/api.d.ts +207 -209
  214. package/dist/render/api.js +476 -578
  215. package/dist/render/api.js.map +1 -1
  216. package/dist/render/future.cjs +28 -32
  217. package/dist/render/future.cjs.map +1 -1
  218. package/dist/render/future.d.ts +15 -11
  219. package/dist/render/future.js +28 -30
  220. package/dist/render/future.js.map +1 -1
  221. package/dist/render/index.cjs +8 -0
  222. package/dist/render/index.d.ts +10 -8
  223. package/dist/render/index.js +8 -0
  224. package/dist/render/internal.cjs +33 -29
  225. package/dist/render/internal.cjs.map +1 -1
  226. package/dist/render/internal.d.ts +78 -72
  227. package/dist/render/internal.js +29 -26
  228. package/dist/render/internal.js.map +1 -1
  229. package/dist/render/traversal_ops.d.ts +42 -43
  230. package/dist/render/util/axis_filtering.cjs +63 -86
  231. package/dist/render/util/axis_filtering.cjs.map +1 -1
  232. package/dist/render/util/axis_filtering.d.ts +10 -7
  233. package/dist/render/util/axis_filtering.js +63 -85
  234. package/dist/render/util/axis_filtering.js.map +1 -1
  235. package/dist/render/util/column_collection.cjs +266 -321
  236. package/dist/render/util/column_collection.cjs.map +1 -1
  237. package/dist/render/util/column_collection.d.ts +47 -47
  238. package/dist/render/util/column_collection.js +264 -319
  239. package/dist/render/util/column_collection.js.map +1 -1
  240. package/dist/render/util/index.cjs +4 -0
  241. package/dist/render/util/index.d.ts +4 -5
  242. package/dist/render/util/index.js +4 -0
  243. package/dist/render/util/label.cjs +129 -163
  244. package/dist/render/util/label.cjs.map +1 -1
  245. package/dist/render/util/label.d.ts +45 -46
  246. package/dist/render/util/label.js +128 -161
  247. package/dist/render/util/label.js.map +1 -1
  248. package/dist/render/util/pcolumn_data.cjs +315 -375
  249. package/dist/render/util/pcolumn_data.cjs.map +1 -1
  250. package/dist/render/util/pcolumn_data.d.ts +33 -32
  251. package/dist/render/util/pcolumn_data.js +314 -373
  252. package/dist/render/util/pcolumn_data.js.map +1 -1
  253. package/dist/render/util/pframe_upgraders.cjs +37 -42
  254. package/dist/render/util/pframe_upgraders.cjs.map +1 -1
  255. package/dist/render/util/pframe_upgraders.js +37 -41
  256. package/dist/render/util/pframe_upgraders.js.map +1 -1
  257. package/dist/render/util/split_selectors.d.ts +13 -9
  258. package/dist/version.cjs +6 -8
  259. package/dist/version.cjs.map +1 -1
  260. package/dist/version.d.ts +7 -4
  261. package/dist/version.js +5 -5
  262. package/dist/version.js.map +1 -1
  263. package/package.json +9 -3
  264. package/src/block_migrations.test.ts +184 -14
  265. package/src/block_migrations.ts +185 -30
  266. package/src/block_model.ts +111 -66
  267. package/src/block_storage.test.ts +147 -3
  268. package/src/block_storage.ts +43 -8
  269. package/src/block_storage_callbacks.ts +9 -4
  270. package/src/env_value.ts +0 -2
  271. package/src/filters/distill.ts +17 -6
  272. package/src/index.ts +12 -11
  273. package/src/internal.ts +0 -1
  274. package/src/platforma.ts +4 -4
  275. package/src/plugin_handle.ts +1 -1
  276. package/src/plugin_model.test.ts +217 -21
  277. package/src/plugin_model.ts +450 -55
  278. package/src/raw_globals.ts +0 -1
  279. package/dist/annotations/converter.d.ts.map +0 -1
  280. package/dist/annotations/index.d.ts.map +0 -1
  281. package/dist/annotations/types.d.ts.map +0 -1
  282. package/dist/bconfig/index.d.ts.map +0 -1
  283. package/dist/bconfig/lambdas.d.ts.map +0 -1
  284. package/dist/bconfig/normalization.d.ts.map +0 -1
  285. package/dist/bconfig/types.d.ts.map +0 -1
  286. package/dist/bconfig/util.d.ts.map +0 -1
  287. package/dist/bconfig/v3.d.ts.map +0 -1
  288. package/dist/block_api_v1.d.ts.map +0 -1
  289. package/dist/block_api_v2.d.ts.map +0 -1
  290. package/dist/block_api_v3.d.ts.map +0 -1
  291. package/dist/block_migrations.d.ts.map +0 -1
  292. package/dist/block_model.d.ts.map +0 -1
  293. package/dist/block_model_legacy.d.ts.map +0 -1
  294. package/dist/block_state_patch.d.ts.map +0 -1
  295. package/dist/block_state_util.d.ts.map +0 -1
  296. package/dist/block_storage.d.ts.map +0 -1
  297. package/dist/block_storage_callbacks.d.ts +0 -115
  298. package/dist/block_storage_callbacks.d.ts.map +0 -1
  299. package/dist/block_storage_facade.d.ts.map +0 -1
  300. package/dist/components/PFrameForGraphs.d.ts.map +0 -1
  301. package/dist/components/PlAnnotations/filter.d.ts.map +0 -1
  302. package/dist/components/PlAnnotations/filters_ui.d.ts.map +0 -1
  303. package/dist/components/PlAnnotations/index.d.ts.map +0 -1
  304. package/dist/components/PlAnnotations/types.d.ts +0 -3
  305. package/dist/components/PlAnnotations/types.d.ts.map +0 -1
  306. package/dist/components/PlDataTable/index.d.ts.map +0 -1
  307. package/dist/components/PlDataTable/labels.d.ts +0 -7
  308. package/dist/components/PlDataTable/labels.d.ts.map +0 -1
  309. package/dist/components/PlDataTable/state-migration.d.ts.map +0 -1
  310. package/dist/components/PlDataTable/table.d.ts.map +0 -1
  311. package/dist/components/PlDataTable/v4.d.ts.map +0 -1
  312. package/dist/components/PlDataTable/v5.d.ts.map +0 -1
  313. package/dist/components/PlMultiSequenceAlignment.d.ts.map +0 -1
  314. package/dist/components/PlSelectionModel.d.ts.map +0 -1
  315. package/dist/components/index.d.ts.map +0 -1
  316. package/dist/config/actions.d.ts.map +0 -1
  317. package/dist/config/actions_kinds.d.ts.map +0 -1
  318. package/dist/config/index.d.ts.map +0 -1
  319. package/dist/config/model.d.ts.map +0 -1
  320. package/dist/config/model_meta.d.ts.map +0 -1
  321. package/dist/config/type_engine.d.ts.map +0 -1
  322. package/dist/config/type_util.d.ts.map +0 -1
  323. package/dist/env_value.d.ts.map +0 -1
  324. package/dist/filters/converters/filterToQuery.d.ts.map +0 -1
  325. package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +0 -1
  326. package/dist/filters/converters/index.d.ts.map +0 -1
  327. package/dist/filters/distill.d.ts.map +0 -1
  328. package/dist/filters/index.d.ts.map +0 -1
  329. package/dist/filters/traverse.d.ts +0 -27
  330. package/dist/filters/traverse.d.ts.map +0 -1
  331. package/dist/filters/types.d.ts.map +0 -1
  332. package/dist/index.cjs.map +0 -1
  333. package/dist/index.d.ts.map +0 -1
  334. package/dist/index.js.map +0 -1
  335. package/dist/internal.d.ts +0 -36
  336. package/dist/internal.d.ts.map +0 -1
  337. package/dist/package.json.cjs +0 -6
  338. package/dist/package.json.cjs.map +0 -1
  339. package/dist/package.json.js +0 -4
  340. package/dist/package.json.js.map +0 -1
  341. package/dist/pframe.d.ts.map +0 -1
  342. package/dist/pframe_utils/axes.d.ts.map +0 -1
  343. package/dist/pframe_utils/columns.d.ts.map +0 -1
  344. package/dist/pframe_utils/index.d.ts.map +0 -1
  345. package/dist/pframe_utils/querySpec.d.ts +0 -2
  346. package/dist/pframe_utils/querySpec.d.ts.map +0 -1
  347. package/dist/platforma.d.ts.map +0 -1
  348. package/dist/plugin_handle.d.ts.map +0 -1
  349. package/dist/plugin_model.d.ts.map +0 -1
  350. package/dist/raw_globals.d.ts.map +0 -1
  351. package/dist/ref_util.d.ts.map +0 -1
  352. package/dist/render/accessor.d.ts.map +0 -1
  353. package/dist/render/api.d.ts.map +0 -1
  354. package/dist/render/future.d.ts.map +0 -1
  355. package/dist/render/index.d.ts.map +0 -1
  356. package/dist/render/internal.d.ts.map +0 -1
  357. package/dist/render/traversal_ops.d.ts.map +0 -1
  358. package/dist/render/util/axis_filtering.d.ts.map +0 -1
  359. package/dist/render/util/column_collection.d.ts.map +0 -1
  360. package/dist/render/util/index.d.ts.map +0 -1
  361. package/dist/render/util/label.d.ts.map +0 -1
  362. package/dist/render/util/pcolumn_data.d.ts.map +0 -1
  363. package/dist/render/util/pframe_upgraders.d.ts +0 -3
  364. package/dist/render/util/pframe_upgraders.d.ts.map +0 -1
  365. package/dist/render/util/split_selectors.d.ts.map +0 -1
  366. package/dist/version.d.ts.map +0 -1
@@ -5,6 +5,31 @@ export type DataMigrateFn<From, To> = (prev: Readonly<From>) => To;
5
5
  export type DataCreateFn<T> = () => T;
6
6
  export type DataRecoverFn<T> = (version: DataVersionKey, data: unknown) => T;
7
7
 
8
+ /**
9
+ * Minimal interface that .transfer() accepts. PluginInstance implements this.
10
+ * Defined here to avoid circular dependency with plugin_model.ts.
11
+ */
12
+ export interface TransferTarget<Id extends string = string, TransferData = never> {
13
+ readonly id: Id;
14
+ /** Version key in the plugin's data model chain where transferred data enters. */
15
+ readonly transferVersion: string;
16
+ /** @internal Phantom field for TransferData type extraction */
17
+ readonly __transferBrand?: TransferData;
18
+ }
19
+
20
+ /** Internal record of a single transfer step in the migration chain. */
21
+ export type TransferStep = {
22
+ pluginId: string;
23
+ /** Capture data before this step index executes. */
24
+ beforeStepIndex: number;
25
+ extract: (data: unknown) => unknown;
26
+ /** Version key in the plugin's data model chain where the transferred data enters. */
27
+ targetVersion: string;
28
+ };
29
+
30
+ /** Map of plugin ID → versioned data extracted during migration. */
31
+ export type TransferRecord = Record<string, DataVersioned<unknown>>;
32
+
8
33
  /** Versioned data wrapper for persistence */
9
34
  export type DataVersioned<T> = {
10
35
  version: DataVersionKey;
@@ -12,7 +37,7 @@ export type DataVersioned<T> = {
12
37
  };
13
38
 
14
39
  /** Create a DataVersioned wrapper with correct shape */
15
- export function makeDataVersioned<T>(version: DataVersionKey, data: T): DataVersioned<T> {
40
+ export function makeVersionedData<T>(version: DataVersionKey, data: T): DataVersioned<T> {
16
41
  return { version, data };
17
42
  }
18
43
 
@@ -68,6 +93,7 @@ export type LegacyV1State<Args, UiState> = { args: Args; uiState: UiState };
68
93
  type BuilderState<S> = {
69
94
  versionChain: DataVersionKey[];
70
95
  steps: MigrationStep[];
96
+ transferSteps: TransferStep[];
71
97
  initialDataFn: () => S;
72
98
  recoverFn?: (version: DataVersionKey, data: unknown) => unknown;
73
99
  /** Index of the first step to run after recovery. Equals the number of steps
@@ -89,13 +115,19 @@ type RecoverState = {
89
115
  *
90
116
  * @internal
91
117
  */
92
- abstract class MigrationChainBase<Current> {
118
+ abstract class MigrationChainBase<Current, Transfers extends Record<string, unknown> = {}> {
93
119
  protected readonly versionChain: DataVersionKey[];
94
120
  protected readonly migrationSteps: MigrationStep[];
121
+ protected readonly transferSteps: TransferStep[];
95
122
 
96
- protected constructor(state: { versionChain: DataVersionKey[]; steps: MigrationStep[] }) {
123
+ protected constructor(state: {
124
+ versionChain: DataVersionKey[];
125
+ steps: MigrationStep[];
126
+ transferSteps?: TransferStep[];
127
+ }) {
97
128
  this.versionChain = state.versionChain;
98
129
  this.migrationSteps = state.steps;
130
+ this.transferSteps = state.transferSteps ?? [];
99
131
  }
100
132
 
101
133
  /** Appends a migration step and returns the new versionChain and steps arrays. */
@@ -118,6 +150,23 @@ abstract class MigrationChainBase<Current> {
118
150
  };
119
151
  }
120
152
 
153
+ /** Validates uniqueness and records a TransferStep. */
154
+ protected buildTransfer<Id extends string, L>(
155
+ target: TransferTarget<Id, L>,
156
+ extract: (data: Current) => L,
157
+ ): { transferSteps: TransferStep[] } {
158
+ if (this.transferSteps.some((t) => t.pluginId === target.id)) {
159
+ throw new Error(`Duplicate transfer for plugin '${target.id}'`);
160
+ }
161
+ const entry: TransferStep = {
162
+ pluginId: target.id,
163
+ beforeStepIndex: this.migrationSteps.length,
164
+ extract: extract as (data: unknown) => unknown,
165
+ targetVersion: target.transferVersion,
166
+ };
167
+ return { transferSteps: [...this.transferSteps, entry] };
168
+ }
169
+
121
170
  /** Returns recover-specific fields for DataModel construction. Overridden by WithRecover. */
122
171
  protected recoverState(): RecoverState {
123
172
  return {};
@@ -129,10 +178,11 @@ abstract class MigrationChainBase<Current> {
129
178
  * @param initialData - Factory function returning the initial state
130
179
  * @returns Finalized DataModel instance
131
180
  */
132
- init(initialData: DataCreateFn<Current>): DataModel<Current> {
133
- return DataModel[FROM_BUILDER]<Current>({
181
+ init(initialData: DataCreateFn<Current>): DataModel<Current, Transfers> {
182
+ return DataModel[FROM_BUILDER]<Current, Transfers>({
134
183
  versionChain: this.versionChain,
135
184
  steps: this.migrationSteps,
185
+ transferSteps: this.transferSteps,
136
186
  initialDataFn: initialData,
137
187
  ...this.recoverState(),
138
188
  });
@@ -141,13 +191,17 @@ abstract class MigrationChainBase<Current> {
141
191
 
142
192
  /**
143
193
  * Migration chain after recover() or upgradeLegacy() has been called.
144
- * Further migrate() calls are allowed; recover() and upgradeLegacy() are not
194
+ * Further migrate() and transfer() calls are allowed; recover() and upgradeLegacy() are not
145
195
  * (enforced by type — no such methods on this class).
146
196
  *
147
197
  * @typeParam Current - Data type at the current point in the chain
198
+ * @typeParam Transfers - Accumulated transfer types keyed by plugin ID
148
199
  * @internal
149
200
  */
150
- class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Current> {
201
+ class DataModelMigrationChainWithRecover<
202
+ Current,
203
+ Transfers extends Record<string, unknown> = {},
204
+ > extends MigrationChainBase<Current, Transfers> {
151
205
  private readonly recoverFn?: (version: DataVersionKey, data: unknown) => unknown;
152
206
  private readonly recoverFromIndex?: number;
153
207
 
@@ -155,6 +209,7 @@ class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Cur
155
209
  constructor(state: {
156
210
  versionChain: DataVersionKey[];
157
211
  steps: MigrationStep[];
212
+ transferSteps?: TransferStep[];
158
213
  recoverFn?: (version: DataVersionKey, data: unknown) => unknown;
159
214
  recoverFromIndex?: number;
160
215
  }) {
@@ -177,11 +232,31 @@ class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Cur
177
232
  migrate<Next>(
178
233
  nextVersion: string,
179
234
  fn: DataMigrateFn<Current, Next>,
180
- ): DataModelMigrationChainWithRecover<Next> {
235
+ ): DataModelMigrationChainWithRecover<Next, Transfers> {
181
236
  const { versionChain, steps } = this.buildStep(nextVersion, fn);
182
- return new DataModelMigrationChainWithRecover<Next>({
237
+ return new DataModelMigrationChainWithRecover<Next, Transfers>({
183
238
  versionChain,
184
239
  steps,
240
+ transferSteps: this.transferSteps,
241
+ recoverFn: this.recoverFn,
242
+ recoverFromIndex: this.recoverFromIndex,
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Extract data at the current chain position for seeding a new plugin.
248
+ * The extract function's return type must match the plugin's transfer data type.
249
+ * Duplicate plugin IDs are rejected at both type and runtime level.
250
+ */
251
+ transfer<Id extends string, L>(
252
+ target: TransferTarget<Id & (Id extends keyof Transfers ? never : string), L>,
253
+ extract: (data: Current) => L,
254
+ ): DataModelMigrationChainWithRecover<Current, Transfers & Record<Id, L>> {
255
+ const { transferSteps } = this.buildTransfer(target, extract);
256
+ return new DataModelMigrationChainWithRecover<Current, Transfers & Record<Id, L>>({
257
+ versionChain: this.versionChain,
258
+ steps: this.migrationSteps,
259
+ transferSteps,
185
260
  recoverFn: this.recoverFn,
186
261
  recoverFromIndex: this.recoverFromIndex,
187
262
  });
@@ -195,18 +270,24 @@ class DataModelMigrationChainWithRecover<Current> extends MigrationChainBase<Cur
195
270
  * Duplicate version keys throw at runtime.
196
271
  *
197
272
  * @typeParam Current - Data type at the current point in the migration chain
273
+ * @typeParam Transfers - Accumulated transfer types keyed by plugin ID
198
274
  * @internal
199
275
  */
200
- class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
276
+ class DataModelMigrationChain<
277
+ Current,
278
+ Transfers extends Record<string, unknown> = {},
279
+ > extends MigrationChainBase<Current, Transfers> {
201
280
  /** @internal */
202
281
  constructor({
203
282
  versionChain,
204
283
  steps = [],
284
+ transferSteps = [],
205
285
  }: {
206
286
  versionChain: DataVersionKey[];
207
287
  steps?: MigrationStep[];
288
+ transferSteps?: TransferStep[];
208
289
  }) {
209
- super({ versionChain, steps });
290
+ super({ versionChain, steps, transferSteps });
210
291
  }
211
292
 
212
293
  /**
@@ -223,9 +304,38 @@ class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
223
304
  migrate<Next>(
224
305
  nextVersion: string,
225
306
  fn: DataMigrateFn<Current, Next>,
226
- ): DataModelMigrationChain<Next> {
307
+ ): DataModelMigrationChain<Next, Transfers> {
227
308
  const { versionChain, steps } = this.buildStep(nextVersion, fn);
228
- return new DataModelMigrationChain<Next>({ versionChain, steps });
309
+ return new DataModelMigrationChain<Next, Transfers>({
310
+ versionChain,
311
+ steps,
312
+ transferSteps: this.transferSteps,
313
+ });
314
+ }
315
+
316
+ /**
317
+ * Extract data at the current chain position for seeding a new plugin.
318
+ * The extract function's return type must match the plugin's transfer data type.
319
+ * Duplicate plugin IDs are rejected at both type and runtime level.
320
+ *
321
+ * Calling .transfer() on DataModelInitialChain returns DataModelMigrationChain,
322
+ * which removes .upgradeLegacy() from the chain (preventing a problematic combination).
323
+ *
324
+ * @example
325
+ * .from<V1>("v1")
326
+ * .transfer(tablePlugin, (v1) => ({ state: v1.tableState }))
327
+ * .migrate<V2>("v2", ({ tableState: _, ...rest }) => rest)
328
+ */
329
+ transfer<Id extends string, L>(
330
+ target: TransferTarget<Id & (Id extends keyof Transfers ? never : string), L>,
331
+ extract: (data: Current) => L,
332
+ ): DataModelMigrationChain<Current, Transfers & Record<Id, L>> {
333
+ const { transferSteps } = this.buildTransfer(target, extract);
334
+ return new DataModelMigrationChain<Current, Transfers & Record<Id, L>>({
335
+ versionChain: this.versionChain,
336
+ steps: this.migrationSteps,
337
+ transferSteps,
338
+ });
229
339
  }
230
340
 
231
341
  /**
@@ -251,10 +361,11 @@ class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
251
361
  * .migrate<V3>("v3", (v2) => ({ ...v2, description: "" }))
252
362
  * .init(() => ({ count: 0, label: "", description: "" }));
253
363
  */
254
- recover(fn: DataRecoverFn<Current>): DataModelMigrationChainWithRecover<Current> {
255
- return new DataModelMigrationChainWithRecover<Current>({
364
+ recover(fn: DataRecoverFn<Current>): DataModelMigrationChainWithRecover<Current, Transfers> {
365
+ return new DataModelMigrationChainWithRecover<Current, Transfers>({
256
366
  versionChain: this.versionChain,
257
367
  steps: this.migrationSteps,
368
+ transferSteps: this.transferSteps,
258
369
  recoverFn: fn as (version: DataVersionKey, data: unknown) => unknown,
259
370
  recoverFromIndex: this.migrationSteps.length,
260
371
  });
@@ -267,9 +378,13 @@ class DataModelMigrationChain<Current> extends MigrationChainBase<Current> {
267
378
  * any `.migrate()` calls, since legacy data always arrives at the initial version.
268
379
  *
269
380
  * @typeParam Current - Data type at the initial version
381
+ * @typeParam Transfers - Accumulated transfer types keyed by plugin ID
270
382
  * @internal
271
383
  */
272
- class DataModelInitialChain<Current> extends DataModelMigrationChain<Current> {
384
+ class DataModelInitialChain<
385
+ Current,
386
+ Transfers extends Record<string, unknown> = {},
387
+ > extends DataModelMigrationChain<Current, Transfers> {
273
388
  /**
274
389
  * Handle legacy V1 model state ({ args, uiState }) when upgrading a block from
275
390
  * BlockModel V1 to BlockModelV3.
@@ -306,7 +421,7 @@ class DataModelInitialChain<Current> extends DataModelMigrationChain<Current> {
306
421
  */
307
422
  upgradeLegacy<Args, UiState = unknown>(
308
423
  fn: (legacy: LegacyV1State<Args, UiState>) => Current,
309
- ): DataModelMigrationChainWithRecover<Current> {
424
+ ): DataModelMigrationChainWithRecover<Current, Transfers> {
310
425
  const wrappedFn = (data: unknown): unknown => {
311
426
  if (data !== null && typeof data === "object" && "args" in data) {
312
427
  return fn(data as LegacyV1State<Args, UiState>);
@@ -322,9 +437,14 @@ class DataModelInitialChain<Current> extends DataModelMigrationChain<Current> {
322
437
  toVersion: initialVersion,
323
438
  migrate: wrappedFn,
324
439
  };
325
- return new DataModelMigrationChainWithRecover<Current>({
440
+ return new DataModelMigrationChainWithRecover<Current, Transfers>({
326
441
  versionChain: [DATA_MODEL_LEGACY_VERSION, ...this.versionChain],
327
442
  steps: [step, ...this.migrationSteps],
443
+ // Shift transfer indices to account for the prepended legacy step
444
+ transferSteps: this.transferSteps.map((t) => ({
445
+ ...t,
446
+ beforeStepIndex: t.beforeStepIndex + 1,
447
+ })),
328
448
  });
329
449
  }
330
450
  }
@@ -407,12 +527,16 @@ export class DataModelBuilder {
407
527
  * .migrate<V3>("v3", (v2) => ({ ...v2, description: "" }))
408
528
  * .init(() => ({ count: 0, label: "", description: "" }));
409
529
  */
410
- export class DataModel<State> {
530
+ export class DataModel<State, Transfers extends Record<string, unknown> = {}> {
531
+ /** @internal Phantom field to anchor the Transfers type parameter. */
532
+ declare readonly __transfers?: Transfers;
533
+
411
534
  /** Latest version key — O(1) access for the common "already current" check. */
412
535
  private readonly latestVersion: DataVersionKey;
413
536
  /** Maps each known version key to the index of the first step to run from it. O(1) lookup. */
414
537
  private readonly stepsByFromVersion: ReadonlyMap<DataVersionKey, number>;
415
538
  private readonly steps: MigrationStep[];
539
+ private readonly transferSteps: TransferStep[];
416
540
  private readonly initialDataFn: () => State;
417
541
  private readonly recoverFn: (version: DataVersionKey, data: unknown) => unknown;
418
542
  private readonly recoverFromIndex: number;
@@ -420,6 +544,7 @@ export class DataModel<State> {
420
544
  private constructor({
421
545
  versionChain,
422
546
  steps,
547
+ transferSteps = [],
423
548
  initialDataFn,
424
549
  recoverFn = defaultRecover,
425
550
  recoverFromIndex,
@@ -430,6 +555,7 @@ export class DataModel<State> {
430
555
  this.latestVersion = versionChain[versionChain.length - 1];
431
556
  this.stepsByFromVersion = new Map(versionChain.map((v, i) => [v, i]));
432
557
  this.steps = steps;
558
+ this.transferSteps = transferSteps;
433
559
  this.initialDataFn = initialDataFn;
434
560
  this.recoverFn = recoverFn;
435
561
  this.recoverFromIndex = recoverFromIndex ?? steps.length;
@@ -440,8 +566,10 @@ export class DataModel<State> {
440
566
  * Uses Symbol key to prevent external access.
441
567
  * @internal
442
568
  */
443
- static [FROM_BUILDER]<S>(state: BuilderState<S>): DataModel<S> {
444
- return new DataModel<S>(state);
569
+ static [FROM_BUILDER]<S, T extends Record<string, unknown> = {}>(
570
+ state: BuilderState<S>,
571
+ ): DataModel<S, T> {
572
+ return new DataModel<S, T>(state);
445
573
  }
446
574
 
447
575
  /**
@@ -463,7 +591,7 @@ export class DataModel<State> {
463
591
  * Used when creating new blocks or resetting to defaults.
464
592
  */
465
593
  getDefaultData(): DataVersioned<State> {
466
- return makeDataVersioned(this.latestVersion, this.initialDataFn());
594
+ return makeVersionedData(this.latestVersion, this.initialDataFn());
467
595
  }
468
596
 
469
597
  private recoverFrom(data: unknown, version: DataVersionKey): DataVersioned<State> {
@@ -482,40 +610,67 @@ export class DataModel<State> {
482
610
 
483
611
  /**
484
612
  * Migrate versioned data from any version to the latest.
613
+ * Collects transfer extractions at their designated chain positions.
485
614
  *
486
615
  * - If version is in chain, applies needed migrations (O(1) lookup)
487
616
  * - If version is unknown, attempts recovery; falls back to initial data
488
617
  * - If a migration step fails, throws so the caller can preserve original data
489
618
  *
619
+ * Transfers only fire during normal step-by-step migration:
620
+ * - Recovery path: returns empty transfers
621
+ * - Fast-path (already at latest): returns empty transfers
622
+ *
490
623
  * @param versioned - Data with version tag
491
- * @returns Migrated data at the latest version
624
+ * @returns Migrated data at the latest version with transfer record
492
625
  * @throws If a migration step from a known version fails
493
626
  */
494
- migrate(versioned: DataVersioned<unknown>): DataVersioned<State> {
627
+ migrate(versioned: DataVersioned<unknown>): DataVersioned<State> & { transfers: TransferRecord } {
495
628
  const { version: fromVersion, data } = versioned;
496
629
 
630
+ // Fast path: already at latest version
497
631
  if (fromVersion === this.latestVersion) {
498
- return { version: this.latestVersion, data: data as State };
632
+ return { version: this.latestVersion, data: data as State, transfers: {} };
499
633
  }
500
634
 
635
+ // Unknown version: recovery path — empty transfers
501
636
  const startIndex = this.stepsByFromVersion.get(fromVersion);
502
637
  if (startIndex === undefined) {
503
638
  try {
504
- return this.recoverFrom(data, fromVersion);
639
+ return { ...this.recoverFrom(data, fromVersion), transfers: {} };
505
640
  } catch {
506
641
  // Recovery failed (unknown version, recover fn threw, or post-recover
507
642
  // migration failed) — reset to initial data rather than blocking the update.
508
- return this.getDefaultData();
643
+ return { ...this.getDefaultData(), transfers: {} };
509
644
  }
510
645
  }
511
646
 
512
647
  let currentData: unknown = data;
648
+ const transfers: TransferRecord = {};
513
649
 
650
+ // Run steps and check transfer entries before each step
514
651
  for (let i = startIndex; i < this.steps.length; i++) {
515
- const step = this.steps[i];
516
- currentData = step.migrate(currentData);
652
+ for (const t of this.transferSteps) {
653
+ if (t.beforeStepIndex === i) {
654
+ transfers[t.pluginId] = {
655
+ version: t.targetVersion,
656
+ data: t.extract(currentData),
657
+ };
658
+ }
659
+ }
660
+ currentData = this.steps[i].migrate(currentData);
517
661
  }
518
662
 
519
- return { version: this.latestVersion, data: currentData as State };
663
+ // Check for transfers positioned at or past the end of the steps array
664
+ // (e.g., .transfer() was the last call before .init(), after all .migrate() calls)
665
+ for (const t of this.transferSteps) {
666
+ if (t.beforeStepIndex >= this.steps.length && t.beforeStepIndex >= startIndex) {
667
+ transfers[t.pluginId] = {
668
+ version: t.targetVersion,
669
+ data: t.extract(currentData),
670
+ };
671
+ }
672
+ }
673
+
674
+ return { version: this.latestVersion, data: currentData as State, transfers };
520
675
  }
521
676
  }