@owlmeans/planning 0.1.18-rc.8 → 0.1.18

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 (295) hide show
  1. package/README.md +122 -29
  2. package/agent-meta/manifest.json +131 -4
  3. package/agent-meta/skills/planning/SKILL.md +78 -171
  4. package/agent-meta/skills/planning/parts/collaboration.md +67 -0
  5. package/agent-meta/skills/planning/parts/errors.md +51 -0
  6. package/agent-meta/skills/planning/parts/fold.md +69 -0
  7. package/agent-meta/skills/planning/parts/mounting.md +64 -0
  8. package/agent-meta/skills/planning/parts/types.md +141 -0
  9. package/build/aliases/types.d.ts +72 -0
  10. package/build/aliases/types.d.ts.map +1 -0
  11. package/build/aliases/types.js +2 -0
  12. package/build/aliases/types.js.map +1 -0
  13. package/build/aliases.d.ts +4 -0
  14. package/build/aliases.d.ts.map +1 -0
  15. package/build/aliases.js +28 -0
  16. package/build/aliases.js.map +1 -0
  17. package/build/consts.d.ts +43 -34
  18. package/build/consts.d.ts.map +1 -1
  19. package/build/consts.js +49 -25
  20. package/build/consts.js.map +1 -1
  21. package/build/entrypoints/types.d.ts +105 -0
  22. package/build/entrypoints/types.d.ts.map +1 -0
  23. package/build/entrypoints/types.js +2 -0
  24. package/build/entrypoints/types.js.map +1 -0
  25. package/build/entrypoints.d.ts +5 -1
  26. package/build/entrypoints.d.ts.map +1 -1
  27. package/build/entrypoints.js +24 -6
  28. package/build/entrypoints.js.map +1 -1
  29. package/build/errors.d.ts +41 -0
  30. package/build/errors.d.ts.map +1 -1
  31. package/build/errors.js +61 -0
  32. package/build/errors.js.map +1 -1
  33. package/build/helpers/app/consts.local.d.ts +5 -0
  34. package/build/helpers/app/consts.local.d.ts.map +1 -0
  35. package/build/helpers/app/consts.local.js +5 -0
  36. package/build/helpers/app/consts.local.js.map +1 -0
  37. package/build/helpers/app/types.d.ts +53 -0
  38. package/build/helpers/app/types.d.ts.map +1 -0
  39. package/build/helpers/app/types.js +2 -0
  40. package/build/helpers/app/types.js.map +1 -0
  41. package/build/helpers/app.d.ts +4 -0
  42. package/build/helpers/app.d.ts.map +1 -0
  43. package/build/helpers/app.js +139 -0
  44. package/build/helpers/app.js.map +1 -0
  45. package/build/helpers/apply/consts.local.d.ts +7 -0
  46. package/build/helpers/apply/consts.local.d.ts.map +1 -0
  47. package/build/helpers/apply/consts.local.js +9 -0
  48. package/build/helpers/apply/consts.local.js.map +1 -0
  49. package/build/helpers/apply/types.d.ts +32 -0
  50. package/build/helpers/apply/types.d.ts.map +1 -0
  51. package/build/helpers/apply/types.js +2 -0
  52. package/build/helpers/apply/types.js.map +1 -0
  53. package/build/helpers/apply.d.ts +5 -23
  54. package/build/helpers/apply.d.ts.map +1 -1
  55. package/build/helpers/apply.js +127 -144
  56. package/build/helpers/apply.js.map +1 -1
  57. package/build/helpers/card/types.d.ts +20 -0
  58. package/build/helpers/card/types.d.ts.map +1 -0
  59. package/build/helpers/card/types.js +2 -0
  60. package/build/helpers/card/types.js.map +1 -0
  61. package/build/helpers/card.d.ts +11 -7
  62. package/build/helpers/card.d.ts.map +1 -1
  63. package/build/helpers/card.js +41 -28
  64. package/build/helpers/card.js.map +1 -1
  65. package/build/helpers/changes/consts.local.d.ts +13 -0
  66. package/build/helpers/changes/consts.local.d.ts.map +1 -0
  67. package/build/helpers/changes/consts.local.js +13 -0
  68. package/build/helpers/changes/consts.local.js.map +1 -0
  69. package/build/helpers/changes/types.d.ts +58 -0
  70. package/build/helpers/changes/types.d.ts.map +1 -0
  71. package/build/helpers/changes/types.js +2 -0
  72. package/build/helpers/changes/types.js.map +1 -0
  73. package/build/helpers/changes.d.ts +11 -42
  74. package/build/helpers/changes.d.ts.map +1 -1
  75. package/build/helpers/changes.js +237 -251
  76. package/build/helpers/changes.js.map +1 -1
  77. package/build/helpers/code/types.d.ts +27 -0
  78. package/build/helpers/code/types.d.ts.map +1 -0
  79. package/build/helpers/code/types.js +2 -0
  80. package/build/helpers/code/types.js.map +1 -0
  81. package/build/helpers/code.d.ts +6 -17
  82. package/build/helpers/code.d.ts.map +1 -1
  83. package/build/helpers/code.js +39 -40
  84. package/build/helpers/code.js.map +1 -1
  85. package/build/helpers/index.d.ts +16 -0
  86. package/build/helpers/index.d.ts.map +1 -1
  87. package/build/helpers/index.js +4 -0
  88. package/build/helpers/index.js.map +1 -1
  89. package/build/helpers/query/types.d.ts +23 -0
  90. package/build/helpers/query/types.d.ts.map +1 -0
  91. package/build/helpers/query/types.js +2 -0
  92. package/build/helpers/query/types.js.map +1 -0
  93. package/build/helpers/query.d.ts +25 -17
  94. package/build/helpers/query.d.ts.map +1 -1
  95. package/build/helpers/query.js +108 -280
  96. package/build/helpers/query.js.map +1 -1
  97. package/build/helpers/reply/consts.d.ts +2 -0
  98. package/build/helpers/reply/consts.d.ts.map +1 -0
  99. package/build/helpers/reply/consts.js +2 -0
  100. package/build/helpers/reply/consts.js.map +1 -0
  101. package/build/helpers/reply/types.d.ts +10 -0
  102. package/build/helpers/reply/types.d.ts.map +1 -0
  103. package/build/helpers/reply/types.js +2 -0
  104. package/build/helpers/reply/types.js.map +1 -0
  105. package/build/helpers/reply.d.ts +5 -0
  106. package/build/helpers/reply.d.ts.map +1 -0
  107. package/build/helpers/reply.js +29 -0
  108. package/build/helpers/reply.js.map +1 -0
  109. package/build/helpers/scoped/types.d.ts +73 -0
  110. package/build/helpers/scoped/types.d.ts.map +1 -0
  111. package/build/helpers/scoped/types.js +2 -0
  112. package/build/helpers/scoped/types.js.map +1 -0
  113. package/build/helpers/scoped.d.ts +25 -0
  114. package/build/helpers/scoped.d.ts.map +1 -0
  115. package/build/helpers/scoped.js +223 -0
  116. package/build/helpers/scoped.js.map +1 -0
  117. package/build/helpers/specification/types.d.ts +24 -0
  118. package/build/helpers/specification/types.d.ts.map +1 -0
  119. package/build/helpers/specification/types.js +2 -0
  120. package/build/helpers/specification/types.js.map +1 -0
  121. package/build/helpers/specification.d.ts +9 -13
  122. package/build/helpers/specification.d.ts.map +1 -1
  123. package/build/helpers/specification.js +47 -44
  124. package/build/helpers/specification.js.map +1 -1
  125. package/build/helpers/status/types.d.ts +48 -0
  126. package/build/helpers/status/types.d.ts.map +1 -0
  127. package/build/helpers/status/types.js +2 -0
  128. package/build/helpers/status/types.js.map +1 -0
  129. package/build/helpers/status.d.ts +16 -29
  130. package/build/helpers/status.d.ts.map +1 -1
  131. package/build/helpers/status.js +77 -73
  132. package/build/helpers/status.js.map +1 -1
  133. package/build/helpers/types.local.d.ts +17 -0
  134. package/build/helpers/types.local.d.ts.map +1 -0
  135. package/build/helpers/types.local.js +2 -0
  136. package/build/helpers/types.local.js.map +1 -0
  137. package/build/helpers/validate/types.d.ts +31 -0
  138. package/build/helpers/validate/types.d.ts.map +1 -0
  139. package/build/helpers/validate/types.js +2 -0
  140. package/build/helpers/validate/types.js.map +1 -0
  141. package/build/helpers/validate.d.ts +8 -19
  142. package/build/helpers/validate.d.ts.map +1 -1
  143. package/build/helpers/validate.js +79 -79
  144. package/build/helpers/validate.js.map +1 -1
  145. package/build/helpers/wire/types.d.ts +28 -0
  146. package/build/helpers/wire/types.d.ts.map +1 -0
  147. package/build/helpers/wire/types.js +2 -0
  148. package/build/helpers/wire/types.js.map +1 -0
  149. package/build/helpers/wire.d.ts +4 -0
  150. package/build/helpers/wire.d.ts.map +1 -0
  151. package/build/helpers/wire.js +216 -0
  152. package/build/helpers/wire.js.map +1 -0
  153. package/build/i18n/be.json +5 -0
  154. package/build/i18n/de.json +5 -0
  155. package/build/i18n/en.json +5 -0
  156. package/build/i18n/es.json +5 -0
  157. package/build/i18n/fr.json +5 -0
  158. package/build/i18n/pl.json +5 -0
  159. package/build/i18n/ru.json +5 -0
  160. package/build/i18n/uk.json +5 -0
  161. package/build/i18n.js +3 -3
  162. package/build/i18n.js.map +1 -1
  163. package/build/index.d.ts +7 -0
  164. package/build/index.d.ts.map +1 -1
  165. package/build/index.js +3 -0
  166. package/build/index.js.map +1 -1
  167. package/build/models/index.d.ts +2 -3
  168. package/build/models/index.d.ts.map +1 -1
  169. package/build/models/index.js +1 -15
  170. package/build/models/index.js.map +1 -1
  171. package/build/models/model.d.ts +5 -0
  172. package/build/models/model.d.ts.map +1 -0
  173. package/build/models/model.js +16 -0
  174. package/build/models/model.js.map +1 -0
  175. package/build/models/project.d.ts +2 -1
  176. package/build/models/project.d.ts.map +1 -1
  177. package/build/models/project.js.map +1 -1
  178. package/build/models/specification.d.ts +2 -1
  179. package/build/models/specification.d.ts.map +1 -1
  180. package/build/models/specification.js.map +1 -1
  181. package/build/models/types.d.ts +69 -0
  182. package/build/models/types.d.ts.map +1 -0
  183. package/build/models/types.js +2 -0
  184. package/build/models/types.js.map +1 -0
  185. package/build/models/workcard.d.ts +2 -1
  186. package/build/models/workcard.d.ts.map +1 -1
  187. package/build/models/workcard.js +12 -12
  188. package/build/models/workcard.js.map +1 -1
  189. package/build/registry.d.ts +3 -2
  190. package/build/registry.d.ts.map +1 -1
  191. package/build/registry.js +51 -3
  192. package/build/registry.js.map +1 -1
  193. package/build/resources/mentions.d.ts +4 -0
  194. package/build/resources/mentions.d.ts.map +1 -0
  195. package/build/resources/mentions.js +15 -0
  196. package/build/resources/mentions.js.map +1 -0
  197. package/build/resources/protocol/types.d.ts +30 -0
  198. package/build/resources/protocol/types.d.ts.map +1 -0
  199. package/build/resources/protocol/types.js +2 -0
  200. package/build/resources/protocol/types.js.map +1 -0
  201. package/build/resources/protocol.d.ts +6 -0
  202. package/build/resources/protocol.d.ts.map +1 -0
  203. package/build/resources/protocol.js +31 -0
  204. package/build/resources/protocol.js.map +1 -0
  205. package/build/resources/types.d.ts +146 -0
  206. package/build/resources/types.d.ts.map +1 -0
  207. package/build/resources/types.js +2 -0
  208. package/build/resources/types.js.map +1 -0
  209. package/build/resources/types.local.d.ts +6 -0
  210. package/build/resources/types.local.d.ts.map +1 -0
  211. package/build/resources/types.local.js +2 -0
  212. package/build/resources/types.local.js.map +1 -0
  213. package/build/schemas.d.ts +21 -2
  214. package/build/schemas.d.ts.map +1 -1
  215. package/build/schemas.js +164 -2
  216. package/build/schemas.js.map +1 -1
  217. package/build/types.d.ts +330 -151
  218. package/build/types.d.ts.map +1 -1
  219. package/build/utils.d.ts +6 -0
  220. package/build/utils.d.ts.map +1 -0
  221. package/build/utils.js +6 -0
  222. package/build/utils.js.map +1 -0
  223. package/package.json +13 -13
  224. package/src/aliases/types.ts +41 -0
  225. package/src/aliases.ts +34 -0
  226. package/src/consts.ts +50 -25
  227. package/src/entrypoints/types.ts +77 -0
  228. package/src/entrypoints.ts +53 -24
  229. package/src/errors.ts +71 -0
  230. package/src/helpers/app/consts.local.ts +5 -0
  231. package/src/helpers/app/types.ts +54 -0
  232. package/src/helpers/app.ts +158 -0
  233. package/src/helpers/apply/consts.local.ts +10 -0
  234. package/src/helpers/apply/types.ts +32 -0
  235. package/src/helpers/apply.ts +141 -153
  236. package/src/helpers/card/types.ts +20 -0
  237. package/src/helpers/card.ts +59 -33
  238. package/src/helpers/changes/consts.local.ts +17 -0
  239. package/src/helpers/changes/types.ts +66 -0
  240. package/src/helpers/changes.ts +270 -280
  241. package/src/helpers/code/types.ts +31 -0
  242. package/src/helpers/code.ts +52 -48
  243. package/src/helpers/index.ts +17 -0
  244. package/src/helpers/query/types.ts +26 -0
  245. package/src/helpers/query.ts +144 -314
  246. package/src/helpers/reply/consts.ts +1 -0
  247. package/src/helpers/reply/types.ts +13 -0
  248. package/src/helpers/reply.ts +27 -0
  249. package/src/helpers/scoped/types.ts +78 -0
  250. package/src/helpers/scoped.ts +281 -0
  251. package/src/helpers/specification/types.ts +26 -0
  252. package/src/helpers/specification.ts +69 -51
  253. package/src/helpers/status/types.ts +46 -0
  254. package/src/helpers/status.ts +117 -93
  255. package/src/helpers/types.local.ts +18 -0
  256. package/src/helpers/validate/types.ts +31 -0
  257. package/src/helpers/validate.ts +89 -77
  258. package/src/helpers/wire/types.ts +31 -0
  259. package/src/helpers/wire.ts +252 -0
  260. package/src/i18n/be.json +5 -0
  261. package/src/i18n/de.json +5 -0
  262. package/src/i18n/en.json +5 -0
  263. package/src/i18n/es.json +5 -0
  264. package/src/i18n/fr.json +5 -0
  265. package/src/i18n/pl.json +5 -0
  266. package/src/i18n/ru.json +5 -0
  267. package/src/i18n/uk.json +5 -0
  268. package/src/i18n.ts +4 -3
  269. package/src/index.ts +8 -0
  270. package/src/models/index.ts +2 -17
  271. package/src/models/model.ts +18 -0
  272. package/src/models/project.ts +2 -1
  273. package/src/models/specification.ts +2 -1
  274. package/src/models/types.ts +70 -0
  275. package/src/models/workcard.ts +14 -16
  276. package/src/registry.ts +55 -4
  277. package/src/resources/mentions.ts +11 -0
  278. package/src/resources/protocol/types.ts +21 -0
  279. package/src/resources/protocol.ts +36 -0
  280. package/src/resources/types.local.ts +5 -0
  281. package/src/resources/types.ts +148 -0
  282. package/src/schemas.ts +179 -4
  283. package/src/types.ts +334 -130
  284. package/src/utils.ts +9 -0
  285. package/tests/app.spec.ts +188 -0
  286. package/tests/apply.spec.ts +95 -31
  287. package/tests/code.spec.ts +9 -9
  288. package/tests/csp.spec.ts +122 -0
  289. package/tests/entrypoints.spec.ts +18 -2
  290. package/tests/error-status.spec.ts +6 -1
  291. package/tests/models.spec.ts +24 -16
  292. package/tests/query.spec.ts +13 -15
  293. package/tests/schemas.spec.ts +8 -8
  294. package/tests/scoped.spec.ts +161 -0
  295. package/tests/status.spec.ts +31 -22
