synstate 6.1.0 → 6.2.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.
- package/README.md +4 -4
- package/dist/core/authoring.d.mts +3 -3
- package/dist/core/class/child-observable-class.d.mts +24 -25
- package/dist/core/class/child-observable-class.d.mts.map +1 -1
- package/dist/core/class/child-observable-class.mjs +41 -42
- package/dist/core/class/child-observable-class.mjs.map +1 -1
- package/dist/core/class/create-child-observable.d.mts +27 -29
- package/dist/core/class/create-child-observable.d.mts.map +1 -1
- package/dist/core/class/create-child-observable.mjs.map +1 -1
- package/dist/core/class/create-root-observable.d.mts +11 -11
- package/dist/core/class/manager-observable-class.d.mts +6 -6
- package/dist/core/class/manager-observable-class.d.mts.map +1 -1
- package/dist/core/class/manager-observable-class.mjs +6 -0
- package/dist/core/class/manager-observable-class.mjs.map +1 -1
- package/dist/core/class/observable-base-class.d.mts +32 -26
- package/dist/core/class/observable-base-class.d.mts.map +1 -1
- package/dist/core/class/observable-base-class.mjs +16 -3
- package/dist/core/class/observable-base-class.mjs.map +1 -1
- package/dist/core/class/observable-node.d.mts +3 -4
- package/dist/core/class/observable-node.d.mts.map +1 -1
- package/dist/core/class/observable-node.mjs +0 -1
- package/dist/core/class/observable-node.mjs.map +1 -1
- package/dist/core/class/propagation-state.d.mts +10 -9
- package/dist/core/class/propagation-state.d.mts.map +1 -1
- package/dist/core/class/propagation-state.mjs +4 -2
- package/dist/core/class/propagation-state.mjs.map +1 -1
- package/dist/core/class/root-observable-class.d.mts +4 -4
- package/dist/core/combine/derive.d.mts +7 -8
- package/dist/core/combine/derive.d.mts.map +1 -1
- package/dist/core/combine/derive.mjs +0 -1
- package/dist/core/combine/derive.mjs.map +1 -1
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts +3 -3
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/counter.d.mts +3 -3
- package/dist/core/create/counter.mjs.map +1 -1
- package/dist/core/create/from-abortable-promise.mjs.map +1 -1
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/operators/audit.mjs.map +1 -1
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/keep-equal-parts.d.mts +14 -15
- package/dist/core/operators/keep-equal-parts.d.mts.map +1 -1
- package/dist/core/operators/keep-equal-parts.mjs +0 -1
- package/dist/core/operators/keep-equal-parts.mjs.map +1 -1
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts +3 -3
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/take.mjs.map +1 -1
- package/dist/core/operators/throttle.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
- package/dist/core/predefined/operators/map-to.d.mts +3 -4
- package/dist/core/predefined/operators/map-to.d.mts.map +1 -1
- package/dist/core/predefined/operators/map-to.mjs +0 -1
- package/dist/core/predefined/operators/map-to.mjs.map +1 -1
- package/dist/core/scope/scope.d.mts +4 -4
- package/dist/core/types/id.d.mts +2 -1
- package/dist/core/types/id.d.mts.map +1 -1
- package/dist/core/types/observable-family.d.mts.map +1 -1
- package/dist/core/types/observable-family.mjs.map +1 -1
- package/dist/core/types/observable.d.mts +7 -6
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/utils/current-scope.d.mts +6 -6
- package/dist/core/utils/id-maker.d.mts +7 -0
- package/dist/core/utils/id-maker.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +9 -0
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/core/utils/observable-brand.d.mts +5 -5
- package/dist/utils/create-boolean-state.d.mts +2 -2
- package/dist/utils/create-reducer.d.mts +20 -20
- package/dist/utils/create-reducer.d.mts.map +1 -1
- package/dist/utils/create-reducer.mjs +4 -16
- package/dist/utils/create-reducer.mjs.map +1 -1
- package/dist/utils/create-state.d.mts +3 -3
- package/dist/utils/create-state.d.mts.map +1 -1
- package/dist/utils/create-state.mjs +10 -13
- package/dist/utils/create-state.mjs.map +1 -1
- package/dist/utils/state-source.d.mts +19 -0
- package/dist/utils/state-source.d.mts.map +1 -0
- package/dist/utils/state-source.mjs +31 -0
- package/dist/utils/state-source.mjs.map +1 -0
- package/package.json +10 -10
- package/src/core/authoring.mts +3 -3
- package/src/core/class/child-observable-class.mts +86 -87
- package/src/core/class/circular-dependency-comparison.test.mts +2 -2
- package/src/core/class/create-child-observable.mts +27 -29
- package/src/core/class/create-root-observable.mts +11 -11
- package/src/core/class/manager-observable-class.mts +16 -9
- package/src/core/class/observable-base-class.mts +48 -30
- package/src/core/class/observable-node.mts +3 -4
- package/src/core/class/propagation-state.mts +31 -29
- package/src/core/class/remove-completed.test.mts +2 -2
- package/src/core/class/root-observable-class.mts +9 -9
- package/src/core/class/unobserved-write.test.mts +194 -0
- package/src/core/combine/derive.mts +10 -11
- package/src/core/combine/merge.mts +2 -2
- package/src/core/combine/zip.mts +7 -7
- package/src/core/create/counter.mts +5 -5
- package/src/core/create/from-abortable-promise.mts +2 -2
- package/src/core/create/from-promise.mts +2 -2
- package/src/core/create/from-subscribable.mts +2 -2
- package/src/core/create/source.mts +5 -5
- package/src/core/create/timer.mts +2 -2
- package/src/core/operators/audit.mts +2 -2
- package/src/core/operators/debounce.mts +2 -2
- package/src/core/operators/filter.mts +4 -4
- package/src/core/operators/keep-equal-parts.mts +16 -17
- package/src/core/operators/map.mts +2 -2
- package/src/core/operators/merge-map.mts +5 -5
- package/src/core/operators/pairwise.mts +4 -4
- package/src/core/operators/scan.mts +2 -2
- package/src/core/operators/skip-if-no-change.mts +4 -4
- package/src/core/operators/skip-until.mts +4 -4
- package/src/core/operators/skip-while.mts +2 -2
- package/src/core/operators/switch-map.mts +5 -5
- package/src/core/operators/take-until.mts +2 -2
- package/src/core/operators/take-while.mts +2 -2
- package/src/core/operators/take.mts +2 -2
- package/src/core/operators/throttle.mts +2 -2
- package/src/core/operators/with-buffered-from.mts +2 -2
- package/src/core/operators/with-current-value-from.mts +2 -2
- package/src/core/operators/with-initial-value.mts +2 -2
- package/src/core/predefined/operators/attach-index.mts +2 -2
- package/src/core/predefined/operators/map-to.mts +3 -4
- package/src/core/scope/scope.mts +6 -6
- package/src/core/types/id.mts +2 -1
- package/src/core/types/observable-family.mts +4 -5
- package/src/core/types/observable.mts +9 -8
- package/src/core/utils/current-scope.mts +8 -8
- package/src/core/utils/id-maker.mts +10 -0
- package/src/core/utils/observable-brand.mts +5 -5
- package/src/utils/create-boolean-state.mts +2 -2
- package/src/utils/create-reducer.mts +27 -42
- package/src/utils/create-state.mts +14 -31
- package/src/utils/create-state.test.mts +20 -2
- package/src/utils/state-source.mts +48 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -79,9 +79,9 @@ class SourceObservableClass<A>
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// Returns the value held after the call: `nextValue`, or, once completed,
|
|
83
|
-
//
|
|
84
|
-
//
|
|
82
|
+
// Returns the value held after the call: `nextValue`, or, once completed, the
|
|
83
|
+
// value already there — `undefined` only on a source that never had one,
|
|
84
|
+
// whose `next` is typed `void`.
|
|
85
85
|
next(nextValue: A): A | undefined {
|
|
86
86
|
if (this.isCompleted) {
|
|
87
87
|
return Optional.unwrap(this.getSnapshot());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -175,8 +175,8 @@ if (import.meta.vitest !== undefined) {
|
|
|
175
175
|
|
|
176
176
|
expectType<typeof _inferred, Observable<number>>('=');
|
|
177
177
|
|
|
178
|
-
// A generic guard is what a single signature with a union parameter
|
|
179
|
-
//
|
|
178
|
+
// A generic guard is what a single signature with a union parameter loses
|
|
179
|
+
// (it infers `unknown`), and why this set stays overloaded.
|
|
180
180
|
const _generic = s.pipe(filter(isNotUndefined));
|
|
181
181
|
|
|
182
182
|
expectType<typeof _generic, Observable<number>>('=');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -20,19 +20,19 @@ import type {
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Passes on each value with every part deeply equal to the same part of the
|
|
23
|
-
* value passed on before replaced by that part, and skips a value deeply
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* value passed on before replaced by that part, and skips a value deeply equal
|
|
24
|
+
* to it altogether (structural sharing). A reader of a part that did not change
|
|
25
|
+
* keeps the object it has, so `skipIfNoChange()` with `Object.is` stops it.
|
|
26
|
+
* Superset of `skipIfNoChange(fastDeepEqual)`.
|
|
27
27
|
*
|
|
28
28
|
* **Prefer keeping references where the value is written** — compare before
|
|
29
|
-
* `setState`, and skip it when nothing changed — so that nothing downstream
|
|
30
|
-
*
|
|
31
|
-
* `createReducer` does it for a state written whole, and `replaceEqualDeep`
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
29
|
+
* `setState`, and skip it when nothing changed — so that nothing downstream has
|
|
30
|
+
* anything to undo. The `keepEqualParts` option of `createState` and
|
|
31
|
+
* `createReducer` does it for a state written whole, and `replaceEqualDeep` of
|
|
32
|
+
* ts-data-forge does it for any other write. This operator lets every update
|
|
33
|
+
* that changes nothing reach the source and everything up to it, and walks the
|
|
34
|
+
* whole value again on each one; reach for it when the source is not yours to
|
|
35
|
+
* change (a stream that arrives whole from outside).
|
|
36
36
|
*
|
|
37
37
|
* Array items are matched by index; pass `{ key }` to match them by key, an
|
|
38
38
|
* item for which `key` returns `undefined` being matched by index. Only plain
|
|
@@ -51,10 +51,9 @@ import type {
|
|
|
51
51
|
* cards: { id: number; text: string }[];
|
|
52
52
|
* }>;
|
|
53
53
|
*
|
|
54
|
-
* // A stream that arrives whole from outside (a WebSocket, say), each
|
|
55
|
-
* //
|
|
56
|
-
* //
|
|
57
|
-
* // instead.
|
|
54
|
+
* // A stream that arrives whole from outside (a WebSocket, say), each message
|
|
55
|
+
* // a new object even when nothing changed. A state you write yourself takes
|
|
56
|
+
* // `createState(initial, { keepEqualParts: true })` instead.
|
|
58
57
|
* const message$ = source<Board>();
|
|
59
58
|
*
|
|
60
59
|
* const board$ = message$.pipe(keepEqualParts());
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -22,9 +22,9 @@ import type {
|
|
|
22
22
|
* Unlike `switchMap`, does not cancel previous inner observables.
|
|
23
23
|
*
|
|
24
24
|
* Each projection runs in a scope of its own (see `createScope`): what it
|
|
25
|
-
* creates is disposed when `mergeMap` completes. An observable it only
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* creates is disposed when `mergeMap` completes. An observable it only returns
|
|
26
|
+
* — one created outside the projection and shared with others — is unsubscribed
|
|
27
|
+
* and left running.
|
|
28
28
|
*
|
|
29
29
|
* @template A - The type of values from the source
|
|
30
30
|
* @template B - The type of values from the projected observable
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -90,8 +90,8 @@ class PairwiseObservableClass<A>
|
|
|
90
90
|
initialValue: Optional.none,
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
// parentObservable.snapshot has value
|
|
94
|
-
//
|
|
93
|
+
// parentObservable.snapshot has value if parentObservable is
|
|
94
|
+
// InitializedObservable
|
|
95
95
|
this.#mut_previousValue = parentObservable.getSnapshot();
|
|
96
96
|
|
|
97
97
|
this.attach();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -104,8 +104,8 @@ class SkipIfNoChangeObservableClass<A>
|
|
|
104
104
|
initialValue: parentObservable.getSnapshot(),
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
// parentObservable.snapshot has value
|
|
108
|
-
//
|
|
107
|
+
// parentObservable.snapshot has value if parentObservable is
|
|
108
|
+
// InitializedObservable
|
|
109
109
|
this.#mut_previousValue = parentObservable.getSnapshot();
|
|
110
110
|
|
|
111
111
|
this.#eq = eq;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -83,8 +83,8 @@ class SkipUntilObservableClass<A>
|
|
|
83
83
|
initialValue: Optional.none,
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
// A notifier that already holds a value, or has completed, would stop
|
|
87
|
-
//
|
|
86
|
+
// A notifier that already holds a value, or has completed, would stop the
|
|
87
|
+
// skipping inside `subscribe`, before the subscription is stored.
|
|
88
88
|
this.#mut_isSkipping =
|
|
89
89
|
Optional.isNone(notifier.getSnapshot()) && !notifier.isCompleted;
|
|
90
90
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -126,9 +126,9 @@ class SwitchMapObservableClass<A, B>
|
|
|
126
126
|
readonly #mapToObservable: (curr: A) => Observable<B>;
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* The scope the operator was created in, so that each inner scope is
|
|
130
|
-
*
|
|
131
|
-
*
|
|
129
|
+
* The scope the operator was created in, so that each inner scope is disposed
|
|
130
|
+
* with it; the projection itself runs during propagation, when the current
|
|
131
|
+
* scope is whatever happens to be running.
|
|
132
132
|
*/
|
|
133
133
|
readonly #ownerScope: Scope | undefined;
|
|
134
134
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
//
|
|
2
|
+
// `mut_` binding; an observable is a class (`ObservableBaseClass` says why), so
|
|
3
|
+
// those rules are waived here (D-63).
|
|
4
4
|
// @sumi-expect-error-file classes/no-class
|
|
5
5
|
// @sumi-expect-error-file banned-syntax/no-this
|
|
6
6
|
// @sumi-expect-error-file functions/prefer-arrow-function
|
|
@@ -4,10 +4,9 @@ import type { KeepInitialValueOperator } from '../../types/index.mjs';
|
|
|
4
4
|
/**
|
|
5
5
|
* Maps all emitted values to a constant value, ignoring the source values.
|
|
6
6
|
* Emits on every source value although the value never changes — where
|
|
7
|
-
* `map(() => value)` would stop every result after the first as equal — so
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `'reset'`, not `string`.
|
|
7
|
+
* `map(() => value)` would stop every result after the first as equal — so it
|
|
8
|
+
* is the one for turning events into a value. The value's type is inferred as
|
|
9
|
+
* written, as with `as const`: `mapTo('reset')` gives `'reset'`, not `string`.
|
|
11
10
|
*
|
|
12
11
|
* @template A - The type of values from the source
|
|
13
12
|
* @template B - The type of the constant value
|
package/src/core/scope/scope.mts
CHANGED
|
@@ -23,8 +23,8 @@ import {
|
|
|
23
23
|
* disposed gives a scope that is born disposed, with a warning.
|
|
24
24
|
*
|
|
25
25
|
* Intended for authors of libraries built on synstate rather than for
|
|
26
|
-
* application code; state defined at module level belongs to no scope and
|
|
27
|
-
*
|
|
26
|
+
* application code; state defined at module level belongs to no scope and lives
|
|
27
|
+
* as long as the page.
|
|
28
28
|
*
|
|
29
29
|
* `run` and `dispose` read the scope they are called on, so call them on it
|
|
30
30
|
* (`scope.dispose()`) rather than taking them off it.
|
|
@@ -50,8 +50,8 @@ export const getCurrentScope = (): Scope | undefined =>
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Registers `cleanup` to be called when the current scope is disposed. Cleanups
|
|
53
|
-
* run after the child scopes are disposed and before the owned observables
|
|
54
|
-
*
|
|
53
|
+
* run after the child scopes are disposed and before the owned observables are,
|
|
54
|
+
* newest first.
|
|
55
55
|
*
|
|
56
56
|
* Outside every scope it warns and registers nothing.
|
|
57
57
|
*
|
|
@@ -85,8 +85,8 @@ export const untracked = <R,>(body: () => R): R =>
|
|
|
85
85
|
* A scope is created for every row and branch of a UI, so creating one has to
|
|
86
86
|
* be cheap. It used to be a set of closures with a `Set` of children, a `Set`
|
|
87
87
|
* of owned observables and a record in a `WeakMap`; it is now one object whose
|
|
88
|
-
* methods live on the prototype and whose lists are arrays made when the
|
|
89
|
-
*
|
|
88
|
+
* methods live on the prototype and whose lists are arrays made when the first
|
|
89
|
+
* entry arrives.
|
|
90
90
|
*
|
|
91
91
|
* Whatever leaves a list on its own (a child scope disposed by itself, an
|
|
92
92
|
* observable that completed) is not looked up and spliced out: it only counts
|
package/src/core/types/id.mts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Brand, UnknownRecord } from 'ts-type-forge';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Identifies one update. Opaque: an object issued per update, which is also
|
|
5
|
-
* that update's queue
|
|
5
|
+
* that update's queue — except for a write nothing observes, which opens no
|
|
6
|
+
* update and is issued a token with no queue behind it.
|
|
6
7
|
*/
|
|
7
8
|
export type UpdateToken = Brand<UnknownRecord, 'update-token'>;
|
|
@@ -65,11 +65,10 @@ export type ScanOperatorObservable<A, B> = InitializedSyncChildObservable<
|
|
|
65
65
|
|
|
66
66
|
// SyncChildObservable
|
|
67
67
|
|
|
68
|
-
// The helpers stay in a namespace so their names do not crowd the module
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
//
|
|
72
|
-
// they check.
|
|
68
|
+
// The helpers stay in a namespace so their names do not crowd the module scope.
|
|
69
|
+
// A namespace holding only types is erasable, so it passes `erasableSyntaxOnly`
|
|
70
|
+
// (TS1294); the `expectType` assertions are call statements, which is why they
|
|
71
|
+
// sit below it rather than beside the types they check.
|
|
73
72
|
namespace SynStateInternals {
|
|
74
73
|
type Cast<A> = A extends NonEmptyUnknownList ? A : never;
|
|
75
74
|
|
|
@@ -32,8 +32,8 @@ type CreateObservableType<A, Kind extends ObservableKind> = Readonly<{
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* One more than the deepest observable this one is derived from; 0 for a
|
|
35
|
-
* root. An update reaches observables in ascending depth, so every parent
|
|
36
|
-
*
|
|
35
|
+
* root. An update reaches observables in ascending depth, so every parent has
|
|
36
|
+
* emitted before its child reads it.
|
|
37
37
|
*/
|
|
38
38
|
depth: Kind extends 'root' ? 0 : number;
|
|
39
39
|
|
|
@@ -44,7 +44,8 @@ type CreateObservableType<A, Kind extends ObservableKind> = Readonly<{
|
|
|
44
44
|
* The token of the update in which this observable last emitted. A child's
|
|
45
45
|
* `tryUpdate` receives the token of the update now propagating; a parent
|
|
46
46
|
* whose token differs did not emit in it. The token is opaque: compare it,
|
|
47
|
-
* store it, or pass
|
|
47
|
+
* store it, or pass the one `tryUpdate` received on to `setNext`. A write
|
|
48
|
+
* nothing observes opens no update, and its token has no queue behind it.
|
|
48
49
|
*/
|
|
49
50
|
updateToken: UpdateToken;
|
|
50
51
|
|
|
@@ -172,9 +173,9 @@ export type Operator<A, B> =
|
|
|
172
173
|
| KeepInitialValueOperator<A, B>;
|
|
173
174
|
|
|
174
175
|
/**
|
|
175
|
-
* Tells an observable made by synstate from any other value, by the brand
|
|
176
|
-
*
|
|
177
|
-
*
|
|
176
|
+
* Tells an observable made by synstate from any other value, by the brand every
|
|
177
|
+
* observable carries. Checking for a `subscribe` method instead would also
|
|
178
|
+
* accept plain values that happen to have one.
|
|
178
179
|
*
|
|
179
180
|
* @example
|
|
180
181
|
*
|
|
@@ -222,8 +223,8 @@ export type WrapInitialized<A extends readonly unknown[]> = Readonly<{
|
|
|
222
223
|
// type GetDestTypeOfOperator<Op extends Operator<unknown, unknown>> =
|
|
223
224
|
// Op extends Operator<unknown, infer B> ? B : never;
|
|
224
225
|
|
|
225
|
-
// Only the members meant for users are public; the rest live on the
|
|
226
|
-
//
|
|
226
|
+
// Only the members meant for users are public; the rest live on the internal
|
|
227
|
+
// node types in `core/class` (#2117).
|
|
227
228
|
expectType<
|
|
228
229
|
keyof Observable<unknown>,
|
|
229
230
|
| typeof observableBrand
|
|
@@ -7,10 +7,10 @@ export type ScopeMember = Readonly<{
|
|
|
7
7
|
}>;
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* The side of a scope the rest of the core talks to, on top of its public
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* The side of a scope the rest of the core talks to, on top of its public face
|
|
11
|
+
* {@link Scope}. Kept out of the public API (`core/utils/**` is excluded from
|
|
12
|
+
* index generation), so that only `createScope` and its siblings decide what a
|
|
13
|
+
* scope owns.
|
|
14
14
|
*/
|
|
15
15
|
export type ScopeInternals = Scope &
|
|
16
16
|
Readonly<{
|
|
@@ -18,8 +18,8 @@ export type ScopeInternals = Scope &
|
|
|
18
18
|
adopt: (node: ScopeMember) => void;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Tells the scope that one of the nodes it adopted completed on its own,
|
|
22
|
-
*
|
|
21
|
+
* Tells the scope that one of the nodes it adopted completed on its own, so
|
|
22
|
+
* that the scope can drop it and keep no reference to it. The node is
|
|
23
23
|
* completed (`isCompleted`) by the time it calls this.
|
|
24
24
|
*/
|
|
25
25
|
release: () => void;
|
|
@@ -28,8 +28,8 @@ export type ScopeInternals = Scope &
|
|
|
28
28
|
}>;
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* The scope whose `run` is executing. A field rather than a module-level
|
|
32
|
-
*
|
|
31
|
+
* The scope whose `run` is executing. A field rather than a module-level `let`,
|
|
32
|
+
* so that the one place writing it is visibly this object.
|
|
33
33
|
*/
|
|
34
34
|
const mut_slot: { current: ScopeInternals | undefined } = {
|
|
35
35
|
current: undefined,
|
|
@@ -8,3 +8,13 @@ import type { UpdateToken } from '../types/index.mjs';
|
|
|
8
8
|
export const notUpdatedYet: UpdateToken =
|
|
9
9
|
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
10
10
|
Object.freeze({}) as UpdateToken;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Issues the token of a write that opens no update, because nothing observes
|
|
14
|
+
* the observable written to (`setNextIfUnobserved`). Nothing is ever queued
|
|
15
|
+
* with it, so it is a token and not a queue, unlike the tokens `openUpdate`
|
|
16
|
+
* issues.
|
|
17
|
+
*/
|
|
18
|
+
export const issueUnqueuedToken = (): UpdateToken =>
|
|
19
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
20
|
+
({}) as UpdateToken;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The key every observable carries, set to `true` by `assembleObservable`. It
|
|
3
|
-
* lets `isObservable` tell an observable from any other value at run time —
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* lets `isObservable` tell an observable from any other value at run time — a
|
|
4
|
+
* `subscribe` method is not enough, since plain values may have one — and, as a
|
|
5
|
+
* type, makes the public observable types impossible to satisfy with an object
|
|
6
|
+
* literal: an imitation passed to an operator would lack the internal members
|
|
7
|
+
* propagation reads and fail at run time instead of at compile time.
|
|
8
8
|
*
|
|
9
9
|
* `Symbol.for`, so that an observable made by another copy of synstate in the
|
|
10
10
|
* same program is still recognized.
|
|
@@ -18,8 +18,8 @@ import { createState } from './create-state.mjs';
|
|
|
18
18
|
* import { useObservableValue } from 'synstate-react-hooks';
|
|
19
19
|
*
|
|
20
20
|
* // Menu drawer open/close state.
|
|
21
|
-
* // setTrue and setFalse can be passed directly as callbacks
|
|
22
|
-
* //
|
|
21
|
+
* // setTrue and setFalse can be passed directly as callbacks — no need to
|
|
22
|
+
* // create wrapper functions like `() => setState(true)`.
|
|
23
23
|
* const [menuOpen$, { setTrue: openMenu, setFalse: closeMenu }] =
|
|
24
24
|
* createBooleanState(false);
|
|
25
25
|
*
|