synstate 5.0.1 → 6.1.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 (50) hide show
  1. package/README.md +6 -5
  2. package/dist/core/class/observable-base-class.mjs.map +1 -1
  3. package/dist/core/class/propagation-state.mjs.map +1 -1
  4. package/dist/core/combine/combine.d.mts.map +1 -1
  5. package/dist/core/combine/combine.mjs +3 -43
  6. package/dist/core/combine/combine.mjs.map +1 -1
  7. package/dist/core/combine/derive.d.mts +63 -0
  8. package/dist/core/combine/derive.d.mts.map +1 -0
  9. package/dist/core/combine/derive.mjs +124 -0
  10. package/dist/core/combine/derive.mjs.map +1 -0
  11. package/dist/core/combine/index.d.mts +1 -0
  12. package/dist/core/combine/index.d.mts.map +1 -1
  13. package/dist/core/combine/index.mjs +1 -0
  14. package/dist/core/combine/index.mjs.map +1 -1
  15. package/dist/core/operators/keep-equal-parts.d.mts +1 -3
  16. package/dist/core/operators/keep-equal-parts.d.mts.map +1 -1
  17. package/dist/core/operators/keep-equal-parts.mjs +0 -2
  18. package/dist/core/operators/keep-equal-parts.mjs.map +1 -1
  19. package/dist/core/operators/map.d.mts +30 -18
  20. package/dist/core/operators/map.d.mts.map +1 -1
  21. package/dist/core/operators/map.mjs +24 -10
  22. package/dist/core/operators/map.mjs.map +1 -1
  23. package/dist/core/predefined/operators/attach-index.d.mts +4 -2
  24. package/dist/core/predefined/operators/attach-index.d.mts.map +1 -1
  25. package/dist/core/predefined/operators/attach-index.mjs +36 -2
  26. package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
  27. package/dist/core/predefined/operators/map-to.d.mts +6 -2
  28. package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
  29. package/dist/core/predefined/operators/map-to.mjs +5 -1
  30. package/dist/core/predefined/operators/map-to.mjs.map +1 -1
  31. package/dist/core/types/observable-family.d.mts +3 -0
  32. package/dist/core/types/observable-family.d.mts.map +1 -1
  33. package/dist/core/types/observable-family.mjs.map +1 -1
  34. package/dist/utils/create-reducer.d.mts +1 -1
  35. package/dist/utils/create-state.d.mts +1 -1
  36. package/package.json +12 -10
  37. package/src/core/class/observable-base-class.mts +2 -2
  38. package/src/core/class/propagation-state.mts +1 -1
  39. package/src/core/combine/combine.mts +7 -72
  40. package/src/core/combine/derive.mts +172 -0
  41. package/src/core/combine/derive.test.mts +190 -0
  42. package/src/core/combine/index.mts +1 -0
  43. package/src/core/operators/keep-equal-parts.mts +1 -3
  44. package/src/core/operators/map-cut-off.test.mts +215 -0
  45. package/src/core/operators/map.mts +48 -31
  46. package/src/core/predefined/operators/attach-index.mts +62 -5
  47. package/src/core/predefined/operators/map-to.mts +7 -3
  48. package/src/core/types/observable-family.mts +18 -0
  49. package/src/utils/create-reducer.mts +1 -1
  50. package/src/utils/create-state.mts +1 -1
@@ -1,4 +1,3 @@
1
- import { map } from '../../operators/index.mjs';
2
1
 
3
2
 
4
3
 
@@ -6,6 +5,8 @@ import { map } from '../../operators/index.mjs';
6
5
 
7
6
 
8
7
 
8
+ import { Optional, SafeUint, asSafeUint } from 'ts-data-forge';
9
+ import { SyncChildObservableClass } from '../../class/index.mjs';
9
10
 
10
11
 
11
12
 
@@ -48,10 +49,43 @@ import { map } from '../../operators/index.mjs';
48
49
 
49
50
 
50
51
 
51
- export const withIndex = () => map((a, i) => [i, a]);
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+ export const withIndex = () =>
62
+
63
+ ((parentObservable) => new WithIndexObservableClass(parentObservable));
52
64
 
53
65
 
54
66
 
55
67
 
56
68
  export const attachIndex = withIndex;
