synstate 3.4.0 → 4.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 (294) hide show
  1. package/README.md +13 -8
  2. package/dist/core/authoring.d.mts +7 -0
  3. package/dist/core/authoring.d.mts.map +1 -0
  4. package/dist/core/authoring.mjs +7 -0
  5. package/dist/core/authoring.mjs.map +1 -0
  6. package/dist/core/class/child-observable-class.d.mts +93 -0
  7. package/dist/core/class/child-observable-class.d.mts.map +1 -0
  8. package/dist/core/class/child-observable-class.mjs +248 -0
  9. package/dist/core/class/child-observable-class.mjs.map +1 -0
  10. package/dist/core/class/create-child-observable.d.mts +159 -0
  11. package/dist/core/class/create-child-observable.d.mts.map +1 -0
  12. package/dist/core/class/create-child-observable.mjs +183 -0
  13. package/dist/core/class/create-child-observable.mjs.map +1 -0
  14. package/dist/core/class/create-root-observable.d.mts +37 -0
  15. package/dist/core/class/create-root-observable.d.mts.map +1 -0
  16. package/dist/core/class/create-root-observable.mjs +52 -0
  17. package/dist/core/class/create-root-observable.mjs.map +1 -0
  18. package/dist/core/class/index.d.mts +9 -0
  19. package/dist/core/class/index.d.mts.map +1 -0
  20. package/dist/core/class/index.mjs +9 -0
  21. package/dist/core/class/index.mjs.map +1 -0
  22. package/dist/core/class/manager-observable-class.d.mts +26 -0
  23. package/dist/core/class/manager-observable-class.d.mts.map +1 -0
  24. package/dist/core/class/manager-observable-class.mjs +116 -0
  25. package/dist/core/class/manager-observable-class.mjs.map +1 -0
  26. package/dist/core/class/observable-base-class.d.mts +97 -0
  27. package/dist/core/class/observable-base-class.d.mts.map +1 -0
  28. package/dist/core/class/observable-base-class.mjs +219 -0
  29. package/dist/core/class/observable-base-class.mjs.map +1 -0
  30. package/dist/core/class/observable-node.d.mts +40 -0
  31. package/dist/core/class/observable-node.d.mts.map +1 -0
  32. package/dist/core/class/observable-node.mjs +10 -0
  33. package/dist/core/class/observable-node.mjs.map +1 -0
  34. package/dist/core/class/propagation-state.d.mts +24 -0
  35. package/dist/core/class/propagation-state.d.mts.map +1 -0
  36. package/dist/core/class/propagation-state.mjs +66 -0
  37. package/dist/core/class/propagation-state.mjs.map +1 -0
  38. package/dist/core/class/root-observable-class.d.mts +23 -0
  39. package/dist/core/class/root-observable-class.d.mts.map +1 -0
  40. package/dist/core/class/root-observable-class.mjs +58 -0
  41. package/dist/core/class/root-observable-class.mjs.map +1 -0
  42. package/dist/core/combine/combine.d.mts.map +1 -1
  43. package/dist/core/combine/combine.mjs +25 -14
  44. package/dist/core/combine/combine.mjs.map +1 -1
  45. package/dist/core/combine/merge.d.mts.map +1 -1
  46. package/dist/core/combine/merge.mjs +26 -14
  47. package/dist/core/combine/merge.mjs.map +1 -1
  48. package/dist/core/combine/zip.d.mts.map +1 -1
  49. package/dist/core/combine/zip.mjs +43 -25
  50. package/dist/core/combine/zip.mjs.map +1 -1
  51. package/dist/core/create/counter.d.mts.map +1 -1
  52. package/dist/core/create/counter.mjs +65 -44
  53. package/dist/core/create/counter.mjs.map +1 -1
  54. package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
  55. package/dist/core/create/from-abortable-promise.mjs +26 -18
  56. package/dist/core/create/from-abortable-promise.mjs.map +1 -1
  57. package/dist/core/create/from-promise.d.mts.map +1 -1
  58. package/dist/core/create/from-promise.mjs +30 -21
  59. package/dist/core/create/from-promise.mjs.map +1 -1
  60. package/dist/core/create/from-subscribable.d.mts.map +1 -1
  61. package/dist/core/create/from-subscribable.mjs +37 -24
  62. package/dist/core/create/from-subscribable.mjs.map +1 -1
  63. package/dist/core/create/just.d.mts.map +1 -1
  64. package/dist/core/create/just.mjs +4 -2
  65. package/dist/core/create/just.mjs.map +1 -1
  66. package/dist/core/create/source.d.mts.map +1 -1
  67. package/dist/core/create/source.mjs +27 -17
  68. package/dist/core/create/source.mjs.map +1 -1
  69. package/dist/core/create/timer.d.mts.map +1 -1
  70. package/dist/core/create/timer.mjs +40 -25
  71. package/dist/core/create/timer.mjs.map +1 -1
  72. package/dist/core/index.d.mts +2 -0
  73. package/dist/core/index.d.mts.map +1 -1
  74. package/dist/core/index.mjs +2 -0
  75. package/dist/core/index.mjs.map +1 -1
  76. package/dist/core/operators/audit.d.mts +3 -0
  77. package/dist/core/operators/audit.d.mts.map +1 -1
  78. package/dist/core/operators/audit.mjs +56 -28
  79. package/dist/core/operators/audit.mjs.map +1 -1
  80. package/dist/core/operators/debounce.d.mts +3 -0
  81. package/dist/core/operators/debounce.d.mts.map +1 -1
  82. package/dist/core/operators/debounce.mjs +57 -26
  83. package/dist/core/operators/debounce.mjs.map +1 -1
  84. package/dist/core/operators/filter.d.mts.map +1 -1
  85. package/dist/core/operators/filter.mjs +35 -21
  86. package/dist/core/operators/filter.mjs.map +1 -1
  87. package/dist/core/operators/index.d.mts +1 -0
  88. package/dist/core/operators/index.d.mts.map +1 -1
  89. package/dist/core/operators/index.mjs +1 -0
  90. package/dist/core/operators/index.mjs.map +1 -1
  91. package/dist/core/operators/map.d.mts.map +1 -1
  92. package/dist/core/operators/map.mjs +31 -17
  93. package/dist/core/operators/map.mjs.map +1 -1
  94. package/dist/core/operators/merge-map.d.mts +5 -0
  95. package/dist/core/operators/merge-map.d.mts.map +1 -1
  96. package/dist/core/operators/merge-map.mjs +52 -26
  97. package/dist/core/operators/merge-map.mjs.map +1 -1
  98. package/dist/core/operators/pairwise.d.mts.map +1 -1
  99. package/dist/core/operators/pairwise.mjs +31 -20
  100. package/dist/core/operators/pairwise.mjs.map +1 -1
  101. package/dist/core/operators/scan.d.mts.map +1 -1
  102. package/dist/core/operators/scan.mjs +27 -14
  103. package/dist/core/operators/scan.mjs.map +1 -1
  104. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  105. package/dist/core/operators/skip-if-no-change.mjs +33 -19
  106. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  107. package/dist/core/operators/skip-until.d.mts.map +1 -1
  108. package/dist/core/operators/skip-until.mjs +40 -26
  109. package/dist/core/operators/skip-until.mjs.map +1 -1
  110. package/dist/core/operators/skip-while.d.mts.map +1 -1
  111. package/dist/core/operators/skip-while.mjs +35 -20
  112. package/dist/core/operators/skip-while.mjs.map +1 -1
  113. package/dist/core/operators/switch-map.d.mts +5 -0
  114. package/dist/core/operators/switch-map.d.mts.map +1 -1
  115. package/dist/core/operators/switch-map.mjs +56 -25
  116. package/dist/core/operators/switch-map.mjs.map +1 -1
  117. package/dist/core/operators/take-until.d.mts.map +1 -1
  118. package/dist/core/operators/take-until.mjs +36 -29
  119. package/dist/core/operators/take-until.mjs.map +1 -1
  120. package/dist/core/operators/take-while.d.mts.map +1 -1
  121. package/dist/core/operators/take-while.mjs +36 -22
  122. package/dist/core/operators/take-while.mjs.map +1 -1
  123. package/dist/core/{predefined/operators → operators}/take.d.mts +7 -3
  124. package/dist/core/operators/take.d.mts.map +1 -0
  125. package/dist/core/operators/take.mjs +102 -0
  126. package/dist/core/operators/take.mjs.map +1 -0
  127. package/dist/core/operators/throttle.d.mts.map +1 -1
  128. package/dist/core/operators/throttle.mjs +41 -26
  129. package/dist/core/operators/throttle.mjs.map +1 -1
  130. package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
  131. package/dist/core/operators/with-buffered-from.mjs +43 -39
  132. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  133. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  134. package/dist/core/operators/with-current-value-from.mjs +36 -21
  135. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  136. package/dist/core/operators/with-initial-value.d.mts.map +1 -1
  137. package/dist/core/operators/with-initial-value.mjs +24 -12
  138. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  139. package/dist/core/predefined/operators/index.d.mts +0 -1
  140. package/dist/core/predefined/operators/index.d.mts.map +1 -1
  141. package/dist/core/predefined/operators/index.mjs +0 -1
  142. package/dist/core/predefined/operators/index.mjs.map +1 -1
  143. package/dist/core/scope/index.d.mts +2 -0
  144. package/dist/core/scope/index.d.mts.map +1 -0
  145. package/dist/core/scope/index.mjs +2 -0
  146. package/dist/core/scope/index.mjs.map +1 -0
  147. package/dist/core/scope/scope.d.mts +51 -0
  148. package/dist/core/scope/scope.d.mts.map +1 -0
  149. package/dist/core/scope/scope.mjs +194 -0
  150. package/dist/core/scope/scope.mjs.map +1 -0
  151. package/dist/core/types/id.d.mts +0 -2
  152. package/dist/core/types/id.d.mts.map +1 -1
  153. package/dist/core/types/index.d.mts +1 -0
  154. package/dist/core/types/index.d.mts.map +1 -1
  155. package/dist/core/types/index.mjs +1 -0
  156. package/dist/core/types/index.mjs.map +1 -1
  157. package/dist/core/types/observable-family.d.mts +1 -0
  158. package/dist/core/types/observable-family.d.mts.map +1 -1
  159. package/dist/core/types/observable.d.mts +40 -28
  160. package/dist/core/types/observable.d.mts.map +1 -1
  161. package/dist/core/types/observable.mjs +24 -0
  162. package/dist/core/types/observable.mjs.map +1 -1
  163. package/dist/core/types/scope.d.mts +27 -0
  164. package/dist/core/types/scope.d.mts.map +1 -0
  165. package/dist/core/types/scope.mjs +2 -0
  166. package/dist/core/types/scope.mjs.map +1 -0
  167. package/dist/core/utils/current-scope.d.mts +30 -0
  168. package/dist/core/utils/current-scope.d.mts.map +1 -0
  169. package/dist/core/utils/current-scope.mjs +26 -0
  170. package/dist/core/utils/current-scope.mjs.map +1 -0
  171. package/dist/core/utils/id-maker.d.mts +14 -3
  172. package/dist/core/utils/id-maker.d.mts.map +1 -1
  173. package/dist/core/utils/id-maker.mjs +18 -14
  174. package/dist/core/utils/id-maker.mjs.map +1 -1
  175. package/dist/core/utils/index.d.mts +2 -1
  176. package/dist/core/utils/index.d.mts.map +1 -1
  177. package/dist/core/utils/index.mjs +2 -1
  178. package/dist/core/utils/index.mjs.map +1 -1
  179. package/dist/core/utils/max-depth.d.mts +1 -0
  180. package/dist/core/utils/max-depth.d.mts.map +1 -1
  181. package/dist/core/utils/max-depth.mjs +9 -7
  182. package/dist/core/utils/max-depth.mjs.map +1 -1
  183. package/dist/core/utils/observable-brand.d.mts +13 -0
  184. package/dist/core/utils/observable-brand.d.mts.map +1 -0
  185. package/dist/core/utils/observable-brand.mjs +13 -0
  186. package/dist/core/utils/observable-brand.mjs.map +1 -0
  187. package/dist/utils/create-boolean-state.d.mts +2 -2
  188. package/dist/utils/create-reducer.d.mts +7 -7
  189. package/dist/utils/create-reducer.mjs +2 -2
  190. package/dist/utils/create-reducer.mjs.map +1 -1
  191. package/dist/utils/create-state.d.mts +2 -2
  192. package/package.json +16 -16
  193. package/src/core/authoring.mts +19 -0
  194. package/src/core/class/child-observable-class.mts +374 -0
  195. package/src/core/{base → class}/circular-dependency-comparison.test.mts +46 -38
  196. package/src/core/{base → class}/circular-dependency.test.mts +38 -2
  197. package/src/core/class/complete-propagation.test.mts +264 -0
  198. package/src/core/class/create-child-observable.mts +370 -0
  199. package/src/core/class/create-root-observable.mts +107 -0
  200. package/src/core/class/index.mts +8 -0
  201. package/src/core/class/manager-observable-class.mts +166 -0
  202. package/src/core/class/observable-base-class.mts +315 -0
  203. package/src/core/{base → class}/observable-base.test.mts +1 -1
  204. package/src/core/class/observable-node.mts +54 -0
  205. package/src/core/class/propagation-order.test.mts +92 -0
  206. package/src/core/class/propagation-state.mts +80 -0
  207. package/src/core/class/remove-completed.test.mts +369 -0
  208. package/src/core/class/root-observable-class.mts +85 -0
  209. package/src/core/{base → class}/write-during-propagation.test.mts +3 -3
  210. package/src/core/combine/combine.mts +67 -55
  211. package/src/core/combine/merge.mts +33 -23
  212. package/src/core/combine/zip.mts +95 -81
  213. package/src/core/create/counter.mts +95 -65
  214. package/src/core/create/from-abortable-promise.mts +54 -42
  215. package/src/core/create/from-promise.mts +38 -29
  216. package/src/core/create/from-subscribable.mts +62 -45
  217. package/src/core/create/from-subscribable.test.mts +8 -3
  218. package/src/core/create/just.mts +4 -5
  219. package/src/core/create/source.mts +29 -20
  220. package/src/core/create/timer.mts +51 -32
  221. package/src/core/index.mts +2 -0
  222. package/src/core/operators/audit.mts +79 -45
  223. package/src/core/operators/debounce-audit-complete.test.mts +121 -0
  224. package/src/core/operators/debounce.mts +81 -40
  225. package/src/core/operators/filter.mts +48 -31
  226. package/src/core/operators/index.mts +1 -0
  227. package/src/core/operators/inner-ownership.test.mts +280 -0
  228. package/src/core/operators/map.mts +49 -32
  229. package/src/core/operators/merge-map.mts +81 -43
  230. package/src/core/operators/pairwise.mts +40 -30
  231. package/src/core/operators/scan.mts +41 -24
  232. package/src/core/operators/skip-if-no-change.mts +45 -31
  233. package/src/core/operators/skip-until.mts +55 -41
  234. package/src/core/operators/skip-while.mts +49 -31
  235. package/src/core/operators/switch-map.mts +74 -35
  236. package/src/core/operators/take-until-skip-until-teardown.test.mts +18 -12
  237. package/src/core/operators/take-until.mts +45 -41
  238. package/src/core/operators/take-while.mts +50 -33
  239. package/src/core/operators/take.mts +138 -0
  240. package/src/core/operators/throttle.mts +55 -38
  241. package/src/core/operators/with-buffered-from.mts +42 -44
  242. package/src/core/operators/with-buffered-from.test.mts +4 -3
  243. package/src/core/operators/with-current-value-from.mts +39 -25
  244. package/src/core/operators/with-initial-value.mts +30 -21
  245. package/src/core/predefined/operators/index.mts +0 -1
  246. package/src/core/scope/index.mts +1 -0
  247. package/src/core/scope/scope.mts +260 -0
  248. package/src/core/scope/scope.test.mts +462 -0
  249. package/src/core/types/id.mts +0 -4
  250. package/src/core/types/index.mts +1 -0
  251. package/src/core/types/observable-family.mts +2 -0
  252. package/src/core/types/observable.mts +77 -42
  253. package/src/core/types/scope.mts +27 -0
  254. package/src/core/utils/current-scope.mts +61 -0
  255. package/src/core/utils/id-maker.mts +20 -30
  256. package/src/core/utils/index.mts +2 -1
  257. package/src/core/utils/max-depth.mts +12 -9
  258. package/src/core/utils/observable-brand.mts +12 -0
  259. package/src/utils/create-boolean-state.mts +2 -2
  260. package/src/utils/create-boolean-state.test.mts +18 -4
  261. package/src/utils/create-reducer.mts +9 -9
  262. package/src/utils/create-reducer.test.mts +31 -14
  263. package/src/utils/create-state.mts +2 -2
  264. package/src/utils/create-state.test.mts +12 -14
  265. package/dist/core/base/create-child-observable.d.mts +0 -72
  266. package/dist/core/base/create-child-observable.d.mts.map +0 -1
  267. package/dist/core/base/create-child-observable.mjs +0 -285
  268. package/dist/core/base/create-child-observable.mjs.map +0 -1
  269. package/dist/core/base/create-observable-base.d.mts +0 -149
  270. package/dist/core/base/create-observable-base.d.mts.map +0 -1
  271. package/dist/core/base/create-observable-base.mjs +0 -273
  272. package/dist/core/base/create-observable-base.mjs.map +0 -1
  273. package/dist/core/base/create-root-observable.d.mts +0 -46
  274. package/dist/core/base/create-root-observable.d.mts.map +0 -1
  275. package/dist/core/base/create-root-observable.mjs +0 -80
  276. package/dist/core/base/create-root-observable.mjs.map +0 -1
  277. package/dist/core/base/index.d.mts +0 -3
  278. package/dist/core/base/index.d.mts.map +0 -1
  279. package/dist/core/base/index.mjs +0 -3
  280. package/dist/core/base/index.mjs.map +0 -1
  281. package/dist/core/predefined/operators/take.d.mts.map +0 -1
  282. package/dist/core/predefined/operators/take.mjs +0 -44
  283. package/dist/core/predefined/operators/take.mjs.map +0 -1
  284. package/dist/core/utils/utils.d.mts +0 -6
  285. package/dist/core/utils/utils.d.mts.map +0 -1
  286. package/dist/core/utils/utils.mjs +0 -37
  287. package/dist/core/utils/utils.mjs.map +0 -1
  288. package/src/core/base/create-child-observable.mts +0 -485
  289. package/src/core/base/create-observable-base.mts +0 -568
  290. package/src/core/base/create-root-observable.mts +0 -147
  291. package/src/core/base/index.mts +0 -2
  292. package/src/core/predefined/operators/take.mts +0 -48
  293. package/src/core/utils/utils.mts +0 -56
  294. package/src/core/utils/utils.test.mts +0 -88
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
  - 🎯 **Simple State Management**: Easy-to-use `createState` and `createReducer` similar to React useState/useReducer for global state
