@repobit/dex-store-elements 1.7.3 → 2.0.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 (227) hide show
  1. package/CHANGELOG.md +5 -913
  2. package/README.md +9 -7
  3. package/dist/src/actions/action.adapter.d.ts +36 -0
  4. package/dist/src/actions/action.adapter.js +183 -0
  5. package/dist/src/actions/action.adapter.js.map +1 -0
  6. package/dist/src/actions/action.attributes.d.ts +15 -0
  7. package/dist/src/actions/action.attributes.js +137 -0
  8. package/dist/src/actions/action.attributes.js.map +1 -0
  9. package/dist/src/actions/action.registry.d.ts +4 -0
  10. package/dist/src/actions/action.registry.js +119 -0
  11. package/dist/src/actions/action.registry.js.map +1 -0
  12. package/dist/src/actions/index.d.ts +3 -2
  13. package/dist/src/actions/index.js +3 -80
  14. package/dist/src/actions/index.js.map +1 -1
  15. package/dist/src/compute/compute.expand.d.ts +70 -0
  16. package/dist/src/compute/compute.expand.js +319 -0
  17. package/dist/src/compute/compute.expand.js.map +1 -0
  18. package/dist/src/compute/compute.scan.d.ts +54 -0
  19. package/dist/src/compute/compute.scan.js +160 -0
  20. package/dist/src/compute/compute.scan.js.map +1 -0
  21. package/dist/src/compute/option-resolver.d.ts +31 -0
  22. package/dist/src/compute/option-resolver.js +147 -0
  23. package/dist/src/compute/option-resolver.js.map +1 -0
  24. package/dist/src/contexts/context.compute.d.ts +12 -0
  25. package/dist/src/contexts/context.compute.js +4 -0
  26. package/dist/src/contexts/context.compute.js.map +1 -0
  27. package/dist/src/contexts/context.scope.d.ts +139 -0
  28. package/dist/src/contexts/context.scope.js +48 -0
  29. package/dist/src/contexts/context.scope.js.map +1 -0
  30. package/dist/src/controllers/controller.action-resolve.d.ts +110 -0
  31. package/dist/src/controllers/controller.action-resolve.js +203 -0
  32. package/dist/src/controllers/controller.action-resolve.js.map +1 -0
  33. package/dist/src/controllers/controller.action-topology.d.ts +59 -0
  34. package/dist/src/controllers/controller.action-topology.js +130 -0
  35. package/dist/src/controllers/controller.action-topology.js.map +1 -0
  36. package/dist/src/controllers/controller.compute.d.ts +72 -0
  37. package/dist/src/controllers/controller.compute.js +110 -0
  38. package/dist/src/controllers/controller.compute.js.map +1 -0
  39. package/dist/src/controllers/controller.resolve.d.ts +78 -0
  40. package/dist/src/controllers/controller.resolve.js +205 -0
  41. package/dist/src/controllers/controller.resolve.js.map +1 -0
  42. package/dist/src/core/action-topology.d.ts +62 -0
  43. package/dist/src/core/action-topology.js +67 -0
  44. package/dist/src/core/action-topology.js.map +1 -0
  45. package/dist/src/core/actions.d.ts +64 -0
  46. package/dist/src/core/actions.js +47 -0
  47. package/dist/src/core/actions.js.map +1 -0
  48. package/dist/src/core/node.element.d.ts +179 -0
  49. package/dist/src/core/node.element.js +573 -0
  50. package/dist/src/core/node.element.js.map +1 -0
  51. package/dist/src/core/node.scope.d.ts +374 -0
  52. package/dist/src/core/node.scope.js +558 -0
  53. package/dist/src/core/node.scope.js.map +1 -0
  54. package/dist/src/core/option-update.d.ts +11 -0
  55. package/dist/src/core/option-update.js +59 -0
  56. package/dist/src/core/option-update.js.map +1 -0
  57. package/dist/src/dsl/compilers/array/compiler.js +13 -14
  58. package/dist/src/dsl/compilers/array/compiler.js.map +1 -1
  59. package/dist/src/dsl/compilers/boolean/compiler.d.ts +1 -1
  60. package/dist/src/dsl/compilers/boolean/compiler.js +14 -27
  61. package/dist/src/dsl/compilers/boolean/compiler.js.map +1 -1
  62. package/dist/src/dsl/compilers/enum/compiler.js +7 -10
  63. package/dist/src/dsl/compilers/enum/compiler.js.map +1 -1
  64. package/dist/src/dsl/compilers/index.d.ts +1 -1
  65. package/dist/src/dsl/compilers/index.js +5 -5
  66. package/dist/src/dsl/compilers/index.js.map +1 -1
  67. package/dist/src/dsl/utilty.d.ts +0 -4
  68. package/dist/src/dsl/utilty.js +3 -30
  69. package/dist/src/dsl/utilty.js.map +1 -1
  70. package/dist/src/eta/batch.d.ts +123 -0
  71. package/dist/src/eta/batch.js +162 -0
  72. package/dist/src/eta/batch.js.map +1 -0
  73. package/dist/src/eta/batcher.d.ts +184 -0
  74. package/dist/src/eta/batcher.js +335 -0
  75. package/dist/src/eta/batcher.js.map +1 -0
  76. package/dist/src/eta/cache.d.ts +36 -0
  77. package/dist/src/eta/cache.js +56 -0
  78. package/dist/src/eta/cache.js.map +1 -0
  79. package/dist/src/eta/controller.d.ts +608 -0
  80. package/dist/src/eta/controller.js +1036 -0
  81. package/dist/src/eta/controller.js.map +1 -0
  82. package/dist/src/eta/factory.d.ts +74 -0
  83. package/dist/src/eta/factory.js +121 -0
  84. package/dist/src/eta/factory.js.map +1 -0
  85. package/dist/src/eta/idle.d.ts +39 -0
  86. package/dist/src/eta/idle.js +52 -0
  87. package/dist/src/eta/idle.js.map +1 -0
  88. package/dist/src/eta/index.d.ts +52 -0
  89. package/dist/src/eta/index.js +13 -0
  90. package/dist/src/eta/index.js.map +1 -0
  91. package/dist/src/eta/observer.d.ts +263 -0
  92. package/dist/src/eta/observer.js +263 -0
  93. package/dist/src/eta/observer.js.map +1 -0
  94. package/dist/src/eta/operations.d.ts +41 -0
  95. package/dist/src/eta/operations.js +59 -0
  96. package/dist/src/eta/operations.js.map +1 -0
  97. package/dist/src/eta/source-registry.d.ts +198 -0
  98. package/dist/src/eta/source-registry.js +267 -0
  99. package/dist/src/eta/source-registry.js.map +1 -0
  100. package/dist/src/eta/template-index.d.ts +285 -0
  101. package/dist/src/eta/template-index.js +642 -0
  102. package/dist/src/eta/template-index.js.map +1 -0
  103. package/dist/src/eta/types.d.ts +529 -0
  104. package/dist/src/eta/types.js +2 -0
  105. package/dist/src/eta/types.js.map +1 -0
  106. package/dist/src/index.d.ts +21 -9
  107. package/dist/src/index.js +22 -11
  108. package/dist/src/index.js.map +1 -1
  109. package/dist/src/nodes/node.context.d.ts +5 -3
  110. package/dist/src/nodes/node.context.js +48 -3
  111. package/dist/src/nodes/node.context.js.map +1 -1
  112. package/dist/src/nodes/node.option.d.ts +11 -31
  113. package/dist/src/nodes/node.option.js +158 -222
  114. package/dist/src/nodes/node.option.js.map +1 -1
  115. package/dist/src/nodes/node.product.d.ts +7 -11
  116. package/dist/src/nodes/node.product.js +85 -64
  117. package/dist/src/nodes/node.product.js.map +1 -1
  118. package/dist/src/renders/attributes/buyLink.d.ts +2 -2
  119. package/dist/src/renders/attributes/buyLink.js +14 -11
  120. package/dist/src/renders/attributes/buyLink.js.map +1 -1
  121. package/dist/src/renders/attributes/devices.d.ts +2 -2
  122. package/dist/src/renders/attributes/devices.js +9 -19
  123. package/dist/src/renders/attributes/devices.js.map +1 -1
  124. package/dist/src/renders/attributes/discount.d.ts +2 -2
  125. package/dist/src/renders/attributes/discount.js +56 -44
  126. package/dist/src/renders/attributes/discount.js.map +1 -1
  127. package/dist/src/renders/attributes/hide.d.ts +2 -2
  128. package/dist/src/renders/attributes/hide.js +49 -14
  129. package/dist/src/renders/attributes/hide.js.map +1 -1
  130. package/dist/src/renders/attributes/index.d.ts +3 -3
  131. package/dist/src/renders/attributes/index.js +2 -4
  132. package/dist/src/renders/attributes/index.js.map +1 -1
  133. package/dist/src/renders/attributes/price.d.ts +2 -2
  134. package/dist/src/renders/attributes/price.js +30 -44
  135. package/dist/src/renders/attributes/price.js.map +1 -1
  136. package/dist/src/renders/attributes/subscription.d.ts +2 -2
  137. package/dist/src/renders/attributes/subscription.js +14 -20
  138. package/dist/src/renders/attributes/subscription.js.map +1 -1
  139. package/dist/src/renders/attributes/utilty.d.ts +2 -0
  140. package/dist/src/renders/attributes/utilty.js +17 -4
  141. package/dist/src/renders/attributes/utilty.js.map +1 -1
  142. package/dist/src/renders/context.d.ts +122 -10
  143. package/dist/src/renders/context.js +140 -80
  144. package/dist/src/renders/context.js.map +1 -1
  145. package/dist/src/renders/format.js +2 -2
  146. package/dist/src/renders/format.js.map +1 -1
  147. package/dist/src/renders/index.d.ts +6 -2
  148. package/dist/src/renders/index.js +67 -29
  149. package/dist/src/renders/index.js.map +1 -1
  150. package/dist/src/renders/observe.d.ts +1 -4
  151. package/dist/src/renders/observe.js +10 -24
  152. package/dist/src/renders/observe.js.map +1 -1
  153. package/dist/src/renders/render.wrapper.d.ts +37 -0
  154. package/dist/src/renders/render.wrapper.js +147 -0
  155. package/dist/src/renders/render.wrapper.js.map +1 -0
  156. package/dist/src/templating/eta.js +1 -4
  157. package/dist/src/templating/eta.js.map +1 -1
  158. package/package.json +4 -5
  159. package/dist/src/actions/action.button.d.ts +0 -2
  160. package/dist/src/actions/action.button.js +0 -8
  161. package/dist/src/actions/action.button.js.map +0 -1
  162. package/dist/src/actions/action.input.d.ts +0 -2
  163. package/dist/src/actions/action.input.js +0 -43
  164. package/dist/src/actions/action.input.js.map +0 -1
  165. package/dist/src/actions/action.select.d.ts +0 -2
  166. package/dist/src/actions/action.select.js +0 -14
  167. package/dist/src/actions/action.select.js.map +0 -1
  168. package/dist/src/actions/utilty.d.ts +0 -16
  169. package/dist/src/actions/utilty.js +0 -149
  170. package/dist/src/actions/utilty.js.map +0 -1
  171. package/dist/src/contexts/context.datalayer.d.ts +0 -9
  172. package/dist/src/contexts/context.datalayer.js +0 -3
  173. package/dist/src/contexts/context.datalayer.js.map +0 -1
  174. package/dist/src/contexts/context.derived.d.ts +0 -12
  175. package/dist/src/contexts/context.derived.js +0 -3
  176. package/dist/src/contexts/context.derived.js.map +0 -1
  177. package/dist/src/contexts/context.option.d.ts +0 -5
  178. package/dist/src/contexts/context.option.js +0 -3
  179. package/dist/src/contexts/context.option.js.map +0 -1
  180. package/dist/src/contexts/context.product.d.ts +0 -5
  181. package/dist/src/contexts/context.product.js +0 -3
  182. package/dist/src/contexts/context.product.js.map +0 -1
  183. package/dist/src/contexts/context.state.d.ts +0 -28
  184. package/dist/src/contexts/context.state.js +0 -3
  185. package/dist/src/contexts/context.state.js.map +0 -1
  186. package/dist/src/contexts/context.store.d.ts +0 -5
  187. package/dist/src/contexts/context.store.js +0 -3
  188. package/dist/src/contexts/context.store.js.map +0 -1
  189. package/dist/src/controllers/collect-controller.d.ts +0 -39
  190. package/dist/src/controllers/collect-controller.js +0 -161
  191. package/dist/src/controllers/collect-controller.js.map +0 -1
  192. package/dist/src/controllers/compute-controller.d.ts +0 -55
  193. package/dist/src/controllers/compute-controller.js +0 -350
  194. package/dist/src/controllers/compute-controller.js.map +0 -1
  195. package/dist/src/controllers/eta-renderer/eta-dom-renderer.d.ts +0 -25
  196. package/dist/src/controllers/eta-renderer/eta-dom-renderer.js +0 -192
  197. package/dist/src/controllers/eta-renderer/eta-dom-renderer.js.map +0 -1
  198. package/dist/src/controllers/eta-renderer/eta-mutation-observer.d.ts +0 -28
  199. package/dist/src/controllers/eta-renderer/eta-mutation-observer.js +0 -206
  200. package/dist/src/controllers/eta-renderer/eta-mutation-observer.js.map +0 -1
  201. package/dist/src/controllers/eta-renderer/eta-renderer.d.ts +0 -21
  202. package/dist/src/controllers/eta-renderer/eta-renderer.js +0 -77
  203. package/dist/src/controllers/eta-renderer/eta-renderer.js.map +0 -1
  204. package/dist/src/controllers/eta-renderer/eta-template-cache.d.ts +0 -24
  205. package/dist/src/controllers/eta-renderer/eta-template-cache.js +0 -61
  206. package/dist/src/controllers/eta-renderer/eta-template-cache.js.map +0 -1
  207. package/dist/src/controllers/eta-renderer/eta-types.d.ts +0 -11
  208. package/dist/src/controllers/eta-renderer/eta-types.js +0 -1
  209. package/dist/src/controllers/eta-renderer/eta-types.js.map +0 -1
  210. package/dist/src/controllers/eta-renderer/index.d.ts +0 -2
  211. package/dist/src/controllers/eta-renderer/index.js +0 -2
  212. package/dist/src/controllers/eta-renderer/index.js.map +0 -1
  213. package/dist/src/controllers/event-pipeline-controller.d.ts +0 -28
  214. package/dist/src/controllers/event-pipeline-controller.js +0 -72
  215. package/dist/src/controllers/event-pipeline-controller.js.map +0 -1
  216. package/dist/src/events/events.d.ts +0 -75
  217. package/dist/src/events/events.js +0 -78
  218. package/dist/src/events/events.js.map +0 -1
  219. package/dist/src/nodes/node.root.d.ts +0 -16
  220. package/dist/src/nodes/node.root.js +0 -49
  221. package/dist/src/nodes/node.root.js.map +0 -1
  222. package/dist/src/nodes/node.state.d.ts +0 -88
  223. package/dist/src/nodes/node.state.js +0 -330
  224. package/dist/src/nodes/node.state.js.map +0 -1
  225. package/dist/src/renders/utility.d.ts +0 -32
  226. package/dist/src/renders/utility.js +0 -191
  227. package/dist/src/renders/utility.js.map +0 -1
