synstate 0.1.0 → 0.1.1

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 (154) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +124 -350
  3. package/assets/synstate-icon.png +0 -0
  4. package/dist/core/combine/combine.d.mts +32 -2
  5. package/dist/core/combine/combine.d.mts.map +1 -1
  6. package/dist/core/combine/combine.mjs +32 -2
  7. package/dist/core/combine/combine.mjs.map +1 -1
  8. package/dist/core/combine/merge.d.mts +30 -4
  9. package/dist/core/combine/merge.d.mts.map +1 -1
  10. package/dist/core/combine/merge.mjs +30 -4
  11. package/dist/core/combine/merge.mjs.map +1 -1
  12. package/dist/core/combine/zip.d.mts +28 -3
  13. package/dist/core/combine/zip.d.mts.map +1 -1
  14. package/dist/core/combine/zip.mjs +28 -3
  15. package/dist/core/combine/zip.mjs.map +1 -1
  16. package/dist/core/create/from-array.d.mts +21 -3
  17. package/dist/core/create/from-array.d.mts.map +1 -1
  18. package/dist/core/create/from-array.mjs +21 -3
  19. package/dist/core/create/from-array.mjs.map +1 -1
  20. package/dist/core/create/from-promise.d.mts +29 -7
  21. package/dist/core/create/from-promise.d.mts.map +1 -1
  22. package/dist/core/create/from-promise.mjs +29 -7
  23. package/dist/core/create/from-promise.mjs.map +1 -1
  24. package/dist/core/create/from-subscribable.d.mts +58 -0
  25. package/dist/core/create/from-subscribable.d.mts.map +1 -1
  26. package/dist/core/create/from-subscribable.mjs +58 -0
  27. package/dist/core/create/from-subscribable.mjs.map +1 -1
  28. package/dist/core/create/interval.d.mts +29 -4
  29. package/dist/core/create/interval.d.mts.map +1 -1
  30. package/dist/core/create/interval.mjs +29 -4
  31. package/dist/core/create/interval.mjs.map +1 -1
  32. package/dist/core/create/of.d.mts +22 -3
  33. package/dist/core/create/of.d.mts.map +1 -1
  34. package/dist/core/create/of.mjs +22 -3
  35. package/dist/core/create/of.mjs.map +1 -1
  36. package/dist/core/create/source.d.mts +20 -1
  37. package/dist/core/create/source.d.mts.map +1 -1
  38. package/dist/core/create/source.mjs.map +1 -1
  39. package/dist/core/create/timer.d.mts +23 -4
  40. package/dist/core/create/timer.d.mts.map +1 -1
  41. package/dist/core/create/timer.mjs +23 -4
  42. package/dist/core/create/timer.mjs.map +1 -1
  43. package/dist/core/operators/audit-time.d.mts +59 -0
  44. package/dist/core/operators/audit-time.d.mts.map +1 -1
  45. package/dist/core/operators/audit-time.mjs +59 -0
  46. package/dist/core/operators/audit-time.mjs.map +1 -1
  47. package/dist/core/operators/debounce-time.d.mts +22 -2
  48. package/dist/core/operators/debounce-time.d.mts.map +1 -1
  49. package/dist/core/operators/debounce-time.mjs +22 -2
  50. package/dist/core/operators/debounce-time.mjs.map +1 -1
  51. package/dist/core/operators/filter.d.mts +26 -1
  52. package/dist/core/operators/filter.d.mts.map +1 -1
  53. package/dist/core/operators/filter.mjs.map +1 -1
  54. package/dist/core/operators/map-with-index.d.mts +19 -4
  55. package/dist/core/operators/map-with-index.d.mts.map +1 -1
  56. package/dist/core/operators/map-with-index.mjs +19 -4
  57. package/dist/core/operators/map-with-index.mjs.map +1 -1
  58. package/dist/core/operators/merge-map.d.mts +47 -5
  59. package/dist/core/operators/merge-map.d.mts.map +1 -1
  60. package/dist/core/operators/merge-map.mjs +47 -5
  61. package/dist/core/operators/merge-map.mjs.map +1 -1
  62. package/dist/core/operators/pairwise.d.mts +30 -1
  63. package/dist/core/operators/pairwise.d.mts.map +1 -1
  64. package/dist/core/operators/pairwise.mjs +30 -1
  65. package/dist/core/operators/pairwise.mjs.map +1 -1
  66. package/dist/core/operators/scan.d.mts +23 -1
  67. package/dist/core/operators/scan.d.mts.map +1 -1
  68. package/dist/core/operators/scan.mjs +23 -1
  69. package/dist/core/operators/scan.mjs.map +1 -1
  70. package/dist/core/operators/skip-if-no-change.d.mts +25 -1
  71. package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
  72. package/dist/core/operators/skip-if-no-change.mjs +25 -1
  73. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  74. package/dist/core/operators/skip-until.d.mts +50 -0
  75. package/dist/core/operators/skip-until.d.mts.map +1 -1
  76. package/dist/core/operators/skip-until.mjs +50 -0
  77. package/dist/core/operators/skip-until.mjs.map +1 -1
  78. package/dist/core/operators/skip-while.d.mts +48 -0
  79. package/dist/core/operators/skip-while.d.mts.map +1 -1
  80. package/dist/core/operators/skip-while.mjs +48 -0
  81. package/dist/core/operators/skip-while.mjs.map +1 -1
  82. package/dist/core/operators/switch-map.d.mts +39 -5
  83. package/dist/core/operators/switch-map.d.mts.map +1 -1
  84. package/dist/core/operators/switch-map.mjs +39 -5
  85. package/dist/core/operators/switch-map.mjs.map +1 -1
  86. package/dist/core/operators/take-until.d.mts +20 -1
  87. package/dist/core/operators/take-until.d.mts.map +1 -1
  88. package/dist/core/operators/take-until.mjs +20 -1
  89. package/dist/core/operators/take-until.mjs.map +1 -1
  90. package/dist/core/operators/take-while.d.mts +47 -0
  91. package/dist/core/operators/take-while.d.mts.map +1 -1
  92. package/dist/core/operators/take-while.mjs +47 -0
  93. package/dist/core/operators/take-while.mjs.map +1 -1
  94. package/dist/core/operators/throttle-time.d.mts +44 -5
  95. package/dist/core/operators/throttle-time.d.mts.map +1 -1
  96. package/dist/core/operators/throttle-time.mjs +44 -5
  97. package/dist/core/operators/throttle-time.mjs.map +1 -1
  98. package/dist/core/operators/with-buffered-from.d.mts +53 -0
  99. package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
  100. package/dist/core/operators/with-buffered-from.mjs +53 -0
  101. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  102. package/dist/core/operators/with-current-value-from.d.mts +55 -0
  103. package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
  104. package/dist/core/operators/with-current-value-from.mjs +55 -0
  105. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  106. package/dist/core/operators/with-initial-value.d.mts +24 -2
  107. package/dist/core/operators/with-initial-value.d.mts.map +1 -1
  108. package/dist/core/operators/with-initial-value.mjs +24 -2
  109. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  110. package/dist/core/types/observable-family.d.mts +7 -7
  111. package/dist/utils/create-event-emitter.d.mts +20 -2
  112. package/dist/utils/create-event-emitter.d.mts.map +1 -1
  113. package/dist/utils/create-event-emitter.mjs +20 -2
  114. package/dist/utils/create-event-emitter.mjs.map +1 -1
  115. package/dist/utils/create-reducer.d.mts +13 -1
  116. package/dist/utils/create-reducer.d.mts.map +1 -1
  117. package/dist/utils/create-reducer.mjs +13 -1
  118. package/dist/utils/create-reducer.mjs.map +1 -1
  119. package/dist/utils/create-state.d.mts +24 -4
  120. package/dist/utils/create-state.d.mts.map +1 -1
  121. package/dist/utils/create-state.mjs +24 -4
  122. package/dist/utils/create-state.mjs.map +1 -1
  123. package/package.json +13 -12
  124. package/src/core/combine/combine.mts +32 -2
  125. package/src/core/combine/merge.mts +30 -4
  126. package/src/core/combine/zip.mts +28 -3
  127. package/src/core/create/from-array.mts +21 -3
  128. package/src/core/create/from-promise.mts +29 -7
  129. package/src/core/create/from-subscribable.mts +58 -0
  130. package/src/core/create/interval.mts +29 -4
  131. package/src/core/create/of.mts +22 -3
  132. package/src/core/create/source.mts +20 -1
  133. package/src/core/create/timer.mts +23 -4
  134. package/src/core/operators/audit-time.mts +59 -0
  135. package/src/core/operators/debounce-time.mts +22 -2
  136. package/src/core/operators/filter.mts +26 -1
  137. package/src/core/operators/map-with-index.mts +19 -4
  138. package/src/core/operators/merge-map.mts +47 -5
  139. package/src/core/operators/pairwise.mts +30 -1
  140. package/src/core/operators/scan.mts +23 -1
  141. package/src/core/operators/skip-if-no-change.mts +25 -1
  142. package/src/core/operators/skip-until.mts +50 -0
  143. package/src/core/operators/skip-while.mts +48 -0
  144. package/src/core/operators/switch-map.mts +39 -5
  145. package/src/core/operators/take-until.mts +20 -1
  146. package/src/core/operators/take-while.mts +47 -0
  147. package/src/core/operators/throttle-time.mts +44 -5
  148. package/src/core/operators/with-buffered-from.mts +53 -0
  149. package/src/core/operators/with-current-value-from.mts +55 -0
  150. package/src/core/operators/with-initial-value.mts +24 -2
  151. package/src/core/types/observable-family.mts +7 -7
  152. package/src/utils/create-event-emitter.mts +20 -2
  153. package/src/utils/create-reducer.mts +13 -1
  154. package/src/utils/create-state.mts +24 -4