69
+
70
+ class WithIndexObservableClass extends SyncChildObservableClass {
71
+ #mut_index;
72
+ constructor(parentObservable) {
73
+ super({
74
+ parents: [parentObservable],
75
+ initialValue: Optional.map(parentObservable.getSnapshot(), (a) => [-1, a]),
76
+ });
77
+ this.#mut_index = -1;
78
+ this.attach();
79
+ }
80
+ tryUpdate(updateToken) {
81
+ const par = this.parents[0];
82
+ const sn = par.getSnapshot();
83
+ if (par.updateToken !== updateToken || Optional.isNone(sn)) {
84
+ return;
85
+ }
86
+ this.#mut_index =
87
+ this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
88
+ this.setNext([this.#mut_index, sn.value], updateToken);
89
+ }
90
+ }
57
91
  //# sourceMappingURL=attach-index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"attach-index.mjs","sourceRoot":"","sources":["../../../../src/core/predefined/operators/attach-index.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAGvB,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAU,CAAC,CAAC;AAEpC;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC"}
1
+ {"version":3,"file":"attach-index.mjs","sourceRoot":"","sources":["../../../../src/core/predefined/operators/attach-index.mts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,6EAA6E;AAC7E,yCAAyC;AACzC,2CAA2C;AAC3C,gDAAgD;AAChD,0DAA0D;AAC1D,kEAAkE;AAClE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAOjE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAGvB,EAAE;AACF,4DAA4D;AAC5D,CAAC,CAAC,gBAAgB,EAAE,EAAE,CACpB,IAAI,wBAAwB,CAAC,gBAAgB,CAAC,CAG/C,CAAC;AAEJ;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AAErC,oBAAoB;AAEpB,MAAM,wBAA4B,SAAQ,wBAGzC;IACC,UAAU,CAAgB;IAE1B,YAAY,gBAA+B;QACzC,KAAK,CAAC;YACJ,OAAO,EAAE,CAAC,gBAAgB,CAAC;YAC3B,YAAY,EAAE,QAAQ,CAAC,GAAG,CACxB,gBAAgB,CAAC,WAAW,EAAE,EAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAU,CACxB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QAErB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEQ,SAAS,CAAC,WAAwB;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAE5B,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAE7B,IAAI,GAAG,CAAC,WAAW,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YAC3D,OAAO,CAAC,cAAc;QACxB,CAAC;QAED,IAAI,CAAC,UAAU;YACb,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAE5E,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC;IACzD,CAAC;CACF"}
@@ -1,7 +1,11 @@
1
1
  import type { KeepInitialValueOperator } from '../../types/index.mjs';
2
2
  /**
3
3
  * Maps all emitted values to a constant value, ignoring the source values.
4
- * Equivalent to `map(() => value)`.
4
+ * Emits on every source value although the value never changes — where
5
+ * `map(() => value)` would stop every result after the first as equal — so
6
+ * it is the one for turning events into a value. The value's type is
7
+ * inferred as written, as with `as const`: `mapTo('reset')` gives
8
+ * `'reset'`, not `string`.
5
9
  *
6
10
  * @template A - The type of values from the source
7
11
  * @template B - The type of the constant value
@@ -39,5 +43,5 @@ import type { KeepInitialValueOperator } from '../../types/index.mjs';
39
43
  * assert.deepStrictEqual(valueHistory, [1, 1, 1]);
40
44
  * ```
41
45
  */
42
- export declare const mapTo: <A, B>(value: B) => KeepInitialValueOperator<A, B>;
46
+ export declare const mapTo: <A, const B>(value: B) => KeepInitialValueOperator<A, B>;
43
47
  //# sourceMappingURL=map-to.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-to.d.mts","sourceRoot":"","sources":["../../../../src/core/predefined/operators/map-to.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,CAAC,SAAS,CAAC,KAAG,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAClD,CAAC"}
1
+ {"version":3,"file":"map-to.d.mts","sourceRoot":"","sources":["../../../../src/core/predefined/operators/map-to.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,KAAG,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAC/B,CAAC"}
@@ -39,5 +39,9 @@ import { map } from '../../operators/index.mjs';
39
39
 
40
40
 
41
41
 
42
- export const mapTo = (value) => map(() => value);
42
+
43
+
44
+
45
+
46
+ export const mapTo = (value) => map(() => value, { equals: () => false });
43
47
  //# sourceMappingURL=map-to.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-to.mjs","sourceRoot":"","sources":["../../../../src/core/predefined/operators/map-to.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAO,KAAQ,EAAkC,EAAE,CACtE,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"map-to.mjs","sourceRoot":"","sources":["../../../../src/core/predefined/operators/map-to.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAGhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAa,KAAQ,EAAkC,EAAE,CAC5E,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC"}
@@ -35,6 +35,7 @@ declare namespace SynStateInternals {
35
35
  type InitializedCombineObservableImpl<A extends NonEmptyUnknownList> = InitializedSyncChildObservable<A, A>;
36
36
  export type CombineObservableImpl<A extends NonEmptyUnknownList> = SyncChildObservable<A, A>;
37
37
  export type CombineObservableRefinedImpl<OS extends NonEmptyTuple<Observable<unknown>>> = EveryInitialized<OS> extends true ? InitializedCombineObservableImpl<Cast<Unwrap<OS>>> : CombineObservableImpl<Unwrap<OS>>;
38
+ export type DeriveObservableRefinedImpl<B, OS extends NonEmptyTuple<Observable<unknown>>> = EveryInitialized<OS> extends true ? InitializedSyncChildObservable<B, Cast<Unwrap<OS>>> : SyncChildObservable<B, Unwrap<OS>>;
38
39
  type InitializedZipObservableImpl<A extends NonEmptyUnknownList> = InitializedSyncChildObservable<A, A>;
39
40
  export type ZipObservableImpl<A extends NonEmptyUnknownList> = SyncChildObservable<A, A>;
40
41
  export type ZipObservableRefinedImpl<OS extends NonEmptyTuple<Observable<unknown>>> = EveryInitialized<OS> extends true ? InitializedZipObservableImpl<Cast<Unwrap<OS>>> : ZipObservableImpl<Unwrap<OS>>;
@@ -45,6 +46,8 @@ declare namespace SynStateInternals {
45
46
  }
46
47
  export type CombineObservable<A extends NonEmptyUnknownList> = SynStateInternals.CombineObservableImpl<A>;
47
48
  export type CombineObservableRefined<OS extends NonEmptyTuple<Observable<unknown>>> = SynStateInternals.CombineObservableRefinedImpl<OS>;
49
+ export type DeriveObservable<B, A extends NonEmptyUnknownList> = SyncChildObservable<B, A>;
50
+ export type DeriveObservableRefined<B, OS extends NonEmptyTuple<Observable<unknown>>> = SynStateInternals.DeriveObservableRefinedImpl<B, OS>;
48
51
  export type ZipObservable<A extends NonEmptyUnknownList> = SynStateInternals.ZipObservableImpl<A>;
49
52
  export type ZipObservableRefined<OS extends NonEmptyTuple<Observable<unknown>>> = SynStateInternals.ZipObservableRefinedImpl<OS>;
50
53
  export type MergeObservable<A extends NonEmptyUnknownList> = SynStateInternals.MergeObservableImpl<A>;
@@ -1 +1 @@
1
- {"version":3,"file":"observable-family.d.mts","sourceRoot":"","sources":["../../../src/core/types/observable-family.mts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACT,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EACV,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,8BAA8B,EAC9B,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,MAAM,EACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAIvD,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,QAAQ,CAAC;IACpD;;;OAGG;IACH,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;CACvB,CAAC,GACA,yBAAyB,CAAC,CAAC,CAAC,CAAC;AAE/B,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,QAAQ,CAAC;IACzC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC1B,CAAC,GACA,cAAc,CAAC,CAAC,CAAC,CAAC;AAEpB,MAAM,MAAM,qBAAqB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,cAAc,CAChE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,cAAc,CACrE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC,GACA,cAAc,CAAC,QAAQ,CAAC,CAAC;AAE3B,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC,GACA,cAAc,CAAC,CAAC,CAAC,CAAC;AAIpB,MAAM,MAAM,kCAAkC,CAC5C,CAAC,EACD,CAAC,GAAG,CAAC,IACH,8BAA8B,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAExD,MAAM,MAAM,sBAAsB,CAAC,CAAC,EAAE,CAAC,IAAI,8BAA8B,CACvE,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AASF,kBAAU,iBAAiB,CAAC;IAC1B,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,mBAAmB,GAAG,CAAC,GAAG,KAAK,CAAC;IAEzD,MAAM,MAAM,gBAAgB,CAAC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IACxE,EAAE,SAAS,aAAa,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;IAE1E,KAAK,aAAa,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,SAAS;QACpD,qBAAqB,CAAC,OAAO,CAAC;KAC/B,GACG,IAAI,GACJ,KAAK,CAAC;IAEV,wDAAwD;IACxD,KAAK,YAAY,CAAC,CAAC,SAAS,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,SAAS,CAAC,IAAI,CAAC,GACvE,IAAI,GACJ,SAAS,CAAC,CAAC,CAAC,SAAS,SAAS,CAAC,KAAK,CAAC,GACnC,KAAK,GACL,IAAI,CAAC;IAEX,KAAK,mBAAmB,CAAC,EAAE,SAAS,UAAU,CAAC,OAAO,CAAC,IAErD,YAAY,CAAC,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC;IAE1D,MAAM,MAAM,eAAe,CAAC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IACvE,mBAAmB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAElC,KAAK,gCAAgC,CAAC,CAAC,SAAS,mBAAmB,IACjE,8BAA8B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvC,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,mBAAmB,IAC7D,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,MAAM,MAAM,4BAA4B,CACtC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAE7C,gBAAgB,CAAC,EAAE,CAAC,SAAS,IAAI,GAC7B,gCAAgC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAClD,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAExC,KAAK,4BAA4B,CAAC,CAAC,SAAS,mBAAmB,IAC7D,8BAA8B,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEvC,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,mBAAmB,IACzD,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,MAAM,MAAM,wBAAwB,CAClC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAE7C,gBAAgB,CAAC,EAAE,CAAC,SAAS,IAAI,GAC7B,4BAA4B,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAC9C,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpC,KAAK,8BAA8B,CAAC,CAAC,SAAS,mBAAmB,IAC/D,8BAA8B,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAErD,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,mBAAmB,IAC3D,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE1C,MAAM,MAAM,0BAA0B,CACpC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAE7C,eAAe,CAAC,EAAE,CAAC,SAAS,IAAI,GAC5B,8BAA8B,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAChD,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;;CACvC;AAgDD,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,mBAAmB,IACzD,iBAAiB,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAE7C,MAAM,MAAM,wBAAwB,CAClC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAC3C,iBAAiB,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;AAEvD,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,mBAAmB,IACrD,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAEzC,MAAM,MAAM,oBAAoB,CAC9B,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAC3C,iBAAiB,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC;AAEnD,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,mBAAmB,IACvD,iBAAiB,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAE3C,MAAM,MAAM,sBAAsB,CAChC,EAAE,SAAS,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAC3C,iBAAiB,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;AAErD,MAAM,MAAM,qBAAqB,CAAC,CAAC,EAAE,CAAC,IAAI,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI,mBAAmB,CAC7D,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,EACtB,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7E,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,mBAAmB,CAC9D,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,mBAAmB,CAC9D,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,mBAAmB,CAC9D,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,mBAAmB,CAC9D,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,sCAAsC,CAAC,CAAC,EAAE,CAAC,IAAI,mBAAmB,CAC5E,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EACf,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,kCAAkC,CAAC,CAAC,EAAE,CAAC,IAAI,mBAAmB,CACxE,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAAC,EAC1B,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,gCAAgC,CAAC,CAAC,IAAI,mBAAmB,CACnE,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,gCAAgC,CAAC,CAAC,IAAI,mBAAmB,CACnE,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI,mBAAmB,CAC7D,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAIF,MAAM,MAAM,uBAAuB,CAAC,CAAC,IAAI,oBAAoB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/E,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI,oBAAoB,CAC9D,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,2BAA2B,CAAC,CAAC,EAAE,CAAC,IAAI,oBAAoB,CAClE,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,CAAC,EAAE,CAAC,IAAI,oBAAoB,CACjE,CAAC,EACD,SAAS,CAAC,CAAC,CAAC,CACb,CAAC"}
1
+ {"version":3,"file":"observable-family.d.mts","sourceRoot":"","sources":["../../../src/core/types/observable-family.mts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"observable-family.mjs","sourceRoot":"","sources":["../../../src/core/types/observable-family.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAe,MAAM,eAAe,CAAC;AA0IxD,UAAU,CACR,GAAG,CACJ,CAAC;AAEF,UAAU,CAGR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC;AAEP,UAAU,CACR,GAAG,CACJ,CAAC;AAEF,UAAU,CAGR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"observable-family.mjs","sourceRoot":"","sources":["../../../src/core/types/observable-family.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAe,MAAM,eAAe,CAAC;AAkJxD,UAAU,CACR,GAAG,CACJ,CAAC;AAEF,UAAU,CAGR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC;AAEP,UAAU,CACR,GAAG,CACJ,CAAC;AAEF,UAAU,CAGR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC;AAEP,UAAU,CAKR,GAAG,CAAC,CAAC"}
@@ -110,7 +110,7 @@ export type StateOptions<S> = Readonly<{
110
110
  * written, and every part of it deeply equal to the same part of the
111
111
  * current state is replaced by that part (`replaceEqualDeep` of
112
112
  * ts-data-forge): a reader of an unchanged part keeps the object it has, so
113
- * `skipIfNoChange()` with `Object.is` stops it. When the whole next state is
113
+ * `map`, comparing with `Object.is`, stops there. When the whole next state is
114
114
  * deeply equal, the current state is kept and nothing is passed on, so
115
115
  * `equals` can stay `Object.is`.
116
116
  *
@@ -80,7 +80,7 @@ import { type StateOptions } from './create-reducer.mjs';
80
80
  * { keepEqualParts: true },
81
81
  * );
82
82
  *
83
- * const summary = report.pipe(map((r) => r.summary)).pipe(skipIfNoChange());
83
+ * const summary = report.pipe(map((r) => r.summary));
84
84
  *
85
85
  * const summaryHistory: unknown[] = [];
86
86
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synstate",
3
- "version": "5.0.1",
3
+ "version": "6.1.0",
4
4
  "description": "Type-safe State Management Library for TypeScript/JavaScript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,31 +34,33 @@
34
34
  "ts-type-forge": "^9.2.2"
35
35
  },
36
36
  "devDependencies": {
37
+ "@preact/signals-core": "1.14.4",
37
38
  "@reduxjs/toolkit": "2.13.0",
38
- "@sumi-lang/cli": "0.1.1",
39
+ "@sumi-lang/cli": "0.1.2",
39
40
  "@types/react": "19.3.0",
40
41
  "@vitest/browser-playwright": "5.0.5",
41
42
  "argparse": "3.0.3",
42
- "eslint-config-typed": "5.19.2",
43
- "eslint-plugin-ts-data-forge": "0.10.3",
44
- "eslint-plugin-ts-fortress": "1.3.8",
45
- "eslint-plugin-ts-type-forge": "0.8.13",
43
+ "eslint-config-typed": "5.20.1",
44
+ "eslint-plugin-ts-data-forge": "0.10.4",
45
+ "eslint-plugin-ts-fortress": "1.3.9",
46
+ "eslint-plugin-ts-type-forge": "0.8.14",
46
47
  "jotai": "3.0.1",
47
- "mobx": "7.0.6",
48
+ "mobx": "7.1.0",
48
49
  "playwright": "1.64.1",
49
50
  "prettier": "3.9.10",
50
51
  "prettier-plugin-organize-imports": "4.3.0",
51
52
  "prettier-plugin-packagejson": "3.0.2",
52
53
  "react": "19.3.1",
53
54
  "rxjs": "7.8.2",
54
- "synstate-react-hooks": "5.0.1",
55
- "synstate-react-hooks-compat": "5.0.1",
55
+ "solid-js": "1.9.17",
56
+ "synstate-react-hooks": "6.1.0",
57
+ "synstate-react-hooks-compat": "6.1.0",
56
58
  "ts-repo-utils": "10.7.1",
57
59
  "valtio": "2.3.2",
58
60
  "zustand": "5.0.15"
59
61
  },
60
62
  "engines": {
61
- "node": ">=22.22.2",
63
+ "node": ">=22.23.4",
62
64
  "pnpm": ">=9.0.0"
63
65
  },
64
66
  "publishConfig": {
@@ -146,7 +146,7 @@ export class ObservableBaseClass<
146
146
  // A set, not an array: a completed child removes itself, and that has to
147
147
  // be O(1) for a UI that creates and completes derived nodes on every mount.
148
148
  if (this.#mut_children === undefined) {
149
- this.#mut_children = new Set([child]);
149
+ this.#mut_children = new Set<ChildNode>([child]);
150
150
  } else {
151
151
  this.#mut_children.add(child);
152
152
  }
@@ -321,7 +321,7 @@ export class ObservableBaseClass<
321
321
 
322
322
  const subscriber = toSubscriber(onNext, onComplete);
323
323
 
324
- this.#mut_subscribers ??= new Set();
324
+ this.#mut_subscribers ??= new Set<Subscriber<A>>();
325
325
 
326
326
  this.#mut_subscribers.add(subscriber);
327
327
 
@@ -251,7 +251,7 @@ class UpdateQueue {
251
251
  // Another open update has queued `child` and may not have visited
252
252
  // it yet: leave its mark alone.
253
253
  if (this.#mut_queuedDespiteMark === undefined) {
254
- this.#mut_queuedDespiteMark = new Set();
254
+ this.#mut_queuedDespiteMark = new Set<ChildNode>();
255
255
  } else if (this.#mut_queuedDespiteMark.has(child)) {
256
256
  continue;
257
257
  }
@@ -1,12 +1,5 @@
1
- // Sumi bans classes, `this`, method syntax and writes to `this` outside a
2
- // `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
3
- // so those rules are waived here (D-63).
4
- // @sumi-expect-error-file classes/no-class
5
- // @sumi-expect-error-file banned-syntax/no-this
6
- // @sumi-expect-error-file functions/prefer-arrow-function
7
- import { Arr, expectType, Optional } from 'ts-data-forge';
8
- import type { NonEmptyTuple, Tuple } from 'ts-type-forge';
9
- import { SyncChildObservableClass } from '../class/index.mjs';
1
+ import { expectType } from 'ts-data-forge';
2
+ import type { NonEmptyTuple } from 'ts-type-forge';
10
3
  import { source } from '../create/index.mjs';
11
4
  import { withInitialValue } from '../operators/index.mjs';
12
5
  import type {
@@ -14,12 +7,10 @@ import type {
14
7
  CombineObservableRefined,
15
8
  InitializedObservable,
16
9
  InitializedSyncChildObservable,
17
- NonEmptyUnknownList,
18
10
  Observable,
19
11
  SyncChildObservable,
20
- UpdateToken,
21
- Wrap,
22
12
  } from '../types/index.mjs';
13
+ import { derive } from './derive.mjs';
23
14
 
24
15
  /**
25
16
  * Combines multiple observables into a single observable that emits an array of their latest values.
@@ -81,9 +72,12 @@ import type {
81
72
  export const combine = <const OS extends NonEmptyTuple<Observable<unknown>>>(
82
73
  parents: OS,
83
74
  ): CombineObservableRefined<OS> =>
75
+ // `derive` collecting the values into a new array on every update, which is
76
+ // never `Object.is` the one before, so every update is passed on.
84
77
  // @sumi-expect-error banned-syntax/no-unsafe-type-assertion
85
- new CombineObservableClass(
78
+ derive(
86
79
  parents,
80
+ (...values) => values,
87
81
  ) as unknown as CombineObservableRefined<OS>;
88
82
 
89
83
  /**
@@ -92,65 +86,6 @@ export const combine = <const OS extends NonEmptyTuple<Observable<unknown>>>(
92
86
  */
93
87
  export const combineLatest = combine;
94
88
 
95
- class CombineObservableClass<const A extends NonEmptyUnknownList>
96
- extends SyncChildObservableClass<A, A>
97
- implements CombineObservable<A>
98
- {
99
- constructor(parents: Wrap<A>) {
100
- const parentsValues: Tuple.MapTo<Optional<A[number]>, A> = Arr.map(
101
- parents,
102
- (p) => p.getSnapshot(),
103
- );
104
-
105
- // The annotation on `initialValue` is what replaces the type assertion.
106
- // `Arr.map` carries a single result element type, so it reports `A[number]`
107
- // at every position, and `Tuple.MapTo<A[number], A>` — the uniform mapping
108
- // — is *not* assignable back to `A`. The positional
109
- // `Readonly<{ [K in keyof A]: A[K] }>` is, and TypeScript accepts the
110
- // uniform result into it because the two mapped types share `keyof A`. So
111
- // it is the annotation, not an assertion, that records the position-wise
112
- // fact the checker cannot derive on its own.
113
- const initialValue: Optional<Readonly<{ [K in keyof A]: A[K] }>> =
114
- Arr.every(parentsValues, Optional.isSome)
115
- ? Optional.some(Arr.map(parentsValues, (c) => c.value))
116
- : Optional.none;
117
-
118
- super({
119
- parents,
120
- initialValue,
121
- });
122
-
123
- this.attach();
124
- }
125
-
126
- override tryUpdate(updateToken: UpdateToken): void {
127
- const parents = this.parents;
128
-
129
- if (parents.every((o) => o.updateToken !== updateToken)) {
130
- return; // all parents are skipped
131
- }
132
-
133
- // Same shape-preserving chain as the initial value: `Arr.map` (not the
134
- // native one, which drops the tuple shape) into the uniform
135
- // `Tuple.MapTo`, then a positional annotation to get back to `A`.
136
- const parentValues: Tuple.MapTo<Optional<A[number]>, A> = Arr.map(
137
- parents,
138
- (a) => a.getSnapshot(),
139
- );
140
-
141
- if (!Arr.every(parentValues, Optional.isSome)) {
142
- return;
143
- }
144
-
145
- const nextValue: Readonly<{ [K in keyof A]: A[K] }> = Arr.map(
146
- parentValues,
147
- (a) => a.value,
148
- );
149
-
150
- this.setNext(nextValue, updateToken);
151
- }
152
- }
153
-
154
89
  if (import.meta.vitest !== undefined) {
155
90
  test('type test', () => {
156
91
  expect(1).toBe(1); // dummy
@@ -0,0 +1,172 @@
1
+ // Sumi bans classes, `this`, method syntax and writes to `this` outside a
2
+ // `mut_` binding; an observable is a class (`ObservableBaseClass` says why),
3
+ // so those rules are waived here (D-63).
4
+ // @sumi-expect-error-file classes/no-class
5
+ // @sumi-expect-error-file banned-syntax/no-this
6
+ // @sumi-expect-error-file functions/prefer-arrow-function
7
+ // @sumi-expect-error-file mutation/no-mutation-without-mut-prefix
8
+ import { Arr, Optional } from 'ts-data-forge';
9
+ import type { NonEmptyTuple } from 'ts-type-forge';
10
+ import { SyncChildObservableClass } from '../class/index.mjs';
11
+ import type {
12
+ DeriveObservable,
13
+ DeriveObservableRefined,
14
+ NonEmptyUnknownList,
15
+ Observable,
16
+ Unwrap,
17
+ UpdateToken,
18
+ Wrap,
19
+ } from '../types/index.mjs';
20
+
21
+ /**
22
+ * Derives one value from the latest values of several observables: one
23
+ * observable that calls `project` with them, as arguments, and emits the
24
+ * result unless it equals the one already held.
25
+ *
26
+ * It emits once every parent has a value, and then whenever any of them
27
+ * emits, as `combine` does; but where `combine(parents).pipe(map(fn))` is two
28
+ * observables and a tuple per update, `derive` is one, and passes the values
29
+ * as arguments (a rest parameter in `project` collects them into an array
30
+ * again).
31
+ * The comparison is `Object.is` unless `equals` says otherwise.
32
+ *
33
+ * @template OS - Tuple type of the parent observables
34
+ * @template B - The type of the derived value
35
+ * @param parents - The observables to derive from
36
+ * @param project - Computes the value from the parents' values, in order
37
+ * @param options - `equals` compares a result with the one held
38
+ * @returns An observable of the derived value, initialized when every parent is
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * // Timeline:
43
+ * //
44
+ * // price$ 100 120
45
+ * // quantity$ 2 3
46
+ * // total$ 200 240 360
47
+ * //
48
+ * // Explanation:
49
+ * // - derive waits for every parent to have a value
50
+ * // - Then calls the projection with their latest values whenever one emits
51
+ *
52
+ * const price$ = source<number>();
53
+ *
54
+ * const quantity$ = source<number>();
55
+ *
56
+ * const total$ = derive(
57
+ * [price$, quantity$],
58
+ * (price, quantity) => price * quantity,
59
+ * );
60
+ *
61
+ * const totalHistory: number[] = [];
62
+ *
63
+ * total$.subscribe((total) => {
64
+ * totalHistory.push(total);
65
+ * });
66
+ *
67
+ * price$.next(100); // nothing yet: quantity$ has no value
68
+ *
69
+ * quantity$.next(2); // 200
70
+ *
71
+ * price$.next(120); // 240
72
+ *
73
+ * quantity$.next(3); // 360
74
+ *
75
+ * assert.deepStrictEqual(totalHistory, [200, 240, 360]);
76
+ * ```
77
+ */
78
+ export const derive = <const OS extends NonEmptyTuple<Observable<unknown>>, B>(
79
+ parents: OS,
80
+ project: (...values: Unwrap<OS>) => B,
81
+ options?: Readonly<{ equals?: (x: B, y: B) => boolean }>,
82
+ ): DeriveObservableRefined<B, OS> =>
83
+ // @sumi-expect-error banned-syntax/no-unsafe-type-assertion
84
+ new DeriveObservableClass(
85
+ parents,
86
+ // `project` is called with the values of `parents`, position by
87
+ // position, which the checker cannot follow through an index.
88
+ // @sumi-expect-error banned-syntax/no-unsafe-type-assertion
89
+ project as (...values: readonly unknown[]) => B,
90
+ options?.equals ?? Object.is,
91
+ ) as unknown as DeriveObservableRefined<B, OS>;
92
+
93
+ class DeriveObservableClass<const A extends NonEmptyUnknownList, B>
94
+ extends SyncChildObservableClass<B, A>
95
+ implements DeriveObservable<B, A>
96
+ {
97
+ readonly #project: (...values: readonly unknown[]) => B;
98
+ readonly #equals: (x: B, y: B) => boolean;
99
+
100
+ /**
101
+ * The parents' values, rewritten by every update. `project` receives them
102
+ * spread, as arguments of its own, so nothing it is given changes later and
103
+ * no array is built per update.
104
+ */
105
+ // @sumi-expect-error readonly/require-readonly-type
106
+ readonly #mut_values: unknown[];
107
+
108
+ constructor(
109
+ parents: Wrap<A>,
110
+ project: (...values: readonly unknown[]) => B,
111
+ equals: (x: B, y: B) => boolean,
112
+ ) {
113
+ const snapshots = Arr.map(parents, (p) => p.getSnapshot());
114
+
115
+ const mut_values = Array.from(snapshots, (s): unknown =>
116
+ Optional.isSome(s) ? s.value : undefined,
117
+ );
118
+
119
+ super({
120
+ parents,
121
+ initialValue: Arr.every(snapshots, Optional.isSome)
122
+ ? Optional.some(project(...mut_values))
123
+ : Optional.none,
124
+ });
125
+
126
+ this.#project = project;
127
+
128
+ this.#equals = equals;
129
+
130
+ this.#mut_values = mut_values;
131
+
132
+ this.attach();
133
+ }
134
+
135
+ override tryUpdate(updateToken: UpdateToken): void {
136
+ const mut_values = this.#mut_values;
137
+
138
+ let mut_updated = false;
139
+
140
+ let mut_index = 0;
141
+
142
+ for (const parent of this.parents) {
143
+ const snapshot = parent.getSnapshot();
144
+
145
+ if (Optional.isNone(snapshot)) {
146
+ return; // a parent has no value yet
147
+ }
148
+
149
+ mut_values[mut_index] = snapshot.value;
150
+
151
+ mut_index += 1;
152
+
153
+ if (parent.updateToken === updateToken) {
154
+ mut_updated = true;
155
+ }
156
+ }
157
+
158
+ if (!mut_updated) {
159
+ return; // all parents are skipped
160
+ }
161
+
162
+ const next = this.#project(...mut_values);
163
+
164
+ const held = this.getSnapshot();
165
+
166
+ if (Optional.isSome(held) && this.#equals(held.value, next)) {
167
+ return; // the result did not change
168
+ }
169
+
170
+ this.setNext(next, updateToken);
171
+ }
172
+ }