synstate 2.0.1 → 3.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 (161) hide show
  1. package/README.md +2 -2
  2. package/dist/core/base/create-child-observable.d.mts +65 -0
  3. package/dist/core/base/create-child-observable.d.mts.map +1 -0
  4. package/dist/core/base/create-child-observable.mjs +157 -0
  5. package/dist/core/base/create-child-observable.mjs.map +1 -0
  6. package/dist/core/base/create-observable-base.d.mts +82 -0
  7. package/dist/core/base/create-observable-base.d.mts.map +1 -0
  8. package/dist/core/base/create-observable-base.mjs +160 -0
  9. package/dist/core/base/create-observable-base.mjs.map +1 -0
  10. package/dist/core/base/create-root-observable.d.mts +37 -0
  11. package/dist/core/base/create-root-observable.d.mts.map +1 -0
  12. package/dist/core/base/create-root-observable.mjs +36 -0
  13. package/dist/core/base/create-root-observable.mjs.map +1 -0
  14. package/dist/core/base/index.d.mts +3 -0
  15. package/dist/core/base/index.d.mts.map +1 -0
  16. package/dist/core/base/index.mjs +3 -0
  17. package/dist/core/{class → base}/index.mjs.map +1 -1
  18. package/dist/core/combine/combine.d.mts.map +1 -1
  19. package/dist/core/combine/combine.mjs +28 -27
  20. package/dist/core/combine/combine.mjs.map +1 -1
  21. package/dist/core/combine/merge.d.mts.map +1 -1
  22. package/dist/core/combine/merge.mjs +11 -13
  23. package/dist/core/combine/merge.mjs.map +1 -1
  24. package/dist/core/combine/zip.d.mts.map +1 -1
  25. package/dist/core/combine/zip.mjs +32 -31
  26. package/dist/core/combine/zip.mjs.map +1 -1
  27. package/dist/core/create/counter.d.mts.map +1 -1
  28. package/dist/core/create/counter.mjs +39 -50
  29. package/dist/core/create/counter.mjs.map +1 -1
  30. package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
  31. package/dist/core/create/from-abortable-promise.mjs +33 -32
  32. package/dist/core/create/from-abortable-promise.mjs.map +1 -1
  33. package/dist/core/create/from-promise.d.mts.map +1 -1
  34. package/dist/core/create/from-promise.mjs +12 -12
  35. package/dist/core/create/from-promise.mjs.map +1 -1
  36. package/dist/core/create/from-subscribable.d.mts.map +1 -1
  37. package/dist/core/create/from-subscribable.mjs +10 -10
  38. package/dist/core/create/from-subscribable.mjs.map +1 -1
  39. package/dist/core/create/just.d.mts.map +1 -1
  40. package/dist/core/create/just.mjs +5 -4
  41. package/dist/core/create/just.mjs.map +1 -1
  42. package/dist/core/create/source.mjs +11 -12
  43. package/dist/core/create/source.mjs.map +1 -1
  44. package/dist/core/create/timer.d.mts.map +1 -1
  45. package/dist/core/create/timer.mjs +32 -38
  46. package/dist/core/create/timer.mjs.map +1 -1
  47. package/dist/core/index.d.mts +0 -1
  48. package/dist/core/index.d.mts.map +1 -1
  49. package/dist/core/index.mjs +0 -3
  50. package/dist/core/index.mjs.map +1 -1
  51. package/dist/core/operators/audit.d.mts.map +1 -1
  52. package/dist/core/operators/audit.mjs +28 -36
  53. package/dist/core/operators/audit.mjs.map +1 -1
  54. package/dist/core/operators/debounce.d.mts.map +1 -1
  55. package/dist/core/operators/debounce.mjs +26 -33
  56. package/dist/core/operators/debounce.mjs.map +1 -1
  57. package/dist/core/operators/filter.d.mts.map +1 -1
  58. package/dist/core/operators/filter.mjs +23 -27
  59. package/dist/core/operators/filter.mjs.map +1 -1
  60. package/dist/core/operators/map.d.mts.map +1 -1
  61. package/dist/core/operators/map.mjs +21 -28
  62. package/dist/core/operators/map.mjs.map +1 -1
  63. package/dist/core/operators/merge-map.d.mts.map +1 -1
  64. package/dist/core/operators/merge-map.mjs +30 -39
  65. package/dist/core/operators/merge-map.mjs.map +1 -1
  66. package/dist/core/operators/pairwise.d.mts.map +1 -1
  67. package/dist/core/operators/pairwise.mjs +22 -24
  68. package/dist/core/operators/pairwise.mjs.map +1 -1
  69. package/dist/core/operators/scan.d.mts.map +1 -1
  70. package/dist/core/operators/scan.mjs +13 -18
  71. package/dist/core/operators/scan.mjs.map +1 -1
  72. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  73. package/dist/core/operators/skip-if-no-change.mjs +22 -26
  74. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  75. package/dist/core/operators/skip-until.d.mts.map +1 -1
  76. package/dist/core/operators/skip-until.mjs +23 -24
  77. package/dist/core/operators/skip-until.mjs.map +1 -1
  78. package/dist/core/operators/skip-while.d.mts.map +1 -1
  79. package/dist/core/operators/skip-while.mjs +27 -32
  80. package/dist/core/operators/skip-while.mjs.map +1 -1
  81. package/dist/core/operators/switch-map.d.mts.map +1 -1
  82. package/dist/core/operators/switch-map.mjs +28 -34
  83. package/dist/core/operators/switch-map.mjs.map +1 -1
  84. package/dist/core/operators/take-until.d.mts.map +1 -1
  85. package/dist/core/operators/take-until.mjs +22 -22
  86. package/dist/core/operators/take-until.mjs.map +1 -1
  87. package/dist/core/operators/take-while.d.mts.map +1 -1
  88. package/dist/core/operators/take-while.mjs +25 -29
  89. package/dist/core/operators/take-while.mjs.map +1 -1
  90. package/dist/core/operators/throttle.d.mts.map +1 -1
  91. package/dist/core/operators/throttle.mjs +27 -35
  92. package/dist/core/operators/throttle.mjs.map +1 -1
  93. package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
  94. package/dist/core/operators/with-buffered-from.mjs +24 -24
  95. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  96. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  97. package/dist/core/operators/with-current-value-from.mjs +20 -25
  98. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  99. package/dist/core/operators/with-initial-value.d.mts.map +1 -1
  100. package/dist/core/operators/with-initial-value.mjs +12 -15
  101. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  102. package/dist/entry-point.mjs +0 -3
  103. package/dist/entry-point.mjs.map +1 -1
  104. package/dist/index.mjs +0 -3
  105. package/dist/index.mjs.map +1 -1
  106. package/package.json +25 -18
  107. package/src/core/{class → base}/circular-dependency-comparison.test.mts +28 -18
  108. package/src/core/base/circular-dependency.test.mts +322 -0
  109. package/src/core/base/create-child-observable.mts +340 -0
  110. package/src/core/base/create-observable-base.mts +358 -0
  111. package/src/core/base/create-root-observable.mts +102 -0
  112. package/src/core/base/index.mts +2 -0
  113. package/src/core/{class/observable.class.test.mts → base/observable-base.test.mts} +25 -17
  114. package/src/core/combine/combine.mts +51 -53
  115. package/src/core/combine/merge.mts +21 -23
  116. package/src/core/combine/zip.mts +54 -58
  117. package/src/core/create/counter.mts +42 -59
  118. package/src/core/create/from-abortable-promise.mts +38 -45
  119. package/src/core/create/from-promise.mts +25 -28
  120. package/src/core/create/from-subscribable.mts +23 -27
  121. package/src/core/create/just.mts +5 -4
  122. package/src/core/create/source.mts +11 -17
  123. package/src/core/create/timer.mts +32 -47
  124. package/src/core/index.mts +0 -1
  125. package/src/core/operators/audit.mts +43 -57
  126. package/src/core/operators/debounce.mts +35 -45
  127. package/src/core/operators/filter.mts +31 -39
  128. package/src/core/operators/map.mts +32 -40
  129. package/src/core/operators/merge-map.mts +44 -59
  130. package/src/core/operators/pairwise.mts +30 -33
  131. package/src/core/operators/scan.mts +24 -35
  132. package/src/core/operators/skip-if-no-change.mts +31 -36
  133. package/src/core/operators/skip-until.mts +32 -35
  134. package/src/core/operators/skip-while.mts +31 -40
  135. package/src/core/operators/switch-map.mts +36 -48
  136. package/src/core/operators/take-until.mts +31 -29
  137. package/src/core/operators/take-while.mts +33 -41
  138. package/src/core/operators/throttle.mts +37 -51
  139. package/src/core/operators/with-buffered-from.mts +35 -30
  140. package/src/core/operators/with-current-value-from.mts +23 -28
  141. package/src/core/operators/with-initial-value.mts +21 -22
  142. package/dist/core/class/child-observable-class.d.mts +0 -39
  143. package/dist/core/class/child-observable-class.d.mts.map +0 -1
  144. package/dist/core/class/child-observable-class.mjs +0 -173
  145. package/dist/core/class/child-observable-class.mjs.map +0 -1
  146. package/dist/core/class/index.d.mts +0 -4
  147. package/dist/core/class/index.d.mts.map +0 -1
  148. package/dist/core/class/index.mjs +0 -4
  149. package/dist/core/class/observable-base-class.d.mts +0 -28
  150. package/dist/core/class/observable-base-class.d.mts.map +0 -1
  151. package/dist/core/class/observable-base-class.mjs +0 -120
  152. package/dist/core/class/observable-base-class.mjs.map +0 -1
  153. package/dist/core/class/root-observable-class.d.mts +0 -14
  154. package/dist/core/class/root-observable-class.d.mts.map +0 -1
  155. package/dist/core/class/root-observable-class.mjs +0 -43
  156. package/dist/core/class/root-observable-class.mjs.map +0 -1
  157. package/src/core/class/child-observable-class.mts +0 -286
  158. package/src/core/class/circular-dependency.test.mts +0 -251
  159. package/src/core/class/index.mts +0 -3
  160. package/src/core/class/observable-base-class.mts +0 -187
  161. package/src/core/class/root-observable-class.mts +0 -73
