reactor-core-ts 3.2.2 → 3.2.3

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 CHANGED
@@ -442,6 +442,7 @@ Every row below includes a minimal example.
442
442
  | `skipUntilOther` | Drop values until another publisher signals. | `Flux.interval(100).skipUntilOther(Mono.delay(300))` |
443
443
  | `distinct` | Keep the first value for each key. | `Flux.just(1, 1, 2).distinct()` |
444
444
  | `distinctUntilChanged` | Drop only adjacent duplicates. | `Flux.just(1, 1, 2, 1).distinctUntilChanged()` |
445
+ | `distinctUntilChangedDeep` | Drop adjacent values with equal nested state. | `users.distinctUntilChangedDeep()` |
445
446
  | `elementAt` | Pick a value by index. | `Flux.just("a", "b").elementAt(1)` |
446
447
  | `defaultIfEmpty` | Emit a fallback value if empty. | `Flux.empty<number>().defaultIfEmpty(0)` |
447
448
  | `switchIfEmpty` | Switch to another source if empty. | `Flux.empty<number>().switchIfEmpty(Flux.just(1))` |
@@ -452,6 +453,10 @@ Every row below includes a minimal example.
452
453
  | `transformDeferredContextual` | Transform per subscription with `Context`. | `Flux.just(1).transformDeferredContextual((f, ctx) => f.map(v => [v, ctx.get("id")]))` |
453
454
  | `hide` | Hide implementation identity. | `Flux.just(1).hide()` |
454
455
 
456
+ `distinctUntilChangedDeep` snapshots arrays, enumerable properties of ordinary
457
+ objects, and local `Date`, `RegExp`, `Map` and `Set` values. Other object types
458
+ keep identity-comparison semantics.
459
+
455
460
  ### Flux Flattening And Combining Methods
456
461
 