@@ -8,6 +8,61 @@ import {
8
8
  } from '../types/index.mjs';
9
9
  import { maxDepth } from '../utils/index.mjs';
10
10
 
11
+ /**
12
+ * Samples the current value from another observable each time the source emits.
13
+ * Emits a tuple of [sourceValue, sampledValue].
14
+ *
15
+ * @template A - The type of values from the source observable
16
+ * @template B - The type of values from the sampled observable
17
+ * @param observable - The observable to sample from
18
+ * @returns An operator that emits tuples of source and sampled values
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Timeline:
23
+ * //
24
+ * // name$ "Alice" "Bob" "Charlie"
25
+ * // age$ 25 30 35 40
26
+ * // result$ ["Alice",25] ["Bob",30] ["Bob",35] ["Charlie",40]
27
+ * //
28
+ * // Explanation:
29
+ * // - withCurrentValueFrom samples the current value from another observable
30
+ * // - Emits a tuple [sourceValue, sampledValue] each time the source emits
31
+ * // - Does not emit until both observables have emitted at least once
32
+ * // - Similar to combine, but only emits when the source (not the sampled) emits
33
+ *
34
+ * const name$ = source<string>();
35
+ *
36
+ * const age$ = source<number>();
37
+ *
38
+ * const result$ = name$.pipe(withCurrentValueFrom(age$));
39
+ *
40
+ * const mut_history: (readonly [string, number])[] = [];
41
+ *
42
+ * result$.subscribe(([name_, currentAge]) => {
43
+ * mut_history.push([name_, currentAge]);
44
+ * });
45
+ *
46
+ * name$.next('Alice'); // nothing logged (age$ hasn't emitted)
47
+ *
48
+ * assert.deepStrictEqual(mut_history, []);
49
+ *
50
+ * age$.next(25);
51
+ *
52
+ * name$.next('Bob'); // logs: Bob is 25 years old
53
+ *
54
+ * assert.deepStrictEqual(mut_history, [['Bob', 25]]);
55
+ *
56
+ * age$.next(30);
57
+ *
58
+ * name$.next('Charlie'); // logs: Charlie is 30 years old
59
+ *
60
+ * assert.deepStrictEqual(mut_history, [
61
+ * ['Bob', 25],
62
+ * ['Charlie', 30],
63
+ * ]);
64
+ * ```
65
+ */
11
66
  export const withCurrentValueFrom =