@@ -0,0 +1,59 @@
1
+ // src/core/option-update.ts
2
+ /**
3
+ * Pure devices/subscription update semantics shared by the runtime OptionNode
4
+ * and the dry-run compute layer.
5
+ *
6
+ * Given a current numeric value and an UpdateByDelta command, this returns the
7
+ * next value. `next` / `prev` walk the product's declared dimension values, so
8
+ * sequential stepping respects what the product actually offers.
9
+ */
10
+ export function applyOptionUpdate(field, currentValue, update, product) {
11
+ if (!update || update.type !== field) {
12
+ return currentValue;
13
+ }
14
+ if (update.useAsValue) {
15
+ if (typeof update.delta !== 'number') {
16
+ return currentValue;
17
+ }
18
+ return clampNumericUpdate(update.delta, update);
19
+ }
20
+ if (currentValue === undefined) {
21
+ return undefined;
22
+ }
23
+ if (update.delta === 'next' ||
24
+ update.delta === 'prev') {
25
+ return applySequentialUpdate(field, currentValue, update, product);
26
+ }
27
+ return clampNumericUpdate(currentValue + update.delta, update);
28
+ }
29
+ function applySequentialUpdate(field, currentValue, update, product) {
30
+ const values = field === 'devices'
31
+ ? product?.getDevices().values
32
+ : product?.getSubscriptions().values;
33
+ if (!values || values.length === 0) {
34
+ return currentValue;
35
+ }
36
+ const currentIndex = values.findIndex((value) => value === currentValue);
37
+ if (currentIndex < 0) {
38
+ return currentValue;
39
+ }
40
+ const nextIndex = update.delta === 'next'
41
+ ? currentIndex + 1
42
+ : currentIndex - 1;
43
+ const nextValue = values[nextIndex];
44
+ if (nextValue === undefined) {
45
+ return currentValue;
46
+ }
47
+ return clampNumericUpdate(nextValue, update);
48
+ }
49
+ function clampNumericUpdate(value, update) {
50
+ let nextValue = value;
51
+ if (update.min !== undefined) {
52
+ nextValue = Math.max(update.min, nextValue);
53
+ }
54
+ if (update.max !== undefined) {
55
+ nextValue = Math.min(update.max, nextValue);
56
+ }
57
+ return nextValue;
58
+ }
59
+ //# sourceMappingURL=option-update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"option-update.js","sourceRoot":"","sources":["../../../src/core/option-update.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAK5B;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAA4B,EAC5B,YAAgC,EAChC,MAAiC,EACjC,OAA4B;IAE5B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrC,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,OAAO,kBAAkB,CACvB,MAAM,CAAC,KAAK,EACZ,MAAM,CACP,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IACE,MAAM,CAAC,KAAK,KAAK,MAAM;QACvB,MAAM,CAAC,KAAK,KAAK,MAAM,EACvB,CAAC;QACD,OAAO,qBAAqB,CAC1B,KAAK,EACL,YAAY,EACZ,MAAM,EACN,OAAO,CACR,CAAC;IACJ,CAAC;IAED,OAAO,kBAAkB,CACvB,YAAY,GAAG,MAAM,CAAC,KAAK,EAC3B,MAAM,CACP,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAA4B,EAC5B,YAAoB,EACpB,MAAqB,EACrB,OAA4B;IAE5B,MAAM,MAAM,GACV,KAAK,KAAK,SAAS;QACjB,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,MAAM;QAC9B,CAAC,CAAC,OAAO,EAAE,gBAAgB,EAAE,CAAC,MAAM,CAAC;IAEzC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,YAAY,GAChB,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC;IAEtD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,SAAS,GACb,MAAM,CAAC,KAAK,KAAK,MAAM;QACrB,CAAC,CAAC,YAAY,GAAG,CAAC;QAClB,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;IAEvB,MAAM,SAAS,GACb,MAAM,CAAC,SAAS,CAAC,CAAC;IAEpB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,kBAAkB,CACvB,SAAS,EACT,MAAM,CACP,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,KAAa,EACb,MAAqB;IAErB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,SAAS,GAAG,IAAI,CAAC,GAAG,CAClB,MAAM,CAAC,GAAG,EACV,SAAS,CACV,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC7B,SAAS,GAAG,IAAI,CAAC,GAAG,CAClB,MAAM,CAAC,GAAG,EACV,SAAS,CACV,CAAC;IACJ,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// src/core/option-update.ts\n\nimport type { UpdateByDelta } from '@/core/actions.js';\nimport type { Product } from '@repobit/dex-store';\n\n/**\n * Pure devices/subscription update semantics shared by the runtime OptionNode\n * and the dry-run compute layer.\n *\n * Given a current numeric value and an UpdateByDelta command, this returns the\n * next value. `next` / `prev` walk the product's declared dimension values, so\n * sequential stepping respects what the product actually offers.\n */\nexport function applyOptionUpdate(\n field: UpdateByDelta['type'],\n currentValue: number | undefined,\n update: UpdateByDelta | undefined,\n product: Product | undefined\n): number | undefined {\n if (!update || update.type !== field) {\n return currentValue;\n }\n\n if (update.useAsValue) {\n if (typeof update.delta !== 'number') {\n return currentValue;\n }\n\n return clampNumericUpdate(\n update.delta,\n update\n );\n }\n\n if (currentValue === undefined) {\n return undefined;\n }\n\n if (\n update.delta === 'next' ||\n update.delta === 'prev'\n ) {\n return applySequentialUpdate(\n field,\n currentValue,\n update,\n product\n );\n }\n\n return clampNumericUpdate(\n currentValue + update.delta,\n update\n );\n}\n\nfunction applySequentialUpdate(\n field: UpdateByDelta['type'],\n currentValue: number,\n update: UpdateByDelta,\n product: Product | undefined\n): number {\n const values =\n field === 'devices'\n ? product?.getDevices().values\n : product?.getSubscriptions().values;\n\n if (!values || values.length === 0) {\n return currentValue;\n }\n\n const currentIndex =\n values.findIndex((value) => value === currentValue);\n\n if (currentIndex < 0) {\n return currentValue;\n }\n\n const nextIndex =\n update.delta === 'next'\n ? currentIndex + 1\n : currentIndex - 1;\n\n const nextValue =\n values[nextIndex];\n\n if (nextValue === undefined) {\n return currentValue;\n }\n\n return clampNumericUpdate(\n nextValue,\n update\n );\n}\n\nfunction clampNumericUpdate(\n value: number,\n update: UpdateByDelta\n): number {\n let nextValue = value;\n\n if (update.min !== undefined) {\n nextValue = Math.max(\n update.min,\n nextValue\n );\n }\n\n if (update.max !== undefined) {\n nextValue = Math.min(\n update.max,\n nextValue\n );\n }\n\n return nextValue;\n}\n"]}
@@ -1,22 +1,21 @@
1
- import { split } from "../../../dsl/utilty.js";
2
- // "2,3,4,5" -> [2,3,4,5]
3
- // "1..4,8,10..7" -> [1,2,3,4,8,10,9,8,7]
4
- // "" -> undefined
1
+ import { split } from '../../../dsl/utilty.js';
5
2
  export const compiler = (raw) => {
6
- const s = raw.trim();
7
- if (s === "")
3
+ const source = raw.trim();
4
+ if (source === '') {
8
5
  return undefined;
6
+ }
9
7
  const out = [];
10
8
  const intRe = /^-?\d+$/;
11
9
  const rangeRe = /^(-?\d+)\s*\.\.\s*(-?\d+)$/;
12
- for (const part of split(s, ",")) {
13
- const m = part.match(rangeRe);
14
- if (m) {
15
- const a = parseInt(m[1], 10);
16
- const b = parseInt(m[2], 10);
17
- const step = a <= b ? 1 : -1;
18
- for (let v = a; v !== b + step; v += step)
19
- out.push(v);
10
+ for (const part of split(source, ',')) {
11
+ const match = part.match(rangeRe);
12
+ if (match) {
13
+ const start = parseInt(match[1], 10);
14
+ const end = parseInt(match[2], 10);
15
+ const step = start <= end ? 1 : -1;
16
+ for (let value = start; value !== end + step; value += step) {
17
+ out.push(value);
18
+ }
20
19
  continue;
21
20
  }
22
21
  if (intRe.test(part)) {
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../../../src/dsl/compilers/array/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,mCAAmC;AACnC,8CAA8C;AAC9C,mCAAmC;AACnC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAwB,EAAE;IAC5D,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACrB,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAE/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAK,SAAS,CAAC;IAC1B,MAAM,OAAO,GAAG,4BAA4B,CAAC;IAE7C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,IAAI;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvD,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC,CAAA","sourcesContent":["import { split } from \"@/dsl/utilty\";\n// \"2,3,4,5\" -> [2,3,4,5]\n// \"1..4,8,10..7\" -> [1,2,3,4,8,10,9,8,7]\n// \"\" -> undefined\nexport const compiler = (raw: string): number[] | undefined => {\n const s = raw.trim();\n if (s === \"\") return undefined;\n\n const out: number[] = [];\n const intRe = /^-?\\d+$/;\n const rangeRe = /^(-?\\d+)\\s*\\.\\.\\s*(-?\\d+)$/;\n\n for (const part of split(s, \",\")) {\n const m = part.match(rangeRe);\n if (m) {\n const a = parseInt(m[1], 10);\n const b = parseInt(m[2], 10);\n const step = a <= b ? 1 : -1;\n for (let v = a; v !== b + step; v += step) out.push(v);\n continue;\n }\n if (intRe.test(part)) {\n out.push(parseInt(part, 10));\n continue;\n }\n throw new Error(`Invalid number token: \"${part}\"`);\n }\n\n return out;\n}\n"]}
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../../../src/dsl/compilers/array/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,GAAW,EACW,EAAE;IACxB,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAE1B,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,SAAS,CAAC;IACxB,MAAM,OAAO,GAAG,4BAA4B,CAAC;IAE7C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAElC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEnC,KAAK,IAAI,KAAK,GAAG,KAAK,EAAE,KAAK,KAAK,GAAG,GAAG,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC;gBAC5D,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAED,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC,CAAC","sourcesContent":["import { split } from '@/dsl/utilty.js';\n\nexport const compiler = (\n raw: string\n): number[] | undefined => {\n const source = raw.trim();\n\n if (source === '') {\n return undefined;\n }\n\n const out: number[] = [];\n const intRe = /^-?\\d+$/;\n const rangeRe = /^(-?\\d+)\\s*\\.\\.\\s*(-?\\d+)$/;\n\n for (const part of split(source, ',')) {\n const match = part.match(rangeRe);\n\n if (match) {\n const start = parseInt(match[1], 10);\n const end = parseInt(match[2], 10);\n const step = start <= end ? 1 : -1;\n\n for (let value = start; value !== end + step; value += step) {\n out.push(value);\n }\n\n continue;\n }\n\n if (intRe.test(part)) {\n out.push(parseInt(part, 10));\n continue;\n }\n\n throw new Error(`Invalid number token: \"${part}\"`);\n }\n\n return out;\n};\n"]}
@@ -1,4 +1,4 @@
1
- import { Ctx } from "../../../dsl/utilty.js";
1
+ import type { Ctx } from '../../../dsl/utilty.js';
2
2
  type Params = {
3
3
  expr: string;
4
4
  ctx: Ctx;
@@ -1,53 +1,40 @@
1
- import eta from "../../../templating/eta.js";
2
- // Very lightweight preflight checks so we can rely on Eta/JS
3
- // for actual expression evaluation while still catching a few
4
- // DSL-specific pitfalls we used to guard against.
1
+ import eta from '../../../templating/eta.js';
5
2
  function preflight(expr) {
6
- // 1) Disallow chained comparisons like: a < b < c
7
- // Match two comparison operators with no logical op (&&, ||) between
8
3
  const chainedCmp = /(<=|>=|<|>)\s*[^&|]+(<=|>=|<|>)/;
9
4
  if (chainedCmp.test(expr)) {
10
- throw new Error("Chained comparisons are not allowed");
5
+ throw new Error('Chained comparisons are not allowed');
11
6
  }
12
- // 2) Basic parentheses balance check to surface a clearer error
13
7
  let depth = 0;
14
- for (const ch of expr) {
15
- if (ch === "(")
8
+ for (const char of expr) {
9
+ if (char === '(') {
16
10
  depth++;
17
- else if (ch === ")") {
11
+ }
12
+ else if (char === ')') {
18
13
  depth--;
19
14
  if (depth < 0) {
20
- // extra closing paren
21
15
  throw new Error("Unexpected ')'");
22
16
  }
23
17
  }
24
18
  }
25
19
  if (depth > 0) {
26
- throw new Error("Expected ')' ");
20
+ throw new Error("Expected ')'");
27
21
  }
28
22
  }
29
23
  export const compiler = ({ expr, ctx }) => {
30
24
  preflight(expr);
31
- // Normalize equality to strict semantics to match legacy DSL behavior
32
- // - '==' -> '==='
33
- // - '!=' -> '!=='
34
- // Note: This is a simple text replacement and does not account for quoted strings,
35
- // but our DSL usage does not place operators inside string literals.
36
25
  const normalized = expr
37
26
  .replace(/!=(?!=)/g, '!==')
38
27
  .replace(/(?<![=!])==(?![=])/g, '===');
39
- // Build a tiny Eta template that coerces the expression to boolean.
40
- const tpl = `{{= !!(${normalized}) }}`;
41
28
  try {
42
- const fn = eta.compile(tpl);
29
+ const fn = eta.compile(`{{= !!(${normalized}) }}`);
43
30
  const out = eta.render(fn, ctx);
44
- // Eta returns a string; normalize to boolean
45
- return String(out).trim() === "true";
31
+ return String(out).trim() === 'true';
46
32
  }
47
- catch (e) {
48
- // Normalize error to a generic syntax error message used in tests
49
- const msg = e instanceof Error ? e.message : String(e);
50
- throw new Error(`Unexpected expression error: ${msg}`);
33
+ catch (error) {
34
+ const message = error instanceof Error
35
+ ? error.message
36
+ : String(error);
37
+ throw new Error(`Unexpected expression error: ${message}`);
51
38
  }
52
39
  };
53
40
  //# sourceMappingURL=compiler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../../../src/dsl/compilers/boolean/compiler.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,kBAAkB,CAAC;AAOnC,6DAA6D;AAC7D,8DAA8D;AAC9D,kDAAkD;AAClD,SAAS,SAAS,CAAC,IAAY;IAC7B,kDAAkD;IAClD,qEAAqE;IACrE,MAAM,UAAU,GAAG,iCAAiC,CAAC;IACrD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,gEAAgE;IAChE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACtB,IAAI,EAAE,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;aACnB,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACpB,KAAK,EAAE,CAAC;YACR,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,sBAAsB;gBACtB,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,EAAU,EAAE,EAAE;IAChD,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhB,sEAAsE;IACtE,mBAAmB;IACnB,mBAAmB;IACnB,mFAAmF;IACnF,qEAAqE;IACrE,MAAM,UAAU,GAAG,IAAI;SACpB,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,OAAO,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;IAEzC,oEAAoE;IACpE,MAAM,GAAG,GAAG,UAAU,UAAU,MAAM,CAAC;IAEvC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChC,6CAA6C;QAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;IACvC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,kEAAkE;QAClE,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC,CAAC","sourcesContent":["import { Ctx } from \"@/dsl/utilty\";\nimport eta from \"@/templating/eta\";\n\ntype Params = {\n expr: string,\n ctx : Ctx\n};\n\n// Very lightweight preflight checks so we can rely on Eta/JS\n// for actual expression evaluation while still catching a few\n// DSL-specific pitfalls we used to guard against.\nfunction preflight(expr: string) {\n // 1) Disallow chained comparisons like: a < b < c\n // Match two comparison operators with no logical op (&&, ||) between\n const chainedCmp = /(<=|>=|<|>)\\s*[^&|]+(<=|>=|<|>)/;\n if (chainedCmp.test(expr)) {\n throw new Error(\"Chained comparisons are not allowed\");\n }\n\n // 2) Basic parentheses balance check to surface a clearer error\n let depth = 0;\n for (const ch of expr) {\n if (ch === \"(\") depth++;\n else if (ch === \")\") {\n depth--;\n if (depth < 0) {\n // extra closing paren\n throw new Error(\"Unexpected ')'\");\n }\n }\n }\n if (depth > 0) {\n throw new Error(\"Expected ')' \");\n }\n}\n\nexport const compiler = ({ expr, ctx }: Params) => {\n preflight(expr);\n\n // Normalize equality to strict semantics to match legacy DSL behavior\n // - '==' -> '==='\n // - '!=' -> '!=='\n // Note: This is a simple text replacement and does not account for quoted strings,\n // but our DSL usage does not place operators inside string literals.\n const normalized = expr\n .replace(/!=(?!=)/g, '!==')\n .replace(/(?<![=!])==(?![=])/g, '===');\n\n // Build a tiny Eta template that coerces the expression to boolean.\n const tpl = `{{= !!(${normalized}) }}`;\n\n try {\n const fn = eta.compile(tpl);\n const out = eta.render(fn, ctx);\n // Eta returns a string; normalize to boolean\n return String(out).trim() === \"true\";\n } catch (e) {\n // Normalize error to a generic syntax error message used in tests\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`Unexpected expression error: ${msg}`);\n }\n};\n"]}
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../../../src/dsl/compilers/boolean/compiler.ts"],"names":[],"mappings":"AACA,OAAO,GAAG,MAAM,qBAAqB,CAAC;AAOtC,SAAS,SAAS,CAChB,IAAY;IAEZ,MAAM,UAAU,GAAG,iCAAiC,CAAC;IAErD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,KAAK,EAAE,CAAC;QACV,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,KAAK,EAAE,CAAC;YAER,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EACvB,IAAI,EACJ,GAAG,EACI,EAAW,EAAE;IACpB,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhB,MAAM,UAAU,GAAG,IAAI;SACpB,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,OAAO,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;IAEzC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,UAAU,MAAM,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CACpB,EAAE,EACF,GAAG,CACJ,CAAC;QAEF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK;YACpB,CAAC,CAAC,KAAK,CAAC,OAAO;YACf,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEpB,MAAM,IAAI,KAAK,CAAC,gCAAgC,OAAO,EAAE,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { Ctx } from '@/dsl/utilty.js';\nimport eta from '@/templating/eta.js';\n\ntype Params = {\n expr: string;\n ctx : Ctx;\n};\n\nfunction preflight(\n expr: string\n): void {\n const chainedCmp = /(<=|>=|<|>)\\s*[^&|]+(<=|>=|<|>)/;\n\n if (chainedCmp.test(expr)) {\n throw new Error('Chained comparisons are not allowed');\n }\n\n let depth = 0;\n\n for (const char of expr) {\n if (char === '(') {\n depth++;\n } else if (char === ')') {\n depth--;\n\n if (depth < 0) {\n throw new Error(\"Unexpected ')'\");\n }\n }\n }\n\n if (depth > 0) {\n throw new Error(\"Expected ')'\");\n }\n}\n\nexport const compiler = ({\n expr,\n ctx\n}: Params): boolean => {\n preflight(expr);\n\n const normalized = expr\n .replace(/!=(?!=)/g, '!==')\n .replace(/(?<![=!])==(?![=])/g, '===');\n\n try {\n const fn = eta.compile(`{{= !!(${normalized}) }}`);\n const out = eta.render(\n fn,\n ctx\n );\n\n return String(out).trim() === 'true';\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : String(error);\n\n throw new Error(`Unexpected expression error: ${message}`);\n }\n};\n"]}
@@ -1,16 +1,13 @@
1
- import { split } from "../../../dsl/utilty.js";
1
+ import { split } from '../../../dsl/utilty.js';
2
2
  export const compiler = ({ expr, allowed, isAvailable }) => {
3
- const tokens = split(expr, "||");
4
- // validate tokens early
5
- for (const t of tokens) {
6
- if (!allowed.includes(t)) {
7
- console.warn(`[store] Unknown token "${t}". Allowed: ${allowed.join(", ")}`);
3
+ const tokens = split(expr, '||');
4
+ for (const rawToken of tokens) {
5
+ const token = rawToken;
6
+ if (allowed.includes(token) &&
7
+ isAvailable(token)) {
8
+ return token;
8
9
  }
9
10
  }
10
- for (const t of tokens) {
11
- if (allowed.includes(t) && isAvailable(t))
12
- return t;
13
- }
14
11
  return undefined;
15
12
  };
16
13
  //# sourceMappingURL=compiler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../../../src/dsl/compilers/enum/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAQrC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAyB,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAmB,EAAuB,EAAE;IACvH,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAc,CAAC;IAC9C,wBAAwB;IACxB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,eAAe,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAA","sourcesContent":["import { split } from \"@/dsl/utilty\";\n\ntype Params<Allowed extends string> = {\n expr : string,\n allowed : readonly Allowed[],\n isAvailable: (variant: Allowed) => boolean,\n}\n\nexport const compiler = <Allowed extends string>({ expr, allowed, isAvailable }: Params<Allowed>): Allowed | undefined => {\n const tokens = split(expr, \"||\") as Allowed[];\n // validate tokens early\n for (const t of tokens) {\n if (!allowed.includes(t)) {\n console.warn(`[store] Unknown token \"${t}\". Allowed: ${allowed.join(\", \")}`);\n }\n }\n\n for (const t of tokens) {\n if (allowed.includes(t) && isAvailable(t)) return t;\n }\n return undefined;\n}"]}
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../../../../src/dsl/compilers/enum/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAQxC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAyB,EAC/C,IAAI,EACJ,OAAO,EACP,WAAW,EACK,EAAuB,EAAE;IACzC,MAAM,MAAM,GAAG,KAAK,CAClB,IAAI,EACJ,IAAI,CACL,CAAC;IAEF,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,QAAmB,CAAC;QAElC,IACE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvB,WAAW,CAAC,KAAK,CAAC,EAClB,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { split } from '@/dsl/utilty.js';\n\ntype Params<Allowed extends string> = {\n expr : string;\n allowed : readonly Allowed[];\n isAvailable: (variant: Allowed) => boolean;\n};\n\nexport const compiler = <Allowed extends string>({\n expr,\n allowed,\n isAvailable\n}: Params<Allowed>): Allowed | undefined => {\n const tokens = split(\n expr,\n '||'\n );\n\n for (const rawToken of tokens) {\n const token = rawToken as Allowed;\n\n if (\n allowed.includes(token) &&\n isAvailable(token)\n ) {\n return token;\n }\n }\n\n return undefined;\n};\n"]}
@@ -1,4 +1,5 @@
1
1
  export declare const Compiler: {
2
+ readonly array: (raw: string) => number[] | undefined;
2
3
  readonly boolean: ({ expr, ctx }: {
3
4
  expr: string;
4
5
  ctx: import("../utilty.js").Ctx;
@@ -8,5 +9,4 @@ export declare const Compiler: {
8
9
  allowed: readonly Allowed[];
9
10
  isAvailable: (variant: Allowed) => boolean;
10
11
  }) => Allowed | undefined;
11
- readonly array: (raw: string) => number[] | undefined;
12
12
  };
@@ -1,9 +1,9 @@
1
- import { compiler as array } from "./array/compiler.js";
2
- import { compiler as boolean } from "./boolean/compiler.js";
3
- import { compiler as enumeration } from "./enum/compiler.js";
1
+ import { compiler as array } from './array/compiler.js';
2
+ import { compiler as boolean } from './boolean/compiler.js';
3
+ import { compiler as enumeration } from './enum/compiler.js';
4
4
  export const Compiler = {
5
+ array,
5
6
  boolean,
6
- enum: enumeration,
7
- array
7
+ enum: enumeration
8
8
  };
9
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/dsl/compilers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,QAAQ,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,OAAO;IACP,IAAI,EAAE,WAAW;IACjB,KAAK;CACG,CAAC","sourcesContent":["import { compiler as array } from \"./array/compiler\";\nimport { compiler as boolean } from \"./boolean/compiler\";\nimport { compiler as enumeration } from \"./enum/compiler\";\n\nexport const Compiler = {\n boolean,\n enum: enumeration,\n array\n} as const;"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/dsl/compilers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,QAAQ,IAAI,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,KAAK;IACL,OAAO;IACP,IAAI,EAAE,WAAW;CACT,CAAC","sourcesContent":["import { compiler as array } from './array/compiler.js';\nimport { compiler as boolean } from './boolean/compiler.js';\nimport { compiler as enumeration } from './enum/compiler.js';\n\nexport const Compiler = {\n array,\n boolean,\n enum: enumeration\n} as const;\n"]}
@@ -1,6 +1,2 @@
1
1
  export type Ctx = Record<string, unknown>;
2
- export declare const isRecord: (v: unknown) => v is Record<string, unknown>;
3
- export declare const getPath: <T = unknown>(ctx: unknown, path: string) => T | undefined;
4
- export declare const isTruthy: (v: unknown) => boolean;
5
- export declare const coerceLiteral: (s: string) => string | number | boolean | null | undefined;
6
2
  export declare const split: (raw: string, sep: string) => string[];
@@ -1,32 +1,5 @@
1
- export const isRecord = (v) => v !== null && typeof v === "object";
2
- export const getPath = (ctx, path) => {
3
- let acc = ctx;
4
- for (const key of path.split(".")) {
5
- if (!isRecord(acc) || !(key in acc))
6
- return undefined;
7
- acc = acc[key];
8
- }
9
- return acc;
10
- };
11
- export const isTruthy = (v) => v !== "" && v !== false && v !== null && v !== undefined;
12
- // Parse quoted literal or pass-through
13
- export const coerceLiteral = (s) => {
14
- if (/^-?\d+(\.\d+)?$/.test(s))
15
- return Number(s);
16
- if (s === "true")
17
- return true;
18
- if (s === "false")
19
- return false;
20
- if (s === "null")
21
- return null;
22
- if (s === "undefined")
23
- return undefined;
24
- const q = s[0], end = s[s.length - 1];
25
- if ((q === "'" && end === "'") || (q === '"' && end === '"'))
26
- return s.slice(1, -1);
27
- return s;
28
- };
29
- // Split by token, trim, drop empties
30
- export const split = (raw, sep) => raw.split(sep).map(s => s.trim())
1
+ export const split = (raw, sep) => raw
2
+ .split(sep)
3
+ .map((s) => s.trim())
31
4
  .filter(Boolean);
32
5
  //# sourceMappingURL=utilty.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utilty.js","sourceRoot":"","sources":["../../../src/dsl/utilty.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAgC,EAAE,CACnE,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC;AAEtC,MAAM,CAAC,MAAM,OAAO,GAAG,CAAc,GAAY,EAAE,IAAY,EAAiB,EAAE;IAChF,IAAI,GAAG,GAAY,GAAG,CAAC;IACvB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QACtD,GAAG,GAAG,GAAG,CAAC,GAAuB,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,GAAoB,CAAC;AAC9B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAE,EAAE,CACrC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,CAAC;AAE3D,uCAAuC;AACvC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAS,EAAE,EAAE;IACzC,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACtC,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,qCAAqC;AACrC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE,CAChD,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;KAC9B,MAAM,CAAC,OAAO,CAAC,CAAC","sourcesContent":["export type Ctx = Record<string, unknown>;\nexport const isRecord = (v: unknown): v is Record<string, unknown> =>\n v !== null && typeof v === \"object\";\n\nexport const getPath = <T = unknown>(ctx: unknown, path: string): T | undefined => {\n let acc: unknown = ctx;\n for (const key of path.split(\".\")) {\n if (!isRecord(acc) || !(key in acc)) return undefined;\n acc = acc[key as keyof typeof acc];\n }\n return acc as T | undefined;\n}\n\nexport const isTruthy = (v: unknown) =>\n v !== \"\" && v !== false && v !== null && v !== undefined;\n\n// Parse quoted literal or pass-through\nexport const coerceLiteral = (s: string) => {\n if (/^-?\\d+(\\.\\d+)?$/.test(s)) return Number(s);\n if (s === \"true\") return true;\n if (s === \"false\") return false;\n if (s === \"null\") return null;\n if (s === \"undefined\") return undefined;\n const q = s[0], end = s[s.length - 1];\n if ((q === \"'\" && end === \"'\") || (q === '\"' && end === '\"')) return s.slice(1, -1);\n return s;\n};\n\n// Split by token, trim, drop empties\nexport const split = (raw: string, sep: string) =>\n raw.split(sep).map(s => s.trim())\n .filter(Boolean);"]}
1
+ {"version":3,"file":"utilty.js","sourceRoot":"","sources":["../../../src/dsl/utilty.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,GAAW,EACX,GAAW,EACD,EAAE,CACZ,GAAG;KACA,KAAK,CAAC,GAAG,CAAC;KACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;KACpB,MAAM,CAAC,OAAO,CAAC,CAAC","sourcesContent":["export type Ctx = Record<string, unknown>;\n\nexport const split = (\n raw: string,\n sep: string\n): string[] =>\n raw\n .split(sep)\n .map((s) => s.trim())\n .filter(Boolean);\n"]}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Accumulator for raw `MutationRecord`s produced by the
3
+ * `EtaMutationObserver` between scheduled flushes.
4
+ *
5
+ * Records fall into four buckets:
6
+ *
7
+ * - `added` — nodes introduced into the DOM via `childList` records.
8
+ * - `removed` — nodes detached via `childList` records.
9
+ * - `text` — `Text` nodes whose data changed via `characterData`
10
+ * records.
11
+ * - `attributes` — `(Element, attributeName)` pairs that flipped via
12
+ * `attributes` records.
13
+ *
14
+ * The buckets are `Set` / `Map` collections rather than arrays so
15
+ * that repeated records for the same target naturally collapse
16
+ * before flush (e.g. five `attributes` flips on the same `title`
17
+ * only yield a single `(element, 'title')` entry by the time the
18
+ * batch is applied).
19
+ *
20
+ * **Compaction rules.** A flush through `EtaMutationBatcher` applies
21
+ * the following reductions to the bucket contents before forwarding
22
+ * the compacted set to the `EtaTemplateIndex`:
23
+ *
24
+ * 1. `add` then `remove` of the same node within one batch is a
25
+ * no-op (the node ends up detached, the index never saw it).
26
+ * 2. `remove` then `add` of the same node is forwarded as both a
27
+ * `remove` and an `add` (the move is real).
28
+ * 3. An ancestor `add` subsumes descendant `add`s — the index walks
29
+ * the subtree on `add`, so descendant adds are redundant.
30
+ * 4. An ancestor `remove` subsumes descendant `remove`s for the
31
+ * same reason.
32
+ * 5. A `text` change inside an added subtree is dropped; the index
33
+ * reads the final text when it walks the new subtree.
34
+ * 6. A `text` / `attribute` change inside a removed subtree is
35
+ * dropped; the node is leaving ownership.
36
+ * 7. Repeated text changes on the same `Text` node collapse to one
37
+ * entry (the `Set` storage already handles this).
38
+ * 8. Repeated attribute changes on the same `(Element, name)` pair
39
+ * collapse to one entry (the inner `Set<string>` storage already
40
+ * handles this).
41
+ *
42
+ * The batch itself does not enforce rules 1–6 — those live in the
43
+ * batcher's compaction pass. Rules 7–8 are enforced automatically
44
+ * by the bucket storage.
45
+ *
46
+ * **Immutability of contents.** Bucket contents are mutable in
47
+ * place for performance reasons (`Set.add` / `Map.set` are O(1)).
48
+ * Callers MUST NOT cache references to bucket internals across a
49
+ * flush — `clear()` resets the bucket to empty. The controller
50
+ * treats the batch as opaque between flushes.
51
+ */
52
+ export declare class EtaMutationBatch {
53
+ /**
54
+ * Nodes added since the last flush.
55
+ *
56
+ * Stored as a `Set<Node>` so multiple adds of the same node
57
+ * collapse automatically (rule 7-equivalent for adds).
58
+ */
59
+ readonly added: Set<Node>;
60
+ /**
61
+ * Nodes removed since the last flush.
62
+ *
63
+ * Stored as a `Set<Node>` for the same dedup reasons as `added`.
64
+ */
65
+ readonly removed: Set<Node>;
66
+ /**
67
+ * `Text` nodes whose character data changed since the last flush.
68
+ *
69
+ * `Set<Text>` collapses repeated changes on the same text node
70
+ * (rule 7).
71
+ */
72
+ readonly text: Set<Text>;
73
+ /**
74
+ * `Element` → set of changed attribute names since the last flush.
75
+ *
76
+ * The inner `Set<string>` collapses repeated changes to the same
77
+ * attribute name (rule 8).
78
+ */
79
+ readonly attributes: Map<Element, Set<string>>;
80
+ /**
81
+ * Reset every bucket to empty.
82
+ *
83
+ * Called by `EtaMutationBatcher.flush()` after the compacted
84
+ * mutations have been applied to the index. The bucket instances
85
+ * are preserved (`Set` / `Map` references stay valid) so callers
86
+ * can safely hold long-lived references to them.
87
+ */
88
+ clear(): void;
89
+ /**
90
+ * `true` when every bucket is empty — i.e. there is nothing to
91
+ * forward to the index on the next flush.
92
+ *
93
+ * Used by `EtaMutationBatcher.flush()` as a fast-path for "no
94
+ * work to do" so the batcher can return `false` without touching
95
+ * the index.
96
+ */
97
+ get empty(): boolean;
98
+ }
99
+ /**
100
+ * Fold a single `MutationRecord` into the appropriate bucket of
101
+ * `batch`.
102
+ *
103
+ * The mapping mirrors `EtaMutationObserver.handleRecord` but
104
+ * accumulates records rather than forwarding them straight to the
105
+ * index. The batcher's compaction pass later walks the accumulated
106
+ * buckets and decides what to actually apply.
107
+ *
108
+ * Mapping:
109
+ *
110
+ * - `childList` → `addedNodes` / `removedNodes` are added to the
111
+ * matching bucket.
112
+ * - `characterData` → the `Text` target is added to `text` (when
113
+ * the target really is a `Text` — the DOM guard is defensive in
114
+ * case some exotic browser delivers a different node type).
115
+ * - `attributes` → `(element, attributeName)` is added to
116
+ * `attributes` (when the target is an `Element` and the
117
+ * attribute name is present — both are required for the entry
118
+ * to be useful to the index).
119
+ *
120
+ * Unknown record types are silently dropped. The DOM only emits
121
+ * the three types above, so this branch is defensive only.
122
+ */
123
+ export declare function enqueueRecord(batch: EtaMutationBatch, record: MutationRecord): void;
@@ -0,0 +1,162 @@
1
+ // src/eta/batch.ts
2
+ /**
3
+ * Accumulator for raw `MutationRecord`s produced by the
4
+ * `EtaMutationObserver` between scheduled flushes.
5
+ *
6
+ * Records fall into four buckets:
7
+ *
8
+ * - `added` — nodes introduced into the DOM via `childList` records.
9
+ * - `removed` — nodes detached via `childList` records.
10
+ * - `text` — `Text` nodes whose data changed via `characterData`
11
+ * records.
12
+ * - `attributes` — `(Element, attributeName)` pairs that flipped via
13
+ * `attributes` records.
14
+ *
15
+ * The buckets are `Set` / `Map` collections rather than arrays so
16
+ * that repeated records for the same target naturally collapse
17
+ * before flush (e.g. five `attributes` flips on the same `title`
18
+ * only yield a single `(element, 'title')` entry by the time the
19
+ * batch is applied).
20
+ *
21
+ * **Compaction rules.** A flush through `EtaMutationBatcher` applies
22
+ * the following reductions to the bucket contents before forwarding
23
+ * the compacted set to the `EtaTemplateIndex`:
24
+ *
25
+ * 1. `add` then `remove` of the same node within one batch is a
26
+ * no-op (the node ends up detached, the index never saw it).
27
+ * 2. `remove` then `add` of the same node is forwarded as both a
28
+ * `remove` and an `add` (the move is real).
29
+ * 3. An ancestor `add` subsumes descendant `add`s — the index walks
30
+ * the subtree on `add`, so descendant adds are redundant.
31
+ * 4. An ancestor `remove` subsumes descendant `remove`s for the
32
+ * same reason.
33
+ * 5. A `text` change inside an added subtree is dropped; the index
34
+ * reads the final text when it walks the new subtree.
35
+ * 6. A `text` / `attribute` change inside a removed subtree is
36
+ * dropped; the node is leaving ownership.
37
+ * 7. Repeated text changes on the same `Text` node collapse to one
38
+ * entry (the `Set` storage already handles this).
39
+ * 8. Repeated attribute changes on the same `(Element, name)` pair
40
+ * collapse to one entry (the inner `Set<string>` storage already
41
+ * handles this).
42
+ *
43
+ * The batch itself does not enforce rules 1–6 — those live in the
44
+ * batcher's compaction pass. Rules 7–8 are enforced automatically
45
+ * by the bucket storage.
46
+ *
47
+ * **Immutability of contents.** Bucket contents are mutable in
48
+ * place for performance reasons (`Set.add` / `Map.set` are O(1)).
49
+ * Callers MUST NOT cache references to bucket internals across a
50
+ * flush — `clear()` resets the bucket to empty. The controller
51
+ * treats the batch as opaque between flushes.
52
+ */
53
+ export class EtaMutationBatch {
54
+ constructor() {
55
+ /**
56
+ * Nodes added since the last flush.
57
+ *
58
+ * Stored as a `Set<Node>` so multiple adds of the same node
59
+ * collapse automatically (rule 7-equivalent for adds).
60
+ */
61
+ this.added = new Set();
62
+ /**
63
+ * Nodes removed since the last flush.
64
+ *
65
+ * Stored as a `Set<Node>` for the same dedup reasons as `added`.
66
+ */
67
+ this.removed = new Set();
68
+ /**
69
+ * `Text` nodes whose character data changed since the last flush.
70
+ *
71
+ * `Set<Text>` collapses repeated changes on the same text node
72
+ * (rule 7).
73
+ */
74
+ this.text = new Set();
75
+ /**
76
+ * `Element` → set of changed attribute names since the last flush.
77
+ *
78
+ * The inner `Set<string>` collapses repeated changes to the same
79
+ * attribute name (rule 8).
80
+ */
81
+ this.attributes = new Map();
82
+ }
83
+ /**
84
+ * Reset every bucket to empty.
85
+ *
86
+ * Called by `EtaMutationBatcher.flush()` after the compacted
87
+ * mutations have been applied to the index. The bucket instances
88
+ * are preserved (`Set` / `Map` references stay valid) so callers
89
+ * can safely hold long-lived references to them.
90
+ */
91
+ clear() {
92
+ this.added.clear();
93
+ this.removed.clear();
94
+ this.text.clear();
95
+ this.attributes.clear();
96
+ }
97
+ /**
98
+ * `true` when every bucket is empty — i.e. there is nothing to
99
+ * forward to the index on the next flush.
100
+ *
101
+ * Used by `EtaMutationBatcher.flush()` as a fast-path for "no
102
+ * work to do" so the batcher can return `false` without touching
103
+ * the index.
104
+ */
105
+ get empty() {
106
+ return (this.added.size === 0 &&
107
+ this.removed.size === 0 &&
108
+ this.text.size === 0 &&
109
+ this.attributes.size === 0);
110
+ }
111
+ }
112
+ /**
113
+ * Fold a single `MutationRecord` into the appropriate bucket of
114
+ * `batch`.
115
+ *
116
+ * The mapping mirrors `EtaMutationObserver.handleRecord` but
117
+ * accumulates records rather than forwarding them straight to the
118
+ * index. The batcher's compaction pass later walks the accumulated
119
+ * buckets and decides what to actually apply.
120
+ *
121
+ * Mapping:
122
+ *
123
+ * - `childList` → `addedNodes` / `removedNodes` are added to the
124
+ * matching bucket.
125
+ * - `characterData` → the `Text` target is added to `text` (when
126
+ * the target really is a `Text` — the DOM guard is defensive in
127
+ * case some exotic browser delivers a different node type).
128
+ * - `attributes` → `(element, attributeName)` is added to
129
+ * `attributes` (when the target is an `Element` and the
130
+ * attribute name is present — both are required for the entry
131
+ * to be useful to the index).
132
+ *
133
+ * Unknown record types are silently dropped. The DOM only emits
134
+ * the three types above, so this branch is defensive only.
135
+ */
136
+ export function enqueueRecord(batch, record) {
137
+ if (record.type === 'childList') {
138
+ for (const node of record.addedNodes) {
139
+ batch.added.add(node);
140
+ }
141
+ for (const node of record.removedNodes) {
142
+ batch.removed.add(node);
143
+ }
144
+ return;
145
+ }
146
+ if (record.type === 'characterData' &&
147
+ record.target instanceof Text) {
148
+ batch.text.add(record.target);
149
+ return;
150
+ }
151
+ if (record.type === 'attributes' &&
152
+ record.target instanceof Element &&
153
+ record.attributeName) {
154
+ let attrs = batch.attributes.get(record.target);
155
+ if (!attrs) {
156
+ attrs = new Set();
157
+ batch.attributes.set(record.target, attrs);
158
+ }
159
+ attrs.add(record.attributeName);
160
+ }
161
+ }
162
+ //# sourceMappingURL=batch.js.map