@evolu/common 8.5.0 → 8.6.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/dist/src/Array.d.ts +170 -97
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +67 -42
- package/dist/src/Assert.d.ts +233 -30
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +150 -30
- package/dist/src/BigInt.d.ts +3 -3
- package/dist/src/BigInt.js +3 -3
- package/dist/src/Brand.d.ts +7 -7
- package/dist/src/Buffer.d.ts +12 -4
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +8 -3
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +8 -4
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +45 -30
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +32 -21
- package/dist/src/Crypto.d.ts +13 -8
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +6 -3
- package/dist/src/Eq.d.ts +107 -58
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +308 -112
- package/dist/src/Function.d.ts +54 -24
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +34 -17
- package/dist/src/Http.d.ts +52 -19
- package/dist/src/Http.d.ts.map +1 -1
- package/dist/src/Identicon.d.ts +9 -4
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +9 -4
- package/dist/src/LockManager.d.ts +12 -10
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/Lookup.d.ts +4 -2
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +4 -2
- package/dist/src/Number.d.ts +28 -24
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +16 -17
- package/dist/src/Object.d.ts +89 -47
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +88 -41
- package/dist/src/Option.d.ts +14 -5
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +14 -5
- package/dist/src/Order.d.ts +12 -12
- package/dist/src/Order.js +12 -12
- package/dist/src/Platform.d.ts +2 -2
- package/dist/src/Random.d.ts +7 -4
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Redacted.d.ts +13 -6
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +4 -2
- package/dist/src/Ref.d.ts +4 -4
- package/dist/src/Relation.d.ts +5 -7
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Resource.d.ts +27 -12
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Result.d.ts +258 -114
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +71 -34
- package/dist/src/Schedule.d.ts +233 -116
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +204 -110
- package/dist/src/Set.d.ts +43 -24
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +25 -13
- package/dist/src/Sqlite.d.ts +4 -4
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +9 -8
- package/dist/src/Task.d.ts +441 -212
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +238 -115
- package/dist/src/Test.d.ts +10 -4
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +10 -4
- package/dist/src/Time.d.ts +27 -17
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +16 -6
- package/dist/src/Type.d.ts +1096 -387
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +1046 -372
- package/dist/src/Types.d.ts +95 -40
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +13 -4
- package/dist/src/WebSocket.d.ts +14 -6
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/Worker.d.ts +10 -6
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/intl/_en.d.ts +3 -1
- package/dist/src/intl/_en.d.ts.map +1 -1
- package/dist/src/intl/_en.js +17 -3
- package/dist/src/intl/ar.d.ts +3 -1
- package/dist/src/intl/ar.d.ts.map +1 -1
- package/dist/src/intl/ar.js +15 -2
- package/dist/src/intl/bn.d.ts +3 -1
- package/dist/src/intl/bn.d.ts.map +1 -1
- package/dist/src/intl/bn.js +16 -3
- package/dist/src/intl/ca.d.ts +3 -1
- package/dist/src/intl/ca.d.ts.map +1 -1
- package/dist/src/intl/ca.js +16 -3
- package/dist/src/intl/cs.d.ts +3 -1
- package/dist/src/intl/cs.d.ts.map +1 -1
- package/dist/src/intl/cs.js +16 -3
- package/dist/src/intl/da.d.ts +3 -1
- package/dist/src/intl/da.d.ts.map +1 -1
- package/dist/src/intl/da.js +16 -3
- package/dist/src/intl/de.d.ts +3 -1
- package/dist/src/intl/de.d.ts.map +1 -1
- package/dist/src/intl/de.js +16 -3
- package/dist/src/intl/el.d.ts +3 -1
- package/dist/src/intl/el.d.ts.map +1 -1
- package/dist/src/intl/el.js +16 -3
- package/dist/src/intl/es.d.ts +3 -1
- package/dist/src/intl/es.d.ts.map +1 -1
- package/dist/src/intl/es.js +16 -3
- package/dist/src/intl/fa.d.ts +3 -1
- package/dist/src/intl/fa.d.ts.map +1 -1
- package/dist/src/intl/fa.js +16 -3
- package/dist/src/intl/fi.d.ts +3 -1
- package/dist/src/intl/fi.d.ts.map +1 -1
- package/dist/src/intl/fi.js +16 -3
- package/dist/src/intl/fil.d.ts +3 -1
- package/dist/src/intl/fil.d.ts.map +1 -1
- package/dist/src/intl/fil.js +16 -3
- package/dist/src/intl/fr.d.ts +3 -1
- package/dist/src/intl/fr.d.ts.map +1 -1
- package/dist/src/intl/fr.js +16 -3
- package/dist/src/intl/he.d.ts +3 -1
- package/dist/src/intl/he.d.ts.map +1 -1
- package/dist/src/intl/he.js +16 -3
- package/dist/src/intl/hi.d.ts +3 -1
- package/dist/src/intl/hi.d.ts.map +1 -1
- package/dist/src/intl/hi.js +16 -3
- package/dist/src/intl/hr.d.ts +3 -1
- package/dist/src/intl/hr.d.ts.map +1 -1
- package/dist/src/intl/hr.js +16 -3
- package/dist/src/intl/hu.d.ts +2 -1
- package/dist/src/intl/hu.d.ts.map +1 -1
- package/dist/src/intl/hu.js +15 -3
- package/dist/src/intl/id.d.ts +3 -1
- package/dist/src/intl/id.d.ts.map +1 -1
- package/dist/src/intl/id.js +16 -3
- package/dist/src/intl/it.d.ts +3 -1
- package/dist/src/intl/it.d.ts.map +1 -1
- package/dist/src/intl/it.js +16 -3
- package/dist/src/intl/ja.d.ts +3 -1
- package/dist/src/intl/ja.d.ts.map +1 -1
- package/dist/src/intl/ja.js +16 -3
- package/dist/src/intl/ko.d.ts +3 -1
- package/dist/src/intl/ko.d.ts.map +1 -1
- package/dist/src/intl/ko.js +16 -3
- package/dist/src/intl/ml.d.ts +3 -1
- package/dist/src/intl/ml.d.ts.map +1 -1
- package/dist/src/intl/ml.js +16 -3
- package/dist/src/intl/mr.d.ts +3 -1
- package/dist/src/intl/mr.d.ts.map +1 -1
- package/dist/src/intl/mr.js +16 -3
- package/dist/src/intl/ms.d.ts +3 -1
- package/dist/src/intl/ms.d.ts.map +1 -1
- package/dist/src/intl/ms.js +15 -2
- package/dist/src/intl/nb.d.ts +2 -1
- package/dist/src/intl/nb.d.ts.map +1 -1
- package/dist/src/intl/nb.js +14 -2
- package/dist/src/intl/nl.d.ts +3 -1
- package/dist/src/intl/nl.d.ts.map +1 -1
- package/dist/src/intl/nl.js +16 -3
- package/dist/src/intl/pa.d.ts +3 -1
- package/dist/src/intl/pa.d.ts.map +1 -1
- package/dist/src/intl/pa.js +16 -3
- package/dist/src/intl/pl.d.ts +2 -0
- package/dist/src/intl/pl.d.ts.map +1 -1
- package/dist/src/intl/pl.js +15 -2
- package/dist/src/intl/pt-BR.d.ts +3 -1
- package/dist/src/intl/pt-BR.d.ts.map +1 -1
- package/dist/src/intl/pt-BR.js +16 -3
- package/dist/src/intl/pt.d.ts +3 -1
- package/dist/src/intl/pt.d.ts.map +1 -1
- package/dist/src/intl/pt.js +15 -2
- package/dist/src/intl/ro.d.ts +3 -1
- package/dist/src/intl/ro.d.ts.map +1 -1
- package/dist/src/intl/ro.js +16 -3
- package/dist/src/intl/sk.d.ts +3 -1
- package/dist/src/intl/sk.d.ts.map +1 -1
- package/dist/src/intl/sk.js +15 -2
- package/dist/src/intl/sl.d.ts +3 -1
- package/dist/src/intl/sl.d.ts.map +1 -1
- package/dist/src/intl/sl.js +16 -3
- package/dist/src/intl/sv.d.ts +3 -1
- package/dist/src/intl/sv.d.ts.map +1 -1
- package/dist/src/intl/sv.js +16 -3
- package/dist/src/intl/sw.d.ts +1 -0
- package/dist/src/intl/sw.d.ts.map +1 -1
- package/dist/src/intl/sw.js +14 -2
- package/dist/src/intl/ta.d.ts +3 -1
- package/dist/src/intl/ta.d.ts.map +1 -1
- package/dist/src/intl/ta.js +16 -3
- package/dist/src/intl/te.d.ts +3 -1
- package/dist/src/intl/te.d.ts.map +1 -1
- package/dist/src/intl/te.js +16 -3
- package/dist/src/intl/th.d.ts +3 -1
- package/dist/src/intl/th.d.ts.map +1 -1
- package/dist/src/intl/th.js +16 -3
- package/dist/src/intl/tr.d.ts +3 -1
- package/dist/src/intl/tr.d.ts.map +1 -1
- package/dist/src/intl/tr.js +16 -3
- package/dist/src/intl/uk.d.ts +3 -1
- package/dist/src/intl/uk.d.ts.map +1 -1
- package/dist/src/intl/uk.js +16 -3
- package/dist/src/intl/ur.d.ts +3 -1
- package/dist/src/intl/ur.d.ts.map +1 -1
- package/dist/src/intl/ur.js +15 -2
- package/dist/src/intl/vi.d.ts +3 -1
- package/dist/src/intl/vi.d.ts.map +1 -1
- package/dist/src/intl/vi.js +16 -3
- package/dist/src/intl/zh-CN.d.ts +3 -1
- package/dist/src/intl/zh-CN.d.ts.map +1 -1
- package/dist/src/intl/zh-CN.js +16 -3
- package/dist/src/intl/zh-TW.d.ts +3 -1
- package/dist/src/intl/zh-TW.d.ts.map +1 -1
- package/dist/src/intl/zh-TW.js +16 -3
- package/dist/src/local-first/Evolu.d.ts +47 -24
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +10 -7
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +10 -7
- package/dist/src/local-first/Protocol.d.ts +5 -5
- package/dist/src/local-first/Protocol.js +5 -5
- package/dist/src/local-first/Query.d.ts +34 -21
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +25 -13
- package/dist/src/local-first/Relay.d.ts +12 -5
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +19 -11
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +11 -6
- package/dist/src/local-first/Storage.d.ts +4 -2
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/package.json +3 -4
- package/src/Array.ts +170 -97
- package/src/Assert.ts +336 -31
- package/src/BigInt.ts +3 -3
- package/src/Brand.ts +7 -7
- package/src/Buffer.ts +12 -4
- package/src/Cache.ts +8 -3
- package/src/Callbacks.ts +8 -4
- package/src/Console.ts +45 -30
- package/src/Crypto.ts +13 -8
- package/src/Eq.ts +450 -122
- package/src/Function.ts +54 -24
- package/src/Http.ts +52 -19
- package/src/Identicon.ts +9 -4
- package/src/LockManager.ts +12 -10
- package/src/Lookup.ts +4 -2
- package/src/Number.ts +28 -24
- package/src/Object.ts +115 -49
- package/src/Option.ts +14 -5
- package/src/Order.ts +12 -12
- package/src/Platform.ts +2 -2
- package/src/Random.ts +7 -4
- package/src/Redacted.ts +13 -6
- package/src/Ref.ts +4 -4
- package/src/Relation.ts +5 -7
- package/src/Resource.ts +27 -12
- package/src/Result.ts +258 -114
- package/src/Schedule.ts +233 -116
- package/src/Set.ts +43 -24
- package/src/Sqlite.ts +9 -8
- package/src/Task.ts +441 -212
- package/src/Test.ts +10 -4
- package/src/Time.ts +27 -17
- package/src/Type.ts +2077 -620
- package/src/Types.ts +108 -40
- package/src/WebSocket.ts +14 -6
- package/src/Worker.ts +10 -6
- package/src/intl/_en.ts +20 -4
- package/src/intl/ar.ts +17 -2
- package/src/intl/bn.ts +19 -4
- package/src/intl/ca.ts +19 -4
- package/src/intl/cs.ts +19 -4
- package/src/intl/da.ts +19 -4
- package/src/intl/de.ts +19 -4
- package/src/intl/el.ts +19 -4
- package/src/intl/es.ts +19 -4
- package/src/intl/fa.ts +19 -4
- package/src/intl/fi.ts +19 -4
- package/src/intl/fil.ts +19 -4
- package/src/intl/fr.ts +19 -4
- package/src/intl/he.ts +19 -4
- package/src/intl/hi.ts +19 -4
- package/src/intl/hr.ts +19 -4
- package/src/intl/hu.ts +18 -4
- package/src/intl/id.ts +19 -4
- package/src/intl/it.ts +19 -4
- package/src/intl/ja.ts +19 -4
- package/src/intl/ko.ts +19 -4
- package/src/intl/ml.ts +19 -4
- package/src/intl/mr.ts +19 -4
- package/src/intl/ms.ts +17 -2
- package/src/intl/nb.ts +16 -2
- package/src/intl/nl.ts +19 -4
- package/src/intl/pa.ts +19 -4
- package/src/intl/pl.ts +18 -2
- package/src/intl/pt-BR.ts +19 -4
- package/src/intl/pt.ts +17 -2
- package/src/intl/ro.ts +19 -4
- package/src/intl/sk.ts +17 -2
- package/src/intl/sl.ts +19 -4
- package/src/intl/sv.ts +19 -4
- package/src/intl/sw.ts +15 -2
- package/src/intl/ta.ts +19 -4
- package/src/intl/te.ts +19 -4
- package/src/intl/th.ts +19 -4
- package/src/intl/tr.ts +19 -4
- package/src/intl/uk.ts +19 -4
- package/src/intl/ur.ts +17 -2
- package/src/intl/vi.ts +19 -3
- package/src/intl/zh-CN.ts +19 -4
- package/src/intl/zh-TW.ts +19 -4
- package/src/local-first/Evolu.ts +47 -24
- package/src/local-first/Owner.ts +10 -7
- package/src/local-first/Protocol.ts +5 -5
- package/src/local-first/Query.ts +34 -21
- package/src/local-first/Relay.ts +12 -5
- package/src/local-first/Schema.ts +19 -11
- package/src/local-first/Storage.ts +4 -2
package/src/Eq.ts
CHANGED
|
@@ -5,12 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { Order } from "./Order.ts";
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
JsonValue,
|
|
12
|
-
JsonValueInput,
|
|
13
|
-
} from "./Type.ts";
|
|
8
|
+
import { getObjectKind } from "./Object.ts";
|
|
9
|
+
import type { Data, IsData, JsonValue, JsonValueInput } from "./Type.ts";
|
|
10
|
+
import type { CompileTimeError } from "./Types.ts";
|
|
14
11
|
|
|
15
12
|
/**
|
|
16
13
|
* Compares two values of the same type `A` for equality.
|
|
@@ -29,54 +26,68 @@ import type {
|
|
|
29
26
|
* ### Example
|
|
30
27
|
*
|
|
31
28
|
* ```ts
|
|
32
|
-
* import {
|
|
29
|
+
* import {
|
|
30
|
+
* assertFalse,
|
|
31
|
+
* assertTrue,
|
|
32
|
+
* createEqObject,
|
|
33
|
+
* eqNumber,
|
|
34
|
+
* } from "@evolu/common";
|
|
33
35
|
*
|
|
34
36
|
* const eqPoint = createEqObject({ x: eqNumber, y: eqNumber });
|
|
35
37
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
+
* assertTrue(eqPoint({ x: 1, y: 2 }, { x: 1, y: 2 }));
|
|
39
|
+
* assertFalse(eqPoint({ x: 1, y: 2 }, { x: 2, y: 1 }));
|
|
38
40
|
* ```
|
|
39
41
|
*/
|
|
40
42
|
export type Eq<in A> = (x: A, y: A) => boolean;
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
|
-
* Compares two values
|
|
45
|
+
* Compares two values using SameValue equality (`Object.is`).
|
|
44
46
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
+
* SameValue considers `NaN` equal to itself, distinguishes `0` from `-0`, and
|
|
48
|
+
* compares objects by reference identity.
|
|
49
|
+
*
|
|
50
|
+
* ### Example
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { assertFalse, assertTrue, eqStrict } from "@evolu/common";
|
|
54
|
+
*
|
|
55
|
+
* assertTrue(eqStrict(NaN, NaN));
|
|
56
|
+
* assertFalse(eqStrict(0, -0));
|
|
57
|
+
* ```
|
|
47
58
|
*/
|
|
48
|
-
export const eqStrict = <A>(x: A, y: A): boolean => x
|
|
59
|
+
export const eqStrict = <A>(x: A, y: A): boolean => Object.is(x, y);
|
|
49
60
|
|
|
50
61
|
/**
|
|
51
62
|
* Compares two values using SameValueZero equality.
|
|
52
63
|
*
|
|
53
64
|
* SameValueZero is the standard equality algorithm used by `Map`, `Set`, and
|
|
54
|
-
* `Array.prototype.includes`.
|
|
55
|
-
*
|
|
65
|
+
* `Array.prototype.includes`. Like SameValue, it considers `NaN` equal to
|
|
66
|
+
* itself, but unlike SameValue, it considers `0` and `-0` equal.
|
|
56
67
|
*
|
|
57
68
|
* ### Example
|
|
58
69
|
*
|
|
59
70
|
* ```ts
|
|
60
|
-
* import { eqSameValueZero } from "@evolu/common";
|
|
71
|
+
* import { assertFalse, assertTrue, eqSameValueZero } from "@evolu/common";
|
|
61
72
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
73
|
+
* assertTrue(eqSameValueZero(NaN, NaN));
|
|
74
|
+
* assertTrue(eqSameValueZero(0, -0));
|
|
75
|
+
* assertFalse(eqSameValueZero({}, {}));
|
|
65
76
|
* ```
|
|
66
77
|
*/
|
|
67
78
|
export const eqSameValueZero = <A>(x: A, y: A): boolean =>
|
|
68
79
|
x === y || Object.is(x, y);
|
|
69
80
|
|
|
70
|
-
/** An {@link Eq} for strings using
|
|
81
|
+
/** An {@link Eq} for strings using {@link eqStrict}. */
|
|
71
82
|
export const eqString: Eq<string> = eqStrict;
|
|
72
83
|
|
|
73
84
|
/** An {@link Eq} for numbers using {@link eqSameValueZero}. */
|
|
74
85
|
export const eqNumber: Eq<number> = eqSameValueZero;
|
|
75
86
|
|
|
76
|
-
/** An {@link Eq} for bigints using
|
|
87
|
+
/** An {@link Eq} for bigints using {@link eqStrict}. */
|
|
77
88
|
export const eqBigInt: Eq<bigint> = eqStrict;
|
|
78
89
|
|
|
79
|
-
/** An {@link Eq} for booleans using
|
|
90
|
+
/** An {@link Eq} for booleans using {@link eqStrict}. */
|
|
80
91
|
export const eqBoolean: Eq<boolean> = eqStrict;
|
|
81
92
|
|
|
82
93
|
/** An {@link Eq} for `undefined`. */
|
|
@@ -98,15 +109,20 @@ export const eqFromOrder =
|
|
|
98
109
|
* ### Example
|
|
99
110
|
*
|
|
100
111
|
* ```ts
|
|
101
|
-
* import {
|
|
112
|
+
* import {
|
|
113
|
+
* assertFalse,
|
|
114
|
+
* assertTrue,
|
|
115
|
+
* createEqArrayLike,
|
|
116
|
+
* eqNumber,
|
|
117
|
+
* } from "@evolu/common";
|
|
102
118
|
*
|
|
103
119
|
* const eqArrayNumber = createEqArrayLike(eqNumber);
|
|
104
120
|
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
121
|
+
* assertTrue(eqArrayNumber([1, 2, 3], [1, 2, 3]));
|
|
122
|
+
* assertTrue(
|
|
107
123
|
* eqArrayNumber(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])),
|
|
108
|
-
* )
|
|
109
|
-
*
|
|
124
|
+
* );
|
|
125
|
+
* assertFalse(eqArrayNumber([1, 2, 3], [1, 2, 4]));
|
|
110
126
|
* ```
|
|
111
127
|
*/
|
|
112
128
|
export const createEqArrayLike =
|
|
@@ -123,19 +139,20 @@ export const createEqArrayLike =
|
|
|
123
139
|
};
|
|
124
140
|
|
|
125
141
|
/**
|
|
126
|
-
* Compares two array-like structures by
|
|
142
|
+
* Compares two array-like structures element by element using {@link eqStrict}.
|
|
127
143
|
*
|
|
128
|
-
* Useful for structural sharing checks where
|
|
144
|
+
* Useful for structural sharing checks where objects are compared by reference
|
|
145
|
+
* identity. `NaN` elements are equal, while `0` and `-0` elements differ.
|
|
129
146
|
*
|
|
130
147
|
* ### Example
|
|
131
148
|
*
|
|
132
149
|
* ```ts
|
|
133
|
-
* import { eqArrayStrict } from "@evolu/common";
|
|
150
|
+
* import { assertFalse, assertTrue, eqArrayStrict } from "@evolu/common";
|
|
134
151
|
*
|
|
135
152
|
* const a = { x: 1 };
|
|
136
153
|
* const b = { x: 1 };
|
|
137
|
-
*
|
|
138
|
-
*
|
|
154
|
+
* assertTrue(eqArrayStrict([a, a], [a, a]));
|
|
155
|
+
* assertFalse(eqArrayStrict([a], [b]));
|
|
139
156
|
* ```
|
|
140
157
|
*/
|
|
141
158
|
export const eqArrayStrict = /*#__PURE__*/ createEqArrayLike(eqStrict);
|
|
@@ -146,13 +163,29 @@ export const eqArrayStrict = /*#__PURE__*/ createEqArrayLike(eqStrict);
|
|
|
146
163
|
* ### Example
|
|
147
164
|
*
|
|
148
165
|
* ```ts
|
|
149
|
-
* import { eqArrayNumber } from "@evolu/common";
|
|
166
|
+
* import { assertTrue, eqArrayNumber } from "@evolu/common";
|
|
150
167
|
*
|
|
151
|
-
*
|
|
168
|
+
* assertTrue(eqArrayNumber([1, NaN], [1, NaN]));
|
|
152
169
|
* ```
|
|
153
170
|
*/
|
|
154
171
|
export const eqArrayNumber = /*#__PURE__*/ createEqArrayLike(eqNumber);
|
|
155
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Compares two Uint8Arrays by byte value.
|
|
175
|
+
*
|
|
176
|
+
* ### Example
|
|
177
|
+
*
|
|
178
|
+
* ```ts
|
|
179
|
+
* import { assertFalse, assertTrue, eqUint8Array } from "@evolu/common";
|
|
180
|
+
*
|
|
181
|
+
* assertTrue(eqUint8Array(new Uint8Array([1, 2]), new Uint8Array([1, 2])));
|
|
182
|
+
* assertFalse(
|
|
183
|
+
* eqUint8Array(new Uint8Array([1, 2]), new Uint8Array([1, 3])),
|
|
184
|
+
* );
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
export const eqUint8Array: Eq<Uint8Array> = eqArrayNumber;
|
|
188
|
+
|
|
156
189
|
/**
|
|
157
190
|
* Creates an equivalence function for objects based on an equivalence for their
|
|
158
191
|
* fields.
|
|
@@ -160,12 +193,17 @@ export const eqArrayNumber = /*#__PURE__*/ createEqArrayLike(eqNumber);
|
|
|
160
193
|
* ### Example
|
|
161
194
|
*
|
|
162
195
|
* ```ts
|
|
163
|
-
* import {
|
|
196
|
+
* import {
|
|
197
|
+
* assertFalse,
|
|
198
|
+
* assertTrue,
|
|
199
|
+
* createEqObject,
|
|
200
|
+
* eqNumber,
|
|
201
|
+
* } from "@evolu/common";
|
|
164
202
|
*
|
|
165
203
|
* const eqObjectNumber = createEqObject({ a: eqNumber });
|
|
166
204
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
205
|
+
* assertTrue(eqObjectNumber({ a: 1 }, { a: 1 }));
|
|
206
|
+
* assertFalse(eqObjectNumber({ a: 1 }, { a: 2 }));
|
|
169
207
|
* ```
|
|
170
208
|
*/
|
|
171
209
|
export const createEqObject =
|
|
@@ -183,122 +221,412 @@ export const createEqObject =
|
|
|
183
221
|
};
|
|
184
222
|
|
|
185
223
|
/**
|
|
186
|
-
*
|
|
224
|
+
* Compares two {@link Data} values.
|
|
187
225
|
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
226
|
+
* Primitive values use SameValueZero, so `NaN` equals itself and `0` equals
|
|
227
|
+
* `-0`. Arrays and Object properties are ordered and keyed respectively. Sets
|
|
228
|
+
* and Maps compare their elements and entries without regard to insertion
|
|
229
|
+
* order. Dates compare their time values, while Uint8Arrays compare their
|
|
230
|
+
* bytes. Cyclic and shared data graphs are supported.
|
|
231
|
+
*
|
|
232
|
+
* The compile-time validation recursively accepts ordinary interfaces whose
|
|
233
|
+
* properties consist only of Data. Runtime representation details are trusted;
|
|
234
|
+
* use the {@link Data} Type at an unknown boundary.
|
|
195
235
|
*
|
|
196
236
|
* ### Example
|
|
197
237
|
*
|
|
198
238
|
* ```ts
|
|
199
|
-
* import {
|
|
239
|
+
* import { assertTrue, eqData } from "@evolu/common";
|
|
240
|
+
*
|
|
241
|
+
* interface User {
|
|
242
|
+
* readonly name: string;
|
|
243
|
+
* readonly roles: ReadonlySet<string>;
|
|
244
|
+
* }
|
|
245
|
+
*
|
|
246
|
+
* const first: User = { name: "Ada", roles: new Set(["admin", "author"]) };
|
|
247
|
+
* const second: User = {
|
|
248
|
+
* name: "Ada",
|
|
249
|
+
* roles: new Set(["author", "admin"]),
|
|
250
|
+
* };
|
|
251
|
+
*
|
|
252
|
+
* assertTrue(eqData(first, second));
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
export function eqData<Actual, Expected>(
|
|
256
|
+
actual: Actual,
|
|
257
|
+
expected: Expected,
|
|
258
|
+
...dataError: EqDataError<Actual | Expected>
|
|
259
|
+
): boolean;
|
|
260
|
+
export function eqData(actual: Data, expected: Data): boolean {
|
|
261
|
+
return eqDataInternal(actual, expected, {
|
|
262
|
+
pairs: [],
|
|
263
|
+
rightsByLeft: new Map(),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Compares two {@link JsonValue} values using {@link eqData}.
|
|
269
|
+
*
|
|
270
|
+
* ### Example
|
|
271
|
+
*
|
|
272
|
+
* ```ts
|
|
273
|
+
* import { assertTrue, eqJsonValue, type JsonValue } from "@evolu/common";
|
|
200
274
|
*
|
|
201
275
|
* const first: JsonValue = { profile: { name: "Ada" } };
|
|
202
276
|
* const second: JsonValue = { profile: { name: "Ada" } };
|
|
203
277
|
*
|
|
204
|
-
*
|
|
278
|
+
* assertTrue(eqJsonValue(first, second));
|
|
205
279
|
* ```
|
|
206
280
|
*/
|
|
207
|
-
export const eqJsonValue
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
281
|
+
export const eqJsonValue: Eq<JsonValue> = eqData;
|
|
282
|
+
|
|
283
|
+
/** Compares two {@link JsonValueInput} values using {@link eqData}. */
|
|
284
|
+
export const eqJsonValueInput: Eq<JsonValueInput> = eqData;
|
|
285
|
+
|
|
286
|
+
type EqDataError<Value> =
|
|
287
|
+
IsData<Value> extends true
|
|
288
|
+
? []
|
|
289
|
+
: [
|
|
290
|
+
error: CompileTimeError<
|
|
291
|
+
"eqData",
|
|
292
|
+
"Actual and expected values must consist only of Data."
|
|
293
|
+
>,
|
|
294
|
+
];
|
|
295
|
+
|
|
296
|
+
interface EqDataContext {
|
|
297
|
+
readonly pairs: Array<readonly [object, object]>;
|
|
298
|
+
readonly rightsByLeft: Map<object, Set<object>>;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
interface EqDataCompareFrame {
|
|
302
|
+
readonly kind: "Compare";
|
|
303
|
+
readonly actual: Data;
|
|
304
|
+
readonly expected: Data;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
interface EqDataSetFrame {
|
|
308
|
+
readonly kind: "Set";
|
|
309
|
+
readonly actual: ReadonlyArray<Data>;
|
|
310
|
+
readonly actualIndex: number;
|
|
311
|
+
readonly unmatched: Array<Data>;
|
|
312
|
+
readonly candidateIndex: number;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
interface EqDataMapFrame {
|
|
316
|
+
readonly kind: "Map";
|
|
317
|
+
readonly actual: ReadonlyArray<readonly [Data, Data]>;
|
|
318
|
+
readonly actualIndex: number;
|
|
319
|
+
readonly unmatched: Array<readonly [Data, Data]>;
|
|
320
|
+
readonly candidateIndex: number;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
interface EqDataCommitSetFrame {
|
|
324
|
+
readonly kind: "CommitSet";
|
|
325
|
+
readonly match: EqDataSetFrame;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
interface EqDataCommitMapFrame {
|
|
329
|
+
readonly kind: "CommitMap";
|
|
330
|
+
readonly match: EqDataMapFrame;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
interface EqDataFailFrame {
|
|
334
|
+
readonly kind: "Fail";
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
type EqDataFrame =
|
|
338
|
+
| EqDataCompareFrame
|
|
339
|
+
| EqDataSetFrame
|
|
340
|
+
| EqDataMapFrame
|
|
341
|
+
| EqDataCommitSetFrame
|
|
342
|
+
| EqDataCommitMapFrame
|
|
343
|
+
| EqDataFailFrame;
|
|
344
|
+
|
|
345
|
+
type EqDataCollectionFrame = EqDataSetFrame | EqDataMapFrame;
|
|
346
|
+
|
|
347
|
+
interface EqDataCandidateAttempt {
|
|
348
|
+
readonly contextCheckpoint: number;
|
|
349
|
+
readonly frameCheckpoint: number;
|
|
350
|
+
readonly retry: EqDataCollectionFrame;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const eqDataInternal = (
|
|
354
|
+
actual: Data,
|
|
355
|
+
expected: Data,
|
|
356
|
+
context: EqDataContext,
|
|
357
|
+
): boolean => {
|
|
358
|
+
const frames: Array<EqDataFrame> = [{ kind: "Compare", actual, expected }];
|
|
359
|
+
const attempts: Array<EqDataCandidateAttempt> = [];
|
|
360
|
+
|
|
361
|
+
const retryFailedCandidate = (_frame: EqDataFailFrame): boolean => {
|
|
362
|
+
const attempt = attempts.pop();
|
|
363
|
+
if (attempt === undefined) return false;
|
|
364
|
+
|
|
365
|
+
rollbackEqDataContext(context, attempt.contextCheckpoint);
|
|
366
|
+
frames.length = attempt.frameCheckpoint;
|
|
367
|
+
frames.push(attempt.retry);
|
|
368
|
+
return true;
|
|
369
|
+
};
|
|
214
370
|
|
|
215
|
-
|
|
371
|
+
while (frames.length > 0) {
|
|
372
|
+
const frame = frames.pop()!;
|
|
216
373
|
|
|
217
|
-
|
|
218
|
-
|
|
374
|
+
if (frame.kind === "Compare") {
|
|
375
|
+
const x = frame.actual;
|
|
376
|
+
const y = frame.expected;
|
|
219
377
|
|
|
220
|
-
|
|
378
|
+
if (eqSameValueZero(x, y)) continue;
|
|
379
|
+
if (typeof x !== typeof y) {
|
|
380
|
+
frames.push({ kind: "Fail" });
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (
|
|
384
|
+
typeof x !== "object" ||
|
|
385
|
+
x === null ||
|
|
386
|
+
typeof y !== "object" ||
|
|
387
|
+
y === null
|
|
388
|
+
) {
|
|
389
|
+
frames.push({ kind: "Fail" });
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
221
392
|
|
|
222
|
-
|
|
223
|
-
continue;
|
|
224
|
-
|
|
393
|
+
const rights = context.rightsByLeft.get(x);
|
|
394
|
+
if (rights?.has(y)) continue;
|
|
395
|
+
if (rights === undefined) {
|
|
396
|
+
context.rightsByLeft.set(x, new Set([y]));
|
|
397
|
+
} else {
|
|
398
|
+
rights.add(y);
|
|
399
|
+
}
|
|
400
|
+
context.pairs.push([x, y]);
|
|
225
401
|
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
402
|
+
const xKind = getObjectKind(x);
|
|
403
|
+
const yKind = getObjectKind(y);
|
|
404
|
+
if (xKind !== yKind) {
|
|
405
|
+
frames.push({ kind: "Fail" });
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
229
408
|
|
|
230
|
-
if (
|
|
409
|
+
if (xKind === "Array") {
|
|
410
|
+
const xArray = x as ReadonlyArray<Data>;
|
|
411
|
+
const yArray = y as ReadonlyArray<Data>;
|
|
412
|
+
if (
|
|
413
|
+
xArray.length !== yArray.length ||
|
|
414
|
+
Reflect.ownKeys(xArray).length !== xArray.length + 1 ||
|
|
415
|
+
Reflect.ownKeys(yArray).length !== yArray.length + 1
|
|
416
|
+
) {
|
|
417
|
+
frames.push({ kind: "Fail" });
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
231
420
|
|
|
232
|
-
|
|
233
|
-
|
|
421
|
+
let valid = true;
|
|
422
|
+
for (let index = 0; index < xArray.length; index++) {
|
|
423
|
+
const xDescriptor = Object.getOwnPropertyDescriptor(xArray, index);
|
|
424
|
+
const yDescriptor = Object.getOwnPropertyDescriptor(yArray, index);
|
|
425
|
+
if (
|
|
426
|
+
xDescriptor === undefined ||
|
|
427
|
+
yDescriptor === undefined ||
|
|
428
|
+
!("value" in xDescriptor) ||
|
|
429
|
+
!("value" in yDescriptor)
|
|
430
|
+
) {
|
|
431
|
+
valid = false;
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
frames.push({
|
|
435
|
+
kind: "Compare",
|
|
436
|
+
actual: xDescriptor.value as Data,
|
|
437
|
+
expected: yDescriptor.value as Data,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
if (!valid) frames.push({ kind: "Fail" });
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
234
443
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
444
|
+
switch (xKind) {
|
|
445
|
+
case "Date":
|
|
446
|
+
if (
|
|
447
|
+
!Object.is(
|
|
448
|
+
Date.prototype.getTime.call(x),
|
|
449
|
+
Date.prototype.getTime.call(y),
|
|
450
|
+
)
|
|
451
|
+
) {
|
|
452
|
+
frames.push({ kind: "Fail" });
|
|
453
|
+
}
|
|
454
|
+
continue;
|
|
455
|
+
case "Uint8Array":
|
|
456
|
+
if (!eqUint8Array(x as Uint8Array, y as Uint8Array)) {
|
|
457
|
+
frames.push({ kind: "Fail" });
|
|
458
|
+
}
|
|
459
|
+
continue;
|
|
460
|
+
case "Set": {
|
|
461
|
+
const xSet = x as ReadonlySet<Data>;
|
|
462
|
+
const ySet = y as ReadonlySet<Data>;
|
|
463
|
+
if (
|
|
464
|
+
Reflect.ownKeys(x).length !== 0 ||
|
|
465
|
+
Reflect.ownKeys(y).length !== 0 ||
|
|
466
|
+
xSet.size !== ySet.size
|
|
467
|
+
) {
|
|
468
|
+
frames.push({ kind: "Fail" });
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
frames.push({
|
|
472
|
+
kind: "Set",
|
|
473
|
+
actual: Array.from(xSet),
|
|
474
|
+
actualIndex: 0,
|
|
475
|
+
unmatched: Array.from(ySet),
|
|
476
|
+
candidateIndex: 0,
|
|
477
|
+
});
|
|
238
478
|
continue;
|
|
239
479
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
480
|
+
case "Map": {
|
|
481
|
+
const xMap = x as ReadonlyMap<Data, Data>;
|
|
482
|
+
const yMap = y as ReadonlyMap<Data, Data>;
|
|
483
|
+
if (
|
|
484
|
+
Reflect.ownKeys(x).length !== 0 ||
|
|
485
|
+
Reflect.ownKeys(y).length !== 0 ||
|
|
486
|
+
xMap.size !== yMap.size
|
|
487
|
+
) {
|
|
488
|
+
frames.push({ kind: "Fail" });
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
frames.push({
|
|
492
|
+
kind: "Map",
|
|
493
|
+
actual: Array.from(xMap),
|
|
494
|
+
actualIndex: 0,
|
|
495
|
+
unmatched: Array.from(yMap),
|
|
496
|
+
candidateIndex: 0,
|
|
497
|
+
});
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
case "Object": {
|
|
501
|
+
const xKeys = Reflect.ownKeys(x);
|
|
502
|
+
const yKeys = Reflect.ownKeys(y);
|
|
503
|
+
if (xKeys.length !== yKeys.length) {
|
|
504
|
+
frames.push({ kind: "Fail" });
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
let valid = true;
|
|
509
|
+
for (const key of xKeys) {
|
|
510
|
+
if (typeof key !== "string") {
|
|
511
|
+
valid = false;
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
const xDescriptor = Object.getOwnPropertyDescriptor(x, key);
|
|
515
|
+
const yDescriptor = Object.getOwnPropertyDescriptor(y, key);
|
|
516
|
+
if (
|
|
517
|
+
xDescriptor === undefined ||
|
|
518
|
+
yDescriptor === undefined ||
|
|
519
|
+
!("value" in xDescriptor) ||
|
|
520
|
+
!("value" in yDescriptor) ||
|
|
521
|
+
!xDescriptor.enumerable ||
|
|
522
|
+
!yDescriptor.enumerable
|
|
523
|
+
) {
|
|
524
|
+
valid = false;
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
frames.push({
|
|
528
|
+
kind: "Compare",
|
|
529
|
+
actual: xDescriptor.value as Data,
|
|
530
|
+
expected: yDescriptor.value as Data,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
if (!valid) frames.push({ kind: "Fail" });
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
case "Unsupported":
|
|
537
|
+
frames.push({ kind: "Fail" });
|
|
538
|
+
continue;
|
|
245
539
|
}
|
|
540
|
+
}
|
|
246
541
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
542
|
+
if (frame.kind === "Set") {
|
|
543
|
+
if (frame.actualIndex === frame.actual.length) continue;
|
|
544
|
+
if (frame.candidateIndex === frame.unmatched.length) {
|
|
545
|
+
frames.push({ kind: "Fail" });
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
250
548
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
549
|
+
const attempt: EqDataCandidateAttempt = {
|
|
550
|
+
contextCheckpoint: context.pairs.length,
|
|
551
|
+
frameCheckpoint: frames.length,
|
|
552
|
+
retry: { ...frame, candidateIndex: frame.candidateIndex + 1 },
|
|
553
|
+
};
|
|
554
|
+
attempts.push(attempt);
|
|
555
|
+
frames.push({ kind: "CommitSet", match: frame });
|
|
556
|
+
frames.push({
|
|
557
|
+
kind: "Compare",
|
|
558
|
+
actual: frame.actual[frame.actualIndex],
|
|
559
|
+
expected: frame.unmatched[frame.candidateIndex],
|
|
560
|
+
});
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
258
563
|
|
|
259
|
-
|
|
260
|
-
|
|
564
|
+
if (frame.kind === "Map") {
|
|
565
|
+
if (frame.actualIndex === frame.actual.length) continue;
|
|
566
|
+
if (frame.candidateIndex === frame.unmatched.length) {
|
|
567
|
+
frames.push({ kind: "Fail" });
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
261
570
|
|
|
262
|
-
|
|
571
|
+
const [actualKey, actualValue] = frame.actual[frame.actualIndex];
|
|
572
|
+
const [expectedKey, expectedValue] =
|
|
573
|
+
frame.unmatched[frame.candidateIndex];
|
|
574
|
+
const attempt: EqDataCandidateAttempt = {
|
|
575
|
+
contextCheckpoint: context.pairs.length,
|
|
576
|
+
frameCheckpoint: frames.length,
|
|
577
|
+
retry: { ...frame, candidateIndex: frame.candidateIndex + 1 },
|
|
578
|
+
};
|
|
579
|
+
attempts.push(attempt);
|
|
580
|
+
frames.push({ kind: "CommitMap", match: frame });
|
|
581
|
+
frames.push({
|
|
582
|
+
kind: "Compare",
|
|
583
|
+
actual: actualValue,
|
|
584
|
+
expected: expectedValue,
|
|
585
|
+
});
|
|
586
|
+
frames.push({
|
|
587
|
+
kind: "Compare",
|
|
588
|
+
actual: actualKey,
|
|
589
|
+
expected: expectedKey,
|
|
590
|
+
});
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
263
593
|
|
|
264
|
-
|
|
594
|
+
if (frame.kind === "CommitSet") {
|
|
595
|
+
attempts.pop();
|
|
596
|
+
frame.match.unmatched.splice(frame.match.candidateIndex, 1);
|
|
597
|
+
frames.push({
|
|
598
|
+
...frame.match,
|
|
599
|
+
actualIndex: frame.match.actualIndex + 1,
|
|
600
|
+
candidateIndex: 0,
|
|
601
|
+
});
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
265
604
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
605
|
+
if (frame.kind === "CommitMap") {
|
|
606
|
+
attempts.pop();
|
|
607
|
+
frame.match.unmatched.splice(frame.match.candidateIndex, 1);
|
|
608
|
+
frames.push({
|
|
609
|
+
...frame.match,
|
|
610
|
+
actualIndex: frame.match.actualIndex + 1,
|
|
611
|
+
candidateIndex: 0,
|
|
612
|
+
});
|
|
613
|
+
continue;
|
|
273
614
|
}
|
|
615
|
+
|
|
616
|
+
if (!retryFailedCandidate(frame)) return false;
|
|
274
617
|
}
|
|
275
618
|
|
|
276
619
|
return true;
|
|
277
620
|
};
|
|
278
621
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
* ### Example
|
|
291
|
-
*
|
|
292
|
-
* ```ts
|
|
293
|
-
* import { eqJsonValueInput, type JsonValueInput } from "@evolu/common";
|
|
294
|
-
*
|
|
295
|
-
* const first: JsonValueInput = { profile: { name: "Ada" } };
|
|
296
|
-
* const second: JsonValueInput = { profile: { name: "Ada" } };
|
|
297
|
-
*
|
|
298
|
-
* expect(eqJsonValueInput(first, second)).toBe(true);
|
|
299
|
-
* ```
|
|
300
|
-
*/
|
|
301
|
-
export const eqJsonValueInput = (
|
|
302
|
-
a: JsonValueInput,
|
|
303
|
-
b: JsonValueInput,
|
|
304
|
-
): boolean => eqJsonValue(a as JsonValue, b as JsonValue);
|
|
622
|
+
const rollbackEqDataContext = (
|
|
623
|
+
context: EqDataContext,
|
|
624
|
+
checkpoint: number,
|
|
625
|
+
): void => {
|
|
626
|
+
while (context.pairs.length > checkpoint) {
|
|
627
|
+
const [left, right] = context.pairs.pop()!;
|
|
628
|
+
const rights = context.rightsByLeft.get(left)!;
|
|
629
|
+
rights.delete(right);
|
|
630
|
+
if (rights.size === 0) context.rightsByLeft.delete(left);
|
|
631
|
+
}
|
|
632
|
+
};
|