25
25
  - ⚡ **High Performance**: Optimized for fast state updates and minimal re-renders
26
26
  - 🎨 **Type-Safe**: Full TypeScript support with precise type inference
27
- - 🚀 **Lightweight**: <!-- bundle-size:synstate -->~5.5 kB min+gzip<!-- /bundle-size:synstate --> with two external runtime dependencies ([ts-data-forge](https://www.npmjs.com/package/ts-data-forge) and [ts-std-forge](https://www.npmjs.com/package/ts-std-forge), and the first depends on the second)
27
+ - 🚀 **Lightweight**: <!-- bundle-size:synstate -->~6 kB min+gzip<!-- /bundle-size:synstate --> with two external runtime dependencies ([ts-data-forge](https://www.npmjs.com/package/ts-data-forge) and [ts-std-forge](https://www.npmjs.com/package/ts-std-forge), and the first depends on the second)
28
28
  - 🌐 **Framework Agnostic**: Works with React, Vue, Svelte, or vanilla JavaScript
29
29
  - 🔄 **Reactive Updates**: Automatic propagation of state changes to all subscribers
30
30
  - 📡 **Event System**: Built-in `createValueEmitter`, `createEventEmitter` for event-driven architecture
@@ -282,7 +282,7 @@ assert.deepStrictEqual(stateHistory, [0, 1, 3, 0]);
282
282
 
283
283
  ### Skipping Updates Equal to the Current State (`equals`)
284
284
 
285
- `createState`, `createReducer` and `createBooleanState` take an `equals` option. When it says the next state is the same as the current one, the update is not passed on: no subscriber, and nothing derived from the state, is told of it, and the current state is kept. Decide this where the state is held rather than downstream with `skipIfNoChange`, because an update passed on reaches whatever reads the state directly before any operator can thin it out.
285
+ `createState`, `createReducer` and `createBooleanState` take an `equals` option, `Object.is` by default. When it says the next state is the same as the current one, the update is not passed on: no subscriber, and nothing derived from the state, is told of it, and the current state is kept. Decide this where the state is held rather than downstream with `skipIfNoChange`, because an update passed on reaches whatever reads the state directly before any operator can thin it out.
286
286
 
287
287
  ```tsx
288
288
  const [filters, setFilters] = createState(
@@ -312,13 +312,13 @@ setFilters({ label: 'bug', page: 2 });
312
312
  assert.deepStrictEqual(queryHistory, ['label:bug page:1', 'label:bug page:2']);
313
313
  ```
314
314
 
315
- The same option is the third argument of `createReducer`:
315
+ The same option is the third argument of `createReducer`. Pass `equals: () => false` to pass on every update, equal or not:
316
316
 
317
317
  ```tsx
318
318
  const [count, dispatch] = createReducer(
319
319
  (s, action: Readonly<{ type: 'add'; amount: number }>) => s + action.amount,
320
320
  0,
321
- { equals: Object.is },
321
+ { equals: () => false },
322
322
  );
323
323
 
324
324
  const countHistory: number[] = [];
@@ -327,15 +327,13 @@ count.subscribe((value: number) => {
327
327
  countHistory.push(value);
328
328
  });
329
329
 
330
- dispatch({ type: 'add', amount: 0 }); // 0 again: nothing is passed on
330
+ dispatch({ type: 'add', amount: 0 }); // 0 again, passed on all the same
331
331
 
332
332
  dispatch({ type: 'add', amount: 2 });
333
333
 
334
- assert.deepStrictEqual(countHistory, [0, 2]);
334
+ assert.deepStrictEqual(countHistory, [0, 0, 2]);
335
335
  ```
336
336
 
337
- When `equals` is omitted, every update is passed on, equal or not. The next major version will make `Object.is` the default; pass `equals: () => false` to keep passing on every update.
338
-
339
337
  ### Global Counter State (React)
340
338
 
341
339
  ```tsx
@@ -709,6 +707,13 @@ For complex scenarios, SynState provides observable-based APIs:
709
707
  - `merge(observables)`: Merge multiple streams
710
708
  - `zip(observables)`: Pair values by index
711
709
 
710
+ #### Scopes (for library authors)
711
+
712
+ - `createScope(parent?)`: Create a scope; observables created synchronously inside `scope.run(body)` belong to it and are disposed by `scope.dispose()`
713
+ - `getCurrentScope()`: The scope whose `run` is executing, if any
714
+ - `onScopeDispose(cleanup)`: Call `cleanup` when the current scope is disposed
715
+ - `untracked(body)`: Call `body` with no current scope
716
+
712
717
  #### Utilities
713
718
 
714
719
  - `isChildObservable(obs)`: Check if observable is a child observable
@@ -0,0 +1,7 @@
1
+ /**
2
+ * What custom creators and operators are written with: the factories every
3
+ * built-in observable is made by (#2117). The rest of `core/base` stays
4
+ * internal.
5
+ */
6
+ export { createAsyncChildObservable, createInitializedSyncChildObservable, createRootObservable, createSyncChildObservable, type AsyncChildObservableHooks, type AsyncChildObservableTools, type ChildObservableConfig, type InitializedChildObservableConfig, type RootObservableConfig, type RootObservableTools, type SyncChildObservableHooks, type SyncChildObservableTools, } from './class/index.mjs';
7
+ //# sourceMappingURL=authoring.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring.d.mts","sourceRoot":"","sources":["../../src/core/authoring.mts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,0BAA0B,EAC1B,oCAAoC,EACpC,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,gCAAgC,EACrC,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+
2
+
3
+
4
+
5
+
6
+ export { createAsyncChildObservable, createInitializedSyncChildObservable, createRootObservable, createSyncChildObservable, } from './class/index.mjs';
7
+ //# sourceMappingURL=authoring.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring.mjs","sourceRoot":"","sources":["../../src/core/authoring.mts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,0BAA0B,EAC1B,oCAAoC,EACpC,oBAAoB,EACpB,yBAAyB,GAS1B,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { type Optional, type Some } from 'ts-data-forge';
2
+ import type { AsyncChildObservable, DropInitialValueOperator, InitializedObservable, InitializedSyncChildObservable, KeepInitialValueOperator, NonEmptyUnknownList, Observable, SyncChildObservable, WithInitialValueOperator, Wrap } from '../types/index.mjs';
3
+ import { ManagerObservableClass } from './manager-observable-class.mjs';
4
+ import { ObservableBaseClass } from './observable-base-class.mjs';
5
+ import { type ManagerNode } from './observable-node.mjs';
6
+ type ChildObservableConfig<A, P extends NonEmptyUnknownList> = Readonly<{
7
+ parents: Wrap<P>;
8
+ /**
9
+ * Defaults to one more than the deepest parent. An update reaches
10
+ * observables in ascending depth, so an observable `tryUpdate` reads with
11
+ * `getSnapshot` without being its child (`withCurrentValueFrom`'s second
12
+ * source) has to be shallower than this one too, or this one reads its value
13
+ * from before the update: pass `1 + Math.max(...)` over both then.
14
+ */
15
+ depth?: number;
16
+ initialValue: Optional<A>;
17
+ }>;
18
+ /**
19
+ * An observable derived from `parents` that emits, if at all, in the same
20
+ * update as they do (`map`, `filter`, `combine`, …).
21
+ *
22
+ * A subclass overrides `tryUpdate`, and, when it holds something to
23
+ * release, `teardown`; its constructor ends with `this.attach()`, once
24
+ * everything `tryUpdate` and `teardown` read is in place.
25
+ */
26
+ export declare class SyncChildObservableClass<A, const P extends NonEmptyUnknownList> extends ObservableBaseClass<A, 'sync child', number> implements SyncChildObservable<A, P> {
27
+ #private;
28
+ readonly parents: Wrap<P>;
29
+ readonly managers: readonly ManagerNode[];
30
+ constructor({ parents, depth, initialValue, }: ChildObservableConfig<A, P>);
31
+ /**
32
+ * Joins the current scope and registers this observable to its parents
33
+ * and the managers it is reached from. Completed parents never update
34
+ * again, so a child created under them is complete from the start
35
+ * (#2248), as is one its constructor completed; registering it would only
36
+ * leave a reference in each parent.
37
+ */
38
+ protected attach(): void;
39
+ protected detach(): void;
40
+ tryComplete(): void;
41
+ /**
42
+ * Whether this observable can emit nothing more although some parent is
43
+ * still live, asked whenever a parent completes. `true` completes it then,
44
+ * as all parents completing does (`zip` once a completed source's queue is
45
+ * empty).
46
+ */
47
+ canEmitNoMore(): boolean;
48
+ /**
49
+ * Completes this observable once the update now propagating has reached
50
+ * every descendant, so that they see the value just passed on first.
51
+ */
52
+ protected completeAfterPropagation(): void;
53
+ }
54
+ /**
55
+ * An observable derived from `parents` that may emit later, in an update of
56
+ * its own, through `startUpdate` (`debounce`, `switchMap`). It may also emit
57
+ * synchronously with `setNext`, as a sync child does. A subclass may also
58
+ * override `flush`, to pass on at completion what it still holds.
59
+ */
60
+ export declare class AsyncChildObservableClass<A, const P extends NonEmptyUnknownList> extends ManagerObservableClass<A, 'async child', number> implements AsyncChildObservable<A, P> {
61
+ #private;
62
+ readonly parents: Wrap<P>;
63
+ constructor({ parents, depth, initialValue, }: ChildObservableConfig<A, P>);
64
+ /** See `SyncChildObservableClass.attach`. */
65
+ protected attach(): void;
66
+ protected detach(): void;
67
+ tryComplete(): void;
68
+ /** See `SyncChildObservableClass.canEmitNoMore`. */
69
+ canEmitNoMore(): boolean;
70
+ /** See `SyncChildObservableClass.completeAfterPropagation`. */
71
+ protected completeAfterPropagation(): void;
72
+ }
73
+ /**
74
+ * A sync child that always holds a value: a subclass passes a `Some` as its
75
+ * `initialValue`. It differs from its base only in the types of
76
+ * `getSnapshot` and `pipe`.
77
+ */
78
+ export declare class InitializedSyncChildObservableClass<A, const P extends NonEmptyUnknownList> extends SyncChildObservableClass<A, P> implements InitializedSyncChildObservable<A, P> {
79
+ getSnapshot(): Some<A>;
80
+ pipe<B>(operator: KeepInitialValueOperator<A, B> | WithInitialValueOperator<A, B>): InitializedObservable<B>;
81
+ pipe<B>(operator: DropInitialValueOperator<A, B>): Observable<B>;
82
+ }
83
+ /**
84
+ * Whether {@link registerChild} checks for a circular dependency: everywhere
85
+ * but in a process whose `NODE_ENV` is `production`. A child's parents exist
86
+ * before it and cannot be changed afterwards, so only code that rewrites an
87
+ * observable's readonly `parents` can make a cycle, while the walk over every
88
+ * ancestor is paid on every creation. Where there is no `process` (a browser
89
+ * bundle) the check is off.
90
+ */
91
+ export declare const checksCircularDependency: boolean;
92
+ export {};
93
+ //# sourceMappingURL=child-observable-class.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-observable-class.d.mts","sourceRoot":"","sources":["../../../src/core/class/child-observable-class.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,248 @@
1
+
2
+
3
+
4
+
5
+ import { Arr, hasKey, isRecord } from 'ts-data-forge';
6
+ import { panic } from 'ts-std-forge';
7
+ import { maxDepth } from '../utils/index.mjs';
8
+ import { ManagerObservableClass } from './manager-observable-class.mjs';
9
+ import { ObservableBaseClass } from './observable-base-class.mjs';
10
+ import { toNode, } from './observable-node.mjs';
11
+ import { runAfterPropagation } from './propagation-state.mjs';
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+ export class SyncChildObservableClass extends ObservableBaseClass {
21
+ #mut_isAttached;
22
+ parents;
23
+ managers;
24
+ constructor({ parents, depth = 1 + maxDepth(parents), initialValue, }) {
25
+ super({
26
+ kind: 'sync child',
27
+ depth,
28
+ initialValue,
29
+ });
30
+ this.parents = parents;
31
+ this.managers = managersOf(parents);
32
+ this.#mut_isAttached = false;
33
+ }
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+ attach() {
42
+ this.adoptIntoCurrentScope();
43
+ if (this.isCompleted || this.parents.every((p) => p.isCompleted)) {
44
+ this.complete();
45
+ }
46
+ else {
47
+ registerChild(this, this.managers);
48
+ this.#mut_isAttached = true;
49
+ }
50
+ }
51
+ detach() {
52
+ if (!this.#mut_isAttached) {
53
+ return;
54
+ }
55
+ this.#mut_isAttached = false;
56
+ unregisterChild(this, this.managers);
57
+ }
58
+ tryComplete() {
59
+ if (shouldComplete(this)) {
60
+ this.complete();
61
+ }
62
+ }
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+ canEmitNoMore() {
71
+ return false;
72
+ }
73
+
74
+
75
+
76
+
77
+ completeAfterPropagation() {
78
+ runAfterPropagation(() => {
79
+ this.complete();
80
+ });
81
+ }
82
+ }
83
+
84
+
85
+
86
+
87
+
88
+
89
+ export class AsyncChildObservableClass extends ManagerObservableClass {
90
+ #mut_isAttached;
91
+ parents;
92
+ constructor({ parents, depth = 1 + maxDepth(parents), initialValue, }) {
93
+ super({
94
+ kind: 'async child',
95
+ depth,
96
+ initialValue,
97
+ });
98
+ this.parents = parents;
99
+ this.#mut_isAttached = false;
100
+ }
101
+
102
+ attach() {
103
+ this.adoptIntoCurrentScope();
104
+ if (this.isCompleted || this.parents.every((p) => p.isCompleted)) {
105
+ this.complete();
106
+ }
107
+ else {
108
+ registerChild(this, managersOf(this.parents));
109
+ this.#mut_isAttached = true;
110
+ }
111
+ }
112
+ detach() {
113
+ if (!this.#mut_isAttached) {
114
+ return;
115
+ }
116
+ this.#mut_isAttached = false;
117
+ unregisterChild(this, managersOf(this.parents));
118
+ }
119
+ tryComplete() {
120
+ if (shouldComplete(this)) {
121
+ this.complete();
122
+ }
123
+ }
124
+
125
+
126
+ canEmitNoMore() {
127
+ return false;
128
+ }
129
+
130
+ completeAfterPropagation() {
131
+ runAfterPropagation(() => {
132
+ this.complete();
133
+ });
134
+ }
135
+ }
136
+
137
+
138
+
139
+
140
+
141
+ export class InitializedSyncChildObservableClass extends SyncChildObservableClass {
142
+ getSnapshot() {
143
+
144
+
145
+ return super.getSnapshot();
146
+ }
147
+ pipe(operator) {
148
+ return operator(this);
149
+ }
150
+ }
151
+
152
+
153
+
154
+
155
+
156
+ const shouldComplete = (child) => !child.isCompleted &&
157
+ (child.parents.every((p) => p.isCompleted) || child.canEmitNoMore());
158
+
159
+ const registerChild = (child, managers) => {
160
+ if (checksCircularDependency) {
161
+ detectCircularDependency(child);
162
+ }
163
+ for (const p of child.parents) {
164
+ toNode(p).addChild(child);
165
+ }
166
+ for (const m of managers) {
167
+ m.addDescendant(child);
168
+ }
169
+ };
170
+
171
+
172
+
173
+
174
+
175
+
176
+ const unregisterChild = (child, managers) => {
177
+ for (const p of child.parents) {
178
+ toNode(p).deleteChild(child);
179
+ }
180
+ for (const m of managers) {
181
+ m.deleteDescendant(child);
182
+ }
183
+ };
184
+
185
+
186
+
187
+
188
+ const managersOf = (parents) => Arr.isFixedLengthArray(1, parents)
189
+ ? toNode(parents[0]).managers
190
+ : Array.from(new Set(parents.flatMap((p) => toNode(p).managers)));
191
+ const isDevelopmentProcess = () => {
192
+ const proc = Reflect.get(globalThis, 'process');
193
+ return (isRecord(proc) &&
194
+ hasKey(proc, 'env') &&
195
+ isRecord(proc.env) &&
196
+ (!hasKey(proc.env, 'NODE_ENV') || proc.env.NODE_ENV !== 'production'));
197
+ };
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+ export const checksCircularDependency = isDevelopmentProcess();
207
+
208
+
209
+
210
+
211
+
212
+
213
+ const detectCircularDependency = (child) => {
214
+ const mut_visited = new Set();
215
+ const mut_inPath = new Set([
216
+
217
+ child,
218
+ ]);
219
+ for (const parent of child.parents) {
220
+ if (hasCircularDependencyFrom(parent, mut_visited, mut_inPath)) {
221
+
222
+
223
+
224
+
225
+ panic('Circular dependency detected in observable graph: a child observable cannot be its own ancestor.');
226
+ }
227
+ }
228
+ };
229
+ const hasCircularDependencyFrom = (node, mut_visited, mut_inPath) => {
230
+ if (mut_inPath.has(node)) {
231
+ return true;
232
+ }
233
+ if (mut_visited.has(node)) {
234
+ return false;
235
+ }
236
+ mut_visited.add(node);
237
+ mut_inPath.add(node);
238
+ if (node.kind !== 'root') {
239
+ for (const parent of node.parents) {
240
+ if (hasCircularDependencyFrom(parent, mut_visited, mut_inPath)) {
241
+ return true;
242
+ }
243
+ }
244
+ }
245
+ mut_inPath.delete(node);
246
+ return false;
247
+ };
248
+ //# sourceMappingURL=child-observable-class.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-observable-class.mjs","sourceRoot":"","sources":["../../../src/core/class/child-observable-class.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ import { type Optional, type Some } from 'ts-data-forge';
2
+ import type { AsyncChildObservable, InitializedSyncChildObservable, NonEmptyUnknownList, SyncChildObservable, UpdateToken, Wrap } from '../types/index.mjs';
3
+ /**
4
+ * The tools a sync-child factory (`map`, `filter`, `zip`, …) receives: what
5
+ * only the observable being created may do to itself.
6
+ */
7
+ export type SyncChildObservableTools<A> = Readonly<{
8
+ /** Emits `nextValue` under `updateToken` and notifies subscribers. */
9
+ setNext: (nextValue: A, updateToken: UpdateToken) => void;
10
+ getSnapshot: () => Optional<A>;
11
+ /** Completes this observable (leaf teardown included). */
12
+ complete: () => void;
13
+ /**
14
+ * Completes this observable once the update now propagating has reached
15
+ * every descendant, so that they see the value just passed on first.
16
+ */
17
+ completeAfterPropagation: () => void;
18
+ /**
19
+ * Registers a teardown (clear timers, unsubscribe inner observables, …) to
20
+ * run when this observable completes or is disposed, in the order
21
+ * registered. Called from `init`, it lets the teardown close over what
22
+ * `init` creates. Registered once the observable has completed, the
23
+ * teardown runs at once.
24
+ */
25
+ onComplete: (teardown: () => void) => void;
26
+ }>;
27
+ /**
28
+ * The tools an async-child factory (`debounce`, `switchMap`, …) receives.
29
+ * Async children additionally start their own update propagation.
30
+ */
31
+ export type AsyncChildObservableTools<A> = Readonly<{
32
+ /** Emits `nextValue` and propagates the update to all descendants. */
33
+ startUpdate: (nextValue: A) => void;
34
+ }> & SyncChildObservableTools<A>;
35
+ /**
36
+ * What a sync child's `init` may return instead of `tryUpdate` alone: the
37
+ * hooks the factory calls, which read the state `init` creates.
38
+ */
39
+ export type SyncChildObservableHooks = Readonly<{
40
+ /** Called with the token of every update that reaches this observable. */
41
+ tryUpdate: (updateToken: UpdateToken) => void;
42
+ /**
43
+ * Whether this observable can emit nothing more although some parent is
44
+ * still live, asked whenever a parent completes. `true` completes it then,
45
+ * as all parents completing does (`zip` once a completed source's queue is
46
+ * empty).
47
+ */
48
+ canEmitNoMore?: () => boolean;
49
+ }>;
50
+ /**
51
+ * What an async child's `init` may return instead of `tryUpdate` alone. An
52
+ * async child can also hold a value it has not passed on yet (`debounce`'s
53
+ * pending value), which completing should not lose.
54
+ */
55
+ export type AsyncChildObservableHooks = SyncChildObservableHooks & Readonly<{
56
+ /**
57
+ * Run at the beginning of `complete()`, before the teardowns, and never
58
+ * by `dispose()`: passes on what this observable still holds through
59
+ * `startUpdate`, so that its subscribers see it before they see the
60
+ * completion. A disposed observable has no one left to tell.
61
+ */
62
+ flush?: () => void;
63
+ }>;
64
+ type ChildObservableConfigBase<P extends NonEmptyUnknownList> = Readonly<{
65
+ parents: Wrap<P>;
66
+ /**
67
+ * Defaults to one more than the deepest parent. An update reaches
68
+ * observables in ascending depth, so an observable `tryUpdate` reads with
69
+ * `getSnapshot` without being its child (`withCurrentValueFrom`'s second
70
+ * source) has to be shallower than this one too, or this one reads its value
71
+ * from before the update: pass `1 + Math.max(...)` over both then.
72
+ */
73
+ depth?: number;
74
+ }>;
75
+ export type ChildObservableConfig<A, P extends NonEmptyUnknownList> = ChildObservableConfigBase<P> & Readonly<{
76
+ initialValue: Optional<A>;
77
+ }>;
78
+ export type InitializedChildObservableConfig<A, P extends NonEmptyUnknownList> = ChildObservableConfigBase<P> & Readonly<{
79
+ initialValue: Some<A>;
80
+ }>;
81
+ /**
82
+ * Creates a sync-child observable: one derived from `parents` that emits, if
83
+ * at all, in the same update as they do. `map`, `filter`, `combine` and the
84
+ * other synchronous operators are built with it.
85
+ *
86
+ * `init` runs during construction and receives the tools. It returns
87
+ * `tryUpdate`, which is called with the token of every update that reaches
88
+ * this observable — a parent that did not emit in that update has a different
89
+ * `updateToken`; to emit, call `setNext` with the token received — or an
90
+ * object holding `tryUpdate` and the other hooks
91
+ * ({@link SyncChildObservableHooks}). State the hooks share can live inside
92
+ * `init`, next to the teardown it registers with the `onComplete` tool.
93
+ * `init` may complete the observable; it is then never registered to its
94
+ * parents.
95
+ *
96
+ * @example
97
+ *
98
+ * ```ts
99
+ * // A custom operator, written as `map((x) => x * 2)` is.
100
+ * const double = (src: Observable<number>): Observable<number> =>
101
+ * createSyncChildObservable(
102
+ * { parents: [src], initialValue: Optional.none },
103
+ * ({ setNext }) =>
104
+ * (updateToken) => {
105
+ * const sn = src.getSnapshot();
106
+ *
107
+ * if (src.updateToken !== updateToken || Optional.isNone(sn)) {
108
+ * return; // `src` did not emit in this update
109
+ * }
110
+ *
111
+ * setNext(sn.value * 2, updateToken);
112
+ * },
113
+ * );
114
+ *
115
+ * const num$ = source<number>();
116
+ *
117
+ * const pair$ = combine([num$, double(num$)]);
118
+ *
119
+ * const valueHistory: FixedLengthTuple<2, number>[] = [];
120
+ *
121
+ * pair$.subscribe((pair) => {
122
+ * valueHistory.push(pair);
123
+ * });
124
+ *
125
+ * num$.next(1);
126
+ *
127
+ * num$.next(2);
128
+ *
129
+ * // `double` joins the same update as `num$`, so `combine` sees no [2, 2].
130
+ * assert.deepStrictEqual(valueHistory, [
131
+ * [1, 2],
132
+ * [2, 4],
133
+ * ]);
134
+ * ```
135
+ */
136
+ export declare const createSyncChildObservable: <A, P extends NonEmptyUnknownList>(config: ChildObservableConfig<A, P>, init: (tools: SyncChildObservableTools<A>) => ((updateToken: UpdateToken) => void) | SyncChildObservableHooks) => SyncChildObservable<A, P>;
137
+ /**
138
+ * Creates a sync-child observable that always holds a value.
139
+ *
140
+ * Runtime-wise this is exactly `createSyncChildObservable`; only the types of
141
+ * `getSnapshot` and `pipe` are narrowed.
142
+ */
143
+ export declare const createInitializedSyncChildObservable: <A, P extends NonEmptyUnknownList>(config: InitializedChildObservableConfig<A, P>, init: (tools: SyncChildObservableTools<A>) => ((updateToken: UpdateToken) => void) | SyncChildObservableHooks) => InitializedSyncChildObservable<A, P>;
144
+ /**
145
+ * Creates an async-child observable: one derived from `parents` that may emit
146
+ * later, in an update of its own, through `startUpdate` (`debounce`,
147
+ * `switchMap`). It may also emit synchronously with `setNext`, as a sync child
148
+ * does. See {@link createSyncChildObservable} for the `init` contract; an
149
+ * async child's `init` may also return a `flush` hook
150
+ * ({@link AsyncChildObservableHooks}).
151
+ */
152
+ export declare const createAsyncChildObservable: <A, P extends NonEmptyUnknownList>(config: ChildObservableConfig<A, P>, init: (tools: AsyncChildObservableTools<A>) => ((updateToken: UpdateToken) => void) | AsyncChildObservableHooks) => AsyncChildObservable<A, P>;
153
+ /**
154
+ * An `init` for a child that never receives a parent update; reaching its
155
+ * `tryUpdate` is the invariant breaking (Sumi D-48).
156
+ */
157
+ export declare const createTryUpdateNotImplemented: () => ((updateToken: UpdateToken) => void);
158
+ export {};
159
+ //# sourceMappingURL=create-child-observable.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-child-observable.d.mts","sourceRoot":"","sources":["../../../src/core/class/create-child-observable.mts"],"names":[],"mappings":"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"}