@@ -1,27 +1,27 @@
1
- import { Optional, Result } from 'ts-data-forge';
1
+ import { Result, Optional } from 'ts-data-forge';
2
2
  import '../utils/id-maker.mjs';
3
- import { RootObservableClass } from '../class/root-observable-class.mjs';
3
+ import { createRootObservable } from '../base/create-root-observable.mjs';
4
4
 
5
- const fromPromise = (promise) => new FromPromiseObservableClass(promise);
6
- class FromPromiseObservableClass extends RootObservableClass {
7
- constructor(promise) {
8
- super({ initialValue: Optional.none });
5
+ const fromPromise = (promise) => createRootObservable(
6
+ { initialValue: Optional.none },
7
+ ({ startUpdate, isCompleted, complete }) => {
9
8
  promise.then((value) => {
10
- if (this.isCompleted) return;
11
- this.startUpdate(Result.ok(value));
9
+ if (isCompleted()) return;
10
+ startUpdate(Result.ok(value));
12
11
  }).catch((error) => {
13
- if (this.isCompleted) return;
14
- this.startUpdate(
12
+ if (isCompleted()) return;
13
+ startUpdate(
15
14
  Result.err(
16
15
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
17
16
  error
18
17
  )
19
18
  );
20
19
  }).finally(() => {
21
- this.complete();
20
+ complete();
22
21
  });
22
+ return {};
23
23
  }
24
- }
24
+ );
25
25
 
26
26
  export { fromPromise };
27
27
  //# sourceMappingURL=from-promise.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"from-promise.mjs","sources":["../../../src/core/create/from-promise.mts"],"sourcesContent":["import { Optional, Result } from 'ts-data-forge';\nimport { RootObservableClass } from '../class/index.mjs';\nimport { type FromPromiseObservable } from '../types/index.mjs';\n\n/**\n * Creates an observable from a Promise.\n * Emits Result.ok when the promise resolves, or Result.err when it rejects.\n *\n * @template A - The type of the resolved value\n * @template E - The type of the error\n * @param promise - The promise to convert to observable\n * @returns An observable that emits the promise result\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // promise [pending...] -> resolved/rejected\n * // data$ Ok(value) or Err(error)\n * //\n * // Explanation:\n * // - fromPromise converts a Promise into an observable\n * // - Emits a Result type: Ok(value) on success, Err(error) on failure\n * // - Completes after emitting the result\n * // - Useful for integrating async operations into reactive flows\n *\n * const fetchData = async (): Promise<Readonly<{ value: number }>> =>\n * ({\n * value: 42,\n * }) as const;\n *\n * const data$ = fromPromise(fetchData());\n *\n * const valueHistory: Readonly<{ value: number }>[] = [];\n *\n * await new Promise<void>((resolve) => {\n * data$.subscribe(\n * (result) => {\n * if (Result.isOk(result)) {\n * valueHistory.push(result.value);\n * }\n * },\n * () => {\n * resolve();\n * },\n * );\n * });\n *\n * assert.deepStrictEqual(valueHistory, [{ value: 42 }]);\n * ```\n */\nexport const fromPromise = <A, E = unknown>(\n promise: Promise<A>,\n): FromPromiseObservable<A, E> => new FromPromiseObservableClass(promise);\n\nclass FromPromiseObservableClass<A, E = unknown>\n extends RootObservableClass<Result<A, E>>\n implements FromPromiseObservable<A, E>\n{\n constructor(promise: Promise<A>) {\n super({ initialValue: Optional.none });\n\n promise\n .then((value) => {\n if (this.isCompleted) return;\n\n this.startUpdate(Result.ok(value));\n })\n .catch((error: unknown) => {\n if (this.isCompleted) return;\n\n this.startUpdate(\n Result.err(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n error as E,\n ),\n );\n })\n .finally(() => {\n this.complete();\n });\n }\n}\n"],"names":[],"mappings":";;;;AAmDO,MAAM,WAAA,GAAc,CACzB,OAAA,KACgC,IAAI,2BAA2B,OAAO;AAExE,MAAM,mCACI,mBAAA,CAEV;AAAA,EACE,YAAY,OAAA,EAAqB;AAC/B,IAAA,KAAA,CAAM,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,EAAM,CAAA;AAErC,IAAA,OAAA,CACG,IAAA,CAAK,CAAC,KAAA,KAAU;AACf,MAAA,IAAI,KAAK,WAAA,EAAa;AAEtB,MAAA,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,EAAA,CAAG,KAAK,CAAC,CAAA;AAAA,IACnC,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAmB;AACzB,MAAA,IAAI,KAAK,WAAA,EAAa;AAEtB,MAAA,IAAA,CAAK,WAAA;AAAA,QACH,MAAA,CAAO,GAAA;AAAA;AAAA,UAEL;AAAA;AACF,OACF;AAAA,IACF,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,IAAA,CAAK,QAAA,EAAS;AAAA,IAChB,CAAC,CAAA;AAAA,EACL;AACF;;;;"}
1
+ {"version":3,"file":"from-promise.mjs","sources":["../../../src/core/create/from-promise.mts"],"sourcesContent":["import { Optional, Result } from 'ts-data-forge';\nimport { createRootObservable } from '../base/index.mjs';\nimport { type FromPromiseObservable } from '../types/index.mjs';\n\n/**\n * Creates an observable from a Promise.\n * Emits Result.ok when the promise resolves, or Result.err when it rejects.\n *\n * @template A - The type of the resolved value\n * @template E - The type of the error\n * @param promise - The promise to convert to observable\n * @returns An observable that emits the promise result\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // promise [pending...] -> resolved/rejected\n * // data$ Ok(value) or Err(error)\n * //\n * // Explanation:\n * // - fromPromise converts a Promise into an observable\n * // - Emits a Result type: Ok(value) on success, Err(error) on failure\n * // - Completes after emitting the result\n * // - Useful for integrating async operations into reactive flows\n *\n * const fetchData = async (): Promise<Readonly<{ value: number }>> =>\n * ({\n * value: 42,\n * }) as const;\n *\n * const data$ = fromPromise(fetchData());\n *\n * const valueHistory: Readonly<{ value: number }>[] = [];\n *\n * await new Promise<void>((resolve) => {\n * data$.subscribe(\n * (result) => {\n * if (Result.isOk(result)) {\n * valueHistory.push(result.value);\n * }\n * },\n * () => {\n * resolve();\n * },\n * );\n * });\n *\n * assert.deepStrictEqual(valueHistory, [{ value: 42 }]);\n * ```\n */\nexport const fromPromise = <A, E = unknown>(\n promise: Promise<A>,\n): FromPromiseObservable<A, E> =>\n createRootObservable<Result<A, E>>(\n { initialValue: Optional.none },\n ({ startUpdate, isCompleted, complete }) => {\n promise\n .then((value) => {\n if (isCompleted()) return;\n\n startUpdate(Result.ok(value));\n })\n .catch((error: unknown) => {\n if (isCompleted()) return;\n\n startUpdate(\n Result.err(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n error as E,\n ),\n );\n })\n .finally(() => {\n complete();\n });\n\n return {};\n },\n );\n"],"names":[],"mappings":";;;;AAmDO,MAAM,WAAA,GAAc,CACzB,OAAA,KAEA,oBAAA;AAAA,EACE,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,EAAK;AAAA,EAC9B,CAAC,EAAE,WAAA,EAAa,WAAA,EAAa,UAAS,KAAM;AAC1C,IAAA,OAAA,CACG,IAAA,CAAK,CAAC,KAAA,KAAU;AACf,MAAA,IAAI,aAAY,EAAG;AAEnB,MAAA,WAAA,CAAY,MAAA,CAAO,EAAA,CAAG,KAAK,CAAC,CAAA;AAAA,IAC9B,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAmB;AACzB,MAAA,IAAI,aAAY,EAAG;AAEnB,MAAA,WAAA;AAAA,QACE,MAAA,CAAO,GAAA;AAAA;AAAA,UAEL;AAAA;AACF,OACF;AAAA,IACF,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,QAAA,EAAS;AAAA,IACX,CAAC,CAAA;AAEH,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"from-subscribable.d.mts","sourceRoot":"","sources":["../../../src/core/create/from-subscribable.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,GAAG,OAAO,gBAC/B,YAAY,CAAC,CAAC,CAAC,KAC5B,0BAA0B,CAAC,CAAC,EAAE,CAAC,CACiB,CAAC"}
1
+ {"version":3,"file":"from-subscribable.d.mts","sourceRoot":"","sources":["../../../src/core/create/from-subscribable.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,GAAG,OAAO,gBAC/B,YAAY,CAAC,CAAC,CAAC,KAC5B,0BAA0B,CAAC,CAAC,EAAE,CAAC,CAuB/B,CAAC"}
@@ -1,17 +1,16 @@
1
- import { Optional, Result } from 'ts-data-forge';
1
+ import { Result, Optional } from 'ts-data-forge';
2
2
  import '../utils/id-maker.mjs';
3
- import { RootObservableClass } from '../class/root-observable-class.mjs';
3
+ import { createRootObservable } from '../base/create-root-observable.mjs';
4
4
 
5
- const fromSubscribable = (subscribable) => new FromSubscribableObservableClass(subscribable);
6
- class FromSubscribableObservableClass extends RootObservableClass {
7
- constructor(subscribable) {
8
- super({ initialValue: Optional.none });
5
+ const fromSubscribable = (subscribable) => createRootObservable(
6
+ { initialValue: Optional.none },
7
+ ({ startUpdate, complete }) => {
9
8
  subscribable.subscribe(
10
9
  (nextValue) => {
11
- this.startUpdate(Result.ok(nextValue));
10
+ startUpdate(Result.ok(nextValue));
12
11
  },
13
12
  (error) => {
14
- this.startUpdate(
13
+ startUpdate(
15
14
  Result.err(
16
15
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
17
16
  error
@@ -19,11 +18,12 @@ class FromSubscribableObservableClass extends RootObservableClass {
19
18
  );
20
19
  },
21
20
  () => {
22
- this.complete();
21
+ complete();
23
22
  }
24
23
  );
24
+ return {};
25
25
  }
26
- }
26
+ );
27
27
 
28
28
  export { fromSubscribable };
29
29
  //# sourceMappingURL=from-subscribable.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"from-subscribable.mjs","sources":["../../../src/core/create/from-subscribable.mts"],"sourcesContent":["import { Optional, Result } from 'ts-data-forge';\nimport { RootObservableClass } from '../class/index.mjs';\nimport {\n type FromSubscribableObservable,\n type Subscribable,\n} from '../types/index.mjs';\n\n/**\n * Converts any subscribable object into a SynState Observable.\n * Works with objects that have a subscribe(onNext, onError, onComplete) method.\n *\n * @template A - The type of values from the subscribable\n * @template E - The type of errors from the subscribable\n * @param subscribable - An object with a subscribe method\n * @returns An observable that wraps values in Result type\n *\n * @example\n * ```ts\n * // Explanation:\n * // - fromSubscribable converts any subscribable object into a SynState Observable\n * // - Works with objects that have a subscribe(onNext, onError, onComplete) method\n * // - Wraps values in Result type for error handling\n * // - Useful for integrating with other reactive libraries or custom subscribables\n *\n * // Example: Converting a custom subscribable\n * const customSubscribable = {\n * subscribe: (\n * onNext: (value: number) => void,\n * _onError?: (error: unknown) => void,\n * onComplete?: () => void,\n * ) => {\n * setTimeout(() => {\n * onNext(1);\n *\n * onNext(2);\n *\n * onNext(3);\n *\n * onComplete?.();\n * }, 0);\n *\n * return { unsubscribe: () => {} };\n * },\n * } as const;\n *\n * const observable$ = fromSubscribable<number>(customSubscribable);\n *\n * const valueHistory: number[] = [];\n *\n * await new Promise<void>((resolve) => {\n * observable$.subscribe(\n * (result) => {\n * if (Result.isOk(result)) {\n * valueHistory.push(result.value);\n * }\n * },\n * () => {\n * resolve();\n * },\n * );\n * });\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3]);\n * ```\n */\nexport const fromSubscribable = <A, E = unknown>(\n subscribable: Subscribable<A>,\n): FromSubscribableObservable<A, E> =>\n new FromSubscribableObservableClass(subscribable);\n\nclass FromSubscribableObservableClass<A, E = unknown>\n extends RootObservableClass<Result<A, E>>\n implements FromSubscribableObservable<A, E>\n{\n constructor(subscribable: Subscribable<A>) {\n super({ initialValue: Optional.none });\n\n subscribable.subscribe(\n (nextValue) => {\n this.startUpdate(Result.ok(nextValue));\n },\n (error?: unknown) => {\n this.startUpdate(\n Result.err(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n error as E,\n ),\n );\n },\n () => {\n this.complete();\n },\n );\n }\n}\n"],"names":[],"mappings":";;;;AAiEO,MAAM,gBAAA,GAAmB,CAC9B,YAAA,KAEA,IAAI,gCAAgC,YAAY;AAElD,MAAM,wCACI,mBAAA,CAEV;AAAA,EACE,YAAY,YAAA,EAA+B;AACzC,IAAA,KAAA,CAAM,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,EAAM,CAAA;AAErC,IAAA,YAAA,CAAa,SAAA;AAAA,MACX,CAAC,SAAA,KAAc;AACb,QAAA,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,EAAA,CAAG,SAAS,CAAC,CAAA;AAAA,MACvC,CAAA;AAAA,MACA,CAAC,KAAA,KAAoB;AACnB,QAAA,IAAA,CAAK,WAAA;AAAA,UACH,MAAA,CAAO,GAAA;AAAA;AAAA,YAEL;AAAA;AACF,SACF;AAAA,MACF,CAAA;AAAA,MACA,MAAM;AACJ,QAAA,IAAA,CAAK,QAAA,EAAS;AAAA,MAChB;AAAA,KACF;AAAA,EACF;AACF;;;;"}
1
+ {"version":3,"file":"from-subscribable.mjs","sources":["../../../src/core/create/from-subscribable.mts"],"sourcesContent":["import { Optional, Result } from 'ts-data-forge';\nimport { createRootObservable } from '../base/index.mjs';\nimport {\n type FromSubscribableObservable,\n type Subscribable,\n} from '../types/index.mjs';\n\n/**\n * Converts any subscribable object into a SynState Observable.\n * Works with objects that have a subscribe(onNext, onError, onComplete) method.\n *\n * @template A - The type of values from the subscribable\n * @template E - The type of errors from the subscribable\n * @param subscribable - An object with a subscribe method\n * @returns An observable that wraps values in Result type\n *\n * @example\n * ```ts\n * // Explanation:\n * // - fromSubscribable converts any subscribable object into a SynState Observable\n * // - Works with objects that have a subscribe(onNext, onError, onComplete) method\n * // - Wraps values in Result type for error handling\n * // - Useful for integrating with other reactive libraries or custom subscribables\n *\n * // Example: Converting a custom subscribable\n * const customSubscribable = {\n * subscribe: (\n * onNext: (value: number) => void,\n * _onError?: (error: unknown) => void,\n * onComplete?: () => void,\n * ) => {\n * setTimeout(() => {\n * onNext(1);\n *\n * onNext(2);\n *\n * onNext(3);\n *\n * onComplete?.();\n * }, 0);\n *\n * return { unsubscribe: () => {} };\n * },\n * } as const;\n *\n * const observable$ = fromSubscribable<number>(customSubscribable);\n *\n * const valueHistory: number[] = [];\n *\n * await new Promise<void>((resolve) => {\n * observable$.subscribe(\n * (result) => {\n * if (Result.isOk(result)) {\n * valueHistory.push(result.value);\n * }\n * },\n * () => {\n * resolve();\n * },\n * );\n * });\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3]);\n * ```\n */\nexport const fromSubscribable = <A, E = unknown>(\n subscribable: Subscribable<A>,\n): FromSubscribableObservable<A, E> =>\n createRootObservable<Result<A, E>>(\n { initialValue: Optional.none },\n ({ startUpdate, complete }) => {\n subscribable.subscribe(\n (nextValue) => {\n startUpdate(Result.ok(nextValue));\n },\n (error?: unknown) => {\n startUpdate(\n Result.err(\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n error as E,\n ),\n );\n },\n () => {\n complete();\n },\n );\n\n return {};\n },\n );\n"],"names":[],"mappings":";;;;AAiEO,MAAM,gBAAA,GAAmB,CAC9B,YAAA,KAEA,oBAAA;AAAA,EACE,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,EAAK;AAAA,EAC9B,CAAC,EAAE,WAAA,EAAa,QAAA,EAAS,KAAM;AAC7B,IAAA,YAAA,CAAa,SAAA;AAAA,MACX,CAAC,SAAA,KAAc;AACb,QAAA,WAAA,CAAY,MAAA,CAAO,EAAA,CAAG,SAAS,CAAC,CAAA;AAAA,MAClC,CAAA;AAAA,MACA,CAAC,KAAA,KAAoB;AACnB,QAAA,WAAA;AAAA,UACE,MAAA,CAAO,GAAA;AAAA;AAAA,YAEL;AAAA;AACF,SACF;AAAA,MACF,CAAA;AAAA,MACA,MAAM;AACJ,QAAA,QAAA,EAAS;AAAA,MACX;AAAA,KACF;AAEA,IAAA,OAAO,EAAC;AAAA,EACV;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"just.d.mts","sourceRoot":"","sources":["../../../src/core/create/just.mts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,CAAC,SAAU,CAAC,KAAG,yBAAyB,CAAC,CAAC,CASpE,CAAC"}
1
+ {"version":3,"file":"just.d.mts","sourceRoot":"","sources":["../../../src/core/create/just.mts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,IAAI,GAAI,KAAK,CAAC,CAAC,SAAU,CAAC,KAAG,yBAAyB,CAAC,CAAC,CAUpE,CAAC"}
@@ -1,11 +1,12 @@
1
1
  import { Optional } from 'ts-data-forge';
2
2
  import '../utils/id-maker.mjs';
3
- import { RootObservableClass } from '../class/root-observable-class.mjs';
3
+ import { createRootObservable } from '../base/create-root-observable.mjs';
4
4
 
5
5
  const just = (value) => {
6
- const obs = new RootObservableClass({
7
- initialValue: Optional.some(value)
8
- });
6
+ const obs = createRootObservable(
7
+ { initialValue: Optional.some(value) },
8
+ () => ({})
9
+ );
9
10
  obs.complete();
10
11
  return obs;
11
12
  };
@@ -1 +1 @@
1
- {"version":3,"file":"just.mjs","sources":["../../../src/core/create/just.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { RootObservableClass } from '../class/index.mjs';\nimport { type InitializedRootObservable } from '../types/index.mjs';\n\n/**\n * Creates an Observable that holds a single static value and immediately\n * completes. Useful inside `switchMap` to emit a fallback value when no\n * asynchronous work is needed.\n *\n * @template A - The type of the value\n * @param value - The value to emit\n * @returns An initialized Observable that holds the value and is already completed\n *\n * @example\n * ```ts\n * const greeting$ = just('hello');\n *\n * const valueHistory: string[] = [];\n *\n * greeting$.subscribe(\n * (value) => {\n * valueHistory.push(value);\n * },\n * () => {\n * // onComplete — called immediately since just() completes right away\n * },\n * );\n *\n * assert.deepStrictEqual(valueHistory, ['hello']);\n *\n * assert.strictEqual(greeting$.isCompleted, true);\n * ```\n */\nexport const just = <const A,>(value: A): InitializedRootObservable<A> => {\n const obs = new RootObservableClass<A>({\n initialValue: Optional.some(value),\n });\n\n obs.complete();\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return obs as InitializedRootObservable<A>;\n};\n"],"names":[],"mappings":";;;;AAiCO,MAAM,IAAA,GAAO,CAAW,KAAA,KAA2C;AACxE,EAAA,MAAM,GAAA,GAAM,IAAI,mBAAA,CAAuB;AAAA,IACrC,YAAA,EAAc,QAAA,CAAS,IAAA,CAAK,KAAK;AAAA,GAClC,CAAA;AAED,EAAA,GAAA,CAAI,QAAA,EAAS;AAGb,EAAA,OAAO,GAAA;AACT;;;;"}
1
+ {"version":3,"file":"just.mjs","sources":["../../../src/core/create/just.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createRootObservable } from '../base/index.mjs';\nimport { type InitializedRootObservable } from '../types/index.mjs';\n\n/**\n * Creates an Observable that holds a single static value and immediately\n * completes. Useful inside `switchMap` to emit a fallback value when no\n * asynchronous work is needed.\n *\n * @template A - The type of the value\n * @param value - The value to emit\n * @returns An initialized Observable that holds the value and is already completed\n *\n * @example\n * ```ts\n * const greeting$ = just('hello');\n *\n * const valueHistory: string[] = [];\n *\n * greeting$.subscribe(\n * (value) => {\n * valueHistory.push(value);\n * },\n * () => {\n * // onComplete — called immediately since just() completes right away\n * },\n * );\n *\n * assert.deepStrictEqual(valueHistory, ['hello']);\n *\n * assert.strictEqual(greeting$.isCompleted, true);\n * ```\n */\nexport const just = <const A,>(value: A): InitializedRootObservable<A> => {\n const obs = createRootObservable<A>(\n { initialValue: Optional.some(value) },\n () => ({}),\n );\n\n obs.complete();\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return obs as InitializedRootObservable<A>;\n};\n"],"names":[],"mappings":";;;;AAiCO,MAAM,IAAA,GAAO,CAAW,KAAA,KAA2C;AACxE,EAAA,MAAM,GAAA,GAAM,oBAAA;AAAA,IACV,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA,EAAE;AAAA,IACrC,OAAO,EAAC;AAAA,GACV;AAEA,EAAA,GAAA,CAAI,QAAA,EAAS;AAGb,EAAA,OAAO,GAAA;AACT;;;;"}
@@ -1,20 +1,19 @@
1
1
  import { Optional, Arr } from 'ts-data-forge';
2
2
  import '../utils/id-maker.mjs';
3
- import { RootObservableClass } from '../class/root-observable-class.mjs';
3
+ import { createRootObservable } from '../base/create-root-observable.mjs';
4
4
 
5
5
  function source(...args) {
6
- return new SourceObservableClass(...args);
7
- }
8
- class SourceObservableClass extends RootObservableClass {
9
- constructor(...args) {
10
- super({
6
+ return createRootObservable(
7
+ {
11
8
  initialValue: Arr.isNonEmpty(args) ? Optional.some(args[0]) : Optional.none
12
- });
13
- }
14
- next(nextValue) {
15
- if (this.isCompleted) return;
16
- this.startUpdate(nextValue);
17
- }
9
+ },
10
+ ({ startUpdate, isCompleted }) => ({
11
+ next: (nextValue) => {
12
+ if (isCompleted()) return;
13
+ startUpdate(nextValue);
14
+ }
15
+ })
16
+ );
18
17
  }
19
18
 
20
19
  export { source };
@@ -1 +1 @@
1
- {"version":3,"file":"source.mjs","sources":["../../../src/core/create/source.mts"],"sourcesContent":["import { Arr, Optional } from 'ts-data-forge';\nimport { RootObservableClass } from '../class/index.mjs';\nimport {\n type InitializedSourceObservable,\n type SourceObservable,\n} from '../types/index.mjs';\n\n/**\n * Creates a new Observable source that can manually emit values.\n * This is the primary way to create root observables that start reactive chains.\n *\n * @template A - The type of values emitted by the source\n * @returns A SourceObservable that can emit values via `.next()` method\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // count$ 1 2 3 ...\n * //\n * // Explanation:\n * // - source creates a new observable that you can manually emit values to\n * // - Use .next() to emit values\n * // - Foundation for building custom observables\n *\n * const count$ = source<number>();\n *\n * const valueHistory: number[] = [];\n *\n * count$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * count$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * count$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n *\n * count$.next(3); // logs: 3\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3]);\n * ```\n */\nexport function source<const A>(\n initialValue: A,\n): InitializedSourceObservable<A>;\n\nexport function source<const A>(): SourceObservable<A>;\n\nexport function source<const A>(...args: readonly A[]): SourceObservable<A> {\n return new SourceObservableClass<A>(...args);\n}\n\nclass SourceObservableClass<A>\n extends RootObservableClass<A>\n implements SourceObservable<A>\n{\n constructor(...args: readonly A[]) {\n super({\n initialValue: Arr.isNonEmpty(args)\n ? Optional.some(args[0])\n : Optional.none,\n });\n }\n\n next(nextValue: A): void {\n if (this.isCompleted) return;\n\n this.startUpdate(nextValue);\n }\n}\n"],"names":[],"mappings":";;;;AAoDO,SAAS,UAAmB,IAAA,EAAyC;AAC1E,EAAA,OAAO,IAAI,qBAAA,CAAyB,GAAG,IAAI,CAAA;AAC7C;AAEA,MAAM,8BACI,mBAAA,CAEV;AAAA,EACE,eAAe,IAAA,EAAoB;AACjC,IAAA,KAAA,CAAM;AAAA,MACJ,YAAA,EAAc,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,GAC7B,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA,GACrB,QAAA,CAAS;AAAA,KACd,CAAA;AAAA,EACH;AAAA,EAEA,KAAK,SAAA,EAAoB;AACvB,IAAA,IAAI,KAAK,WAAA,EAAa;AAEtB,IAAA,IAAA,CAAK,YAAY,SAAS,CAAA;AAAA,EAC5B;AACF;;;;"}
1
+ {"version":3,"file":"source.mjs","sources":["../../../src/core/create/source.mts"],"sourcesContent":["import { Arr, Optional } from 'ts-data-forge';\nimport { createRootObservable } from '../base/index.mjs';\nimport {\n type InitializedSourceObservable,\n type SourceObservable,\n} from '../types/index.mjs';\n\n/**\n * Creates a new Observable source that can manually emit values.\n * This is the primary way to create root observables that start reactive chains.\n *\n * @template A - The type of values emitted by the source\n * @returns A SourceObservable that can emit values via `.next()` method\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // count$ 1 2 3 ...\n * //\n * // Explanation:\n * // - source creates a new observable that you can manually emit values to\n * // - Use .next() to emit values\n * // - Foundation for building custom observables\n *\n * const count$ = source<number>();\n *\n * const valueHistory: number[] = [];\n *\n * count$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * count$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * count$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n *\n * count$.next(3); // logs: 3\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 3]);\n * ```\n */\nexport function source<const A>(\n initialValue: A,\n): InitializedSourceObservable<A>;\n\nexport function source<const A>(): SourceObservable<A>;\n\nexport function source<const A>(...args: readonly A[]): SourceObservable<A> {\n return createRootObservable<A, Readonly<{ next: (nextValue: A) => void }>>(\n {\n initialValue: Arr.isNonEmpty(args)\n ? Optional.some(args[0])\n : Optional.none,\n },\n ({ startUpdate, isCompleted }) => ({\n next: (nextValue: A) => {\n if (isCompleted()) return;\n\n startUpdate(nextValue);\n },\n }),\n );\n}\n"],"names":[],"mappings":";;;;AAoDO,SAAS,UAAmB,IAAA,EAAyC;AAC1E,EAAA,OAAO,oBAAA;AAAA,IACL;AAAA,MACE,YAAA,EAAc,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,GAC7B,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA,GACrB,QAAA,CAAS;AAAA,KACf;AAAA,IACA,CAAC,EAAE,WAAA,EAAa,WAAA,EAAY,MAAO;AAAA,MACjC,IAAA,EAAM,CAAC,SAAA,KAAiB;AACtB,QAAA,IAAI,aAAY,EAAG;AAEnB,QAAA,WAAA,CAAY,SAAS,CAAA;AAAA,MACvB;AAAA,KACF;AAAA,GACF;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"timer.d.mts","sourceRoot":"","sources":["../../../src/core/create/timer.mts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,KAAK,iBACF,MAAM,YACV,QAAQ,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC,KACD,eACsE,CAAC"}
1
+ {"version":3,"file":"timer.d.mts","sourceRoot":"","sources":["../../../src/core/create/timer.mts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,KAAK,iBACF,MAAM,YACV,QAAQ,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC,KACD,eA2CF,CAAC"}
@@ -1,46 +1,40 @@
1
1
  import { Optional } from 'ts-data-forge';
2
2
  import '../utils/id-maker.mjs';
3
- import { RootObservableClass } from '../class/root-observable-class.mjs';
3
+ import { createRootObservable } from '../base/create-root-observable.mjs';
4
4
 
5
- const timer = (milliSeconds, options) => new TimerObservableClass(milliSeconds, options?.startManually ?? false);
6
- class TimerObservableClass extends RootObservableClass {
7
- #milliSeconds;
8
- #mut_timerId;
9
- #mut_isStarted;
10
- constructor(milliSeconds, startManually) {
11
- super({ initialValue: Optional.none });
12
- this.#milliSeconds = milliSeconds;
13
- this.#mut_timerId = void 0;
14
- this.#mut_isStarted = false;
15
- if (!startManually) {
16
- this.start();
5
+ const timer = (milliSeconds, options) => {
6
+ let mut_timerId = void 0;
7
+ let mut_isStarted = false;
8
+ const resetTimer = () => {
9
+ if (mut_timerId !== void 0) {
10
+ clearTimeout(mut_timerId);
17
11
  }
12
+ };
13
+ const observable = createRootObservable(
14
+ { initialValue: Optional.none, onComplete: resetTimer },
15
+ ({ startUpdate, isCompleted, complete }) => ({
16
+ start: () => {
17
+ if (mut_isStarted) {
18
+ console.warn("cannot start twice");
19
+ return;
20
+ }
21
+ mut_isStarted = true;
22
+ if (isCompleted()) {
23
+ console.warn("cannot restart stopped TimerObservable");
24
+ return;
25
+ }
26
+ mut_timerId = setTimeout(() => {
27
+ startUpdate(0);
28
+ complete();
29
+ }, milliSeconds);
30
+ }
31
+ })
32
+ );
33
+ if (!(options?.startManually ?? false)) {
34
+ observable.start();
18
35
  }
19
- #resetTimer() {
20
- if (this.#mut_timerId !== void 0) {
21
- clearTimeout(this.#mut_timerId);
22
- }
23
- }
24
- start() {
25
- if (this.#mut_isStarted) {
26
- console.warn("cannot start twice");
27
- return;
28
- }
29
- this.#mut_isStarted = true;
30
- if (this.isCompleted) {
31
- console.warn("cannot restart stopped TimerObservable");
32
- return;
33
- }
34
- this.#mut_timerId = setTimeout(() => {
35
- this.startUpdate(0);
36
- this.complete();
37
- }, this.#milliSeconds);
38
- }
39
- complete() {
40
- this.#resetTimer();
41
- super.complete();
42
- }
43
- }
36
+ return observable;
37
+ };
44
38
 
45
39
  export { timer };
46
40
  //# sourceMappingURL=timer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"timer.mjs","sources":["../../../src/core/create/timer.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { RootObservableClass } from '../class/index.mjs';\nimport { type TimerId, type TimerObservable } from '../types/index.mjs';\n\n/**\n * Creates an observable that emits 0 after a specified delay and then completes.\n *\n * @param milliSeconds - The delay in milliseconds before emission\n * @param startManually - If true, waits for manual start (default: false)\n * @returns An observable that emits after delay\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // Time(ms) 0 ... 1000\n * // delayed$ X (emits and completes)\n * //\n * // Explanation:\n * // - timer emits once after the specified delay, then completes\n * // - Useful for delayed actions or timeouts\n *\n * const delayed$ = timer(100);\n *\n * const valueHistory: number[] = [];\n *\n * await new Promise<void>((resolve) => {\n * delayed$.subscribe(\n * () => {\n * valueHistory.push(1);\n * },\n * () => {\n * resolve();\n * },\n * );\n * });\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n * ```\n */\nexport const timer = (\n milliSeconds: number,\n options?: Readonly<{\n startManually?: boolean;\n }>,\n): TimerObservable =>\n new TimerObservableClass(milliSeconds, options?.startManually ?? false);\n\nclass TimerObservableClass\n extends RootObservableClass<0>\n implements TimerObservable\n{\n readonly #milliSeconds: number;\n #mut_timerId: TimerId | undefined;\n #mut_isStarted: boolean;\n\n constructor(milliSeconds: number, startManually: boolean) {\n super({ initialValue: Optional.none });\n\n this.#milliSeconds = milliSeconds;\n\n this.#mut_timerId = undefined;\n\n this.#mut_isStarted = false;\n\n if (!startManually) {\n this.start();\n }\n }\n\n #resetTimer(): void {\n if (this.#mut_timerId !== undefined) {\n clearTimeout(this.#mut_timerId);\n }\n }\n\n start(): void {\n if (this.#mut_isStarted) {\n console.warn('cannot start twice');\n\n return;\n }\n\n this.#mut_isStarted = true;\n\n if (this.isCompleted) {\n console.warn('cannot restart stopped TimerObservable');\n\n return;\n }\n\n this.#mut_timerId = setTimeout(() => {\n this.startUpdate(0);\n\n this.complete();\n }, this.#milliSeconds);\n }\n\n override complete(): void {\n this.#resetTimer();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AAwCO,MAAM,KAAA,GAAQ,CACnB,YAAA,EACA,OAAA,KAIA,IAAI,oBAAA,CAAqB,YAAA,EAAc,OAAA,EAAS,aAAA,IAAiB,KAAK;AAExE,MAAM,6BACI,mBAAA,CAEV;AAAA,EACW,aAAA;AAAA,EACT,YAAA;AAAA,EACA,cAAA;AAAA,EAEA,WAAA,CAAY,cAAsB,aAAA,EAAwB;AACxD,IAAA,KAAA,CAAM,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,EAAM,CAAA;AAErC,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAErB,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAEpB,IAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AAEtB,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,IAAA,CAAK,KAAA,EAAM;AAAA,IACb;AAAA,EACF;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,YAAA,CAAa,KAAK,YAAY,CAAA;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,OAAA,CAAQ,KAAK,oBAAoB,CAAA;AAEjC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAEtB,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,OAAA,CAAQ,KAAK,wCAAwC,CAAA;AAErD,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,MAAM;AACnC,MAAA,IAAA,CAAK,YAAY,CAAC,CAAA;AAElB,MAAA,IAAA,CAAK,QAAA,EAAS;AAAA,IAChB,CAAA,EAAG,KAAK,aAAa,CAAA;AAAA,EACvB;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,WAAA,EAAY;AAEjB,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
1
+ {"version":3,"file":"timer.mjs","sources":["../../../src/core/create/timer.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createRootObservable } from '../base/index.mjs';\nimport { type TimerId, type TimerObservable } from '../types/index.mjs';\n\n/**\n * Creates an observable that emits 0 after a specified delay and then completes.\n *\n * @param milliSeconds - The delay in milliseconds before emission\n * @param startManually - If true, waits for manual start (default: false)\n * @returns An observable that emits after delay\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // Time(ms) 0 ... 1000\n * // delayed$ X (emits and completes)\n * //\n * // Explanation:\n * // - timer emits once after the specified delay, then completes\n * // - Useful for delayed actions or timeouts\n *\n * const delayed$ = timer(100);\n *\n * const valueHistory: number[] = [];\n *\n * await new Promise<void>((resolve) => {\n * delayed$.subscribe(\n * () => {\n * valueHistory.push(1);\n * },\n * () => {\n * resolve();\n * },\n * );\n * });\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n * ```\n */\nexport const timer = (\n milliSeconds: number,\n options?: Readonly<{\n startManually?: boolean;\n }>,\n): TimerObservable => {\n let mut_timerId: TimerId | undefined = undefined;\n\n let mut_isStarted = false;\n\n const resetTimer = (): void => {\n if (mut_timerId !== undefined) {\n clearTimeout(mut_timerId);\n }\n };\n\n const observable = createRootObservable<0, Readonly<{ start: () => void }>>(\n { initialValue: Optional.none, onComplete: resetTimer },\n ({ startUpdate, isCompleted, complete }) => ({\n start: () => {\n if (mut_isStarted) {\n console.warn('cannot start twice');\n\n return;\n }\n\n mut_isStarted = true;\n\n if (isCompleted()) {\n console.warn('cannot restart stopped TimerObservable');\n\n return;\n }\n\n mut_timerId = setTimeout(() => {\n startUpdate(0);\n\n complete();\n }, milliSeconds);\n },\n }),\n );\n\n if (!(options?.startManually ?? false)) {\n observable.start();\n }\n\n return observable;\n};\n"],"names":[],"mappings":";;;;AAwCO,MAAM,KAAA,GAAQ,CACnB,YAAA,EACA,OAAA,KAGoB;AACpB,EAAA,IAAI,WAAA,GAAmC,MAAA;AAEvC,EAAA,IAAI,aAAA,GAAgB,KAAA;AAEpB,EAAA,MAAM,aAAa,MAAY;AAC7B,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,YAAA,CAAa,WAAW,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAA,GAAa,oBAAA;AAAA,IACjB,EAAE,YAAA,EAAc,QAAA,CAAS,IAAA,EAAM,YAAY,UAAA,EAAW;AAAA,IACtD,CAAC,EAAE,WAAA,EAAa,WAAA,EAAa,UAAS,MAAO;AAAA,MAC3C,OAAO,MAAM;AACX,QAAA,IAAI,aAAA,EAAe;AACjB,UAAA,OAAA,CAAQ,KAAK,oBAAoB,CAAA;AAEjC,UAAA;AAAA,QACF;AAEA,QAAA,aAAA,GAAgB,IAAA;AAEhB,QAAA,IAAI,aAAY,EAAG;AACjB,UAAA,OAAA,CAAQ,KAAK,wCAAwC,CAAA;AAErD,UAAA;AAAA,QACF;AAEA,QAAA,WAAA,GAAc,WAAW,MAAM;AAC7B,UAAA,WAAA,CAAY,CAAC,CAAA;AAEb,UAAA,QAAA,EAAS;AAAA,QACX,GAAG,YAAY,CAAA;AAAA,MACjB;AAAA,KACF;AAAA,GACF;AAEA,EAAA,IAAI,EAAE,OAAA,EAAS,aAAA,IAAiB,KAAA,CAAA,EAAQ;AACtC,IAAA,UAAA,CAAW,KAAA,EAAM;AAAA,EACnB;AAEA,EAAA,OAAO,UAAA;AACT;;;;"}
@@ -1,4 +1,3 @@
1
- export * from './class/index.mjs';
2
1
  export * from './combine/index.mjs';
3
2
  export * from './create/index.mjs';
4
3
  export * from './operators/index.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/core/index.mts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/core/index.mts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC"}
@@ -1,6 +1,3 @@
1
- export { AsyncChildObservableClass, InitializedSyncChildObservableClass, SyncChildObservableClass } from './class/child-observable-class.mjs';
2
- export { ObservableBaseClass } from './class/observable-base-class.mjs';
3
- export { RootObservableClass } from './class/root-observable-class.mjs';
4
1
  export { combine, combineLatest } from './combine/combine.mjs';
5
2
  export { merge } from './combine/merge.mjs';
6
3
  export { zip } from './combine/zip.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.mts","sourceRoot":"","sources":["../../../src/core/operators/audit.mts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6FG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,gBACP,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
1
+ {"version":3,"file":"audit.d.mts","sourceRoot":"","sources":["../../../src/core/operators/audit.mts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAG9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6FG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,gBACP,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
@@ -1,50 +1,42 @@
1
1
  import { Optional } from 'ts-data-forge';
2
- import { AsyncChildObservableClass } from '../class/child-observable-class.mjs';
2
+ import { createAsyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
5
  const audit = (milliSeconds) => (
6
6
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
7
- ((parentObservable) => new AuditObservableClass(
7
+ ((parentObservable) => createAuditObservable(
8
8
  parentObservable,
9
9
  milliSeconds
10
10
  ))
11
11
  );
12
- class AuditObservableClass extends AsyncChildObservableClass {
13
- #milliSeconds;
14
- #mut_timerId;
15
- #mut_isSkipping;
16
- constructor(parentObservable, milliSeconds) {
17
- super({
18
- parents: [parentObservable],
19
- initialValue: parentObservable.getSnapshot()
20
- });
21
- this.#mut_isSkipping = false;
22
- this.#mut_timerId = void 0;
23
- this.#milliSeconds = milliSeconds;
24
- }
25
- #resetTimer() {
26
- if (this.#mut_timerId !== void 0) {
27
- clearTimeout(this.#mut_timerId);
12
+ const createAuditObservable = (parentObservable, milliSeconds) => {
13
+ let mut_timerId = void 0;
14
+ let mut_isSkipping = false;
15
+ const resetTimer = () => {
16
+ if (mut_timerId !== void 0) {
17
+ clearTimeout(mut_timerId);
28
18
  }
29
- }
30
- tryUpdate(updateToken) {
31
- const par = this.parents[0];
32
- if (par.updateToken !== updateToken || Optional.isNone(par.getSnapshot()) || this.#mut_isSkipping) {
33
- return;
19
+ };
20
+ return createAsyncChildObservable(
21
+ {
22
+ parents: [parentObservable],
23
+ initialValue: parentObservable.getSnapshot(),
24
+ onComplete: resetTimer
25
+ },
26
+ ({ startUpdate }) => (updateToken) => {
27
+ if (mut_isSkipping || parentObservable.updateToken !== updateToken || Optional.isNone(parentObservable.getSnapshot())) {
28
+ return;
29
+ }
30
+ mut_isSkipping = true;
31
+ mut_timerId = setTimeout(() => {
32
+ const sn = parentObservable.getSnapshot();
33
+ if (Optional.isNone(sn)) return;
34
+ startUpdate(sn.value);
35
+ mut_isSkipping = false;
36
+ }, milliSeconds);
34
37
  }
35
- this.#mut_isSkipping = true;
36
- this.#mut_timerId = setTimeout(() => {
37
- const sn = par.getSnapshot();
38
- if (Optional.isNone(sn)) return;
39
- this.startUpdate(sn.value);
40
- this.#mut_isSkipping = false;
41
- }, this.#milliSeconds);
42
- }
43
- complete() {
44
- this.#resetTimer();
45
- super.complete();
46
- }
47
- }
38
+ );
39
+ };
48
40
 
49
41
  export { audit };
50
42
  //# sourceMappingURL=audit.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit.mjs","sources":["../../../src/core/operators/audit.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { AsyncChildObservableClass } from '../class/index.mjs';\nimport {\n type AuditOperatorObservable,\n type KeepInitialValueOperator,\n type Observable,\n type TimerId,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.\n *\n * Unlike `throttle` which emits the first value, `audit` emits the last value.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The audit time window in milliseconds\n * @returns An operator that audits emissions from the observable\n *\n * @example\n * ```ts\n * // Timeline (250ms audit):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->\n * // audited$ 2 3 11 14 (emitted at end of window)\n * //\n * // Explanation:\n * // - audit emits the LAST value received during each time window\n * // - Unlike throttle (which emits the FIRST value), audit emits the LAST\n * // - Useful when you want the most recent value after a burst of events\n *\n * const input$ = source<number>();\n *\n * const audited$ = input$.pipe(audit(250));\n *\n * const valueHistory: number[] = [];\n *\n * audited$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * input$.next(0);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2]);\n *\n * input$.next(3);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3]);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * input$.next(12);\n *\n * await sleep(100);\n *\n * input$.next(13);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * await sleep(100);\n *\n * input$.next(14);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11, 14]);\n * ```\n */\nexport const audit = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new AuditObservableClass(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nclass AuditObservableClass<A>\n extends AsyncChildObservableClass<A, readonly [A]>\n implements AuditOperatorObservable<A>\n{\n readonly #milliSeconds: number;\n #mut_timerId: TimerId | undefined;\n #mut_isSkipping: boolean;\n\n constructor(parentObservable: Observable<A>, milliSeconds: number) {\n super({\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n });\n\n this.#mut_isSkipping = false;\n\n this.#mut_timerId = undefined;\n\n this.#milliSeconds = milliSeconds;\n }\n\n #resetTimer(): void {\n if (this.#mut_timerId !== undefined) {\n clearTimeout(this.#mut_timerId);\n }\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n if (\n par.updateToken !== updateToken ||\n Optional.isNone(par.getSnapshot()) ||\n this.#mut_isSkipping\n ) {\n return; // skip update\n }\n\n // set timer\n this.#mut_isSkipping = true;\n\n this.#mut_timerId = setTimeout(() => {\n const sn = par.getSnapshot();\n\n if (Optional.isNone(sn)) return;\n\n this.startUpdate(sn.value);\n\n this.#mut_isSkipping = false;\n }, this.#milliSeconds);\n }\n\n override complete(): void {\n this.#resetTimer();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AAwGO,MAAM,QAAQ,CACnB,YAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,oBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,6BACI,yBAAA,CAEV;AAAA,EACW,aAAA;AAAA,EACT,YAAA;AAAA,EACA,eAAA;AAAA,EAEA,WAAA,CAAY,kBAAiC,YAAA,EAAsB;AACjE,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC5C,CAAA;AAED,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAEvB,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAEpB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,YAAA,CAAa,KAAK,YAAY,CAAA;AAAA,IAChC;AAAA,EACF;AAAA,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,IACE,GAAA,CAAI,WAAA,KAAgB,WAAA,IACpB,QAAA,CAAS,MAAA,CAAO,IAAI,WAAA,EAAa,CAAA,IACjC,IAAA,CAAK,eAAA,EACL;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAEvB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,MAAM;AACnC,MAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,MAAA,IAAI,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAEzB,MAAA,IAAA,CAAK,WAAA,CAAY,GAAG,KAAK,CAAA;AAEzB,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAA;AAAA,IACzB,CAAA,EAAG,KAAK,aAAa,CAAA;AAAA,EACvB;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,WAAA,EAAY;AAEjB,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
1
+ {"version":3,"file":"audit.mjs","sources":["../../../src/core/operators/audit.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createAsyncChildObservable } from '../base/index.mjs';\nimport {\n type AuditOperatorObservable,\n type KeepInitialValueOperator,\n type Observable,\n type TimerId,\n} from '../types/index.mjs';\n\n/**\n * Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.\n *\n * Unlike `throttle` which emits the first value, `audit` emits the last value.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The audit time window in milliseconds\n * @returns An operator that audits emissions from the observable\n *\n * @example\n * ```ts\n * // Timeline (250ms audit):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms -> |- 250ms -> |- 250ms ->\n * // audited$ 2 3 11 14 (emitted at end of window)\n * //\n * // Explanation:\n * // - audit emits the LAST value received during each time window\n * // - Unlike throttle (which emits the FIRST value), audit emits the LAST\n * // - Useful when you want the most recent value after a burst of events\n *\n * const input$ = source<number>();\n *\n * const audited$ = input$.pipe(audit(250));\n *\n * const valueHistory: number[] = [];\n *\n * audited$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * input$.next(0);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2]);\n *\n * input$.next(3);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3]);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * input$.next(12);\n *\n * await sleep(100);\n *\n * input$.next(13);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * await sleep(100);\n *\n * input$.next(14);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11]);\n *\n * await sleep(100);\n *\n * assert.deepStrictEqual(valueHistory, [2, 3, 11, 14]);\n * ```\n */\nexport const audit = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n createAuditObservable(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nconst createAuditObservable = <A,>(\n parentObservable: Observable<A>,\n milliSeconds: number,\n): AuditOperatorObservable<A> => {\n let mut_timerId: TimerId | undefined = undefined;\n\n let mut_isSkipping = false;\n\n const resetTimer = (): void => {\n if (mut_timerId !== undefined) {\n clearTimeout(mut_timerId);\n }\n };\n\n return createAsyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n onComplete: resetTimer,\n },\n ({ startUpdate }) =>\n (updateToken) => {\n if (\n mut_isSkipping ||\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(parentObservable.getSnapshot())\n ) {\n return; // skip update\n }\n\n // set timer\n mut_isSkipping = true;\n\n mut_timerId = setTimeout(() => {\n const sn = parentObservable.getSnapshot();\n\n if (Optional.isNone(sn)) return;\n\n startUpdate(sn.value);\n\n mut_isSkipping = false;\n }, milliSeconds);\n },\n );\n};\n"],"names":[],"mappings":";;;;AAuGO,MAAM,QAAQ,CACnB,YAAA;AAAA;AAAA,GAGC,CAAC,gBAAA,KACA,qBAAA;AAAA,IACE,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,qBAAA,GAAwB,CAC5B,gBAAA,EACA,YAAA,KAC+B;AAC/B,EAAA,IAAI,WAAA,GAAmC,MAAA;AAEvC,EAAA,IAAI,cAAA,GAAiB,KAAA;AAErB,EAAA,MAAM,aAAa,MAAY;AAC7B,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,YAAA,CAAa,WAAW,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,0BAAA;AAAA,IACL;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA,EAAY;AAAA,MAC3C,UAAA,EAAY;AAAA,KACd;AAAA,IACA,CAAC,EAAE,WAAA,EAAY,KACb,CAAC,WAAA,KAAgB;AACf,MAAA,IACE,cAAA,IACA,iBAAiB,WAAA,KAAgB,WAAA,IACjC,SAAS,MAAA,CAAO,gBAAA,CAAiB,WAAA,EAAa,CAAA,EAC9C;AACA,QAAA;AAAA,MACF;AAGA,MAAA,cAAA,GAAiB,IAAA;AAEjB,MAAA,WAAA,GAAc,WAAW,MAAM;AAC7B,QAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,QAAA,IAAI,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAEzB,QAAA,WAAA,CAAY,GAAG,KAAK,CAAA;AAEpB,QAAA,cAAA,GAAiB,KAAA;AAAA,MACnB,GAAG,YAAY,CAAA;AAAA,IACjB;AAAA,GACJ;AACF,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"debounce.d.mts","sourceRoot":"","sources":["../../../src/core/operators/debounce.mts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,gBACV,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
1
+ {"version":3,"file":"debounce.d.mts","sourceRoot":"","sources":["../../../src/core/operators/debounce.mts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,wBAAwB,EAG9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoFG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,gBACV,MAAM,KACnB,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC"}
@@ -1,47 +1,40 @@
1
1
  import { Optional } from 'ts-data-forge';
2
- import { AsyncChildObservableClass } from '../class/child-observable-class.mjs';
2
+ import { createAsyncChildObservable } from '../base/create-child-observable.mjs';
3
3
  import '../utils/id-maker.mjs';
4
4
 
5
5
  const debounce = (milliSeconds) => (
6
6
  // eslint-disable-next-line total-functions/no-unsafe-type-assertion
7
- ((parentObservable) => new DebounceObservableClass(
7
+ ((parentObservable) => createDebounceObservable(
8
8
  parentObservable,
9
9
  milliSeconds
10
10
  ))
11
11
  );
12
- class DebounceObservableClass extends AsyncChildObservableClass {
13
- #milliSeconds;
14
- #mut_timerId;
15
- constructor(parentObservable, milliSeconds) {
16
- super({
17
- parents: [parentObservable],
18
- initialValue: parentObservable.getSnapshot()
19
- });
20
- this.#mut_timerId = void 0;
21
- this.#milliSeconds = milliSeconds;
22
- }
23
- #resetTimer() {
24
- if (this.#mut_timerId !== void 0) {
25
- clearTimeout(this.#mut_timerId);
12
+ const createDebounceObservable = (parentObservable, milliSeconds) => {
13
+ let mut_timerId = void 0;
14
+ const resetTimer = () => {
15
+ if (mut_timerId !== void 0) {
16
+ clearTimeout(mut_timerId);
26
17
  }
27
- }
28
- tryUpdate(updateToken) {
29
- const par = this.parents[0];
30
- const sn = par.getSnapshot();
31
- if (par.updateToken !== updateToken || Optional.isNone(sn)) {
32
- return;
18
+ };
19
+ return createAsyncChildObservable(
20
+ {
21
+ parents: [parentObservable],
22
+ initialValue: parentObservable.getSnapshot(),
23
+ onComplete: resetTimer
24
+ },
25
+ ({ startUpdate }) => (updateToken) => {
26
+ const sn = parentObservable.getSnapshot();
27
+ if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
28
+ return;
29
+ }
30
+ resetTimer();
31
+ mut_timerId = setTimeout(() => {
32
+ if (Optional.isNone(sn)) return;
33
+ startUpdate(sn.value);
34
+ }, milliSeconds);
33
35
  }
34
- this.#resetTimer();
35
- this.#mut_timerId = setTimeout(() => {
36
- if (Optional.isNone(sn)) return;
37
- this.startUpdate(sn.value);
38
- }, this.#milliSeconds);
39
- }
40
- complete() {
41
- this.#resetTimer();
42
- super.complete();
43
- }
44
- }
36
+ );
37
+ };
45
38
 
46
39
  export { debounce };
47
40
  //# sourceMappingURL=debounce.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"debounce.mjs","sources":["../../../src/core/operators/debounce.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { AsyncChildObservableClass } from '../class/index.mjs';\nimport {\n type DebounceOperatorObservable,\n type KeepInitialValueOperator,\n type Observable,\n type TimerId,\n type UpdateToken,\n} from '../types/index.mjs';\n\n/**\n * Delays emissions from the source observable until a specified time has passed without another emission.\n * Useful for handling user input events like typing or scrolling.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The debounce duration in milliseconds\n * @returns An operator that debounces the observable\n *\n * @example\n * ```ts\n * // Timeline (250ms debounce):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms ->\n * // debounced$ 3 14 (emitted after 250ms silence)\n * //\n * // Explanation:\n * // - debounce emits the latest value AFTER a quiet period with no new emissions\n * // - Unlike audit (which uses a fixed window), debounce resets the timer on every emission\n * // - Useful for search-as-you-type and form validation\n *\n * const input$ = source<number>();\n *\n * const debounced$ = input$.pipe(debounce(250));\n *\n * const valueHistory: number[] = [];\n *\n * debounced$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * input$.next(0);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * await sleep(100);\n *\n * input$.next(3);\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * await sleep(100);\n *\n * input$.next(12);\n *\n * await sleep(100);\n *\n * input$.next(13);\n *\n * await sleep(100);\n *\n * input$.next(14);\n *\n * assert.deepStrictEqual(valueHistory, [3]);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [3, 14]);\n * ```\n */\nexport const debounce = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n new DebounceObservableClass(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nclass DebounceObservableClass<A>\n extends AsyncChildObservableClass<A, readonly [A]>\n implements DebounceOperatorObservable<A>\n{\n readonly #milliSeconds: number;\n #mut_timerId: TimerId | undefined;\n\n constructor(parentObservable: Observable<A>, milliSeconds: number) {\n super({\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n });\n\n this.#mut_timerId = undefined;\n\n this.#milliSeconds = milliSeconds;\n }\n\n #resetTimer(): void {\n if (this.#mut_timerId !== undefined) {\n clearTimeout(this.#mut_timerId);\n }\n }\n\n override tryUpdate(updateToken: UpdateToken): void {\n const par = this.parents[0];\n\n const sn = par.getSnapshot();\n\n if (par.updateToken !== updateToken || Optional.isNone(sn)) {\n return; // skip update\n }\n\n this.#resetTimer();\n\n // set timer\n this.#mut_timerId = setTimeout(() => {\n if (Optional.isNone(sn)) return;\n\n this.startUpdate(sn.value);\n }, this.#milliSeconds);\n }\n\n override complete(): void {\n this.#resetTimer();\n\n super.complete();\n }\n}\n"],"names":[],"mappings":";;;;AA+FO,MAAM,WAAW,CACtB,YAAA;AAAA;AAAA,GAGC,CAAC,qBACA,IAAI,uBAAA;AAAA,IACF,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,gCACI,yBAAA,CAEV;AAAA,EACW,aAAA;AAAA,EACT,YAAA;AAAA,EAEA,WAAA,CAAY,kBAAiC,YAAA,EAAsB;AACjE,IAAA,KAAA,CAAM;AAAA,MACJ,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,KAC5C,CAAA;AAED,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA;AAEpB,IAAA,IAAA,CAAK,aAAA,GAAgB,YAAA;AAAA,EACvB;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,YAAA,CAAa,KAAK,YAAY,CAAA;AAAA,IAChC;AAAA,EACF;AAAA,EAES,UAAU,WAAA,EAAgC;AACjD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA;AAE1B,IAAA,MAAM,EAAA,GAAK,IAAI,WAAA,EAAY;AAE3B,IAAA,IAAI,IAAI,WAAA,KAAgB,WAAA,IAAe,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,WAAA,EAAY;AAGjB,IAAA,IAAA,CAAK,YAAA,GAAe,WAAW,MAAM;AACnC,MAAA,IAAI,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAEzB,MAAA,IAAA,CAAK,WAAA,CAAY,GAAG,KAAK,CAAA;AAAA,IAC3B,CAAA,EAAG,KAAK,aAAa,CAAA;AAAA,EACvB;AAAA,EAES,QAAA,GAAiB;AACxB,IAAA,IAAA,CAAK,WAAA,EAAY;AAEjB,IAAA,KAAA,CAAM,QAAA,EAAS;AAAA,EACjB;AACF;;;;"}
1
+ {"version":3,"file":"debounce.mjs","sources":["../../../src/core/operators/debounce.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createAsyncChildObservable } from '../base/index.mjs';\nimport {\n type DebounceOperatorObservable,\n type KeepInitialValueOperator,\n type Observable,\n type TimerId,\n} from '../types/index.mjs';\n\n/**\n * Delays emissions from the source observable until a specified time has passed without another emission.\n * Useful for handling user input events like typing or scrolling.\n *\n * @template A - The type of values from the source\n * @param milliSeconds - The debounce duration in milliseconds\n * @returns An operator that debounces the observable\n *\n * @example\n * ```ts\n * // Timeline (250ms debounce):\n * //\n * // Time(x50ms) 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0\n * //\n * // input$ 0 2 3 9 10 11 12 13 14\n * // |- 250ms -> |- 250ms ->\n * // debounced$ 3 14 (emitted after 250ms silence)\n * //\n * // Explanation:\n * // - debounce emits the latest value AFTER a quiet period with no new emissions\n * // - Unlike audit (which uses a fixed window), debounce resets the timer on every emission\n * // - Useful for search-as-you-type and form validation\n *\n * const input$ = source<number>();\n *\n * const debounced$ = input$.pipe(debounce(250));\n *\n * const valueHistory: number[] = [];\n *\n * debounced$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * input$.next(0);\n *\n * await sleep(200);\n *\n * input$.next(2);\n *\n * await sleep(100);\n *\n * input$.next(3);\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [3]);\n *\n * await sleep(300);\n *\n * input$.next(9);\n *\n * await sleep(100);\n *\n * input$.next(10);\n *\n * await sleep(100);\n *\n * input$.next(11);\n *\n * await sleep(100);\n *\n * input$.next(12);\n *\n * await sleep(100);\n *\n * input$.next(13);\n *\n * await sleep(100);\n *\n * input$.next(14);\n *\n * assert.deepStrictEqual(valueHistory, [3]);\n *\n * await sleep(300);\n *\n * assert.deepStrictEqual(valueHistory, [3, 14]);\n * ```\n */\nexport const debounce = <A,>(\n milliSeconds: number,\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n createDebounceObservable(\n parentObservable,\n milliSeconds,\n )) as KeepInitialValueOperator<A, A>;\n\nconst createDebounceObservable = <A,>(\n parentObservable: Observable<A>,\n milliSeconds: number,\n): DebounceOperatorObservable<A> => {\n let mut_timerId: TimerId | undefined = undefined;\n\n const resetTimer = (): void => {\n if (mut_timerId !== undefined) {\n clearTimeout(mut_timerId);\n }\n };\n\n return createAsyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n onComplete: resetTimer,\n },\n ({ startUpdate }) =>\n (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n resetTimer();\n\n // set timer\n mut_timerId = setTimeout(() => {\n if (Optional.isNone(sn)) return;\n\n startUpdate(sn.value);\n }, milliSeconds);\n },\n );\n};\n"],"names":[],"mappings":";;;;AA8FO,MAAM,WAAW,CACtB,YAAA;AAAA;AAAA,GAGC,CAAC,gBAAA,KACA,wBAAA;AAAA,IACE,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAEJ,MAAM,wBAAA,GAA2B,CAC/B,gBAAA,EACA,YAAA,KACkC;AAClC,EAAA,IAAI,WAAA,GAAmC,MAAA;AAEvC,EAAA,MAAM,aAAa,MAAY;AAC7B,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,YAAA,CAAa,WAAW,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,0BAAA;AAAA,IACL;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,YAAA,EAAc,iBAAiB,WAAA,EAAY;AAAA,MAC3C,UAAA,EAAY;AAAA,KACd;AAAA,IACA,CAAC,EAAE,WAAA,EAAY,KACb,CAAC,WAAA,KAAgB;AACf,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,UAAA,EAAW;AAGX,MAAA,WAAA,GAAc,WAAW,MAAM;AAC7B,QAAA,IAAI,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AAEzB,QAAA,WAAA,CAAY,GAAG,KAAK,CAAA;AAAA,MACtB,GAAG,YAAY,CAAA;AAAA,IACjB;AAAA,GACJ;AACF,CAAA;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"filter.d.mts","sourceRoot":"","sources":["../../../src/core/operators/filter.mts"],"names":[],"mappings":"AAAA,OAAO,EAKL,QAAQ,EACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,wBAAwB,EAK9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,EACnC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,GACxD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAElC,wBAAgB,MAAM,CAAC,CAAC,EACtB,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,GACrD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"filter.d.mts","sourceRoot":"","sources":["../../../src/core/operators/filter.mts"],"names":[],"mappings":"AAAA,OAAO,EAKL,QAAQ,EACT,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,wBAAwB,EAI9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,EACnC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,GACxD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAElC,wBAAgB,MAAM,CAAC,CAAC,EACtB,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,OAAO,GACrD,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}