@@ -1,51 +1,20 @@
1
- import type { AnyTypeSchema, PlanningSchemaRegistry, SpecificationSlot, TransitionExecution, Workcard, WorkcardChanges } from '../types.js';
2
- type FlowLookup = Pick<PlanningSchemaRegistry, 'flow'>;
3
- export interface ChangeSet {
4
- changes: WorkcardChanges;
5
- unset: string[];
6
- /** Transit only: the flow that moved, and the move. */
7
- flow?: string;
8
- from?: string;
9
- to?: string;
10
- }
11
- /** Structural equality over JSON values. */
1
+ import type { AnyTypeSchema, SpecificationSlot, TransitionExecution, Workcard } from '../types.js';
2
+ import type { ChangeSet, ChangesHelper } from './changes/types.js';
3
+ import type { FlowLookup } from './types.local.js';
4
+ export declare const createChangesHelper: () => ChangesHelper;
5
+ export declare const changesHelper: ChangesHelper;
6
+ /** @deprecated compat:factory-refactor — use `changesHelper.sameValue(…)` */
12
7
  export declare const sameValue: (left: unknown, right: unknown) => boolean;
13
- /** A shallow merge that drops keys patched to `null`. */
8
+ /** @deprecated compat:factory-refactor — use `changesHelper.mergeFields(…)` */
14
9
  export declare const mergeFields: (base?: Record<string, unknown> | null, patch?: Record<string, unknown> | null) => Record<string, unknown>;