457
462
  | Method | What it does and why | Example |
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Internal helpers for snapshotting and comparing nested JavaScript values.
4
+ */
5
+ /** Creates a detached snapshot of nested enumerable state and supported mutable value types. */
6
+ export declare function snapshotDeep(value: unknown): unknown;
7
+ /** Compares nested enumerable state, supported mutable values, cycles and shared references. */
8
+ export declare function deepEqual(left: unknown, right: unknown): boolean;
9
+ //# sourceMappingURL=deep-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-value.d.ts","sourceRoot":"","sources":["../../src/internal/deep-value.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAkEpD;AAED,gGAAgG;AAChG,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAyEhE"}
@@ -0,0 +1,159 @@
1
+ //#region src/internal/deep-value.ts
2
+ /** Retains reliable kind metadata for snapshots whose prototypes may contain stateful getters. */
3
+ var SNAPSHOT_KINDS = /* @__PURE__ */ new WeakMap();
4
+ /** Creates a detached snapshot of nested enumerable state and supported mutable value types. */
5
+ function snapshotDeep(value) {
6
+ const snapshots = /* @__PURE__ */ new Map();
7
+ function snapshotValue(current) {
8
+ if (!isObject(current) || typeof current === "function") return current;
9
+ if (snapshots.has(current)) return snapshots.get(current);
10
+ const kind = valueKind(current);
11
+ let snapshot;
12
+ switch (kind) {
13
+ case "array":
14
+ snapshot = new Array(current.length);
15
+ break;
16
+ case "date":
17
+ snapshot = new Date(current.getTime());
18
+ break;
19
+ case "regexp": {
20
+ const source = current;
21
+ const regexp = new RegExp(source.source, source.flags);
22
+ regexp.lastIndex = source.lastIndex;
23
+ snapshot = regexp;
24
+ break;
25
+ }
26
+ case "map":
27
+ snapshot = /* @__PURE__ */ new Map();
28
+ break;
29
+ case "set":
30
+ snapshot = /* @__PURE__ */ new Set();
31
+ break;
32
+ case "record":
33
+ snapshot = Object.create(Object.getPrototypeOf(current));
34
+ break;
35
+ case "opaque": return current;
36
+ }
37
+ if (kind === "array") Object.setPrototypeOf(snapshot, Object.getPrototypeOf(current));
38
+ SNAPSHOT_KINDS.set(snapshot, kind);
39
+ snapshots.set(current, snapshot);
40
+ if (kind === "map") {
41
+ const source = current;
42
+ const target = snapshot;
43
+ for (const [key, entryValue] of source) target.set(snapshotValue(key), snapshotValue(entryValue));
44
+ } else if (kind === "set") {
45
+ const source = current;
46
+ const target = snapshot;
47
+ for (const entryValue of source) target.add(snapshotValue(entryValue));
48
+ }
49
+ copyEnumerableState(current, snapshot, snapshotValue);
50
+ return snapshot;
51
+ }
52
+ return snapshotValue(value);
53
+ }
54
+ /** Compares nested enumerable state, supported mutable values, cycles and shared references. */
55
+ function deepEqual(left, right) {
56
+ const leftToRight = /* @__PURE__ */ new Map();
57
+ const rightToLeft = /* @__PURE__ */ new Map();
58
+ function equal(leftValue, rightValue) {
59
+ if (Object.is(leftValue, rightValue)) {
60
+ if (isObject(leftValue)) {
61
+ if (leftToRight.has(leftValue) || rightToLeft.has(leftValue)) return leftToRight.get(leftValue) === leftValue && rightToLeft.get(leftValue) === leftValue;
62
+ leftToRight.set(leftValue, leftValue);
63
+ rightToLeft.set(leftValue, leftValue);
64
+ }
65
+ return true;
66
+ }
67
+ if (!isObject(leftValue) || !isObject(rightValue)) return false;
68
+ if (typeof leftValue === "function" || typeof rightValue === "function") return false;
69
+ if (Object.getPrototypeOf(leftValue) !== Object.getPrototypeOf(rightValue)) return false;
70
+ const kind = valueKind(leftValue);
71
+ if (kind === "opaque" || kind !== valueKind(rightValue)) return false;
72
+ if (leftToRight.has(leftValue) || rightToLeft.has(rightValue)) return leftToRight.get(leftValue) === rightValue && rightToLeft.get(rightValue) === leftValue;
73
+ leftToRight.set(leftValue, rightValue);
74
+ rightToLeft.set(rightValue, leftValue);
75
+ switch (kind) {
76
+ case "array":
77
+ if (leftValue.length !== rightValue.length) return false;
78
+ break;
79
+ case "date":
80
+ if (!Object.is(leftValue.getTime(), rightValue.getTime())) return false;
81
+ break;
82
+ case "regexp": {
83
+ const leftRegExp = leftValue;
84
+ const rightRegExp = rightValue;
85
+ if (leftRegExp.source !== rightRegExp.source || leftRegExp.flags !== rightRegExp.flags || leftRegExp.lastIndex !== rightRegExp.lastIndex) return false;
86
+ break;
87
+ }
88
+ case "map":
89
+ if (!equalMap(leftValue, rightValue, equal)) return false;
90
+ break;
91
+ case "set":
92
+ if (!equalSet(leftValue, rightValue, equal)) return false;
93
+ break;
94
+ case "record": break;
95
+ }
96
+ return equalEnumerableState(leftValue, rightValue, equal);
97
+ }
98
+ return equal(left, right);
99
+ }
100
+ /** Returns true for non-null object and function values. */
101
+ function isObject(value) {
102
+ return typeof value === "object" && value !== null || typeof value === "function";
103
+ }
104
+ /** Classifies values with observable state supported by the deep snapshot. */
105
+ function valueKind(value) {
106
+ const snapshotKind = SNAPSHOT_KINDS.get(value);
107
+ if (snapshotKind) return snapshotKind;
108
+ if (Array.isArray(value)) return "array";
109
+ const prototype = Object.getPrototypeOf(value);
110
+ if (value instanceof Date && prototype === Date.prototype) return "date";
111
+ if (value instanceof RegExp && prototype === RegExp.prototype) return "regexp";
112
+ if (value instanceof Map && prototype === Map.prototype) return "map";
113
+ if (value instanceof Set && prototype === Set.prototype) return "set";
114
+ return Object.prototype.toString.call(value) === "[object Object]" ? "record" : "opaque";
115
+ }
116
+ /** Copies enumerable own properties without retaining nested object references. */
117
+ function copyEnumerableState(source, target, snapshot) {
118
+ for (const key of enumerableKeys(source)) if (!Object.prototype.hasOwnProperty.call(target, key)) Object.defineProperty(target, key, {
119
+ configurable: true,
120
+ enumerable: true,
121
+ value: snapshot(Reflect.get(source, key)),
122
+ writable: true
123
+ });
124
+ }
125
+ /** Compares enumerable own properties in linear time. */
126
+ function equalEnumerableState(left, right, equal) {
127
+ const leftKeys = enumerableKeys(left);
128
+ if (leftKeys.length !== enumerableKeys(right).length) return false;
129
+ for (const key of leftKeys) if (!Object.prototype.propertyIsEnumerable.call(right, key) || !equal(Reflect.get(left, key), Reflect.get(right, key))) return false;
130
+ return true;
131
+ }
132
+ /** Lists enumerable string and symbol properties owned by a value. */
133
+ function enumerableKeys(value) {
134
+ return Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
135
+ }
136
+ /** Compares Maps in their observable iteration order. */
137
+ function equalMap(left, right, equal) {
138
+ if (left.size !== right.size) return false;
139
+ const rightEntries = right.entries();
140
+ for (const [leftKey, leftValue] of left) {
141
+ const rightEntry = rightEntries.next();
142
+ if (rightEntry.done || !equal(leftKey, rightEntry.value[0]) || !equal(leftValue, rightEntry.value[1])) return false;
143
+ }
144
+ return true;
145
+ }
146
+ /** Compares Sets in their observable iteration order. */
147
+ function equalSet(left, right, equal) {
148
+ if (left.size !== right.size) return false;
149
+ const rightValues = right.values();
150
+ for (const leftValue of left) {
151
+ const rightValue = rightValues.next();
152
+ if (rightValue.done || !equal(leftValue, rightValue.value)) return false;
153
+ }
154
+ return true;
155
+ }
156
+ //#endregion
157
+ export { deepEqual, snapshotDeep };
158
+
159
+ //# sourceMappingURL=deep-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deep-value.js","names":[],"sources":["../../src/internal/deep-value.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Internal helpers for snapshotting and comparing nested JavaScript values.\n */\n\n/** Value categories whose mutable state can be captured without retaining the source object. */\ntype DeepValueKind = \"array\" | \"date\" | \"regexp\" | \"map\" | \"set\" | \"record\" | \"opaque\";\n\n/** Retains reliable kind metadata for snapshots whose prototypes may contain stateful getters. */\nconst SNAPSHOT_KINDS = new WeakMap<object, DeepValueKind>();\n\n/** Creates a detached snapshot of nested enumerable state and supported mutable value types. */\nexport function snapshotDeep(value: unknown): unknown {\n const snapshots = new Map<object, unknown>();\n\n function snapshotValue(current: unknown): unknown {\n if (!isObject(current) || typeof current === \"function\") {\n return current;\n }\n\n if (snapshots.has(current)) {\n return snapshots.get(current);\n }\n\n const kind = valueKind(current);\n let snapshot: object;\n switch (kind) {\n case \"array\":\n snapshot = new Array((current as unknown[]).length);\n break;\n case \"date\":\n snapshot = new Date((current as unknown as Date).getTime());\n break;\n case \"regexp\": {\n const source = current as unknown as RegExp;\n const regexp = new RegExp(source.source, source.flags);\n regexp.lastIndex = source.lastIndex;\n snapshot = regexp;\n break;\n }\n case \"map\":\n snapshot = new Map();\n break;\n case \"set\":\n snapshot = new Set();\n break;\n case \"record\":\n snapshot = Object.create(Object.getPrototypeOf(current)) as object;\n break;\n case \"opaque\":\n return current;\n }\n\n if (kind === \"array\") {\n Object.setPrototypeOf(snapshot, Object.getPrototypeOf(current));\n }\n SNAPSHOT_KINDS.set(snapshot, kind);\n snapshots.set(current, snapshot);\n\n if (kind === \"map\") {\n const source = current as unknown as Map<unknown, unknown>;\n const target = snapshot as Map<unknown, unknown>;\n for (const [key, entryValue] of source) {\n target.set(snapshotValue(key), snapshotValue(entryValue));\n }\n } else if (kind === \"set\") {\n const source = current as unknown as Set<unknown>;\n const target = snapshot as Set<unknown>;\n for (const entryValue of source) {\n target.add(snapshotValue(entryValue));\n }\n }\n\n copyEnumerableState(current, snapshot, snapshotValue);\n return snapshot;\n }\n\n return snapshotValue(value);\n}\n\n/** Compares nested enumerable state, supported mutable values, cycles and shared references. */\nexport function deepEqual(left: unknown, right: unknown): boolean {\n const leftToRight = new Map<object, object>();\n const rightToLeft = new Map<object, object>();\n\n function equal(leftValue: unknown, rightValue: unknown): boolean {\n if (Object.is(leftValue, rightValue)) {\n if (isObject(leftValue)) {\n if (leftToRight.has(leftValue) || rightToLeft.has(leftValue)) {\n return leftToRight.get(leftValue) === leftValue && rightToLeft.get(leftValue) === leftValue;\n }\n leftToRight.set(leftValue, leftValue);\n rightToLeft.set(leftValue, leftValue);\n }\n return true;\n }\n if (!isObject(leftValue) || !isObject(rightValue)) {\n return false;\n }\n if (typeof leftValue === \"function\" || typeof rightValue === \"function\") {\n return false;\n }\n if (Object.getPrototypeOf(leftValue) !== Object.getPrototypeOf(rightValue)) {\n return false;\n }\n\n const kind = valueKind(leftValue);\n if (kind === \"opaque\" || kind !== valueKind(rightValue)) {\n return false;\n }\n if (leftToRight.has(leftValue) || rightToLeft.has(rightValue)) {\n return leftToRight.get(leftValue) === rightValue && rightToLeft.get(rightValue) === leftValue;\n }\n leftToRight.set(leftValue, rightValue);\n rightToLeft.set(rightValue, leftValue);\n\n switch (kind) {\n case \"array\":\n if ((leftValue as unknown[]).length !== (rightValue as unknown[]).length) {\n return false;\n }\n break;\n case \"date\":\n if (!Object.is((leftValue as Date).getTime(), (rightValue as Date).getTime())) {\n return false;\n }\n break;\n case \"regexp\": {\n const leftRegExp = leftValue as RegExp;\n const rightRegExp = rightValue as RegExp;\n if (leftRegExp.source !== rightRegExp.source\n || leftRegExp.flags !== rightRegExp.flags\n || leftRegExp.lastIndex !== rightRegExp.lastIndex) {\n return false;\n }\n break;\n }\n case \"map\":\n if (!equalMap(leftValue as Map<unknown, unknown>, rightValue as Map<unknown, unknown>, equal)) {\n return false;\n }\n break;\n case \"set\":\n if (!equalSet(leftValue as Set<unknown>, rightValue as Set<unknown>, equal)) {\n return false;\n }\n break;\n case \"record\":\n break;\n }\n return equalEnumerableState(leftValue, rightValue, equal);\n }\n\n return equal(left, right);\n}\n\n/** Returns true for non-null object and function values. */\nfunction isObject(value: unknown): value is object {\n return (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n\n/** Classifies values with observable state supported by the deep snapshot. */\nfunction valueKind(value: object): DeepValueKind {\n const snapshotKind = SNAPSHOT_KINDS.get(value);\n if (snapshotKind) {\n return snapshotKind;\n }\n if (Array.isArray(value)) {\n return \"array\";\n }\n const prototype = Object.getPrototypeOf(value);\n if (value instanceof Date && prototype === Date.prototype) {\n return \"date\";\n }\n if (value instanceof RegExp && prototype === RegExp.prototype) {\n return \"regexp\";\n }\n if (value instanceof Map && prototype === Map.prototype) {\n return \"map\";\n }\n if (value instanceof Set && prototype === Set.prototype) {\n return \"set\";\n }\n return Object.prototype.toString.call(value) === \"[object Object]\" ? \"record\" : \"opaque\";\n}\n\n/** Copies enumerable own properties without retaining nested object references. */\nfunction copyEnumerableState(source: object, target: object, snapshot: (value: unknown) => unknown): void {\n for (const key of enumerableKeys(source)) {\n if (!Object.prototype.hasOwnProperty.call(target, key)) {\n Object.defineProperty(target, key, {\n configurable: true,\n enumerable: true,\n value: snapshot(Reflect.get(source, key)),\n writable: true\n });\n }\n }\n}\n\n/** Compares enumerable own properties in linear time. */\nfunction equalEnumerableState(\n left: object,\n right: object,\n equal: (left: unknown, right: unknown) => boolean\n): boolean {\n const leftKeys = enumerableKeys(left);\n if (leftKeys.length !== enumerableKeys(right).length) {\n return false;\n }\n for (const key of leftKeys) {\n if (!Object.prototype.propertyIsEnumerable.call(right, key)\n || !equal(Reflect.get(left, key), Reflect.get(right, key))) {\n return false;\n }\n }\n return true;\n}\n\n/** Lists enumerable string and symbol properties owned by a value. */\nfunction enumerableKeys(value: object): PropertyKey[] {\n return Reflect.ownKeys(value).filter(key => Object.prototype.propertyIsEnumerable.call(value, key));\n}\n\n/** Compares Maps in their observable iteration order. */\nfunction equalMap(\n left: Map<unknown, unknown>,\n right: Map<unknown, unknown>,\n equal: (left: unknown, right: unknown) => boolean\n): boolean {\n if (left.size !== right.size) {\n return false;\n }\n const rightEntries = right.entries();\n for (const [leftKey, leftValue] of left) {\n const rightEntry = rightEntries.next();\n if (rightEntry.done || !equal(leftKey, rightEntry.value[0]) || !equal(leftValue, rightEntry.value[1])) {\n return false;\n }\n }\n return true;\n}\n\n/** Compares Sets in their observable iteration order. */\nfunction equalSet(\n left: Set<unknown>,\n right: Set<unknown>,\n equal: (left: unknown, right: unknown) => boolean\n): boolean {\n if (left.size !== right.size) {\n return false;\n }\n const rightValues = right.values();\n for (const leftValue of left) {\n const rightValue = rightValues.next();\n if (rightValue.done || !equal(leftValue, rightValue.value)) {\n return false;\n }\n }\n return true;\n}\n"],"mappings":"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"}
@@ -3,6 +3,13 @@
3
3
  * Internal iterable transformation helpers.
