synstate 3.0.3 → 3.0.5
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 +6 -6
- package/dist/core/base/create-child-observable.d.mts.map +1 -1
- package/dist/core/base/create-child-observable.mjs +7 -3
- package/dist/core/base/create-child-observable.mjs.map +1 -1
- package/dist/core/base/create-observable-base.d.mts +2 -1
- package/dist/core/base/create-observable-base.d.mts.map +1 -1
- package/dist/core/base/create-observable-base.mjs +5 -2
- package/dist/core/base/create-observable-base.mjs.map +1 -1
- package/dist/core/base/create-root-observable.d.mts.map +1 -1
- package/dist/core/base/create-root-observable.mjs.map +1 -1
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +7 -4
- package/dist/core/combine/combine.mjs.map +1 -1
- package/dist/core/combine/merge.d.mts.map +1 -1
- package/dist/core/combine/merge.mjs +4 -1
- package/dist/core/combine/merge.mjs.map +1 -1
- package/dist/core/combine/zip.d.mts.map +1 -1
- package/dist/core/combine/zip.mjs +8 -5
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
- package/dist/core/create/from-abortable-promise.mjs +6 -2
- package/dist/core/create/from-abortable-promise.mjs.map +1 -1
- package/dist/core/create/from-promise.d.mts.map +1 -1
- package/dist/core/create/from-promise.mjs +5 -2
- package/dist/core/create/from-promise.mjs.map +1 -1
- package/dist/core/create/from-subscribable.d.mts.map +1 -1
- package/dist/core/create/from-subscribable.mjs +1 -0
- package/dist/core/create/from-subscribable.mjs.map +1 -1
- package/dist/core/create/just.d.mts.map +1 -1
- package/dist/core/create/just.mjs +1 -0
- package/dist/core/create/just.mjs.map +1 -1
- package/dist/core/create/source.mjs +2 -1
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/operators/audit.d.mts.map +1 -1
- package/dist/core/operators/audit.mjs +3 -1
- package/dist/core/operators/audit.mjs.map +1 -1
- package/dist/core/operators/debounce.d.mts.map +1 -1
- package/dist/core/operators/debounce.mjs +3 -1
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/map.d.mts.map +1 -1
- package/dist/core/operators/map.mjs +1 -0
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/skip-if-no-change.d.mts.map +1 -1
- package/dist/core/operators/skip-if-no-change.mjs +1 -0
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts.map +1 -1
- package/dist/core/operators/take-until.mjs +1 -0
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/throttle.d.mts.map +1 -1
- package/dist/core/operators/throttle.mjs +1 -0
- package/dist/core/operators/throttle.mjs.map +1 -1
- package/dist/core/operators/with-buffered-from.d.mts.map +1 -1
- package/dist/core/operators/with-buffered-from.mjs +1 -0
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +2 -1
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-optional.d.mts.map +1 -1
- package/dist/core/predefined/operators/unwrap-optional.mjs +1 -0
- package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-ok.d.mts.map +1 -1
- package/dist/core/predefined/operators/unwrap-result-ok.mjs +1 -0
- package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
- package/dist/core/types/observable.d.mts +1 -1
- package/dist/core/types/observable.d.mts.map +1 -1
- package/dist/core/types/observable.mjs +5 -0
- package/dist/core/types/observable.mjs.map +1 -1
- package/dist/core/types/timer.d.mts +1 -11
- package/dist/core/types/timer.d.mts.map +1 -1
- package/dist/core/utils/id-maker.d.mts.map +1 -1
- package/dist/core/utils/id-maker.mjs +1 -0
- package/dist/core/utils/id-maker.mjs.map +1 -1
- package/dist/core/utils/utils.d.mts.map +1 -1
- package/dist/core/utils/utils.mjs +5 -2
- package/dist/core/utils/utils.mjs.map +1 -1
- package/package.json +36 -38
- package/src/core/base/circular-dependency-comparison.test.mts +5 -6
- package/src/core/base/circular-dependency.test.mts +20 -21
- package/src/core/base/create-child-observable.mts +10 -3
- package/src/core/base/create-observable-base.mts +12 -4
- package/src/core/base/create-root-observable.mts +2 -0
- package/src/core/combine/combine.mts +13 -8
- package/src/core/combine/merge.mts +5 -1
- package/src/core/combine/zip.mts +12 -8
- package/src/core/create/from-abortable-promise.mts +8 -2
- package/src/core/create/from-promise.mts +7 -2
- package/src/core/create/from-subscribable.mts +1 -0
- package/src/core/create/just.mts +1 -0
- package/src/core/create/source.mts +3 -1
- package/src/core/operators/audit.mts +4 -1
- package/src/core/operators/debounce.mts +4 -1
- package/src/core/operators/map.mts +1 -0
- package/src/core/operators/skip-if-no-change.mts +1 -0
- package/src/core/operators/take-until.mts +1 -0
- package/src/core/operators/throttle.mts +1 -0
- package/src/core/operators/with-buffered-from.mts +1 -0
- package/src/core/operators/with-current-value-from.mts +3 -1
- package/src/core/predefined/operators/unwrap-optional.mts +1 -0
- package/src/core/predefined/operators/unwrap-result-ok.mts +1 -0
- package/src/core/types/observable.mts +11 -1
- package/src/core/types/timer.mts +2 -11
- package/src/core/utils/id-maker.mts +1 -0
- package/src/core/utils/utils.mts +7 -2
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable functional/immutable-data */
|
|
2
1
|
import { Optional } from 'ts-data-forge';
|
|
3
2
|
import { combine, merge } from '../combine/index.mjs';
|
|
4
3
|
import { source } from '../create/index.mjs';
|
|
@@ -18,7 +17,7 @@ describe('circular dependency detection', () => {
|
|
|
18
17
|
() => ({}),
|
|
19
18
|
);
|
|
20
19
|
|
|
21
|
-
const
|
|
20
|
+
const mut_childA = createSyncChildObservable(
|
|
22
21
|
{
|
|
23
22
|
parents: [root],
|
|
24
23
|
initialValue: Optional.some(0),
|
|
@@ -28,14 +27,14 @@ describe('circular dependency detection', () => {
|
|
|
28
27
|
|
|
29
28
|
const childB = createSyncChildObservable(
|
|
30
29
|
{
|
|
31
|
-
parents: [
|
|
30
|
+
parents: [mut_childA],
|
|
32
31
|
initialValue: Optional.some(0),
|
|
33
32
|
},
|
|
34
33
|
createTryUpdateNotImplemented,
|
|
35
34
|
);
|
|
36
35
|
|
|
37
|
-
// Mutate
|
|
38
|
-
Object.defineProperty(
|
|
36
|
+
// Mutate mut_childA.parents to create a cycle: mut_childA -> childB -> mut_childA
|
|
37
|
+
Object.defineProperty(mut_childA, 'parents', {
|
|
39
38
|
value: [childB],
|
|
40
39
|
writable: false,
|
|
41
40
|
configurable: true,
|
|
@@ -44,7 +43,7 @@ describe('circular dependency detection', () => {
|
|
|
44
43
|
expect(() => {
|
|
45
44
|
createSyncChildObservable(
|
|
46
45
|
{
|
|
47
|
-
parents: [
|
|
46
|
+
parents: [mut_childA],
|
|
48
47
|
initialValue: Optional.some(0),
|
|
49
48
|
},
|
|
50
49
|
createTryUpdateNotImplemented,
|
|
@@ -60,7 +59,7 @@ describe('circular dependency detection', () => {
|
|
|
60
59
|
() => ({}),
|
|
61
60
|
);
|
|
62
61
|
|
|
63
|
-
const
|
|
62
|
+
const mut_childA = createAsyncChildObservable(
|
|
64
63
|
{
|
|
65
64
|
parents: [root],
|
|
66
65
|
initialValue: Optional.some(0),
|
|
@@ -70,14 +69,14 @@ describe('circular dependency detection', () => {
|
|
|
70
69
|
|
|
71
70
|
const childB = createSyncChildObservable(
|
|
72
71
|
{
|
|
73
|
-
parents: [
|
|
72
|
+
parents: [mut_childA],
|
|
74
73
|
initialValue: Optional.some(0),
|
|
75
74
|
},
|
|
76
75
|
createTryUpdateNotImplemented,
|
|
77
76
|
);
|
|
78
77
|
|
|
79
|
-
// Create cycle:
|
|
80
|
-
Object.defineProperty(
|
|
78
|
+
// Create cycle: mut_childA -> childB -> mut_childA
|
|
79
|
+
Object.defineProperty(mut_childA, 'parents', {
|
|
81
80
|
value: [childB],
|
|
82
81
|
writable: false,
|
|
83
82
|
configurable: true,
|
|
@@ -86,7 +85,7 @@ describe('circular dependency detection', () => {
|
|
|
86
85
|
expect(() => {
|
|
87
86
|
createAsyncChildObservable(
|
|
88
87
|
{
|
|
89
|
-
parents: [
|
|
88
|
+
parents: [mut_childA],
|
|
90
89
|
initialValue: Optional.some(0),
|
|
91
90
|
},
|
|
92
91
|
createTryUpdateNotImplemented,
|
|
@@ -102,7 +101,7 @@ describe('circular dependency detection', () => {
|
|
|
102
101
|
() => ({}),
|
|
103
102
|
);
|
|
104
103
|
|
|
105
|
-
const
|
|
104
|
+
const mut_childA = createSyncChildObservable(
|
|
106
105
|
{
|
|
107
106
|
parents: [root],
|
|
108
107
|
initialValue: Optional.some(0),
|
|
@@ -112,7 +111,7 @@ describe('circular dependency detection', () => {
|
|
|
112
111
|
|
|
113
112
|
const childB = createSyncChildObservable(
|
|
114
113
|
{
|
|
115
|
-
parents: [
|
|
114
|
+
parents: [mut_childA],
|
|
116
115
|
initialValue: Optional.some(0),
|
|
117
116
|
},
|
|
118
117
|
createTryUpdateNotImplemented,
|
|
@@ -126,8 +125,8 @@ describe('circular dependency detection', () => {
|
|
|
126
125
|
createTryUpdateNotImplemented,
|
|
127
126
|
);
|
|
128
127
|
|
|
129
|
-
// Create cycle:
|
|
130
|
-
Object.defineProperty(
|
|
128
|
+
// Create cycle: mut_childA -> childC -> childB -> mut_childA
|
|
129
|
+
Object.defineProperty(mut_childA, 'parents', {
|
|
131
130
|
value: [childC],
|
|
132
131
|
writable: false,
|
|
133
132
|
configurable: true,
|
|
@@ -136,7 +135,7 @@ describe('circular dependency detection', () => {
|
|
|
136
135
|
expect(() => {
|
|
137
136
|
createSyncChildObservable(
|
|
138
137
|
{
|
|
139
|
-
parents: [
|
|
138
|
+
parents: [mut_childA],
|
|
140
139
|
initialValue: Optional.some(0),
|
|
141
140
|
},
|
|
142
141
|
createTryUpdateNotImplemented,
|
|
@@ -152,7 +151,7 @@ describe('circular dependency detection', () => {
|
|
|
152
151
|
() => ({}),
|
|
153
152
|
);
|
|
154
153
|
|
|
155
|
-
const
|
|
154
|
+
const mut_childA = createSyncChildObservable(
|
|
156
155
|
{
|
|
157
156
|
parents: [root],
|
|
158
157
|
initialValue: Optional.some(0),
|
|
@@ -160,9 +159,9 @@ describe('circular dependency detection', () => {
|
|
|
160
159
|
createTryUpdateNotImplemented,
|
|
161
160
|
);
|
|
162
161
|
|
|
163
|
-
// Make
|
|
164
|
-
Object.defineProperty(
|
|
165
|
-
value: [
|
|
162
|
+
// Make mut_childA's parents reference mut_childA itself (self-loop)
|
|
163
|
+
Object.defineProperty(mut_childA, 'parents', {
|
|
164
|
+
value: [mut_childA],
|
|
166
165
|
writable: false,
|
|
167
166
|
configurable: true,
|
|
168
167
|
});
|
|
@@ -170,7 +169,7 @@ describe('circular dependency detection', () => {
|
|
|
170
169
|
expect(() => {
|
|
171
170
|
createSyncChildObservable(
|
|
172
171
|
{
|
|
173
|
-
parents: [
|
|
172
|
+
parents: [mut_childA],
|
|
174
173
|
initialValue: Optional.some(0),
|
|
175
174
|
},
|
|
176
175
|
createTryUpdateNotImplemented,
|
|
@@ -160,6 +160,7 @@ export const createInitializedSyncChildObservable = <
|
|
|
160
160
|
return (
|
|
161
161
|
// `getSnapshot` always returns `Some` here: `initialValue` is a `Some` and
|
|
162
162
|
// `setNext` only ever stores a `Some`.
|
|
163
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
163
164
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
164
165
|
observable as InitializedSyncChildObservable<A, P>
|
|
165
166
|
);
|
|
@@ -240,9 +241,13 @@ const hasCircularDependencyFrom = (
|
|
|
240
241
|
mut_visited: MutableSet<ObservableId>,
|
|
241
242
|
mut_inPath: MutableSet<ObservableId>,
|
|
242
243
|
): boolean => {
|
|
243
|
-
if (mut_inPath.has(node.id))
|
|
244
|
+
if (mut_inPath.has(node.id)) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
244
247
|
|
|
245
|
-
if (mut_visited.has(node.id))
|
|
248
|
+
if (mut_visited.has(node.id)) {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
246
251
|
|
|
247
252
|
mut_visited.add(node.id);
|
|
248
253
|
|
|
@@ -304,7 +309,9 @@ const registerChild = <A,>(
|
|
|
304
309
|
while (Arr.isNonEmpty(mut_rest)) {
|
|
305
310
|
const p = mut_rest.pop();
|
|
306
311
|
|
|
307
|
-
if (p === undefined)
|
|
312
|
+
if (p === undefined) {
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
308
315
|
|
|
309
316
|
if (isManagerObservable(p)) {
|
|
310
317
|
p.addDescendant(child);
|
|
@@ -130,7 +130,9 @@ export const createObservableBaseHandle = <A,>(
|
|
|
130
130
|
};
|
|
131
131
|
|
|
132
132
|
const completeBase = (): void => {
|
|
133
|
-
if (mut_isCompleted)
|
|
133
|
+
if (mut_isCompleted) {
|
|
134
|
+
return; // terminate only once
|
|
135
|
+
}
|
|
134
136
|
|
|
135
137
|
// change state
|
|
136
138
|
mut_isCompleted = true;
|
|
@@ -220,7 +222,9 @@ export const createManagerObservableParts = <A,>(
|
|
|
220
222
|
const mut_descendantsIdSet: MutableSet<ObservableId> = new Set();
|
|
221
223
|
|
|
222
224
|
const addDescendant = <B,>(child: ChildObservable<B>): void => {
|
|
223
|
-
if (mut_descendantsIdSet.has(child.id))
|
|
225
|
+
if (mut_descendantsIdSet.has(child.id)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
224
228
|
|
|
225
229
|
mut_descendantsIdSet.add(child.id);
|
|
226
230
|
|
|
@@ -270,7 +274,7 @@ type AssembleObservableArgs<
|
|
|
270
274
|
Extra extends ReadonlyRecord<string, unknown>,
|
|
271
275
|
> = Readonly<{
|
|
272
276
|
kind: Kind;
|
|
273
|
-
depth: number;
|
|
277
|
+
depth: Kind extends 'root' ? 0 : number;
|
|
274
278
|
handle: ObservableBaseHandle<A>;
|
|
275
279
|
tryUpdate: (updateToken: UpdateToken) => void;
|
|
276
280
|
tryComplete: () => void;
|
|
@@ -305,7 +309,10 @@ export const assembleObservable = <
|
|
|
305
309
|
extra,
|
|
306
310
|
}: AssembleObservableArgs<A, Kind, Extra>): Extra &
|
|
307
311
|
ObservableBase<A> &
|
|
308
|
-
Readonly<{
|
|
312
|
+
Readonly<{
|
|
313
|
+
kind: Kind;
|
|
314
|
+
depth: AssembleObservableArgs<A, Kind, Extra>['depth'];
|
|
315
|
+
}> => {
|
|
309
316
|
function pipe<B>(
|
|
310
317
|
operator: WithInitialValueOperator<A, B>,
|
|
311
318
|
): InitializedObservable<B>;
|
|
@@ -314,6 +321,7 @@ export const assembleObservable = <
|
|
|
314
321
|
|
|
315
322
|
function pipe<B>(operator: Operator<A, B>): Observable<B> {
|
|
316
323
|
return operator(
|
|
324
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
317
325
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
318
326
|
observable as unknown as InitializedObservable<A>,
|
|
319
327
|
);
|
|
@@ -47,6 +47,8 @@ export type RootObservableConfig<A> = Readonly<{
|
|
|
47
47
|
*/
|
|
48
48
|
export const createRootObservable = <
|
|
49
49
|
A,
|
|
50
|
+
// The default is deliberately empty: a root leaf without `init` adds no members.
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-generated-empty-object-type
|
|
50
52
|
Extension extends ReadonlyRecord<string, unknown> = ReadonlyRecord<
|
|
51
53
|
never,
|
|
52
54
|
never
|
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
export const combine = <const OS extends NonEmptyTuple<Observable<unknown>>>(
|
|
75
75
|
parents: OS,
|
|
76
76
|
): CombineObservableRefined<OS> =>
|
|
77
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
77
78
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
78
79
|
createCombineObservable(parents) as unknown as CombineObservableRefined<OS>;
|
|
79
80
|
|
|
@@ -113,7 +114,9 @@ const createCombineObservable = <const A extends NonEmptyUnknownList>(
|
|
|
113
114
|
},
|
|
114
115
|
({ setNext }) =>
|
|
115
116
|
(updateToken) => {
|
|
116
|
-
if (parents.every((o) => o.updateToken !== updateToken))
|
|
117
|
+
if (parents.every((o) => o.updateToken !== updateToken)) {
|
|
118
|
+
return; // all parents are skipped
|
|
119
|
+
}
|
|
117
120
|
|
|
118
121
|
// Same shape-preserving chain as the initial value: `Arr.map` (not the
|
|
119
122
|
// native one, which drops the tuple shape) into the uniform
|
|
@@ -123,14 +126,16 @@ const createCombineObservable = <const A extends NonEmptyUnknownList>(
|
|
|
123
126
|
(a) => a.getSnapshot(),
|
|
124
127
|
);
|
|
125
128
|
|
|
126
|
-
if (Arr.every(parentValues, Optional.isSome)) {
|
|
127
|
-
|
|
128
|
-
parentValues,
|
|
129
|
-
(a) => a.value,
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
setNext(nextValue, updateToken);
|
|
129
|
+
if (!Arr.every(parentValues, Optional.isSome)) {
|
|
130
|
+
return;
|
|
133
131
|
}
|
|
132
|
+
|
|
133
|
+
const nextValue: Readonly<{ [K in keyof A]: A[K] }> = Arr.map(
|
|
134
|
+
parentValues,
|
|
135
|
+
(a) => a.value,
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
setNext(nextValue, updateToken);
|
|
134
139
|
},
|
|
135
140
|
);
|
|
136
141
|
};
|
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
export const merge = <const OS extends NonEmptyTuple<Observable<unknown>>>(
|
|
66
66
|
parents: OS,
|
|
67
67
|
): MergeObservableRefined<OS> =>
|
|
68
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
68
69
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
69
70
|
createMergeObservable(parents) as MergeObservableRefined<OS>;
|
|
70
71
|
|
|
@@ -83,9 +84,12 @@ const createMergeObservable = <const P extends NonEmptyUnknownList>(
|
|
|
83
84
|
o.updateToken === updateToken && Optional.isSome(o.getSnapshot()),
|
|
84
85
|
);
|
|
85
86
|
|
|
86
|
-
if (parentToUse === undefined)
|
|
87
|
+
if (parentToUse === undefined) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
87
90
|
|
|
88
91
|
const nextValue =
|
|
92
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
89
93
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
90
94
|
Optional.unwrap(parentToUse.getSnapshot()) as ArrayElement<P>;
|
|
91
95
|
|
package/src/core/combine/zip.mts
CHANGED
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
export const zip = <const OS extends NonEmptyTuple<Observable<unknown>>>(
|
|
68
68
|
parents: OS,
|
|
69
69
|
): ZipObservableRefined<OS> =>
|
|
70
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
70
71
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
71
72
|
createZipObservable(parents) as unknown as ZipObservableRefined<OS>;
|
|
72
73
|
|
|
@@ -110,15 +111,18 @@ const createZipObservable = <const A extends NonEmptyUnknownList>(
|
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
if (queues.
|
|
114
|
-
|
|
115
|
-
// `Arr.map` has a single result element type, so it reports
|
|
116
|
-
// `A[number] | undefined` per position rather than `A[P]`.
|
|
117
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
118
|
-
Arr.map(queues, (q) => Optional.unwrap(q.dequeue())) as A;
|
|
119
|
-
|
|
120
|
-
setNext(nextValue, updateToken);
|
|
114
|
+
if (queues.some((list) => list.isEmpty)) {
|
|
115
|
+
return;
|
|
121
116
|
}
|
|
117
|
+
|
|
118
|
+
const nextValue =
|
|
119
|
+
// `Arr.map` has a single result element type, so it reports
|
|
120
|
+
// `A[number] | undefined` per position rather than `A[P]`.
|
|
121
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
122
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
123
|
+
Arr.map(queues, (q) => Optional.unwrap(q.dequeue())) as A;
|
|
124
|
+
|
|
125
|
+
setNext(nextValue, updateToken);
|
|
122
126
|
},
|
|
123
127
|
);
|
|
124
128
|
};
|
|
@@ -70,6 +70,7 @@ import { type FromPromiseObservable } from '../types/index.mjs';
|
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
72
72
|
export const fromAbortablePromise = <A, E = unknown>(
|
|
73
|
+
// @sumi-expect-error readonly/require-readonly-parameter
|
|
73
74
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
74
75
|
factory: (signal: AbortSignal) => Promise<A>,
|
|
75
76
|
): FromPromiseObservable<A, E> => {
|
|
@@ -87,12 +88,16 @@ export const fromAbortablePromise = <A, E = unknown>(
|
|
|
87
88
|
|
|
88
89
|
promise
|
|
89
90
|
.then((value) => {
|
|
90
|
-
if (isCompleted())
|
|
91
|
+
if (isCompleted()) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
91
94
|
|
|
92
95
|
startUpdate(Result.ok(value));
|
|
93
96
|
})
|
|
94
97
|
.catch((error: unknown) => {
|
|
95
|
-
if (isCompleted())
|
|
98
|
+
if (isCompleted()) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
96
101
|
|
|
97
102
|
// Silently ignore AbortError — it means the observable was
|
|
98
103
|
// intentionally completed (e.g., by switchMap).
|
|
@@ -102,6 +107,7 @@ export const fromAbortablePromise = <A, E = unknown>(
|
|
|
102
107
|
|
|
103
108
|
startUpdate(
|
|
104
109
|
Result.err(
|
|
110
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
105
111
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
106
112
|
error as E,
|
|
107
113
|
),
|
|
@@ -57,15 +57,20 @@ export const fromPromise = <A, E = unknown>(
|
|
|
57
57
|
({ startUpdate, isCompleted, complete }) => {
|
|
58
58
|
promise
|
|
59
59
|
.then((value) => {
|
|
60
|
-
if (isCompleted())
|
|
60
|
+
if (isCompleted()) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
61
63
|
|
|
62
64
|
startUpdate(Result.ok(value));
|
|
63
65
|
})
|
|
64
66
|
.catch((error: unknown) => {
|
|
65
|
-
if (isCompleted())
|
|
67
|
+
if (isCompleted()) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
66
70
|
|
|
67
71
|
startUpdate(
|
|
68
72
|
Result.err(
|
|
73
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
69
74
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
70
75
|
error as E,
|
|
71
76
|
),
|
|
@@ -76,6 +76,7 @@ export const fromSubscribable = <A, E = unknown>(
|
|
|
76
76
|
(error?: unknown) => {
|
|
77
77
|
startUpdate(
|
|
78
78
|
Result.err(
|
|
79
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
79
80
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
80
81
|
error as E,
|
|
81
82
|
),
|
package/src/core/create/just.mts
CHANGED
|
@@ -39,6 +39,7 @@ export const just = <const A,>(value: A): InitializedRootObservable<A> => {
|
|
|
39
39
|
|
|
40
40
|
obs.complete();
|
|
41
41
|
|
|
42
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
42
43
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
43
44
|
return obs as InitializedRootObservable<A>;
|
|
44
45
|
};
|
|
@@ -59,7 +59,9 @@ export function source<const A>(...args: readonly A[]): SourceObservable<A> {
|
|
|
59
59
|
},
|
|
60
60
|
({ startUpdate, isCompleted }) => ({
|
|
61
61
|
next: (nextValue: A) => {
|
|
62
|
-
if (isCompleted())
|
|
62
|
+
if (isCompleted()) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
63
65
|
|
|
64
66
|
startUpdate(nextValue);
|
|
65
67
|
},
|
|
@@ -104,6 +104,7 @@ import {
|
|
|
104
104
|
export const audit = <A,>(
|
|
105
105
|
milliSeconds: number,
|
|
106
106
|
): KeepInitialValueOperator<A, A> =>
|
|
107
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
107
108
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
108
109
|
((parentObservable) =>
|
|
109
110
|
createAuditObservable(
|
|
@@ -147,7 +148,9 @@ const createAuditObservable = <A,>(
|
|
|
147
148
|
mut_timerId = setTimeout(() => {
|
|
148
149
|
const sn = parentObservable.getSnapshot();
|
|
149
150
|
|
|
150
|
-
if (Optional.isNone(sn))
|
|
151
|
+
if (Optional.isNone(sn)) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
151
154
|
|
|
152
155
|
startUpdate(sn.value);
|
|
153
156
|
|
|
@@ -95,6 +95,7 @@ import {
|
|
|
95
95
|
export const debounce = <A,>(
|
|
96
96
|
milliSeconds: number,
|
|
97
97
|
): KeepInitialValueOperator<A, A> =>
|
|
98
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
98
99
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
99
100
|
((parentObservable) =>
|
|
100
101
|
createDebounceObservable(
|
|
@@ -135,7 +136,9 @@ const createDebounceObservable = <A,>(
|
|
|
135
136
|
|
|
136
137
|
// set timer
|
|
137
138
|
mut_timerId = setTimeout(() => {
|
|
138
|
-
if (Optional.isNone(sn))
|
|
139
|
+
if (Optional.isNone(sn)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
139
142
|
|
|
140
143
|
startUpdate(sn.value);
|
|
141
144
|
}, milliSeconds);
|
|
@@ -50,6 +50,7 @@ import { withInitialValue } from './with-initial-value.mjs';
|
|
|
50
50
|
export const map = <A, B>(
|
|
51
51
|
mapFn: (x: A, index: SafeUint | -1) => B,
|
|
52
52
|
): KeepInitialValueOperator<A, B> =>
|
|
53
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
53
54
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
54
55
|
((parentObservable) =>
|
|
55
56
|
createMapObservable(parentObservable, mapFn)) as KeepInitialValueOperator<
|
|
@@ -70,6 +70,7 @@ import {
|
|
|
70
70
|
export const skipIfNoChange = <A,>(
|
|
71
71
|
eq: (x: A, y: A) => boolean = (x, y) => Object.is(x, y),
|
|
72
72
|
): KeepInitialValueOperator<A, A> =>
|
|
73
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
73
74
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
74
75
|
((parentObservable) =>
|
|
75
76
|
createSkipIfNoChangeObservable(
|
|
@@ -57,6 +57,7 @@ import {
|
|
|
57
57
|
export const takeUntil = <A,>(
|
|
58
58
|
notifier: Observable<unknown>,
|
|
59
59
|
): KeepInitialValueOperator<A, A> =>
|
|
60
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
60
61
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
61
62
|
((parentObservable) =>
|
|
62
63
|
createTakeUntilObservable(
|
|
@@ -88,6 +88,7 @@ import {
|
|
|
88
88
|
export const throttle = <A,>(
|
|
89
89
|
milliSeconds: number,
|
|
90
90
|
): KeepInitialValueOperator<A, A> =>
|
|
91
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
91
92
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
92
93
|
((parentObservable) =>
|
|
93
94
|
createThrottleObservable(
|
|
@@ -63,6 +63,7 @@ import { maxDepth } from '../utils/index.mjs';
|
|
|
63
63
|
export const withBufferedFrom = <A, B>(
|
|
64
64
|
observable: Observable<B>,
|
|
65
65
|
): KeepInitialValueOperator<A, readonly [A, readonly B[]]> =>
|
|
66
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
66
67
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
67
68
|
((parentObservable) =>
|
|
68
69
|
createWithBufferedFromObservable(
|
|
@@ -106,7 +106,9 @@ const createWithCurrentValueFromObservable = <A, B>(
|
|
|
106
106
|
|
|
107
107
|
const curr = observable.getSnapshot();
|
|
108
108
|
|
|
109
|
-
if (Optional.isNone(curr))
|
|
109
|
+
if (Optional.isNone(curr)) {
|
|
110
|
+
return; // skip update
|
|
111
|
+
}
|
|
110
112
|
|
|
111
113
|
setNext([ps.value, curr.value], updateToken);
|
|
112
114
|
},
|
|
@@ -46,5 +46,6 @@ import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
|
46
46
|
export const unwrapOptional = <
|
|
47
47
|
O extends UnknownOptional,
|
|
48
48
|
>(): KeepInitialValueOperator<O, Optional.Unwrap<O> | undefined> =>
|
|
49
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
49
50
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
50
51
|
map(Optional.unwrap as Fn<O, Optional.Unwrap<O> | undefined>);
|
|
@@ -46,5 +46,6 @@ import { type KeepInitialValueOperator } from '../../types/index.mjs';
|
|
|
46
46
|
export const unwrapResultOk = <
|
|
47
47
|
R extends UnknownResult,
|
|
48
48
|
>(): KeepInitialValueOperator<R, Result.UnwrapOk<R> | undefined> =>
|
|
49
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
49
50
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
50
51
|
map(Result.unwrapOk as Fn<R, Result.UnwrapOk<R> | undefined>);
|
|
@@ -23,7 +23,7 @@ type CreateObservableType<A, Kind extends ObservableKind> = Readonly<{
|
|
|
23
23
|
kind: Kind;
|
|
24
24
|
|
|
25
25
|
// reactive dependency tree structure
|
|
26
|
-
depth:
|
|
26
|
+
depth: Kind extends 'root' ? 0 : number;
|
|
27
27
|
addChild: <B>(child: ChildObservable<B>) => void;
|
|
28
28
|
|
|
29
29
|
// state
|
|
@@ -193,6 +193,16 @@ expectType<keyof AsyncChildObservable<unknown>, 'addDescendant'>('>=');
|
|
|
193
193
|
|
|
194
194
|
expectType<keyof RootObservable<unknown>, 'addDescendant'>('>=');
|
|
195
195
|
|
|
196
|
+
expectType<RootObservable<unknown>['depth'], 0>('=');
|
|
197
|
+
|
|
198
|
+
expectType<InitializedRootObservable<unknown>['depth'], 0>('=');
|
|
199
|
+
|
|
200
|
+
expectType<SyncChildObservable<unknown>['depth'], number>('=');
|
|
201
|
+
|
|
202
|
+
expectType<AsyncChildObservable<unknown>['depth'], number>('=');
|
|
203
|
+
|
|
204
|
+
expectType<ObservableBase<unknown>['depth'], number>('=');
|
|
205
|
+
|
|
196
206
|
expectType<Unwrap<Wrap<readonly [1, 2, 3]>>, readonly [1, 2, 3]>('=');
|
|
197
207
|
|
|
198
208
|
expectType<number, ObservableValue<Observable<number>>>('<=');
|
package/src/core/types/timer.mts
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Defined by what `clearTimeout` accepts rather than by what `setTimeout`
|
|
5
|
-
* returns. The two are not the same type under the strict standard library:
|
|
6
|
-
* `setTimeout` there returns `{} | null`, which `clearTimeout`'s
|
|
7
|
-
* `number | undefined` parameter rejects. Every use of this type here is a
|
|
8
|
-
* handle on its way to `clearTimeout` / `clearInterval`, so the consumer's
|
|
9
|
-
* side is the one that has to fit.
|
|
10
|
-
*/
|
|
11
|
-
export type TimerId = NonNullable<Parameters<typeof clearTimeout>[0]>;
|
|
1
|
+
// Timer types for Node.js/Browser compatibility
|
|
2
|
+
export type TimerId = ReturnType<typeof setTimeout>;
|
|
@@ -8,6 +8,7 @@ function* idMaker<T extends symbol>(): Generator<T, T, T> {
|
|
|
8
8
|
let mut_i = 0;
|
|
9
9
|
|
|
10
10
|
while (true) {
|
|
11
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
11
12
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
12
13
|
yield Symbol(mut_i.toString()) as T;
|
|
13
14
|
|
package/src/core/utils/utils.mts
CHANGED
|
@@ -34,9 +34,13 @@ export const binarySearch = <N extends number>(
|
|
|
34
34
|
while (mut_left <= mut_right) {
|
|
35
35
|
const curr = sortedArray[mut_mid];
|
|
36
36
|
|
|
37
|
-
if (x === curr)
|
|
37
|
+
if (x === curr) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
38
40
|
|
|
39
|
-
if (curr === undefined)
|
|
41
|
+
if (curr === undefined) {
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
40
44
|
|
|
41
45
|
if (curr > x) {
|
|
42
46
|
mut_right = SafeInt.sub(mut_mid, 1);
|
|
@@ -47,6 +51,7 @@ export const binarySearch = <N extends number>(
|
|
|
47
51
|
mut_mid = SafeInt.add(mut_left, halfInt(SafeInt.sub(mut_right, mut_left)));
|
|
48
52
|
}
|
|
49
53
|
|
|
54
|
+
// @sumi-expect-error banned-syntax/no-unsafe-type-assertion
|
|
50
55
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
51
56
|
return mut_mid as NegativeInt32 | Uint32;
|
|
52
57
|
};
|