15
- /** A copy of the record with the paths (`key`, `fields.key`, `flows.id`) removed. */
10
+ /** @deprecated compat:factory-refactor — use `changesHelper.applyUnset(…)` */
16
11
  export declare const applyUnset: <T extends object>(record: T, unset?: string[]) => T;
17
- /**
18
- * Refuse an execution that writes what only the transition, the flow or the executor may write.
19
- *
20
- * `status`/`intrinsic`/`flows`/`closedAt` move only through `transit` (a create's draft may name
21
- * the initial status); `code` is fixed once minted unless the type's policy says `mutable`;
22
- * `category` is fixed; `revision`/`bodyChars` are computed.
23
- *
24
- * @throws {PlanningError} `planning:immutable:<field>`
25
- */
12
+ /** @deprecated compat:factory-refactor — use `changesHelper.assertMutable(…)` */
26
13
  export declare const assertMutable: (exec: TransitionExecution, type: AnyTypeSchema) => void;
27
- /**
28
- * The `changes`/`unset` a transition records (plan step 9).
29
- *
30
- * - `create`: the whole initial record from the draft (overlaid by `exec.changes`) — `parents`
31
- * normalized, every flow at its initial status (the draft's `status` for the primary one),
32
- * `status`/`intrinsic` mirrored, `closedAt` when it starts closed; a specification gets its
33
- * format, `bodyChars` and revision 1 when the slot is revisioned.
34
- * - `update`: only what differs; `null` or `exec.unset` clears a field that has a value; a moved
35
- * `parent` replaces the old one in `parents`; a revisioned document whose content changed gets
36
- * `revision + 1`. An update that changes nothing is empty ({@link isEmptyChange}).
37
- * - `transit`: `flows[flow] = rule.to`, `status` when the flow is primary, `intrinsic` when it
38
- * moves, `closedAt` set on entering closed and cleared on leaving it — plus the caller's own
39
- * changes, diffed as in an update.
40
- * - `link`, `unlink`, `delete`: nothing.
41
- *
42
- * @throws {IllegalTransition} a transit the flow does not offer from the current status
43
- * @throws {PlanningError} `malformed:*` for an execution missing what its action needs
44
- */
14
+ /** @deprecated compat:factory-refactor — use `changesHelper.computeChanges(…)` */
45
15
  export declare const computeChanges: (card: Workcard | null | undefined, exec: TransitionExecution, type: AnyTypeSchema, registry: FlowLookup, at: string, opts?: {
46
16
  slot?: SpecificationSlot | null;
47
17
  }) => ChangeSet;