4
4
  */
5
5
  import { type AnyIterable } from "./iterable.js";
6
+ /** Defines how adjacent selected keys are compared and retained. */
7
+ export interface DistinctUntilChangedStrategy<K> {
8
+ /** Returns true when adjacent keys represent the same state. */
9
+ equals(previous: unknown, current: K): boolean;
10
+ /** Captures the state retained for the next comparison. */
11
+ snapshot(value: K): unknown;
12
+ }
6
13
  /** Maps an iterable, preserving synchronous iteration when possible. */
7
14
  export declare function mapIterable<T, R>(source: AnyIterable<T>, mapper: (value: T) => R): AnyIterable<R>;
8
15
  /** Filters an iterable, preserving synchronous iteration when possible. */
@@ -18,7 +25,7 @@ export declare function skipWhileIterable<T>(source: AnyIterable<T>, predicate:
18
25
  /** Keeps the first value for every selected key, preserving synchronous iteration when possible. */
19
26
  export declare function distinctIterable<T, K>(source: AnyIterable<T>, keySelector: (value: T) => K): AnyIterable<T>;
20
27
  /** Keeps values whose selected key differs from the previous key. */
21
- export declare function distinctUntilChangedIterable<T, K>(source: AnyIterable<T>, keySelector: (value: T) => K): AnyIterable<T>;
28
+ export declare function distinctUntilChangedIterable<T, K>(source: AnyIterable<T>, keySelector: (value: T) => K, strategy?: DistinctUntilChangedStrategy<K>): AnyIterable<T>;
22
29
  /** Emits a fallback value when the source is empty. */
23
30
  export declare function defaultIfEmptyIterable<T>(source: AnyIterable<T>, defaultValue: T): AnyIterable<T>;
24
31
  //# sourceMappingURL=iterable-transform.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"iterable-transform.d.ts","sourceRoot":"","sources":["../../src/internal/iterable-transform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAC,KAAK,WAAW,EAAkB,MAAM,wBAAwB,CAAC;AAEzE,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAajG;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAiB1G;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAmB7G;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAmB7G;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAuBrF;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAuB7G;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAuB3G;AAED,qEAAqE;AACrE,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,CAAC,EAC7C,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAC7B,WAAW,CAAC,CAAC,CAAC,CA2BhB;AAED,uDAAuD;AACvD,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAuBjG"}
1
+ {"version":3,"file":"iterable-transform.d.ts","sourceRoot":"","sources":["../../src/internal/iterable-transform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAC,KAAK,WAAW,EAAkB,MAAM,wBAAwB,CAAC;AAEzE,oEAAoE;AACpE,MAAM,WAAW,4BAA4B,CAAC,CAAC;IAC3C,gEAAgE;IAChE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;IAE/C,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC;CAC/B;AAED,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAajG;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAiB1G;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAmB7G;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAmB7G;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAuBrF;AAED,mGAAmG;AACnG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAuB7G;AAED,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAuB3G;AAED,qEAAqE;AACrE,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,CAAC,EAC7C,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAC5B,QAAQ,CAAC,EAAE,4BAA4B,CAAC,CAAC,CAAC,GAC3C,WAAW,CAAC,CAAC,CAAC,CA6BhB;AAED,uDAAuD;AACvD,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAuBjG"}
@@ -108,15 +108,17 @@ function distinctIterable(source, keySelector) {
108
108
  })();
109
109
  }
