synstate 2.0.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/core/base/create-child-observable.d.mts +65 -0
- package/dist/core/base/create-child-observable.d.mts.map +1 -0
- package/dist/core/base/create-child-observable.mjs +157 -0
- package/dist/core/base/create-child-observable.mjs.map +1 -0
- package/dist/core/base/create-observable-base.d.mts +82 -0
- package/dist/core/base/create-observable-base.d.mts.map +1 -0
- package/dist/core/base/create-observable-base.mjs +160 -0
- package/dist/core/base/create-observable-base.mjs.map +1 -0
- package/dist/core/base/create-root-observable.d.mts +37 -0
- package/dist/core/base/create-root-observable.d.mts.map +1 -0
- package/dist/core/base/create-root-observable.mjs +36 -0
- package/dist/core/base/create-root-observable.mjs.map +1 -0
- package/dist/core/base/index.d.mts +3 -0
- package/dist/core/base/index.d.mts.map +1 -0
- package/dist/core/base/index.mjs +3 -0
- package/dist/core/{class → base}/index.mjs.map +1 -1
- package/dist/core/combine/combine.d.mts.map +1 -1
- package/dist/core/combine/combine.mjs +28 -27
- 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 +11 -13
- 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 +32 -31
- package/dist/core/combine/zip.mjs.map +1 -1
- package/dist/core/create/counter.d.mts.map +1 -1
- package/dist/core/create/counter.mjs +39 -50
- package/dist/core/create/counter.mjs.map +1 -1
- package/dist/core/create/from-abortable-promise.d.mts.map +1 -1
- package/dist/core/create/from-abortable-promise.mjs +33 -32
- 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 +12 -12
- 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 +10 -10
- 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 +5 -4
- package/dist/core/create/just.mjs.map +1 -1
- package/dist/core/create/source.mjs +11 -12
- package/dist/core/create/source.mjs.map +1 -1
- package/dist/core/create/timer.d.mts.map +1 -1
- package/dist/core/create/timer.mjs +32 -38
- package/dist/core/create/timer.mjs.map +1 -1
- package/dist/core/index.d.mts +0 -1
- package/dist/core/index.d.mts.map +1 -1
- package/dist/core/index.mjs +0 -3
- package/dist/core/index.mjs.map +1 -1
- package/dist/core/operators/audit.d.mts.map +1 -1
- package/dist/core/operators/audit.mjs +28 -36
- 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 +26 -33
- package/dist/core/operators/debounce.mjs.map +1 -1
- package/dist/core/operators/filter.d.mts.map +1 -1
- package/dist/core/operators/filter.mjs +23 -27
- package/dist/core/operators/filter.mjs.map +1 -1
- package/dist/core/operators/map.d.mts.map +1 -1
- package/dist/core/operators/map.mjs +21 -28
- package/dist/core/operators/map.mjs.map +1 -1
- package/dist/core/operators/merge-map.d.mts.map +1 -1
- package/dist/core/operators/merge-map.mjs +30 -39
- package/dist/core/operators/merge-map.mjs.map +1 -1
- package/dist/core/operators/pairwise.d.mts.map +1 -1
- package/dist/core/operators/pairwise.mjs +22 -24
- package/dist/core/operators/pairwise.mjs.map +1 -1
- package/dist/core/operators/scan.d.mts.map +1 -1
- package/dist/core/operators/scan.mjs +13 -18
- package/dist/core/operators/scan.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 +22 -26
- package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
- package/dist/core/operators/skip-until.d.mts.map +1 -1
- package/dist/core/operators/skip-until.mjs +23 -24
- package/dist/core/operators/skip-until.mjs.map +1 -1
- package/dist/core/operators/skip-while.d.mts.map +1 -1
- package/dist/core/operators/skip-while.mjs +27 -32
- package/dist/core/operators/skip-while.mjs.map +1 -1
- package/dist/core/operators/switch-map.d.mts.map +1 -1
- package/dist/core/operators/switch-map.mjs +28 -34
- package/dist/core/operators/switch-map.mjs.map +1 -1
- package/dist/core/operators/take-until.d.mts.map +1 -1
- package/dist/core/operators/take-until.mjs +22 -22
- package/dist/core/operators/take-until.mjs.map +1 -1
- package/dist/core/operators/take-while.d.mts.map +1 -1
- package/dist/core/operators/take-while.mjs +25 -29
- package/dist/core/operators/take-while.mjs.map +1 -1
- package/dist/core/operators/throttle.d.mts.map +1 -1
- package/dist/core/operators/throttle.mjs +27 -35
- 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 +24 -24
- package/dist/core/operators/with-buffered-from.mjs.map +1 -1
- package/dist/core/operators/with-current-value-from.d.mts.map +1 -1
- package/dist/core/operators/with-current-value-from.mjs +20 -25
- package/dist/core/operators/with-current-value-from.mjs.map +1 -1
- package/dist/core/operators/with-initial-value.d.mts.map +1 -1
- package/dist/core/operators/with-initial-value.mjs +12 -15
- package/dist/core/operators/with-initial-value.mjs.map +1 -1
- package/dist/entry-point.mjs +0 -3
- package/dist/entry-point.mjs.map +1 -1
- package/dist/index.mjs +0 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -16
- package/src/core/{class → base}/circular-dependency-comparison.test.mts +28 -18
- package/src/core/base/circular-dependency.test.mts +322 -0
- package/src/core/base/create-child-observable.mts +340 -0
- package/src/core/base/create-observable-base.mts +358 -0
- package/src/core/base/create-root-observable.mts +102 -0
- package/src/core/base/index.mts +2 -0
- package/src/core/{class/observable.class.test.mts → base/observable-base.test.mts} +25 -17
- package/src/core/combine/combine.mts +51 -53
- package/src/core/combine/merge.mts +21 -23
- package/src/core/combine/zip.mts +54 -58
- package/src/core/create/counter.mts +42 -59
- package/src/core/create/from-abortable-promise.mts +38 -45
- package/src/core/create/from-promise.mts +25 -28
- package/src/core/create/from-subscribable.mts +23 -27
- package/src/core/create/just.mts +5 -4
- package/src/core/create/source.mts +11 -17
- package/src/core/create/timer.mts +32 -47
- package/src/core/index.mts +0 -1
- package/src/core/operators/audit.mts +43 -57
- package/src/core/operators/debounce.mts +35 -45
- package/src/core/operators/filter.mts +31 -39
- package/src/core/operators/map.mts +32 -40
- package/src/core/operators/merge-map.mts +44 -59
- package/src/core/operators/pairwise.mts +30 -33
- package/src/core/operators/scan.mts +24 -35
- package/src/core/operators/skip-if-no-change.mts +31 -36
- package/src/core/operators/skip-until.mts +32 -35
- package/src/core/operators/skip-while.mts +31 -40
- package/src/core/operators/switch-map.mts +36 -48
- package/src/core/operators/take-until.mts +31 -29
- package/src/core/operators/take-while.mts +33 -41
- package/src/core/operators/throttle.mts +37 -51
- package/src/core/operators/with-buffered-from.mts +35 -30
- package/src/core/operators/with-current-value-from.mts +23 -28
- package/src/core/operators/with-initial-value.mts +21 -22
- package/dist/core/class/child-observable-class.d.mts +0 -39
- package/dist/core/class/child-observable-class.d.mts.map +0 -1
- package/dist/core/class/child-observable-class.mjs +0 -173
- package/dist/core/class/child-observable-class.mjs.map +0 -1
- package/dist/core/class/index.d.mts +0 -4
- package/dist/core/class/index.d.mts.map +0 -1
- package/dist/core/class/index.mjs +0 -4
- package/dist/core/class/observable-base-class.d.mts +0 -28
- package/dist/core/class/observable-base-class.d.mts.map +0 -1
- package/dist/core/class/observable-base-class.mjs +0 -120
- package/dist/core/class/observable-base-class.mjs.map +0 -1
- package/dist/core/class/root-observable-class.d.mts +0 -14
- package/dist/core/class/root-observable-class.d.mts.map +0 -1
- package/dist/core/class/root-observable-class.mjs +0 -43
- package/dist/core/class/root-observable-class.mjs.map +0 -1
- package/src/core/class/child-observable-class.mts +0 -286
- package/src/core/class/circular-dependency.test.mts +0 -251
- package/src/core/class/index.mts +0 -3
- package/src/core/class/observable-base-class.mts +0 -187
- package/src/core/class/root-observable-class.mts +0 -73
|
@@ -1,35 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Optional, asSafeUint, SafeUint, pipe } from 'ts-data-forge';
|
|
2
|
+
import { createSyncChildObservable } from '../base/create-child-observable.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
5
|
function filter(predicate) {
|
|
6
|
-
return (parentObservable) =>
|
|
6
|
+
return (parentObservable) => createFilterObservable(parentObservable, predicate);
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
const createFilterObservable = (parentObservable, predicate) => createSyncChildObservable(
|
|
9
|
+
{
|
|
10
|
+
parents: [parentObservable],
|
|
11
|
+
initialValue: pipe(parentObservable.getSnapshot()).map(
|
|
12
|
+
(sn) => Optional.isNone(sn) ? Optional.none : predicate(sn.value, -1) ? sn : Optional.none
|
|
13
|
+
).value
|
|
14
|
+
},
|
|
15
|
+
({ setNext }) => {
|
|
16
|
+
let mut_index = -1;
|
|
17
|
+
return (updateToken) => {
|
|
18
|
+
const sn = parentObservable.getSnapshot();
|
|
19
|
+
if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
mut_index = mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);
|
|
23
|
+
if (predicate(sn.value, mut_index)) {
|
|
24
|
+
setNext(sn.value, updateToken);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
20
27
|
}
|
|
21
|
-
|
|
22
|
-
const par = this.parents[0];
|
|
23
|
-
const sn = par.getSnapshot();
|
|
24
|
-
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
28
|
-
if (this.#predicate(sn.value, this.#mut_index)) {
|
|
29
|
-
this.setNext(sn.value, updateToken);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
28
|
+
);
|
|
33
29
|
|
|
34
30
|
export { filter };
|
|
35
31
|
//# sourceMappingURL=filter.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.mjs","sources":["../../../src/core/operators/filter.mts"],"sourcesContent":["import {\n asSafeUint,\n expectType,\n Optional,\n pipe,\n SafeUint,\n} from 'ts-data-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"filter.mjs","sources":["../../../src/core/operators/filter.mts"],"sourcesContent":["import {\n asSafeUint,\n expectType,\n Optional,\n pipe,\n SafeUint,\n} from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type DropInitialValueOperator,\n type FilterOperatorObservable,\n type InitializedObservable,\n type Observable,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Filters values emitted by the source observable based on a predicate function.\n * Only values that satisfy the predicate will be emitted by the resulting observable.\n *\n * @template A - The type of values from the source\n * @template B - The narrowed type when using type guard\n * @param predicate - A function that tests each value (receives value and index)\n * @returns An operator that filters the observable\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4 5 6\n * // even$ 2 4 6\n * //\n * // Explanation:\n * // - filter passes through only values that satisfy the predicate\n * // - Only even numbers (2, 4, 6) are emitted\n *\n * const num$ = source<number>();\n *\n * const even$ = num$.pipe(filter((x) => x % 2 === 0));\n *\n * const valueHistory: number[] = [];\n *\n * even$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [2]);\n *\n * num$.next(3); // nothing logged\n *\n * num$.next(4); // logs: 4\n *\n * assert.deepStrictEqual(valueHistory, [2, 4]);\n *\n * num$.next(5);\n *\n * num$.next(6);\n *\n * assert.deepStrictEqual(valueHistory, [2, 4, 6]);\n * ```\n */\nexport function filter<A, B extends A>(\n predicate: (value: A, index: SafeUint | -1) => value is B,\n): DropInitialValueOperator<A, B>;\n\nexport function filter<A>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): DropInitialValueOperator<A, A>;\n\nexport function filter<A>(\n predicate: (value: A, index: SafeUint | -1) => boolean,\n): DropInitialValueOperator<A, A> {\n return (parentObservable) =>\n createFilterObservable(parentObservable, predicate);\n}\n\nconst createFilterObservable = <A,>(\n parentObservable: Observable<A>,\n predicate: (x: A, index: SafeUint | -1) => boolean,\n): FilterOperatorObservable<A> =>\n createSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: pipe(parentObservable.getSnapshot()).map((sn) =>\n Optional.isNone(sn)\n ? Optional.none\n : predicate(sn.value, -1)\n ? sn\n : Optional.none,\n ).value,\n },\n ({ setNext }) => {\n let mut_index: SafeUint | -1 = -1;\n\n return (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n mut_index =\n mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);\n\n if (predicate(sn.value, mut_index)) {\n setNext(sn.value, updateToken);\n }\n };\n },\n );\n\nif (import.meta.vitest !== undefined) {\n test('type test', () => {\n expect(1).toBe(1); // dummy\n });\n\n {\n const s: Observable<number> = source<number>();\n\n const _d1 = s.pipe(filter((x) => x % 2 === 0));\n\n expectType<typeof _d1, Observable<number>>('=');\n }\n\n {\n const s = source<number>();\n\n const m: InitializedObservable<number> = s.pipe(withInitialValue(0));\n\n const _d = m.pipe(filter((x) => x % 2 === 0));\n\n expectType<typeof _d, Observable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AA0EO,SAAS,OACd,SAAA,EACgC;AAChC,EAAA,OAAO,CAAC,gBAAA,KACN,sBAAA,CAAuB,gBAAA,EAAkB,SAAS,CAAA;AACtD;AAEA,MAAM,sBAAA,GAAyB,CAC7B,gBAAA,EACA,SAAA,KAEA,yBAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,YAAA,EAAc,IAAA,CAAK,gBAAA,CAAiB,WAAA,EAAa,CAAA,CAAE,GAAA;AAAA,MAAI,CAAC,EAAA,KACtD,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,GACd,QAAA,CAAS,IAAA,GACT,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,EAAE,CAAA,GACpB,KACA,QAAA,CAAS;AAAA,KACjB,CAAE;AAAA,GACJ;AAAA,EACA,CAAC,EAAE,OAAA,EAAQ,KAAM;AACf,IAAA,IAAI,SAAA,GAA2B,EAAA;AAE/B,IAAA,OAAO,CAAC,WAAA,KAAgB;AACtB,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MAAA;AAGF,MAAA,SAAA,GACE,SAAA,KAAc,KAAK,UAAA,CAAW,CAAC,IAAI,QAAA,CAAS,GAAA,CAAI,GAAG,SAAS,CAAA;AAE9D,MAAA,IAAI,SAAA,CAAU,EAAA,CAAG,KAAA,EAAO,SAAS,CAAA,EAAG;AAClC,QAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAAA,MAAA;AAC/B,IAAA,CACF;AAAA,EAAA;AAEJ,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/map.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAA0B,MAAM,eAAe,CAAC;AAG3E,OAAO,EAEL,KAAK,wBAAwB,
|
|
1
|
+
{"version":3,"file":"map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/map.mts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAA0B,MAAM,eAAe,CAAC;AAG3E,OAAO,EAEL,KAAK,wBAAwB,EAG9B,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,CAAC,SACf,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,KACvC,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAM7B,CAAC"}
|
|
@@ -1,38 +1,31 @@
|
|
|
1
1
|
import { Optional, asSafeUint, SafeUint } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
2
|
+
import { createSyncChildObservable } from '../base/create-child-observable.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
5
|
const map = (mapFn) => (
|
|
6
6
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
7
|
-
((parentObservable) =>
|
|
8
|
-
parentObservable,
|
|
9
|
-
mapFn
|
|
10
|
-
))
|
|
7
|
+
((parentObservable) => createMapObservable(parentObservable, mapFn))
|
|
11
8
|
);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
9
|
+
const createMapObservable = (parentObservable, mapFn) => createSyncChildObservable(
|
|
10
|
+
{
|
|
11
|
+
parents: [parentObservable],
|
|
12
|
+
initialValue: Optional.map(
|
|
13
|
+
parentObservable.getSnapshot(),
|
|
14
|
+
(x) => mapFn(x, -1)
|
|
15
|
+
)
|
|
16
|
+
},
|
|
17
|
+
({ setNext }) => {
|
|
18
|
+
let mut_index = -1;
|
|
19
|
+
return (updateToken) => {
|
|
20
|
+
const sn = parentObservable.getSnapshot();
|
|
21
|
+
if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
mut_index = mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);
|
|
25
|
+
setNext(mapFn(sn.value, mut_index), updateToken);
|
|
26
|
+
};
|
|
25
27
|
}
|
|
26
|
-
|
|
27
|
-
const par = this.parents[0];
|
|
28
|
-
const sn = par.getSnapshot();
|
|
29
|
-
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
this.#mut_index = this.#mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, this.#mut_index);
|
|
33
|
-
this.setNext(this.#mapFn(sn.value, this.#mut_index), updateToken);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
28
|
+
);
|
|
36
29
|
|
|
37
30
|
export { map };
|
|
38
31
|
//# sourceMappingURL=map.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.mjs","sources":["../../../src/core/operators/map.mts"],"sourcesContent":["import { Optional, SafeUint, asSafeUint, expectType } from 'ts-data-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"map.mjs","sources":["../../../src/core/operators/map.mts"],"sourcesContent":["import { Optional, SafeUint, asSafeUint, expectType } from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport { source } from '../create/index.mjs';\nimport {\n type InitializedObservable,\n type KeepInitialValueOperator,\n type MapOperatorObservable,\n type Observable,\n} from '../types/index.mjs';\nimport { withInitialValue } from './with-initial-value.mjs';\n\n/**\n * Transforms each value emitted by the source using a mapping function that also receives the emission index.\n *\n * @template A - The type of values from the source\n * @template B - The type of mapped values\n * @param mapFn - A function that maps each value (receives value and index)\n * @returns An operator that maps values with index\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ \"A\" \"B\" \"C\"\n * // indexed$ \"0: A\" \"1: B\" \"2: C\"\n * //\n * // Explanation:\n * // - mapWithIndex transforms each value along with its index\n * // - Index starts at 0 and increments with each emission\n *\n * const num$ = source<string>();\n *\n * const indexed$ = num$.pipe(map((x, i) => `${i}: ${x}`));\n *\n * const valueHistory: string[] = [];\n *\n * indexed$.subscribe((s) => {\n * valueHistory.push(s);\n * });\n *\n * num$.next('A'); // 0: A\n *\n * num$.next('B'); // 1: B\n *\n * num$.next('C'); // 2: C\n *\n * assert.deepStrictEqual(valueHistory, ['0: A', '1: B', '2: C']);\n * ```\n */\nexport const map = <A, B>(\n mapFn: (x: A, index: SafeUint | -1) => B,\n): KeepInitialValueOperator<A, B> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n createMapObservable(parentObservable, mapFn)) as KeepInitialValueOperator<\n A,\n B\n >;\n\n/* implementation */\n\nconst createMapObservable = <A, B>(\n parentObservable: Observable<A>,\n mapFn: (x: A, index: SafeUint | -1) => B,\n): MapOperatorObservable<A, B> =>\n createSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: Optional.map(parentObservable.getSnapshot(), (x) =>\n mapFn(x, -1),\n ),\n },\n ({ setNext }) => {\n let mut_index: SafeUint | -1 = -1;\n\n return (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n mut_index =\n mut_index === -1 ? asSafeUint(0) : SafeUint.add(1, mut_index);\n\n setNext(mapFn(sn.value, mut_index), updateToken);\n };\n },\n );\n\nif (import.meta.vitest !== undefined) {\n test('type test', () => {\n expect(1).toBe(1); // dummy\n });\n\n {\n const s: Observable<number> = source<number>();\n\n const _d1 = s.pipe(map((x, i) => x + i));\n\n expectType<typeof _d1, Observable<number>>('=');\n }\n\n {\n const s = source<number>();\n\n const m: InitializedObservable<number> = s.pipe(withInitialValue(0));\n\n const _d = m.pipe(map((x, i) => x + i));\n\n expectType<typeof _d, InitializedObservable<number>>('=');\n }\n}\n"],"names":[],"mappings":";;;;AAiDO,MAAM,MAAM,CACjB,KAAA;AAAA;AAAA,GAGC,CAAC,gBAAA,KACA,mBAAA,CAAoB,gBAAA,EAAkB,KAAK,CAAA;AAAA;AAO/C,MAAM,mBAAA,GAAsB,CAC1B,gBAAA,EACA,KAAA,KAEA,yBAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,cAAc,QAAA,CAAS,GAAA;AAAA,MAAI,iBAAiB,WAAA,EAAY;AAAA,MAAG,CAAC,CAAA,KAC1D,KAAA,CAAM,CAAA,EAAG,EAAE;AAAA;AACb,GACF;AAAA,EACA,CAAC,EAAE,OAAA,EAAQ,KAAM;AACf,IAAA,IAAI,SAAA,GAA2B,EAAA;AAE/B,IAAA,OAAO,CAAC,WAAA,KAAgB;AACtB,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MAAA;AAGF,MAAA,SAAA,GACE,SAAA,KAAc,KAAK,UAAA,CAAW,CAAC,IAAI,QAAA,CAAS,GAAA,CAAI,GAAG,SAAS,CAAA;AAE9D,MAAA,OAAA,CAAQ,KAAA,CAAM,EAAA,CAAG,KAAA,EAAO,SAAS,GAAG,WAAW,CAAA;AAAA,IAAA,CACjD;AAAA,EAAA;AAEJ,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/merge-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"merge-map.d.mts","sourceRoot":"","sources":["../../../src/core/operators/merge-map.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,eAAO,MAAM,QAAQ,GAClB,CAAC,EAAE,CAAC,mBACc,CAAC,IAAI,EAAE,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAC1C,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAE6B,CAAC;AAEhE;;;GAGG;AACH,eAAO,MAAM,OAAO,iBAAW,CAAC"}
|
|
@@ -1,48 +1,39 @@
|
|
|
1
1
|
import { Optional, Arr } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
2
|
+
import { createAsyncChildObservable } from '../base/create-child-observable.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
|
-
const mergeMap = (mapToObservable) => (parentObservable) =>
|
|
5
|
+
const mergeMap = (mapToObservable) => (parentObservable) => createMergeMapObservable(parentObservable, mapToObservable);
|
|
6
6
|
const flatMap = mergeMap;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
super({
|
|
7
|
+
const createMergeMapObservable = (parentObservable, mapToObservable) => {
|
|
8
|
+
let mut_observables = [];
|
|
9
|
+
let mut_subscriptions = [];
|
|
10
|
+
return createAsyncChildObservable(
|
|
11
|
+
{
|
|
13
12
|
parents: [parentObservable],
|
|
14
|
-
initialValue: Optional.none
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
initialValue: Optional.none,
|
|
14
|
+
onComplete: () => {
|
|
15
|
+
for (const s of mut_subscriptions) {
|
|
16
|
+
s.unsubscribe();
|
|
17
|
+
}
|
|
18
|
+
for (const o of mut_observables) {
|
|
19
|
+
o.complete();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
({ startUpdate }) => (updateToken) => {
|
|
24
|
+
const sn = parentObservable.getSnapshot();
|
|
25
|
+
if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const observable = mapToObservable(sn.value);
|
|
29
|
+
mut_observables = Arr.toPushed(mut_observables, observable);
|
|
30
|
+
const subscription = observable.subscribe((curr) => {
|
|
31
|
+
startUpdate(curr);
|
|
32
|
+
});
|
|
33
|
+
mut_subscriptions = Arr.toPushed(mut_subscriptions, subscription);
|
|
25
34
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const subscription = observable.subscribe((curr) => {
|
|
29
|
-
this.startUpdate(curr);
|
|
30
|
-
});
|
|
31
|
-
this.#mut_subscriptions = Arr.toPushed(
|
|
32
|
-
this.#mut_subscriptions,
|
|
33
|
-
subscription
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
complete() {
|
|
37
|
-
for (const s of this.#mut_subscriptions) {
|
|
38
|
-
s.unsubscribe();
|
|
39
|
-
}
|
|
40
|
-
for (const o of this.#mut_observables) {
|
|
41
|
-
o.complete();
|
|
42
|
-
}
|
|
43
|
-
super.complete();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
35
|
+
);
|
|
36
|
+
};
|
|
46
37
|
|
|
47
38
|
export { flatMap, mergeMap };
|
|
48
39
|
//# sourceMappingURL=merge-map.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-map.mjs","sources":["../../../src/core/operators/merge-map.mts"],"sourcesContent":["import { Arr, Optional } from 'ts-data-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"merge-map.mjs","sources":["../../../src/core/operators/merge-map.mts"],"sourcesContent":["import { Arr, Optional } from 'ts-data-forge';\nimport { createAsyncChildObservable } from '../base/index.mjs';\nimport {\n type DropInitialValueOperator,\n type MergeMapOperatorObservable,\n type Observable,\n type Subscription,\n} from '../types/index.mjs';\n\n/**\n * Projects each source value to an observable and merges all inner observables.\n * Unlike `switchMap`, does not cancel previous inner observables.\n *\n * @template A - The type of values from the source\n * @template B - The type of values from the projected observable\n * @param mapToObservable - A function that maps each source value to an observable\n * @returns An operator that merges mapped observables\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // input$ A B C\n * // inner A A1 A2 A3\n * // inner B B1 B2 B3\n * // inner C C1 C2 C3\n * // result$ A1 A2 A3 B1 B2 C1 B3 C2 C3\n * //\n * // Explanation:\n * // - mergeMap creates an inner observable for each source value\n * // - Unlike switchMap, previous inner observables are NOT cancelled\n * // - B's inner continues even after C arrives (B3 is still emitted)\n * // - All inner observables run concurrently and their results are merged\n *\n * const input$ = source<string>();\n *\n * const result$ = input$.pipe(\n * mergeMap((letter) => {\n * const inner$ = source<string>();\n *\n * setTimeout(() => {\n * inner$.next(`${letter}1`);\n * }, 10);\n *\n * setTimeout(() => {\n * inner$.next(`${letter}2`);\n * }, 110);\n *\n * setTimeout(() => {\n * inner$.next(`${letter}3`);\n * }, 210);\n *\n * return inner$;\n * }),\n * );\n *\n * const valueHistory: string[] = [];\n *\n * result$.subscribe((value) => {\n * valueHistory.push(value);\n * });\n *\n * const sleep = (ms: number): Promise<void> =>\n * new Promise((resolve) => {\n * setTimeout(resolve, ms);\n * });\n *\n * // Emit A - inner emits A1, A2, A3 at 10ms, 110ms, 210ms\n * input$.next('A');\n *\n * await sleep(250);\n *\n * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3']);\n *\n * // Emit B - inner starts emitting B1, B2 at 10ms, 110ms\n * input$.next('B');\n *\n * await sleep(150);\n *\n * assert.deepStrictEqual(valueHistory, ['A1', 'A2', 'A3', 'B1', 'B2']);\n *\n * // Emit C while B's inner is still running (B3 at 210ms not yet fired)\n * // Unlike switchMap, B's inner is NOT cancelled\n * input$.next('C');\n *\n * await sleep(250);\n *\n * // B3 appears between C1 and C2, showing the merge behavior\n * assert.deepStrictEqual(valueHistory, [\n * 'A1',\n * 'A2',\n * 'A3',\n * 'B1',\n * 'B2',\n * 'C1',\n * 'B3',\n * 'C2',\n * 'C3',\n * ]);\n * ```\n *\n * @note To improve code readability, consider using `createState` instead of `mergeMap`,\n * subscribing to `parentObservable` and calling `setState` within it.\n */\nexport const mergeMap =\n <A, B>(\n mapToObservable: (curr: A) => Observable<B>,\n ): DropInitialValueOperator<A, B> =>\n (parentObservable) =>\n createMergeMapObservable(parentObservable, mapToObservable);\n\n/**\n * Alias for `mergeMap`.\n * @see mergeMap\n */\nexport const flatMap = mergeMap;\n\nconst createMergeMapObservable = <A, B>(\n parentObservable: Observable<A>,\n mapToObservable: (curr: A) => Observable<B>,\n): MergeMapOperatorObservable<A, B> => {\n let mut_observables: readonly Observable<B>[] = [];\n\n let mut_subscriptions: readonly Subscription[] = [];\n\n return createAsyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: Optional.none,\n onComplete: () => {\n for (const s of mut_subscriptions) {\n s.unsubscribe();\n }\n\n for (const o of mut_observables) {\n o.complete();\n }\n },\n },\n ({ startUpdate }) =>\n (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n const observable = mapToObservable(sn.value);\n\n mut_observables = Arr.toPushed(mut_observables, observable);\n\n const subscription = observable.subscribe((curr) => {\n startUpdate(curr);\n });\n\n mut_subscriptions = Arr.toPushed(mut_subscriptions, subscription);\n },\n );\n};\n"],"names":[],"mappings":";;;;AAwGO,MAAM,WACX,CACE,eAAA,KAEF,CAAC,gBAAA,KACC,wBAAA,CAAyB,kBAAkB,eAAe;AAMvD,MAAM,OAAA,GAAU;AAEvB,MAAM,wBAAA,GAA2B,CAC/B,gBAAA,EACA,eAAA,KACqC;AACrC,EAAA,IAAI,kBAA4C,EAAC;AAEjD,EAAA,IAAI,oBAA6C,EAAC;AAElD,EAAA,OAAO,0BAAA;AAAA,IACL;AAAA,MACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,MAC1B,cAAc,QAAA,CAAS,IAAA;AAAA,MACvB,YAAY,MAAM;AAChB,QAAA,KAAA,MAAW,KAAK,iBAAA,EAAmB;AACjC,UAAA,CAAA,CAAE,WAAA,EAAY;AAAA,QAChB;AAEA,QAAA,KAAA,MAAW,KAAK,eAAA,EAAiB;AAC/B,UAAA,CAAA,CAAE,QAAA,EAAS;AAAA,QACb;AAAA,MACF;AAAA,KACF;AAAA,IACA,CAAC,EAAE,WAAA,EAAY,KACb,CAAC,WAAA,KAAgB;AACf,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,EAAA,CAAG,KAAK,CAAA;AAE3C,MAAA,eAAA,GAAkB,GAAA,CAAI,QAAA,CAAS,eAAA,EAAiB,UAAU,CAAA;AAE1D,MAAA,MAAM,YAAA,GAAe,UAAA,CAAW,SAAA,CAAU,CAAC,IAAA,KAAS;AAClD,QAAA,WAAA,CAAY,IAAI,CAAA;AAAA,MAClB,CAAC,CAAA;AAED,MAAA,iBAAA,GAAoB,GAAA,CAAI,QAAA,CAAS,iBAAA,EAAmB,YAAY,CAAA;AAAA,IAClE;AAAA,GACJ;AACF,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairwise.d.mts","sourceRoot":"","sources":["../../../src/core/operators/pairwise.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EACL,KAAK,wBAAwB,
|
|
1
|
+
{"version":3,"file":"pairwise.d.mts","sourceRoot":"","sources":["../../../src/core/operators/pairwise.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EACL,KAAK,wBAAwB,EAG9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,OAAM,wBAAwB,CACtD,CAAC,EACD,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAClB,CAAC"}
|
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
import { Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
2
|
+
import { createSyncChildObservable } from '../base/create-child-observable.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
5
|
const pairwise = () => f;
|
|
6
|
-
const f = (parentObservable) =>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
const f = (parentObservable) => createPairwiseObservable(parentObservable);
|
|
7
|
+
const createPairwiseObservable = (parentObservable) => createSyncChildObservable(
|
|
8
|
+
{
|
|
9
|
+
parents: [parentObservable],
|
|
10
|
+
initialValue: Optional.none
|
|
11
|
+
},
|
|
12
|
+
({ setNext }) => {
|
|
13
|
+
let mut_previousValue = parentObservable.getSnapshot();
|
|
14
|
+
return (updateToken) => {
|
|
15
|
+
const sn = parentObservable.getSnapshot();
|
|
16
|
+
if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const prev = mut_previousValue;
|
|
20
|
+
const cond = !Optional.isNone(prev);
|
|
21
|
+
mut_previousValue = parentObservable.getSnapshot();
|
|
22
|
+
if (cond) {
|
|
23
|
+
setNext([prev.value, sn.value], updateToken);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
15
26
|
}
|
|
16
|
-
|
|
17
|
-
const par = this.parents[0];
|
|
18
|
-
const sn = par.getSnapshot();
|
|
19
|
-
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const prev = this.#mut_previousValue;
|
|
23
|
-
const cond = !Optional.isNone(prev);
|
|
24
|
-
this.#mut_previousValue = par.getSnapshot();
|
|
25
|
-
if (cond) {
|
|
26
|
-
this.setNext([prev.value, sn.value], updateToken);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
27
|
+
);
|
|
30
28
|
|
|
31
29
|
export { pairwise };
|
|
32
30
|
//# sourceMappingURL=pairwise.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairwise.mjs","sources":["../../../src/core/operators/pairwise.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { type FixedLengthTuple } from 'ts-type-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"pairwise.mjs","sources":["../../../src/core/operators/pairwise.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { type FixedLengthTuple } from 'ts-type-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport {\n type DropInitialValueOperator,\n type Observable,\n type PairwiseOperatorObservable,\n} from '../types/index.mjs';\n\n/**\n * Emits the previous and current values as a pair.\n * Does not emit until the source has emitted at least twice.\n *\n * @template A - The type of values from the source\n * @returns An operator that pairs consecutive values\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 2 3 4\n * // pairs$ [1,2] [2,3] [3,4]\n * //\n * // Explanation:\n * // - pairwise emits the current and previous values as a tuple\n * // - Nothing is emitted for the first value (no previous value yet)\n * // - Useful for tracking changes between consecutive values\n *\n * const num$ = source<number>();\n *\n * const pairs$ = num$.pipe(pairwise());\n *\n * const valueHistory: FixedLengthTuple<2, number>[] = [];\n *\n * pairs$.subscribe(([prev, curr]) => {\n * valueHistory.push([prev, curr]);\n * });\n *\n * num$.next(1); // nothing logged\n *\n * assert.deepStrictEqual(valueHistory, []);\n *\n * num$.next(2); // logs: 1, 2\n *\n * assert.deepStrictEqual(valueHistory, [[1, 2]]);\n *\n * num$.next(3); // logs: 2, 3\n *\n * assert.deepStrictEqual(valueHistory, [\n * [1, 2],\n * [2, 3],\n * ]);\n *\n * num$.next(4); // logs: 3, 4\n *\n * assert.deepStrictEqual(valueHistory, [\n * [1, 2],\n * [2, 3],\n * [3, 4],\n * ]);\n * ```\n */\nexport const pairwise = <A,>(): DropInitialValueOperator<\n A,\n FixedLengthTuple<2, A>\n> => f;\n\nconst f = <A,>(\n parentObservable: Observable<A>,\n): Observable<FixedLengthTuple<2, A>> =>\n createPairwiseObservable(parentObservable);\n\nconst createPairwiseObservable = <A,>(\n parentObservable: Observable<A>,\n): PairwiseOperatorObservable<A> =>\n createSyncChildObservable<FixedLengthTuple<2, A>, readonly [A]>(\n {\n parents: [parentObservable],\n initialValue: Optional.none,\n },\n ({ setNext }) => {\n // parentObservable.snapshot has value\n // if parentObservable is InitializedObservable\n let mut_previousValue: Optional<A> = parentObservable.getSnapshot();\n\n return (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n const prev = mut_previousValue;\n\n const cond = !Optional.isNone(prev);\n\n // NOTE: Must update before setNext, otherwise Optional.isNone(prev) remains true when tryUpdate is called consecutively\n mut_previousValue = parentObservable.getSnapshot();\n\n if (cond) {\n setNext([prev.value, sn.value], updateToken);\n }\n };\n },\n );\n"],"names":[],"mappings":";;;;AA8DO,MAAM,WAAW,MAGnB;AAEL,MAAM,CAAA,GAAI,CACR,gBAAA,KAEA,wBAAA,CAAyB,gBAAgB,CAAA;AAE3C,MAAM,wBAAA,GAA2B,CAC/B,gBAAA,KAEA,yBAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,cAAc,QAAA,CAAS;AAAA,GACzB;AAAA,EACA,CAAC,EAAE,OAAA,EAAQ,KAAM;AAGf,IAAA,IAAI,iBAAA,GAAiC,iBAAiB,WAAA,EAAY;AAElE,IAAA,OAAO,CAAC,WAAA,KAAgB;AACtB,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,iBAAA;AAEb,MAAA,MAAM,IAAA,GAAO,CAAC,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA;AAGlC,MAAA,iBAAA,GAAoB,iBAAiB,WAAA,EAAY;AAEjD,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,OAAA,CAAQ,CAAC,IAAA,CAAK,KAAA,EAAO,EAAA,CAAG,KAAK,GAAG,WAAW,CAAA;AAAA,MAC7C;AAAA,IACF,CAAA;AAAA,EACF;AACF,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.d.mts","sourceRoot":"","sources":["../../../src/core/operators/scan.mts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"scan.d.mts","sourceRoot":"","sources":["../../../src/core/operators/scan.mts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,eAAO,MAAM,IAAI,GACd,CAAC,EAAE,CAAC,WACM,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,gBACjB,CAAC,KACd,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAE+B,CAAC"}
|
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import { Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
2
|
+
import { createInitializedSyncChildObservable } from '../base/create-child-observable.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
|
-
const scan = (reducer, initialValue) => (parentObservable) =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
tryUpdate(updateToken) {
|
|
16
|
-
const par = this.parents[0];
|
|
17
|
-
const psn = par.getSnapshot();
|
|
18
|
-
const sn = this.getSnapshot();
|
|
19
|
-
if (par.updateToken !== updateToken || Optional.isNone(psn) || Optional.isNone(sn)) {
|
|
5
|
+
const scan = (reducer, initialValue) => (parentObservable) => createScanObservable(parentObservable, reducer, initialValue);
|
|
6
|
+
const createScanObservable = (parentObservable, reducer, initialValue) => createInitializedSyncChildObservable(
|
|
7
|
+
{
|
|
8
|
+
parents: [parentObservable],
|
|
9
|
+
initialValue: Optional.some(initialValue)
|
|
10
|
+
},
|
|
11
|
+
({ setNext, getSnapshot }) => (updateToken) => {
|
|
12
|
+
const psn = parentObservable.getSnapshot();
|
|
13
|
+
const sn = getSnapshot();
|
|
14
|
+
if (parentObservable.updateToken !== updateToken || Optional.isNone(psn) || Optional.isNone(sn)) {
|
|
20
15
|
return;
|
|
21
16
|
}
|
|
22
|
-
|
|
17
|
+
setNext(reducer(sn.value, psn.value), updateToken);
|
|
23
18
|
}
|
|
24
|
-
|
|
19
|
+
);
|
|
25
20
|
|
|
26
21
|
export { scan };
|
|
27
22
|
//# sourceMappingURL=scan.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.mjs","sources":["../../../src/core/operators/scan.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"scan.mjs","sources":["../../../src/core/operators/scan.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createInitializedSyncChildObservable } from '../base/index.mjs';\nimport {\n type Observable,\n type ScanOperatorObservable,\n type WithInitialValueOperator,\n} from '../types/index.mjs';\n\n/**\n * Applies an accumulator function over the source observable and emits each intermediate result.\n * Similar to Array.reduce but emits accumulated value after each source emission.\n *\n * @template A - The type of values from the source\n * @template B - The type of the accumulated value\n * @param reducer - The accumulator function\n * @param initialValue - The initial accumulated value (seed)\n * @returns An operator that accumulates values\n *\n * @example\n * ```ts\n * // Timeline (accumulating sum):\n * //\n * // num$ 1 2 3 4 5\n * // sum$ 1 3 6 10 15\n * // | | | | |\n * // 0+1 1+2 3+3 6+4 10+5\n * //\n * // Explanation:\n * // - scan accumulates values over time using a reducer function\n * // - Starting with seed value 0, each emission adds to the accumulator\n * // - Similar to Array.reduce, but for streams\n *\n * const num$ = source<number>();\n *\n * const sum$ = num$.pipe(scan((acc, curr) => acc + curr, 0));\n *\n * const valueHistory: number[] = [];\n *\n * sum$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * assert.deepStrictEqual(valueHistory, [0]);\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [0, 1]);\n *\n * num$.next(2); // logs: 3\n *\n * assert.deepStrictEqual(valueHistory, [0, 1, 3]);\n *\n * num$.next(3); // logs: 6\n *\n * assert.deepStrictEqual(valueHistory, [0, 1, 3, 6]);\n * ```\n */\nexport const scan =\n <A, B>(\n reducer: (acc: B, curr: A) => B,\n initialValue: B,\n ): WithInitialValueOperator<A, B> =>\n (parentObservable) =>\n createScanObservable(parentObservable, reducer, initialValue);\n\nconst createScanObservable = <A, B>(\n parentObservable: Observable<A>,\n reducer: (acc: B, curr: A) => B,\n initialValue: B,\n): ScanOperatorObservable<A, B> =>\n createInitializedSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: Optional.some(initialValue),\n },\n ({ setNext, getSnapshot }) =>\n (updateToken) => {\n const psn = parentObservable.getSnapshot();\n\n const sn = getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(psn) ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n setNext(reducer(sn.value, psn.value), updateToken);\n },\n );\n"],"names":[],"mappings":";;;;AAyDO,MAAM,IAAA,GACX,CACE,OAAA,EACA,YAAA,KAEF,CAAC,gBAAA,KACC,oBAAA,CAAqB,gBAAA,EAAkB,OAAA,EAAS,YAAY;AAEhE,MAAM,oBAAA,GAAuB,CAC3B,gBAAA,EACA,OAAA,EACA,YAAA,KAEA,oCAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,YAAA,EAAc,QAAA,CAAS,IAAA,CAAK,YAAY;AAAA,GAC1C;AAAA,EACA,CAAC,EAAE,OAAA,EAAS,WAAA,EAAY,KACtB,CAAC,WAAA,KAAgB;AACf,IAAA,MAAM,GAAA,GAAM,iBAAiB,WAAA,EAAY;AAEzC,IAAA,MAAM,KAAK,WAAA,EAAY;AAEvB,IAAA,IACE,gBAAA,CAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,IACnB,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,MAAA;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,QAAQ,EAAA,CAAG,KAAA,EAAO,GAAA,CAAI,KAAK,GAAG,WAAW,CAAA;AAAA,EACnD;AACJ,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skip-if-no-change.d.mts","sourceRoot":"","sources":["../../../src/core/operators/skip-if-no-change.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,
|
|
1
|
+
{"version":3,"file":"skip-if-no-change.d.mts","sourceRoot":"","sources":["../../../src/core/operators/skip-if-no-change.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAG9B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,OAC1B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,OAAO,KAC1B,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAMQ,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,uBAAiB,CAAC"}
|
|
@@ -1,40 +1,36 @@
|
|
|
1
1
|
import { Optional } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
2
|
+
import { createSyncChildObservable } from '../base/create-child-observable.mjs';
|
|
3
3
|
import '../utils/id-maker.mjs';
|
|
4
4
|
|
|
5
5
|
const skipIfNoChange = (eq = (x, y) => Object.is(x, y)) => (
|
|
6
6
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
7
|
-
((parentObservable) =>
|
|
7
|
+
((parentObservable) => createSkipIfNoChangeObservable(
|
|
8
8
|
parentObservable,
|
|
9
9
|
eq
|
|
10
10
|
))
|
|
11
11
|
);
|
|
12
12
|
const distinctUntilChanged = skipIfNoChange;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
const createSkipIfNoChangeObservable = (parentObservable, eq) => createSyncChildObservable(
|
|
14
|
+
{
|
|
15
|
+
parents: [parentObservable],
|
|
16
|
+
initialValue: parentObservable.getSnapshot()
|
|
17
|
+
},
|
|
18
|
+
({ setNext }) => {
|
|
19
|
+
let mut_previousValue = parentObservable.getSnapshot();
|
|
20
|
+
return (updateToken) => {
|
|
21
|
+
const sn = parentObservable.getSnapshot();
|
|
22
|
+
if (parentObservable.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const prev = mut_previousValue;
|
|
26
|
+
const cond = Optional.isNone(prev) || !eq(prev.value, sn.value);
|
|
27
|
+
mut_previousValue = sn;
|
|
28
|
+
if (cond) {
|
|
29
|
+
setNext(sn.value, updateToken);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
23
32
|
}
|
|
24
|
-
|
|
25
|
-
const par = this.parents[0];
|
|
26
|
-
const sn = par.getSnapshot();
|
|
27
|
-
if (par.updateToken !== updateToken || Optional.isNone(sn)) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const prev = this.#mut_previousValue;
|
|
31
|
-
const cond = Optional.isNone(prev) || !this.#eq(prev.value, sn.value);
|
|
32
|
-
this.#mut_previousValue = sn;
|
|
33
|
-
if (cond) {
|
|
34
|
-
this.setNext(sn.value, updateToken);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
33
|
+
);
|
|
38
34
|
|
|
39
35
|
export { distinctUntilChanged, skipIfNoChange };
|
|
40
36
|
//# sourceMappingURL=skip-if-no-change.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skip-if-no-change.mjs","sources":["../../../src/core/operators/skip-if-no-change.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport {
|
|
1
|
+
{"version":3,"file":"skip-if-no-change.mjs","sources":["../../../src/core/operators/skip-if-no-change.mts"],"sourcesContent":["import { Optional } from 'ts-data-forge';\nimport { createSyncChildObservable } from '../base/index.mjs';\nimport {\n type KeepInitialValueOperator,\n type Observable,\n type SkipIfNoChangeOperatorObservable,\n} from '../types/index.mjs';\n\n/**\n * Skips emissions if the value hasn't changed from the previous emission.\n * Uses a custom equality function or Object.is by default.\n *\n * @template A - The type of values from the source\n * @param eq - Equality comparison function (default: Object.is)\n * @returns An operator that skips duplicate consecutive values\n *\n * @example\n * ```ts\n * // Timeline:\n * //\n * // num$ 1 1 2 2 1 2 3 2\n * // distinct$ 1 2 1 2 3 2\n * //\n * // Explanation:\n * // - skipIfNoChange filters out consecutive duplicate values\n * // - Uses strict equality (===) for comparison\n * // - Only emits when the value actually changes\n *\n * const num$ = source<number>();\n *\n * const distinct$ = num$.pipe(skipIfNoChange());\n *\n * const valueHistory: number[] = [];\n *\n * distinct$.subscribe((x) => {\n * valueHistory.push(x);\n * });\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * num$.next(1); // nothing logged\n *\n * assert.deepStrictEqual(valueHistory, [1]);\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2]);\n *\n * num$.next(2); // nothing logged\n *\n * num$.next(1); // logs: 1\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 1]);\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 1, 2]);\n *\n * num$.next(3); // logs: 3\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 1, 2, 3]);\n *\n * num$.next(2); // logs: 2\n *\n * assert.deepStrictEqual(valueHistory, [1, 2, 1, 2, 3, 2]);\n * ```\n */\nexport const skipIfNoChange = <A,>(\n eq: (x: A, y: A) => boolean = (x, y) => Object.is(x, y),\n): KeepInitialValueOperator<A, A> =>\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n ((parentObservable) =>\n createSkipIfNoChangeObservable(\n parentObservable,\n eq,\n )) as KeepInitialValueOperator<A, A>;\n\n/**\n * Alias for `skipIfNoChange`.\n * @see skipIfNoChange\n */\nexport const distinctUntilChanged = skipIfNoChange;\n\nconst createSkipIfNoChangeObservable = <A,>(\n parentObservable: Observable<A>,\n eq: (x: A, y: A) => boolean,\n): SkipIfNoChangeOperatorObservable<A> =>\n createSyncChildObservable(\n {\n parents: [parentObservable],\n initialValue: parentObservable.getSnapshot(),\n },\n ({ setNext }) => {\n // parentObservable.snapshot has value\n // if parentObservable is InitializedObservable\n let mut_previousValue: Optional<A> = parentObservable.getSnapshot();\n\n return (updateToken) => {\n const sn = parentObservable.getSnapshot();\n\n if (\n parentObservable.updateToken !== updateToken ||\n Optional.isNone(sn)\n ) {\n return; // skip update\n }\n\n const prev = mut_previousValue;\n\n const cond = Optional.isNone(prev) || !eq(prev.value, sn.value);\n\n // NOTE: Must update before setNext, otherwise Optional.isNone(prev) remains true when tryUpdate is called consecutively\n mut_previousValue = sn;\n\n if (cond) {\n setNext(sn.value, updateToken);\n }\n };\n },\n );\n"],"names":[],"mappings":";;;;AAqEO,MAAM,cAAA,GAAiB,CAC5B,EAAA,GAA8B,CAAC,GAAG,CAAA,KAAM,MAAA,CAAO,EAAA,CAAG,CAAA,EAAG,CAAC,CAAA;AAAA;AAAA,GAGrD,CAAC,gBAAA,KACA,8BAAA;AAAA,IACE,gBAAA;AAAA,IACA;AAAA,GACF;AAAA;AAMG,MAAM,oBAAA,GAAuB;AAEpC,MAAM,8BAAA,GAAiC,CACrC,gBAAA,EACA,EAAA,KAEA,yBAAA;AAAA,EACE;AAAA,IACE,OAAA,EAAS,CAAC,gBAAgB,CAAA;AAAA,IAC1B,YAAA,EAAc,iBAAiB,WAAA;AAAY,GAC7C;AAAA,EACA,CAAC,EAAE,OAAA,EAAQ,KAAM;AAGf,IAAA,IAAI,iBAAA,GAAiC,iBAAiB,WAAA,EAAY;AAElE,IAAA,OAAO,CAAC,WAAA,KAAgB;AACtB,MAAA,MAAM,EAAA,GAAK,iBAAiB,WAAA,EAAY;AAExC,MAAA,IACE,iBAAiB,WAAA,KAAgB,WAAA,IACjC,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAClB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,iBAAA;AAEb,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,MAAA,CAAO,IAAI,CAAA,IAAK,CAAC,EAAA,CAAG,IAAA,CAAK,KAAA,EAAO,EAAA,CAAG,KAAK,CAAA;AAG9D,MAAA,iBAAA,GAAoB,EAAA;AAEpB,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,WAAW,CAAA;AAAA,MAC/B;AAAA,IACF,CAAA;AAAA,EACF;AACF,CAAA;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skip-until.d.mts","sourceRoot":"","sources":["../../../src/core/operators/skip-until.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"skip-until.d.mts","sourceRoot":"","sources":["../../../src/core/operators/skip-until.mts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,SAAS,GACnB,CAAC,YAAa,UAAU,CAAC,OAAO,CAAC,KAAG,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAEX,CAAC"}
|