48
- /** Nothing to write: no changed value and nothing to clear. */
18
+ /** @deprecated compat:factory-refactor — use `changesHelper.isEmptyChange(…)` */
49
19
  export declare const isEmptyChange: (set: Pick<ChangeSet, 'changes' | 'unset'>) => boolean;
50
- export {};
51
20
  //# sourceMappingURL=changes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/helpers/changes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EAAE,sBAAsB,EAAiB,iBAAiB,EAAE,mBAAmB,EAC5F,QAAQ,EAAE,eAAe,EAC1B,MAAM,aAAa,CAAA;AAKpB,KAAK,UAAU,GAAG,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAA;AAEtD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,eAAe,CAAA;IACxB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAgBD,4CAA4C;AAC5C,eAAO,MAAM,SAAS,SAAU,OAAO,SAAS,OAAO,KAAG,OAczD,CAAA;AAKD,yDAAyD;AACzD,eAAO,MAAM,WAAW,UACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KAC5E,MAAM,CAAC,MAAM,EAAE,OAAO,CACuC,CAAA;AAEhE,qFAAqF;AACrF,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,MAAM,UAAU,CAAC,UAAU,MAAM,EAAE,KAAG,CAe1E,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,SAAU,mBAAmB,QAAQ,aAAa,KAAG,IA0B9E,CAAA;AAsID;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,SACnB,QAAQ,GAAG,IAAI,GAAG,SAAS,QAC3B,mBAAmB,QACnB,aAAa,YACT,UAAU,MAChB,MAAM,SACH;IAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAAE,KACzC,SAsDF,CAAA;AAED,+DAA+D;AAC/D,eAAO,MAAM,aAAa,QAAS,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,KAAG,OAEW,CAAA"}