110
110
  /** Keeps values whose selected key differs from the previous key. */
111
- function distinctUntilChangedIterable(source, keySelector) {
111
+ function distinctUntilChangedIterable(source, keySelector, strategy) {
112
+ const equals = strategy?.equals ?? Object.is;
113
+ const snapshot = strategy?.snapshot ?? ((value) => value);
112
114
  if (isAsyncIterable(source)) return (async function* () {
113
115
  let hasPrevious = false;
114
116
  let previous;
115
117
  for await (const value of source) {
116
118
  const key = keySelector(value);
117
- if (!hasPrevious || !Object.is(previous, key)) {
119
+ if (!hasPrevious || !equals(previous, key)) {
118
120
  hasPrevious = true;
119
- previous = key;
121
+ previous = snapshot(key);
120
122
  yield value;
121
123
  }
122
124
  }
@@ -126,9 +128,9 @@ function distinctUntilChangedIterable(source, keySelector) {
126
128
  let previous;
127
129
  for (const value of source) {
128
130
  const key = keySelector(value);
129
- if (!hasPrevious || !Object.is(previous, key)) {
131
+ if (!hasPrevious || !equals(previous, key)) {
130
132
  hasPrevious = true;
131
- previous = key;
133
+ previous = snapshot(key);
132
134
  yield value;
133
135
  }
134
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"iterable-transform.js","names":[],"sources":["../../src/internal/iterable-transform.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Internal iterable transformation helpers.\n */\nimport {type AnyIterable, isAsyncIterable} from \"@/internal/iterable.js\";\n\n/** Maps an iterable, preserving synchronous iteration when possible. */\nexport function mapIterable<T, R>(source: AnyIterable<T>, mapper: (value: T) => R): AnyIterable<R> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n yield mapper(value);\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n yield mapper(value);\n }\n })();\n}\n\n/** Filters an iterable, preserving synchronous iteration when possible. */\nexport function filterIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n if (predicate(value)) {\n yield value;\n }\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n if (predicate(value)) {\n yield value;\n }\n }\n })();\n}\n\n/** Takes values while a predicate returns true, preserving synchronous iteration when possible. */\nexport function takeWhileIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n if (!predicate(value)) {\n return;\n }\n yield value;\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n if (!predicate(value)) {\n return;\n }\n yield value;\n }\n })();\n}\n\n/** Takes values until a predicate returns true, preserving synchronous iteration when possible. */\nexport function takeUntilIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n yield value;\n if (predicate(value)) {\n return;\n }\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n yield value;\n if (predicate(value)) {\n return;\n }\n }\n })();\n}\n\n/** Skips a fixed number of values, preserving synchronous iteration when possible. */\nexport function skipIterable<T>(source: AnyIterable<T>, count: number): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let skipped = 0;\n for await (const value of source) {\n if (skipped < count) {\n skipped += 1;\n } else {\n yield value;\n }\n }\n })();\n }\n return (function* () {\n let skipped = 0;\n for (const value of source) {\n if (skipped < count) {\n skipped += 1;\n } else {\n yield value;\n }\n }\n })();\n}\n\n/** Skips values while a predicate returns true, preserving synchronous iteration when possible. */\nexport function skipWhileIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let skipping = true;\n for await (const value of source) {\n if (skipping && predicate(value)) {\n continue;\n }\n skipping = false;\n yield value;\n }\n })();\n }\n return (function* () {\n let skipping = true;\n for (const value of source) {\n if (skipping && predicate(value)) {\n continue;\n }\n skipping = false;\n yield value;\n }\n })();\n}\n\n/** Keeps the first value for every selected key, preserving synchronous iteration when possible. */\nexport function distinctIterable<T, K>(source: AnyIterable<T>, keySelector: (value: T) => K): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n const seen = new Set<K>();\n for await (const value of source) {\n const key = keySelector(value);\n if (!seen.has(key)) {\n seen.add(key);\n yield value;\n }\n }\n })();\n }\n return (function* () {\n const seen = new Set<K>();\n for (const value of source) {\n const key = keySelector(value);\n if (!seen.has(key)) {\n seen.add(key);\n yield value;\n }\n }\n })();\n}\n\n/** Keeps values whose selected key differs from the previous key. */\nexport function distinctUntilChangedIterable<T, K>(\n source: AnyIterable<T>,\n keySelector: (value: T) => K\n): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let hasPrevious = false;\n let previous: K | undefined;\n for await (const value of source) {\n const key = keySelector(value);\n if (!hasPrevious || !Object.is(previous, key)) {\n hasPrevious = true;\n previous = key;\n yield value;\n }\n }\n })();\n }\n return (function* () {\n let hasPrevious = false;\n let previous: K | undefined;\n for (const value of source) {\n const key = keySelector(value);\n if (!hasPrevious || !Object.is(previous, key)) {\n hasPrevious = true;\n previous = key;\n yield value;\n }\n }\n })();\n}\n\n/** Emits a fallback value when the source is empty. */\nexport function defaultIfEmptyIterable<T>(source: AnyIterable<T>, defaultValue: T): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let empty = true;\n for await (const value of source) {\n empty = false;\n yield value;\n }\n if (empty) {\n yield defaultValue;\n }\n })();\n }\n return (function* () {\n let empty = true;\n for (const value of source) {\n empty = false;\n yield value;\n }\n if (empty) {\n yield defaultValue;\n }\n })();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"iterable-transform.js","names":[],"sources":["../../src/internal/iterable-transform.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Internal iterable transformation helpers.\n */\nimport {type AnyIterable, isAsyncIterable} from \"@/internal/iterable.js\";\n\n/** Defines how adjacent selected keys are compared and retained. */\nexport interface DistinctUntilChangedStrategy<K> {\n /** Returns true when adjacent keys represent the same state. */\n equals(previous: unknown, current: K): boolean;\n\n /** Captures the state retained for the next comparison. */\n snapshot(value: K): unknown;\n}\n\n/** Maps an iterable, preserving synchronous iteration when possible. */\nexport function mapIterable<T, R>(source: AnyIterable<T>, mapper: (value: T) => R): AnyIterable<R> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n yield mapper(value);\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n yield mapper(value);\n }\n })();\n}\n\n/** Filters an iterable, preserving synchronous iteration when possible. */\nexport function filterIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n if (predicate(value)) {\n yield value;\n }\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n if (predicate(value)) {\n yield value;\n }\n }\n })();\n}\n\n/** Takes values while a predicate returns true, preserving synchronous iteration when possible. */\nexport function takeWhileIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n if (!predicate(value)) {\n return;\n }\n yield value;\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n if (!predicate(value)) {\n return;\n }\n yield value;\n }\n })();\n}\n\n/** Takes values until a predicate returns true, preserving synchronous iteration when possible. */\nexport function takeUntilIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n for await (const value of source) {\n yield value;\n if (predicate(value)) {\n return;\n }\n }\n })();\n }\n return (function* () {\n for (const value of source) {\n yield value;\n if (predicate(value)) {\n return;\n }\n }\n })();\n}\n\n/** Skips a fixed number of values, preserving synchronous iteration when possible. */\nexport function skipIterable<T>(source: AnyIterable<T>, count: number): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let skipped = 0;\n for await (const value of source) {\n if (skipped < count) {\n skipped += 1;\n } else {\n yield value;\n }\n }\n })();\n }\n return (function* () {\n let skipped = 0;\n for (const value of source) {\n if (skipped < count) {\n skipped += 1;\n } else {\n yield value;\n }\n }\n })();\n}\n\n/** Skips values while a predicate returns true, preserving synchronous iteration when possible. */\nexport function skipWhileIterable<T>(source: AnyIterable<T>, predicate: (value: T) => boolean): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let skipping = true;\n for await (const value of source) {\n if (skipping && predicate(value)) {\n continue;\n }\n skipping = false;\n yield value;\n }\n })();\n }\n return (function* () {\n let skipping = true;\n for (const value of source) {\n if (skipping && predicate(value)) {\n continue;\n }\n skipping = false;\n yield value;\n }\n })();\n}\n\n/** Keeps the first value for every selected key, preserving synchronous iteration when possible. */\nexport function distinctIterable<T, K>(source: AnyIterable<T>, keySelector: (value: T) => K): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n const seen = new Set<K>();\n for await (const value of source) {\n const key = keySelector(value);\n if (!seen.has(key)) {\n seen.add(key);\n yield value;\n }\n }\n })();\n }\n return (function* () {\n const seen = new Set<K>();\n for (const value of source) {\n const key = keySelector(value);\n if (!seen.has(key)) {\n seen.add(key);\n yield value;\n }\n }\n })();\n}\n\n/** Keeps values whose selected key differs from the previous key. */\nexport function distinctUntilChangedIterable<T, K>(\n source: AnyIterable<T>,\n keySelector: (value: T) => K,\n strategy?: DistinctUntilChangedStrategy<K>\n): AnyIterable<T> {\n const equals = strategy?.equals ?? Object.is;\n const snapshot = strategy?.snapshot ?? ((value: K): unknown => value);\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let hasPrevious = false;\n let previous: unknown;\n for await (const value of source) {\n const key = keySelector(value);\n if (!hasPrevious || !equals(previous, key)) {\n hasPrevious = true;\n previous = snapshot(key);\n yield value;\n }\n }\n })();\n }\n return (function* () {\n let hasPrevious = false;\n let previous: unknown;\n for (const value of source) {\n const key = keySelector(value);\n if (!hasPrevious || !equals(previous, key)) {\n hasPrevious = true;\n previous = snapshot(key);\n yield value;\n }\n }\n })();\n}\n\n/** Emits a fallback value when the source is empty. */\nexport function defaultIfEmptyIterable<T>(source: AnyIterable<T>, defaultValue: T): AnyIterable<T> {\n if (isAsyncIterable<T>(source)) {\n return (async function* () {\n let empty = true;\n for await (const value of source) {\n empty = false;\n yield value;\n }\n if (empty) {\n yield defaultValue;\n }\n })();\n }\n return (function* () {\n let empty = true;\n for (const value of source) {\n empty = false;\n yield value;\n }\n if (empty) {\n yield defaultValue;\n }\n })();\n}\n"],"mappings":"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"}
@@ -16,6 +16,11 @@ declare module "../flux.js" {
16
16
  distinct<K = T>(keySelector?: (value: T) => K): Flux<T>;
17
17
  /** Drops adjacent values whose selected key is equal to the previous key. */
18
18
  distinctUntilChanged<K = T>(keySelector?: (value: T) => K): Flux<T>;
19
+ /**
20
+ * Drops adjacent values with equal nested state. Snapshots arrays, enumerable properties of ordinary objects,
21
+ * and local `Date`, `RegExp`, `Map` and `Set` values; other object types retain identity comparison.
22
+ */
23
+ distinctUntilChangedDeep<K = T>(keySelector?: (value: T) => K): Flux<T>;
19
24
  /** Emits `defaultValue` when the source completes without values. */
20
25
  defaultIfEmpty(defaultValue: T): Flux<T>;
21
26
  /** Switches to `alternate` when the source completes without values. */
@@ -1 +1 @@
1
- {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/publisher/operators/selection.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEzD,OAAO,QAAQ,qBAAqB,CAAC;IACjC,uDAAuD;IACvD,UAAU,IAAI,CAAC,CAAC;QACZ,iDAAiD;QACjD,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzB,4EAA4E;QAC5E,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErD,mFAAmF;QACnF,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErD,yCAAyC;QACzC,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzB,2EAA2E;QAC3E,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErD,wDAAwD;QACxD,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAExD,6EAA6E;QAC7E,oBAAoB,CAAC,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpE,qEAAqE;QACrE,cAAc,CAAC,YAAY,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzC,wEAAwE;QACxE,aAAa,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;KACxD;CACJ"}
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/publisher/operators/selection.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AAEzD,OAAO,QAAQ,qBAAqB,CAAC;IACjC,uDAAuD;IACvD,UAAU,IAAI,CAAC,CAAC;QACZ,iDAAiD;QACjD,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzB,4EAA4E;QAC5E,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErD,mFAAmF;QACnF,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErD,yCAAyC;QACzC,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzB,2EAA2E;QAC3E,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAErD,wDAAwD;QACxD,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAExD,6EAA6E;QAC7E,oBAAoB,CAAC,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpE;;;WAGG;QACH,wBAAwB,CAAC,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAExE,qEAAqE;QACrE,cAAc,CAAC,YAAY,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzC,wEAAwE;QACxE,aAAa,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;KACxD;CACJ"}
@@ -2,6 +2,7 @@ import { isAsyncIterable, toAsyncIterator } from "../../internal/iterable.js";
2
2
  import { defaultIfEmptyIterable, distinctIterable, distinctUntilChangedIterable, skipIterable, skipWhileIterable, takeUntilIterable, takeWhileIterable } from "../../internal/iterable-transform.js";
3
3
  import { identity } from "../helpers.js";
4
4
  import { Flux } from "../flux.js";
5
+ import { deepEqual, snapshotDeep } from "../../internal/deep-value.js";
5
6
  //#region src/publisher/operators/selection.ts
6
7
  /**
7
8
  * @packageDocumentation
@@ -88,6 +89,13 @@ Flux.prototype.distinctUntilChanged = function distinctUntilChanged(keySelector
88
89
  const source = this;
89
90
  return new Flux((signal, context) => distinctUntilChangedIterable(source.iterate(signal, context), keySelector));
90
91
  };
92
+ Flux.prototype.distinctUntilChangedDeep = function distinctUntilChangedDeep(keySelector = identity) {
93
+ const source = this;
94
+ return new Flux((signal, context) => distinctUntilChangedIterable(source.iterate(signal, context), keySelector, {
95
+ equals: deepEqual,
96
+ snapshot: snapshotDeep
97
+ }));
98
+ };
91
99
  Flux.prototype.defaultIfEmpty = function defaultIfEmpty(defaultValue) {
92
100
  const source = this;
93
101
  return new Flux((signal, context) => defaultIfEmptyIterable(source.iterate(signal, context), defaultValue));
@@ -1 +1 @@
1
- {"version":3,"file":"selection.js","names":[],"sources":["../../../src/publisher/operators/selection.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Flux, Mono and operator implementation modules.\n */\nimport {Flux} from \"@/publisher/flux.js\";\nimport {\n type AnyIterable,\n isAsyncIterable,\n toAsyncIterator\n} from \"@/internal/iterable.js\";\nimport {\n defaultIfEmptyIterable,\n distinctIterable,\n distinctUntilChangedIterable,\n skipIterable,\n skipWhileIterable,\n takeUntilIterable,\n takeWhileIterable\n} from \"@/internal/iterable-transform.js\";\nimport {identity} from \"@/publisher/helpers.js\";\nimport type {PublisherInput} from \"@/publisher/types.js\";\n\ndeclare module \"@/publisher/flux.js\" {\n /** Selection and filtering operators added to Flux. */\n interface Flux<T> {\n /** Emits at most the first `n` source values. */\n take(n: number): Flux<T>;\n\n /** Emits values while the predicate returns true, then cancels upstream. */\n takeWhile(predicate: (value: T) => boolean): Flux<T>;\n\n /** Emits values until the predicate returns true, including the matching value. */\n takeUntil(predicate: (value: T) => boolean): Flux<T>;\n\n /** Drops the first `n` source values. */\n skip(n: number): Flux<T>;\n\n /** Drops values while the predicate returns true, then relays the rest. */\n skipWhile(predicate: (value: T) => boolean): Flux<T>;\n\n /** Emits only the first value for each selected key. */\n distinct<K = T>(keySelector?: (value: T) => K): Flux<T>;\n\n /** Drops adjacent values whose selected key is equal to the previous key. */\n distinctUntilChanged<K = T>(keySelector?: (value: T) => K): Flux<T>;\n\n /** Emits `defaultValue` when the source completes without values. */\n defaultIfEmpty(defaultValue: T): Flux<T>;\n\n /** Switches to `alternate` when the source completes without values. */\n switchIfEmpty(alternate: PublisherInput<T>): Flux<T>;\n }\n}\n\nFlux.prototype.take = function take<T>(this: Flux<T>, n: number): Flux<T> {\n if (!Number.isInteger(n) || n < 0) {\n throw new RangeError(\"take expects a non-negative integer\");\n }\n if (n === 0) {\n return Flux.empty<T>();\n }\n const source = this;\n return new Flux((signal, context) => {\n const controller = new AbortController();\n const abort = () => controller.abort(signal.reason);\n signal.addEventListener(\"abort\", abort, {once: true});\n let values: AnyIterable<T>;\n try {\n values = source.iterate(controller.signal, context);\n } catch (error) {\n signal.removeEventListener(\"abort\", abort);\n throw error;\n }\n if (!isAsyncIterable<T>(values)) {\n return (function* () {\n let remaining = n;\n try {\n for (const value of values) {\n yield value;\n remaining -= 1;\n if (remaining === 0) {\n controller.abort();\n return;\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n if (signal.aborted && !controller.signal.aborted) {\n controller.abort(signal.reason);\n }\n }\n })();\n }\n return (async function* () {\n const iterator = toAsyncIterator(values);\n let remaining = n;\n let cancelledSource = false;\n try {\n while (!signal.aborted) {\n const result = await iterator.next();\n if (result.done) {\n return;\n }\n yield result.value;\n remaining -= 1;\n if (remaining === 0) {\n cancelledSource = true;\n controller.abort();\n return;\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n if (signal.aborted && !controller.signal.aborted) {\n controller.abort(signal.reason);\n }\n if (cancelledSource || signal.aborted) {\n await iterator.return?.();\n }\n }\n })();\n });\n};\n\nFlux.prototype.takeWhile = function takeWhile<T>(this: Flux<T>, predicate: (value: T) => boolean): Flux<T> {\n const source = this;\n return new Flux((signal, context) => takeWhileIterable(source.iterate(signal, context), predicate));\n};\n\nFlux.prototype.takeUntil = function takeUntil<T>(this: Flux<T>, predicate: (value: T) => boolean): Flux<T> {\n const source = this;\n return new Flux((signal, context) => takeUntilIterable(source.iterate(signal, context), predicate));\n};\n\nFlux.prototype.skip = function skip<T>(this: Flux<T>, n: number): Flux<T> {\n if (!Number.isInteger(n) || n < 0) {\n throw new RangeError(\"skip expects a non-negative integer\");\n }\n if (n === 0) {\n return this;\n }\n const source = this;\n return new Flux((signal, context) => skipIterable(source.iterate(signal, context), n));\n};\n\nFlux.prototype.skipWhile = function skipWhile<T>(this: Flux<T>, predicate: (value: T) => boolean): Flux<T> {\n const source = this;\n return new Flux((signal, context) => skipWhileIterable(source.iterate(signal, context), predicate));\n};\n\nFlux.prototype.distinct = function distinct<T, K = T>(\n this: Flux<T>,\n keySelector: (value: T) => K = identity as (value: T) => K\n): Flux<T> {\n const source = this;\n return new Flux((signal, context) => distinctIterable(source.iterate(signal, context), keySelector));\n};\n\nFlux.prototype.distinctUntilChanged = function distinctUntilChanged<T, K = T>(\n this: Flux<T>,\n keySelector: (value: T) => K = identity as (value: T) => K\n): Flux<T> {\n const source = this;\n return new Flux((signal, context) => distinctUntilChangedIterable(source.iterate(signal, context), keySelector));\n};\n\nFlux.prototype.defaultIfEmpty = function defaultIfEmpty<T>(this: Flux<T>, defaultValue: T): Flux<T> {\n const source = this;\n return new Flux((signal, context) => defaultIfEmptyIterable(source.iterate(signal, context), defaultValue));\n};\n\nFlux.prototype.switchIfEmpty = function switchIfEmpty<T>(this: Flux<T>, alternate: PublisherInput<T>): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n let empty = true;\n for await (const value of source.iterate(signal, context)) {\n empty = false;\n yield value;\n }\n if (empty) {\n for await (const value of Flux.from(alternate).iterate(signal, context)) {\n yield value;\n }\n }\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"selection.js","names":[],"sources":["../../../src/publisher/operators/selection.ts"],"sourcesContent":["/**\n * @packageDocumentation\n * Flux, Mono and operator implementation modules.\n */\nimport {deepEqual, snapshotDeep} from \"@/internal/deep-value.js\";\nimport {\n type AnyIterable,\n isAsyncIterable,\n toAsyncIterator\n} from \"@/internal/iterable.js\";\nimport {\n defaultIfEmptyIterable,\n distinctIterable,\n distinctUntilChangedIterable,\n skipIterable,\n skipWhileIterable,\n takeUntilIterable,\n takeWhileIterable\n} from \"@/internal/iterable-transform.js\";\nimport {Flux} from \"@/publisher/flux.js\";\nimport {identity} from \"@/publisher/helpers.js\";\nimport type {PublisherInput} from \"@/publisher/types.js\";\n\ndeclare module \"@/publisher/flux.js\" {\n /** Selection and filtering operators added to Flux. */\n interface Flux<T> {\n /** Emits at most the first `n` source values. */\n take(n: number): Flux<T>;\n\n /** Emits values while the predicate returns true, then cancels upstream. */\n takeWhile(predicate: (value: T) => boolean): Flux<T>;\n\n /** Emits values until the predicate returns true, including the matching value. */\n takeUntil(predicate: (value: T) => boolean): Flux<T>;\n\n /** Drops the first `n` source values. */\n skip(n: number): Flux<T>;\n\n /** Drops values while the predicate returns true, then relays the rest. */\n skipWhile(predicate: (value: T) => boolean): Flux<T>;\n\n /** Emits only the first value for each selected key. */\n distinct<K = T>(keySelector?: (value: T) => K): Flux<T>;\n\n /** Drops adjacent values whose selected key is equal to the previous key. */\n distinctUntilChanged<K = T>(keySelector?: (value: T) => K): Flux<T>;\n\n /**\n * Drops adjacent values with equal nested state. Snapshots arrays, enumerable properties of ordinary objects,\n * and local `Date`, `RegExp`, `Map` and `Set` values; other object types retain identity comparison.\n */\n distinctUntilChangedDeep<K = T>(keySelector?: (value: T) => K): Flux<T>;\n\n /** Emits `defaultValue` when the source completes without values. */\n defaultIfEmpty(defaultValue: T): Flux<T>;\n\n /** Switches to `alternate` when the source completes without values. */\n switchIfEmpty(alternate: PublisherInput<T>): Flux<T>;\n }\n}\n\nFlux.prototype.take = function take<T>(this: Flux<T>, n: number): Flux<T> {\n if (!Number.isInteger(n) || n < 0) {\n throw new RangeError(\"take expects a non-negative integer\");\n }\n if (n === 0) {\n return Flux.empty<T>();\n }\n const source = this;\n return new Flux((signal, context) => {\n const controller = new AbortController();\n const abort = () => controller.abort(signal.reason);\n signal.addEventListener(\"abort\", abort, {once: true});\n let values: AnyIterable<T>;\n try {\n values = source.iterate(controller.signal, context);\n } catch (error) {\n signal.removeEventListener(\"abort\", abort);\n throw error;\n }\n if (!isAsyncIterable<T>(values)) {\n return (function* () {\n let remaining = n;\n try {\n for (const value of values) {\n yield value;\n remaining -= 1;\n if (remaining === 0) {\n controller.abort();\n return;\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n if (signal.aborted && !controller.signal.aborted) {\n controller.abort(signal.reason);\n }\n }\n })();\n }\n return (async function* () {\n const iterator = toAsyncIterator(values);\n let remaining = n;\n let cancelledSource = false;\n try {\n while (!signal.aborted) {\n const result = await iterator.next();\n if (result.done) {\n return;\n }\n yield result.value;\n remaining -= 1;\n if (remaining === 0) {\n cancelledSource = true;\n controller.abort();\n return;\n }\n }\n } finally {\n signal.removeEventListener(\"abort\", abort);\n if (signal.aborted && !controller.signal.aborted) {\n controller.abort(signal.reason);\n }\n if (cancelledSource || signal.aborted) {\n await iterator.return?.();\n }\n }\n })();\n });\n};\n\nFlux.prototype.takeWhile = function takeWhile<T>(this: Flux<T>, predicate: (value: T) => boolean): Flux<T> {\n const source = this;\n return new Flux((signal, context) => takeWhileIterable(source.iterate(signal, context), predicate));\n};\n\nFlux.prototype.takeUntil = function takeUntil<T>(this: Flux<T>, predicate: (value: T) => boolean): Flux<T> {\n const source = this;\n return new Flux((signal, context) => takeUntilIterable(source.iterate(signal, context), predicate));\n};\n\nFlux.prototype.skip = function skip<T>(this: Flux<T>, n: number): Flux<T> {\n if (!Number.isInteger(n) || n < 0) {\n throw new RangeError(\"skip expects a non-negative integer\");\n }\n if (n === 0) {\n return this;\n }\n const source = this;\n return new Flux((signal, context) => skipIterable(source.iterate(signal, context), n));\n};\n\nFlux.prototype.skipWhile = function skipWhile<T>(this: Flux<T>, predicate: (value: T) => boolean): Flux<T> {\n const source = this;\n return new Flux((signal, context) => skipWhileIterable(source.iterate(signal, context), predicate));\n};\n\nFlux.prototype.distinct = function distinct<T, K = T>(\n this: Flux<T>,\n keySelector: (value: T) => K = identity as (value: T) => K\n): Flux<T> {\n const source = this;\n return new Flux((signal, context) => distinctIterable(source.iterate(signal, context), keySelector));\n};\n\nFlux.prototype.distinctUntilChanged = function distinctUntilChanged<T, K = T>(\n this: Flux<T>,\n keySelector: (value: T) => K = identity as (value: T) => K\n): Flux<T> {\n const source = this;\n return new Flux((signal, context) => distinctUntilChangedIterable(source.iterate(signal, context), keySelector));\n};\n\nFlux.prototype.distinctUntilChangedDeep = function distinctUntilChangedDeep<T, K = T>(\n this: Flux<T>,\n keySelector: (value: T) => K = identity as (value: T) => K\n): Flux<T> {\n const source = this;\n return new Flux((signal, context) => distinctUntilChangedIterable(source.iterate(signal, context), keySelector, {\n equals: deepEqual,\n snapshot: snapshotDeep\n }));\n};\n\nFlux.prototype.defaultIfEmpty = function defaultIfEmpty<T>(this: Flux<T>, defaultValue: T): Flux<T> {\n const source = this;\n return new Flux((signal, context) => defaultIfEmptyIterable(source.iterate(signal, context), defaultValue));\n};\n\nFlux.prototype.switchIfEmpty = function switchIfEmpty<T>(this: Flux<T>, alternate: PublisherInput<T>): Flux<T> {\n const source = this;\n return new Flux(async function* (signal, context) {\n let empty = true;\n for await (const value of source.iterate(signal, context)) {\n empty = false;\n yield value;\n }\n if (empty) {\n for await (const value of Flux.from(alternate).iterate(signal, context)) {\n yield value;\n }\n }\n });\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactor-core-ts",
3
- "version": "3.2.2",
3
+ "version": "3.2.3",
4
4
  "description": "Browser-first TypeScript implementation inspired by Project Reactor Core.",
5
5
  "license": "LGPL-3.0-only",
6
6
  "author": "CKATEPTb",