12
67
  <A, B>(
13
68
  observable: Observable<B>,
@@ -21,15 +21,37 @@ import {
21
21
  *
22
22
  * @example
23
23
  * ```ts
24
+ * // Timeline:
25
+ * //
26
+ * // num$ 1 2 3
27
+ * // withInitial$ 0 1 2 3
28
+ * // ^
29
+ * // initial value
30
+ * //
31
+ * // Explanation:
32
+ * // - withInitialValue provides an initial value before the source emits
33
+ * // - Converts an uninitialized observable to an initialized one
34
+ * // - Useful when you need a default value immediately
35
+ *
24
36
  * const num$ = source<number>();
25
37
  *
26
38
  * const initialized$ = num$.pipe(withInitialValue(0));
27
39
  *
40
+ * const mut_history: number[] = [];
41
+ *
28
42
  * initialized$.subscribe((x) => {
29
- * console.log(x);
30
- * }); // immediately logs: 0
43
+ * mut_history.push(x);
44
+ * });
45
+ *
46
+ * assert.deepStrictEqual(mut_history, [0]);
31
47
  *
32
48
  * num$.next(1); // logs: 1
49
+ *
50
+ * assert.deepStrictEqual(mut_history, [0, 1]);
51
+ *
52
+ * num$.next(2); // logs: 2
53
+ *
54
+ * assert.deepStrictEqual(mut_history, [0, 1, 2]);
33
55
  * ```
34
56
  */
35
57
  export const withInitialValue =
@@ -65,7 +65,7 @@ export type ScanOperatorObservable<A, B> = InitializedSyncChildObservable<
65
65
 
66
66
  // SyncChildObservable
67
67
 
68
- namespace SyncFlowInternals {
68
+ namespace SynStateInternals {
69
69
  type Cast<A> = A extends NonEmptyUnknownList ? A : never;
70
70
 
71
71
  type EveryInitialized<OS extends NonEmptyArray<Observable<unknown>>> =
@@ -164,25 +164,25 @@ namespace SyncFlowInternals {
164
164
  }
165
165
 
166
166
  export type CombineObservable<A extends NonEmptyUnknownList> =
167
- SyncFlowInternals.CombineObservableImpl<A>;
167
+ SynStateInternals.CombineObservableImpl<A>;
168
168
 
169
169
  export type CombineObservableRefined<
170
170
  OS extends NonEmptyArray<Observable<unknown>>,
171
- > = SyncFlowInternals.CombineObservableRefinedImpl<OS>;
171
+ > = SynStateInternals.CombineObservableRefinedImpl<OS>;
172
172
 
173
173
  export type ZipObservable<A extends NonEmptyUnknownList> =
174
- SyncFlowInternals.ZipObservableImpl<A>;
174
+ SynStateInternals.ZipObservableImpl<A>;
175
175
 
176
176
  export type ZipObservableRefined<
177
177
  OS extends NonEmptyArray<Observable<unknown>>,
178
- > = SyncFlowInternals.ZipObservableRefinedImpl<OS>;
178
+ > = SynStateInternals.ZipObservableRefinedImpl<OS>;
179
179
 
180
180
  export type MergeObservable<A extends NonEmptyUnknownList> =
181
- SyncFlowInternals.MergeObservableImpl<A>;
181
+ SynStateInternals.MergeObservableImpl<A>;
182
182
 
183
183
  export type MergeObservableRefined<
184
184
  OS extends NonEmptyArray<Observable<unknown>>,
185
- > = SyncFlowInternals.MergeObservableRefinedImpl<OS>;
185
+ > = SynStateInternals.MergeObservableRefinedImpl<OS>;
186
186
 
187
187
  export type MapWithIndexOperatorObservable<A, B> = SyncChildObservable<
188
188
  B,
@@ -10,11 +10,21 @@ import { source, type Observable } from '../core/index.mjs';
10
10
  * ```ts
11
11
  * const [click$, emitClick] = createEventEmitter();
12
12
  *
13
+ * const mut_clickCount = { value: 0 };
14
+ *
13
15
  * click$.subscribe(() => {
14
- * console.log('Clicked!');
16
+ * mut_clickCount.value += 1;
15
17
  * });
16
18
  *
17
19
  * emitClick(); // logs: Clicked!
20
+ *
21
+ * assert.deepStrictEqual(mut_clickCount.value, 1);
22
+ *
23
+ * emitClick();
24
+ *
25
+ * emitClick();
26
+ *
27
+ * assert.deepStrictEqual(mut_clickCount.value, 3);
18
28
  * ```
19
29
  */
20
30
  export const createEventEmitter = (): readonly [
@@ -41,11 +51,19 @@ export const createEventEmitter = (): readonly [
41
51
  * ```ts
42
52
  * const [message$, emitMessage] = createValueEmitter<string>();
43
53
  *
54
+ * const mut_history: string[] = [];
55
+ *
44
56
  * message$.subscribe((msg) => {
45
- * console.log(msg);
57
+ * mut_history.push(msg);
46
58
  * });
47
59
  *
48
60
  * emitMessage('Hello'); // logs: Hello
61
+ *
62
+ * assert.deepStrictEqual(mut_history, ['Hello']);
63
+ *
64
+ * emitMessage('World');
65
+ *
66
+ * assert.deepStrictEqual(mut_history, ['Hello', 'World']);
49
67
  * ```
50
68
  */
51
69
  export const createValueEmitter = <A,>(): readonly [
@@ -24,11 +24,23 @@ import { source, type InitializedObservable } from '../core/index.mjs';
24
24
  * 0,
25
25
  * );
26
26
  *
27
+ * const mut_history: number[] = [];
28
+ *
27
29
  * state.subscribe((value: number) => {
28
- * console.log(value);
30
+ * mut_history.push(value);
29
31
  * });
30
32
  *
33
+ * assert.deepStrictEqual(mut_history, [0]);
34
+ *
31
35
  * dispatch({ type: 'increment' }); // logs: 1
36
+ *
37
+ * assert.deepStrictEqual(mut_history, [0, 1]);
38
+ *
39
+ * dispatch({ type: 'increment' });
40
+ *
41
+ * dispatch({ type: 'decrement' });
42
+ *
43
+ * assert.deepStrictEqual(mut_history, [0, 1, 2, 1]);
32
44
  * ```
33
45
  */
34
46
  export const createReducer = <S, A>(
@@ -34,15 +34,25 @@ const reducer = <S,>(state: S, action: Action<S>): S => {
34
34
  * ```ts
35
35
  * const [state, setState, { updateState, resetState }] = createState(0);
36
36
  *
37
+ * const mut_history: number[] = [];
38
+ *
37
39
  * state.subscribe((value: number) => {
38
- * console.log(value);
39
- * }); // logs: 0
40
+ * mut_history.push(value);
41
+ * });
42
+ *
43
+ * assert.deepStrictEqual(mut_history, [0]);
40
44
  *
41
45
  * setState(10); // logs: 10
42
46
  *
47
+ * assert.deepStrictEqual(mut_history, [0, 10]);
48
+ *
43
49
  * updateState((prev: number) => prev + 1); // logs: 11
44
50
  *
51
+ * assert.deepStrictEqual(mut_history, [0, 10, 11]);
52
+ *
45
53
  * resetState(); // logs: 0
54
+ *
55
+ * assert.deepStrictEqual(mut_history, [0, 10, 11, 0]);
46
56
  * ```
47
57
  */
48
58
  export const createState = <S,>(
@@ -91,15 +101,25 @@ export const createState = <S,>(
91
101
  * ```ts
92
102
  * const [state, { setTrue, toggle }] = createBooleanState(false);
93
103
  *
104
+ * const mut_history: boolean[] = [];
105
+ *
94
106
  * state.subscribe((value: boolean) => {
95
- * console.log(value);
96
- * }); // logs: false
107
+ * mut_history.push(value);
108
+ * });
109
+ *
110
+ * assert.deepStrictEqual(mut_history, [false]);
97
111
  *
98
112
  * setTrue(); // logs: true
99
113
  *
114
+ * assert.deepStrictEqual(mut_history, [false, true]);
115
+ *
100
116
  * toggle(); // logs: false
101
117
  *
118
+ * assert.deepStrictEqual(mut_history, [false, true, false]);
119
+ *
102
120
  * toggle(); // logs: true
121
+ *
122
+ * assert.deepStrictEqual(mut_history, [false, true, false, true]);
103
123
  * ```
104
124
  */
105
125
  export const createBooleanState = (