1
+ {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/helpers/changes.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAiB,iBAAiB,EAAE,mBAAmB,EAAE,QAAQ,EAAkC,MAAM,aAAa,CAAA;AAEjJ,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAIlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAQlD,eAAO,MAAM,mBAAmB,QAAO,aAqRtC,CAAA;AAED,eAAO,MAAM,aAAa,eAAwB,CAAA;AAElD,6EAA6E;AAC7E,eAAO,MAAM,SAAS,SAAU,OAAO,SAAS,OAAO,KAAG,OAA+C,CAAA;AAEzG,+EAA+E;AAC/E,eAAO,MAAM,WAAW,UACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KAC5E,MAAM,CAAC,MAAM,EAAE,OAAO,CAA2C,CAAA;AAEpE,8EAA8E;AAC9E,eAAO,MAAM,UAAU,GAAI,CAAC,SAAS,MAAM,UAAU,CAAC,UAAU,MAAM,EAAE,KAAG,CAA+C,CAAA;AAE1H,iFAAiF;AACjF,eAAO,MAAM,aAAa,SAAU,mBAAmB,QAAQ,aAAa,KAAG,IAA+C,CAAA;AAE9H,kFAAkF;AAClF,eAAO,MAAM,cAAc,SACnB,QAAQ,GAAG,IAAI,GAAG,SAAS,QAC3B,mBAAmB,QACnB,aAAa,YACT,UAAU,MAChB,MAAM,SACH;IAAE,IAAI,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAAE,KACzC,SAA+E,CAAA;AAElF,iFAAiF;AACjF,eAAO,MAAM,aAAa,QAAS,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,KAAG,OAA2C,CAAA"}
@@ -1,277 +1,263 @@
1
1
  import { IntrinsicStatus, SpecificationFormat, TransitionAction, WorkcardKind } from '../consts.js';
2
2
  import { IllegalTransition, PlanningError } from '../errors.js';
3
- import { normalizeParents } from './card.js';
4
- import { bodyCharsOf, nextRevision } from './specification.js';
5
- import { initialFlowsOf, initialStatusOf, primaryFlowOf, resolveIntrinsic, ruleOf } from './status.js';
6
- /** Never in a caller's changes: the transition itself carries them. */
7
- const IDENTITY_KEYS = ['id', 'kind', 'type', 'entityId', 'seq', 'head', 'createdAt'];
8
- /** Move only through `transit` (or a create's draft). */
9
- const FLOW_KEYS = ['status', 'intrinsic', 'flows', 'closedAt'];
10
- /** Computed by the executor, never supplied. */
11
- const DERIVED_KEYS = ['revision', 'bodyChars'];
12
- /** Cannot be cleared. */
13
- const REQUIRED_KEYS = ['title', 'parents', 'labels', 'fields', 'category', 'format'];
14
- /** Changing one of these produces a new revision of a revisioned document. */
15
- const CONTENT_KEYS = ['body', 'ref', 'format', 'version'];
3
+ import { cardHelper } from './card.js';
4
+ import { CONTENT_KEYS, DERIVED_KEYS, FLOW_KEYS, IDENTITY_KEYS, PROVENANCE_KEYS, REQUIRED_KEYS } from './changes/consts.local.js';
5
+ import { specificationHelper } from './specification.js';
6
+ import { statusHelper } from './status.js';
16
7
  const isPlainObject = (value) => value != null && typeof value === 'object' && !Array.isArray(value);
17
- /** Structural equality over JSON values. */
18
- export const sameValue = (left, right) => {
19
- if (left === right) {
20
- return true;
21
- }
22
- if (Array.isArray(left) && Array.isArray(right)) {
23
- return left.length === right.length && left.every((entry, index) => sameValue(entry, right[index]));
24
- }
25
- if (isPlainObject(left) && isPlainObject(right)) {
26
- const keys = Object.keys(left).filter(key => left[key] !== undefined);
27
- const other = Object.keys(right).filter(key => right[key] !== undefined);
28
- return keys.length === other.length && keys.every(key => sameValue(left[key], right[key]));
29
- }
30
- return false;
31
- };
32
8
  const clean = (record) => Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
33
- /** A shallow merge that drops keys patched to `null`. */
34
- export const mergeFields = (base, patch) => Object.fromEntries(Object.entries({ ...(base ?? {}), ...(patch ?? {}) })
35
- .filter(([, value]) => value !== null && value !== undefined));
36
- /** A copy of the record with the paths (`key`, `fields.key`, `flows.id`) removed. */
37
- export const applyUnset = (record, unset) => {
38
- const copy = structuredClone(record);
39
- for (const path of unset ?? []) {
40
- const [head, ...rest] = path.split('.');
41
- if (rest.length > 0) {
42
- const map = copy[head];
43
- if (isPlainObject(map)) {
44
- delete map[rest.join('.')];
45
- }
9
+ export const createChangesHelper = () => {
10
+ const sameValue = (left, right) => {
11
+ if (left === right) {
12
+ return true;
46
13
  }
47
- else {
48
- delete copy[head];
14
+ if (Array.isArray(left) && Array.isArray(right)) {
15
+ return left.length === right.length && left.every((entry, index) => sameValue(entry, right[index]));
49
16
  }
50
- }
51
- return copy;
52
- };
53
- /**
54
- * Refuse an execution that writes what only the transition, the flow or the executor may write.
55
- *
56
- * `status`/`intrinsic`/`flows`/`closedAt` move only through `transit` (a create's draft may name
57
- * the initial status); `code` is fixed once minted unless the type's policy says `mutable`;
58
- * `category` is fixed; `revision`/`bodyChars` are computed.
59
- *
60
- * @throws {PlanningError} `planning:immutable:<field>`
61
- */
62
- export const assertMutable = (exec, type) => {
63
- const create = exec.action === TransitionAction.Create;
64
- const codeFixed = type.code != null && type.code.mutable !== true;
65
- const refuse = (key) => {
66
- throw new PlanningError(`immutable:${FLOW_KEYS.includes(key) ? 'status' : key}`);
67
- };
68
- for (const [key, value] of Object.entries(exec.changes ?? {})) {
69
- if (value === undefined) {
70
- continue;
17
+ if (isPlainObject(left) && isPlainObject(right)) {
18
+ const keys = Object.keys(left).filter(key => left[key] !== undefined);
19
+ const other = Object.keys(right).filter(key => right[key] !== undefined);
20
+ return keys.length === other.length && keys.every(key => sameValue(left[key], right[key]));
71
21
  }
72
- if (IDENTITY_KEYS.includes(key) || DERIVED_KEYS.includes(key)) {
73
- refuse(key);
74
- }
75
- if (!create && (FLOW_KEYS.includes(key) || key === 'category' || (key === 'code' && codeFixed))) {
76
- refuse(key);
22
+ return false;
23
+ };
24
+ const mergeFields = (base, patch) => Object.fromEntries(Object.entries({ ...(base ?? {}), ...(patch ?? {}) })
25
+ .filter(([, value]) => value !== null && value !== undefined));
26
+ const applyUnset = (record, unset) => {
27
+ const copy = structuredClone(record);
28
+ for (const path of unset ?? []) {
29
+ const [head, ...rest] = path.split('.');
30
+ if (rest.length > 0) {
31
+ const map = copy[head];
32
+ if (isPlainObject(map)) {
33
+ delete map[rest.join('.')];
34
+ }
35
+ }
36
+ else {
37
+ delete copy[head];
38
+ }
77
39
  }
78
- }
79
- for (const path of exec.unset ?? []) {
80
- const head = path.split('.')[0];
81
- if (IDENTITY_KEYS.includes(path) || DERIVED_KEYS.includes(path) || REQUIRED_KEYS.includes(path)
82
- || FLOW_KEYS.includes(head) || (path === 'code' && codeFixed)) {
83
- refuse(path);
40
+ return copy;
41
+ };
42
+ const assertMutable = (exec, type) => {
43
+ const create = exec.action === TransitionAction.Create;
44
+ const codeFixed = type.code != null && type.code.mutable !== true;
45
+ const refuse = (key) => {
46
+ throw new PlanningError(`immutable:${FLOW_KEYS.includes(key) ? 'status' : key}`);
47
+ };
48
+ for (const [key, value] of Object.entries(exec.changes ?? {})) {
49
+ if (value === undefined) {
50
+ continue;
51
+ }
52
+ if (IDENTITY_KEYS.includes(key) || PROVENANCE_KEYS.includes(key) || DERIVED_KEYS.includes(key)) {
53
+ refuse(key);
54
+ }
55
+ if (!create && (FLOW_KEYS.includes(key) || key === 'category' || (key === 'code' && codeFixed))) {
56
+ refuse(key);
57
+ }
84
58
  }
85
- }
86
- };
87
- const reach = (record, path) => path.split('.')
88
- .reduce((value, step) => isPlainObject(value) ? value[step] : undefined, record);
89
- /** Only what differs from the card; `null` becomes an unset of a field that has a value. */
90
- const diffInto = (card, changes, skip, set) => {
91
- const out = set.changes;
92
- const current = card;
93
- for (const [key, value] of Object.entries(changes ?? {})) {
94
- if (value === undefined || IDENTITY_KEYS.includes(key) || skip.includes(key)) {
95
- continue;
59
+ for (const path of exec.unset ?? []) {
60
+ const head = path.split('.')[0];
61
+ if (PROVENANCE_KEYS.includes(head)) {
62
+ refuse(head);
63
+ }
64
+ if (IDENTITY_KEYS.includes(path) || DERIVED_KEYS.includes(path) || REQUIRED_KEYS.includes(path)
65
+ || FLOW_KEYS.includes(head) || (path === 'code' && codeFixed)) {
66
+ refuse(path);
67
+ }
96
68
  }
97
- if (key === 'fields' || key === 'flows') {
98
- const own = (current[key] ?? {});
99
- const patch = {};
100
- for (const [entry, entryValue] of Object.entries(value ?? {})) {
101
- if (entryValue === undefined) {
102
- continue;
103
- }
104
- if (entryValue === null) {
105
- if (own[entry] !== undefined) {
106
- set.unset.push(`${key}.${entry}`);
69
+ };
70
+ const reach = (record, path) => path.split('.')
71
+ .reduce((value, step) => isPlainObject(value) ? value[step] : undefined, record);
72
+ /** Only what differs from the card; `null` becomes an unset of a field that has a value. */
73
+ const diffInto = (card, changes, skip, set) => {
74
+ const out = set.changes;
75
+ const current = card;
76
+ for (const [key, value] of Object.entries(changes ?? {})) {
77
+ if (value === undefined || IDENTITY_KEYS.includes(key) || PROVENANCE_KEYS.includes(key) || skip.includes(key)) {
78
+ continue;
79
+ }
80
+ if (key === 'fields' || key === 'flows') {
81
+ const own = (current[key] ?? {});
82
+ const patch = {};
83
+ for (const [entry, entryValue] of Object.entries(value ?? {})) {
84
+ if (entryValue === undefined) {
85
+ continue;
107
86
  }
87
+ if (entryValue === null) {
88
+ if (own[entry] !== undefined) {
89
+ set.unset.push(`${key}.${entry}`);
90
+ }
91
+ }
92
+ else if (!sameValue(own[entry], entryValue)) {
93
+ patch[entry] = entryValue;
94
+ }
95
+ }
96
+ if (Object.keys(patch).length > 0) {
97
+ out[key] = patch;
108
98
  }
109
- else if (!sameValue(own[entry], entryValue)) {
110
- patch[entry] = entryValue;
99
+ continue;
100
+ }
101
+ if (value === null) {
102
+ if (current[key] != null) {
103
+ set.unset.push(key);
111
104
  }
105
+ continue;
112
106
  }
113
- if (Object.keys(patch).length > 0) {
114
- out[key] = patch;
107
+ if (!sameValue(current[key], value)) {
108
+ out[key] = value;
115
109
  }
116
- continue;
117
110
  }
118
- if (value === null) {
119
- if (current[key] != null) {
120
- set.unset.push(key);
111
+ };
112
+ const unsetInto = (card, unset, set) => {
113
+ for (const path of unset ?? []) {
114
+ if (PROVENANCE_KEYS.includes(path.split('.')[0])) {
115
+ continue;
116
+ }
117
+ if (reach(card, path) !== undefined && !set.unset.includes(path)) {
118
+ set.unset.push(path);
121
119
  }
122
- continue;
123
120
  }
124
- if (!sameValue(current[key], value)) {
125
- out[key] = value;
121
+ };
122
+ /** A moved primary parent replaces the old one in `parents`. */
123
+ const reparent = (card, set) => {
124
+ const out = set.changes;
125
+ const moved = out.parent !== undefined || set.unset.includes('parent');
126
+ if (!moved || out.parents !== undefined) {
127
+ return;
126
128
  }
127
- }
128
- };
129
- const unsetInto = (card, unset, set) => {
130
- for (const path of unset ?? []) {
131
- if (reach(card, path) !== undefined && !set.unset.includes(path)) {
132
- set.unset.push(path);
129
+ const parents = cardHelper.normalizeParents(out.parent, card.parents.filter(parent => parent !== card.parent));
130
+ if (!sameValue(parents, card.parents)) {
131
+ out.parents = parents;
133
132
  }
134
- }
135
- };
136
- /** A moved primary parent replaces the old one in `parents`. */
137
- const reparent = (card, set) => {
138
- const out = set.changes;
139
- const moved = out.parent !== undefined || set.unset.includes('parent');
140
- if (!moved || out.parents !== undefined) {
141
- return;
142
- }
143
- const parents = normalizeParents(out.parent, card.parents.filter(parent => parent !== card.parent));
144
- if (!sameValue(parents, card.parents)) {
145
- out.parents = parents;
146
- }
147
- };
148
- const reviseInto = (card, slot, set) => {
149
- if (card.kind !== WorkcardKind.Specification) {
150
- return;
151
- }
152
- const out = set.changes;
153
- if (out.body !== undefined) {
154
- out.bodyChars = bodyCharsOf(out.body);
155
- }
156
- else if (set.unset.includes('body') && !set.unset.includes('bodyChars')) {
157
- set.unset.push('bodyChars');
158
- }
159
- const revised = CONTENT_KEYS.some(key => out[key] !== undefined || set.unset.includes(key));
160
- if (revised) {
161
- const revision = nextRevision(card, slot);
162
- if (revision != null) {
163
- out.revision = revision;
133
+ };
134
+ const reviseInto = (card, slot, set) => {
135
+ if (card.kind !== WorkcardKind.Specification) {
136
+ return;
137
+ }
138
+ const out = set.changes;
139
+ if (out.body !== undefined) {
140
+ out.bodyChars = specificationHelper.bodyCharsOf(out.body);
141
+ }
142
+ else if (set.unset.includes('body') && !set.unset.includes('bodyChars')) {
143
+ set.unset.push('bodyChars');
144
+ }
145
+ const revised = CONTENT_KEYS.some(key => out[key] !== undefined || set.unset.includes(key));
146
+ if (revised) {
147
+ const revision = specificationHelper.nextRevision(card, slot);
148
+ if (revision != null) {
149
+ out.revision = revision;
150
+ }
164
151
  }
165
- }
166
- };
167
- const createOf = (exec, type, registry, at, slot) => {
168
- if (typeof exec.card === 'string') {
169
- throw new PlanningError('malformed:create-without-draft');
170
- }
171
- const draft = exec.card;
172
- const overlay = Object.fromEntries(Object.entries(exec.changes ?? {})
173
- .filter(([key]) => !FLOW_KEYS.includes(key) && !IDENTITY_KEYS.includes(key) && !DERIVED_KEYS.includes(key)));
174
- const parent = overlay.parent ?? draft.parent;
175
- const flows = initialFlowsOf(type, registry, draft.status ?? exec.changes?.status);
176
- const intrinsic = resolveIntrinsic(type, flows, registry);
177
- const record = {
178
- title: draft.title,
179
- description: draft.description,
180
- code: draft.code,
181
- order: draft.order,
182
- createdBy: draft.createdBy,
183
- ...overlay,
184
- labels: [...new Set(overlay.labels ?? draft.labels ?? [])],
185
- parent,
186
- parents: normalizeParents(parent, overlay.parents ?? draft.parents),
187
- fields: mergeFields(draft.fields, overlay.fields),
188
- flows,
189
- status: flows[primaryFlowOf(type)],
190
- intrinsic,
191
- closedAt: intrinsic === IntrinsicStatus.Closed ? at : undefined,
192
152
  };
193
- if (draft.kind === WorkcardKind.Specification) {
194
- const body = overlay.body ?? draft.body;
195
- Object.assign(record, {
196
- category: overlay.category ?? draft.category ?? slot?.category,
197
- format: overlay.format ?? draft.format ?? slot?.format ?? SpecificationFormat.Markdown,
198
- body,
199
- ref: overlay.ref ?? draft.ref,
200
- version: overlay.version ?? draft.version ?? slot?.version,
201
- bodyChars: bodyCharsOf(body),
202
- revision: nextRevision(null, slot),
203
- });
204
- }
205
- return { changes: clean(record), unset: [] };
206
- };
207
- /**
208
- * The `changes`/`unset` a transition records (plan step 9).
209
- *
210
- * - `create`: the whole initial record from the draft (overlaid by `exec.changes`) — `parents`
211
- * normalized, every flow at its initial status (the draft's `status` for the primary one),
212
- * `status`/`intrinsic` mirrored, `closedAt` when it starts closed; a specification gets its
213
- * format, `bodyChars` and revision 1 when the slot is revisioned.
214
- * - `update`: only what differs; `null` or `exec.unset` clears a field that has a value; a moved
215
- * `parent` replaces the old one in `parents`; a revisioned document whose content changed gets
216
- * `revision + 1`. An update that changes nothing is empty ({@link isEmptyChange}).
217
- * - `transit`: `flows[flow] = rule.to`, `status` when the flow is primary, `intrinsic` when it
218
- * moves, `closedAt` set on entering closed and cleared on leaving it — plus the caller's own
219
- * changes, diffed as in an update.
220
- * - `link`, `unlink`, `delete`: nothing.
221
- *
222
- * @throws {IllegalTransition} a transit the flow does not offer from the current status
223
- * @throws {PlanningError} `malformed:*` for an execution missing what its action needs
224
- */
225
- export const computeChanges = (card, exec, type, registry, at, opts) => {
226
- if (exec.action === TransitionAction.Create) {
227
- return createOf(exec, type, registry, at, opts?.slot);
228
- }
229
- const set = { changes: {}, unset: [] };
230
- if (exec.action !== TransitionAction.Update && exec.action !== TransitionAction.Transit) {
231
- return set;
232
- }
233
- if (card == null) {
234
- throw new PlanningError(`malformed:${exec.action}-without-card`);
235
- }
236
- if (exec.action === TransitionAction.Update) {
237
- diffInto(card, exec.changes, [], set);
238
- unsetInto(card, exec.unset, set);
153
+ const createOf = (exec, type, registry, at, slot) => {
154
+ if (typeof exec.card === 'string') {
155
+ throw new PlanningError('malformed:create-without-draft');
156
+ }
157
+ const draft = exec.card;
158
+ const overlay = Object.fromEntries(Object.entries(exec.changes ?? {})
159
+ .filter(([key]) => !FLOW_KEYS.includes(key) && !IDENTITY_KEYS.includes(key) && !PROVENANCE_KEYS.includes(key)
160
+ && !DERIVED_KEYS.includes(key)));
161
+ const parent = overlay.parent ?? draft.parent;
162
+ const flows = statusHelper.initialFlowsOf(type, registry, draft.status ?? exec.changes?.status);
163
+ const intrinsic = statusHelper.resolveIntrinsic(type, flows, registry);
164
+ const record = {
165
+ title: draft.title,
166
+ description: draft.description,
167
+ code: draft.code,
168
+ order: draft.order,
169
+ createdBy: draft.createdBy,
170
+ reporter: draft.reporter,
171
+ assignee: draft.assignee,
172
+ mode: draft.mode ?? (draft.kind === WorkcardKind.Project ? 'opened' : undefined),
173
+ ...overlay,
174
+ labels: [...new Set(overlay.labels ?? draft.labels ?? [])],
175
+ parent,
176
+ parents: cardHelper.normalizeParents(parent, overlay.parents ?? draft.parents),
177
+ fields: mergeFields(draft.fields, overlay.fields),
178
+ flows,
179
+ status: flows[statusHelper.primaryFlowOf(type)],
180
+ intrinsic,
181
+ closedAt: intrinsic === IntrinsicStatus.Closed ? at : undefined,
182
+ };
183
+ if (draft.kind === WorkcardKind.Specification) {
184
+ const body = overlay.body ?? draft.body;
185
+ Object.assign(record, {
186
+ category: overlay.category ?? draft.category ?? slot?.category,
187
+ format: overlay.format ?? draft.format ?? slot?.format ?? SpecificationFormat.Markdown,
188
+ body,
189
+ ref: overlay.ref ?? draft.ref,
190
+ version: overlay.version ?? draft.version ?? slot?.version,
191
+ bodyChars: specificationHelper.bodyCharsOf(body),
192
+ revision: specificationHelper.nextRevision(null, slot),
193
+ });
194
+ }
195
+ return { changes: clean(record), unset: [] };
196
+ };
197
+ const computeChanges = (card, exec, type, registry, at, opts) => {
198
+ if (exec.action === TransitionAction.Create) {
199
+ return createOf(exec, type, registry, at, opts?.slot);
200
+ }
201
+ const set = { changes: {}, unset: [] };
202
+ if (exec.action !== TransitionAction.Update && exec.action !== TransitionAction.Transit) {
203
+ return set;
204
+ }
205
+ if (card == null) {
206
+ throw new PlanningError(`malformed:${exec.action}-without-card`);
207
+ }
208
+ if (exec.action === TransitionAction.Update) {
209
+ diffInto(card, exec.changes, [], set);
210
+ unsetInto(card, exec.unset, set);
211
+ reparent(card, set);
212
+ reviseInto(card, opts?.slot, set);
213
+ return set;
214
+ }
215
+ if (exec.transition == null) {
216
+ throw new PlanningError('malformed:transit-without-transition');
217
+ }
218
+ const primary = statusHelper.primaryFlowOf(type);
219
+ const flowId = exec.flow ?? primary;
220
+ const flow = registry.flow(flowId);
221
+ const from = card.flows[flowId] ?? (flowId === primary ? card.status : statusHelper.initialStatusOf(flow));
222
+ const rule = statusHelper.ruleOf(flow, exec.transition, from);
223
+ if (rule == null) {
224
+ throw new IllegalTransition(`${flowId}:${exec.transition}:${from}`);
225
+ }
226
+ diffInto(card, exec.changes, FLOW_KEYS, set);
227
+ unsetInto(card, exec.unset?.filter(path => !FLOW_KEYS.includes(path.split('.')[0])), set);
239
228
  reparent(card, set);
240
229
  reviseInto(card, opts?.slot, set);
241
- return set;
242
- }
243
- if (exec.transition == null) {
244
- throw new PlanningError('malformed:transit-without-transition');
245
- }
246
- const primary = primaryFlowOf(type);
247
- const flowId = exec.flow ?? primary;
248
- const flow = registry.flow(flowId);
249
- const from = card.flows[flowId] ?? (flowId === primary ? card.status : initialStatusOf(flow));
250
- const rule = ruleOf(flow, exec.transition, from);
251
- if (rule == null) {
252
- throw new IllegalTransition(`${flowId}:${exec.transition}:${from}`);
253
- }
254
- diffInto(card, exec.changes, FLOW_KEYS, set);
255
- unsetInto(card, exec.unset?.filter(path => !FLOW_KEYS.includes(path.split('.')[0])), set);
256
- reparent(card, set);
257
- reviseInto(card, opts?.slot, set);
258
- const flows = { ...card.flows, [flowId]: rule.to };
259
- set.changes.flows = { [flowId]: rule.to };
260
- if (flowId === primary) {
261
- set.changes.status = rule.to;
262
- }
263
- const intrinsic = resolveIntrinsic(type, flows, registry);
264
- if (intrinsic !== card.intrinsic) {
265
- set.changes.intrinsic = intrinsic;
266
- }
267
- if (intrinsic === IntrinsicStatus.Closed && card.intrinsic !== IntrinsicStatus.Closed) {
268
- set.changes.closedAt = at;
269
- }
270
- else if (intrinsic !== IntrinsicStatus.Closed && card.closedAt != null) {
271
- set.unset.push('closedAt');
272
- }
273
- return { ...set, flow: flowId, from, to: rule.to };
230
+ const flows = { ...card.flows, [flowId]: rule.to };
231
+ set.changes.flows = { [flowId]: rule.to };
232
+ if (flowId === primary) {
233
+ set.changes.status = rule.to;
234
+ }
235
+ const intrinsic = statusHelper.resolveIntrinsic(type, flows, registry);
236
+ if (intrinsic !== card.intrinsic) {
237
+ set.changes.intrinsic = intrinsic;
238
+ }
239
+ if (intrinsic === IntrinsicStatus.Closed && card.intrinsic !== IntrinsicStatus.Closed) {
240
+ set.changes.closedAt = at;
241
+ }
242
+ else if (intrinsic !== IntrinsicStatus.Closed && card.closedAt != null) {
243
+ set.unset.push('closedAt');
244
+ }
245
+ return { ...set, flow: flowId, from, to: rule.to };
246
+ };
247
+ const isEmptyChange = (set) => set.unset.length === 0 && Object.entries(set.changes).every(([, value]) => value === undefined || (isPlainObject(value) && Object.keys(value).length === 0));
248
+ return { sameValue, mergeFields, applyUnset, assertMutable, computeChanges, isEmptyChange };
274
249
  };
275
- /** Nothing to write: no changed value and nothing to clear. */
276
- export const isEmptyChange = (set) => set.unset.length === 0 && Object.entries(set.changes).every(([, value]) => value === undefined || (isPlainObject(value) && Object.keys(value).length === 0));
250
+ export const changesHelper = createChangesHelper();
251
+ /** @deprecated compat:factory-refactor — use `changesHelper.sameValue(…)` */
252
+ export const sameValue = (left, right) => changesHelper.sameValue(left, right);
253
+ /** @deprecated compat:factory-refactor — use `changesHelper.mergeFields(…)` */
254
+ export const mergeFields = (base, patch) => changesHelper.mergeFields(base, patch);
255
+ /** @deprecated compat:factory-refactor — use `changesHelper.applyUnset(…)` */
256
+ export const applyUnset = (record, unset) => changesHelper.applyUnset(record, unset);
257
+ /** @deprecated compat:factory-refactor — use `changesHelper.assertMutable(…)` */
258
+ export const assertMutable = (exec, type) => changesHelper.assertMutable(exec, type);
259
+ /** @deprecated compat:factory-refactor — use `changesHelper.computeChanges(…)` */
260
+ export const computeChanges = (card, exec, type, registry, at, opts) => changesHelper.computeChanges(card, exec, type, registry, at, opts);
261
+ /** @deprecated compat:factory-refactor — use `changesHelper.isEmptyChange(…)` */
262
+ export const isEmptyChange = (set) => changesHelper.isEmptyChange(set);
277
263
  //# sourceMappingURL=changes.js.map