@evolu/common 8.4.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 +191 -94
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +91 -40
- package/dist/src/Assert.d.ts +233 -30
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +151 -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/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +4 -1
- 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 +5 -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/Platform.js +1 -0
- 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/Relation.js +3 -3
- package/dist/src/Resource.d.ts +27 -12
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +9 -3
- package/dist/src/Result.d.ts +258 -114
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +74 -39
- 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 +18 -15
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +3 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +1 -1
- package/dist/src/Task.d.ts +555 -264
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +278 -168
- package/dist/src/Test.d.ts +10 -4
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +11 -4
- package/dist/src/Time.d.ts +27 -17
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +25 -8
- package/dist/src/Type.d.ts +1218 -372
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +1056 -379
- 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/WebSocket.js +8 -0
- package/dist/src/Worker.d.ts +10 -6
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +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/Db.js +3 -2
- 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/Evolu.js +1 -0
- package/dist/src/local-first/Owner.d.ts +18 -14
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +14 -11
- package/dist/src/local-first/Protocol.d.ts +5 -5
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +35 -29
- 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 +27 -14
- 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/Relay.js +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/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +4 -2
- package/dist/src/local-first/Storage.d.ts +4 -2
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +1 -1
- package/package.json +3 -4
- package/src/Array.ts +195 -95
- package/src/Assert.ts +337 -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/LeakDetector.ts +4 -3
- package/src/LockManager.ts +12 -10
- package/src/Lookup.ts +5 -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 +3 -2
- package/src/Random.ts +7 -4
- package/src/Redacted.ts +13 -6
- package/src/Ref.ts +4 -4
- package/src/Relation.ts +8 -10
- package/src/Resource.ts +36 -15
- package/src/Result.ts +263 -119
- package/src/Schedule.ts +233 -116
- package/src/Set.ts +43 -24
- package/src/Sqlite.ts +18 -15
- package/src/Store.ts +3 -1
- package/src/String.ts +1 -1
- package/src/Task.ts +566 -286
- package/src/Test.ts +11 -4
- package/src/Time.ts +36 -19
- package/src/Type.ts +2191 -590
- package/src/Types.ts +108 -40
- package/src/WebSocket.ts +22 -6
- package/src/Worker.ts +11 -7
- 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/Db.ts +2 -1
- package/src/local-first/Evolu.ts +48 -24
- package/src/local-first/Owner.ts +18 -14
- package/src/local-first/Protocol.ts +45 -35
- package/src/local-first/Query.ts +40 -24
- package/src/local-first/Relay.ts +13 -6
- package/src/local-first/Schema.ts +19 -11
- package/src/local-first/Shared.ts +4 -2
- package/src/local-first/Storage.ts +4 -2
- package/src/local-first/Timestamp.ts +1 -1
package/src/Object.ts
CHANGED
|
@@ -10,43 +10,88 @@
|
|
|
10
10
|
*/
|
|
11
11
|
export type ReadonlyRecord<K extends keyof any, V> = Readonly<Record<K, V>>;
|
|
12
12
|
|
|
13
|
+
/** An Object representation recognized by {@link getObjectKind}. */
|
|
14
|
+
export type ObjectKind =
|
|
15
|
+
"Array" | "Date" | "Map" | "Object" | "Set" | "Uint8Array" | "Unsupported";
|
|
16
|
+
|
|
13
17
|
/**
|
|
14
|
-
*
|
|
18
|
+
* Classifies Object representations supported by Evolu's structural data APIs.
|
|
19
|
+
*
|
|
20
|
+
* Plain Objects are classified from their prototype without reading their
|
|
21
|
+
* properties, including `Symbol.toStringTag`.
|
|
22
|
+
*
|
|
23
|
+
* ### Example
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { assertEqual, getObjectKind } from "@evolu/common";
|
|
15
27
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
28
|
+
* assertEqual(getObjectKind({}), "Object");
|
|
29
|
+
* assertEqual(getObjectKind(new Map()), "Map");
|
|
30
|
+
* assertEqual(getObjectKind(/value/u), "Unsupported");
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export const getObjectKind = (value: object): ObjectKind => {
|
|
34
|
+
if (Array.isArray(value)) return "Array";
|
|
35
|
+
if (isPlainObject(value)) return "Object";
|
|
36
|
+
|
|
37
|
+
switch (Object.prototype.toString.call(value)) {
|
|
38
|
+
case "[object Date]":
|
|
39
|
+
return "Date";
|
|
40
|
+
case "[object Map]":
|
|
41
|
+
return "Map";
|
|
42
|
+
case "[object Set]":
|
|
43
|
+
return "Set";
|
|
44
|
+
case "[object Uint8Array]":
|
|
45
|
+
return "Uint8Array";
|
|
46
|
+
default:
|
|
47
|
+
return "Unsupported";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Checks if a value is a plain object (e.g., created with `{}` or `Object`).
|
|
20
53
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
54
|
+
* Accepts objects with a `null` prototype. Otherwise, it uses a realm-neutral
|
|
55
|
+
* structural heuristic: the immediate prototype must be a root object with own
|
|
56
|
+
* `hasOwnProperty` and `isPrototypeOf` properties. This recognizes ordinary
|
|
57
|
+
* Objects from another JavaScript realm without relying on prototype identity.
|
|
24
58
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
59
|
+
* A custom root prototype with the same shape can therefore be classified as
|
|
60
|
+
* plain. This function assumes trusted JavaScript and is not a prototype
|
|
61
|
+
* authentication or security boundary. Other custom prototypes, class
|
|
62
|
+
* instances, and built-in objects are rejected.
|
|
27
63
|
*
|
|
28
64
|
* ### Example
|
|
29
65
|
*
|
|
30
66
|
* ```ts
|
|
31
|
-
* import { isPlainObject } from "@evolu/common";
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
67
|
+
* import { assertFalse, assertTrue, isPlainObject } from "@evolu/common";
|
|
68
|
+
*
|
|
69
|
+
* class Example {
|
|
70
|
+
* readonly value = "example";
|
|
71
|
+
* }
|
|
72
|
+
*
|
|
73
|
+
* assertTrue(isPlainObject({}));
|
|
74
|
+
* assertTrue(isPlainObject(Object.create(null)));
|
|
75
|
+
* assertFalse(isPlainObject(new Date()));
|
|
76
|
+
* assertFalse(isPlainObject(new Example()));
|
|
77
|
+
* assertFalse(isPlainObject([]));
|
|
78
|
+
* assertFalse(isPlainObject(null));
|
|
39
79
|
* ```
|
|
40
80
|
*/
|
|
41
81
|
export const isPlainObject = (
|
|
42
82
|
value: unknown,
|
|
43
83
|
): value is Record<string, unknown> => {
|
|
44
|
-
if (
|
|
84
|
+
if (value === null || typeof value !== "object") {
|
|
45
85
|
return false;
|
|
46
86
|
}
|
|
47
87
|
|
|
48
88
|
const prototype = Object.getPrototypeOf(value) as object | null;
|
|
49
|
-
|
|
89
|
+
if (prototype === null) return true;
|
|
90
|
+
return (
|
|
91
|
+
Object.getPrototypeOf(prototype) === null &&
|
|
92
|
+
Object.hasOwn(prototype, "hasOwnProperty") &&
|
|
93
|
+
Object.hasOwn(prototype, "isPrototypeOf")
|
|
94
|
+
);
|
|
50
95
|
};
|
|
51
96
|
|
|
52
97
|
/**
|
|
@@ -55,11 +100,11 @@ export const isPlainObject = (
|
|
|
55
100
|
* ### Example
|
|
56
101
|
*
|
|
57
102
|
* ```ts
|
|
58
|
-
* import { isFunction } from "@evolu/common";
|
|
103
|
+
* import { assertFalse, assertTrue, isFunction } from "@evolu/common";
|
|
59
104
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
105
|
+
* assertTrue(isFunction(() => {}));
|
|
106
|
+
* assertTrue(isFunction(function () {}));
|
|
107
|
+
* assertFalse(isFunction({}));
|
|
63
108
|
* ```
|
|
64
109
|
*/
|
|
65
110
|
export const isFunction = (value: unknown): value is globalThis.Function =>
|
|
@@ -71,11 +116,11 @@ export const isFunction = (value: unknown): value is globalThis.Function =>
|
|
|
71
116
|
* ### Example
|
|
72
117
|
*
|
|
73
118
|
* ```ts
|
|
74
|
-
* import { isIterable } from "@evolu/common";
|
|
119
|
+
* import { assertFalse, assertTrue, isIterable } from "@evolu/common";
|
|
75
120
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
121
|
+
* assertTrue(isIterable([1, 2, 3]));
|
|
122
|
+
* assertTrue(isIterable("abc"));
|
|
123
|
+
* assertFalse(isIterable({}));
|
|
79
124
|
* ```
|
|
80
125
|
*/
|
|
81
126
|
export const isIterable = (value: unknown): value is Iterable<unknown> =>
|
|
@@ -89,6 +134,8 @@ export const isIterable = (value: unknown): value is Iterable<unknown> =>
|
|
|
89
134
|
*
|
|
90
135
|
* ```ts
|
|
91
136
|
* import {
|
|
137
|
+
* assertEqual,
|
|
138
|
+
* assertType,
|
|
92
139
|
* objectToEntries,
|
|
93
140
|
* type Brand,
|
|
94
141
|
* type ReadonlyRecord,
|
|
@@ -100,8 +147,8 @@ export const isIterable = (value: unknown): value is Iterable<unknown> =>
|
|
|
100
147
|
* const users: ReadonlyRecord<UserId, string> = { [userId]: "Alice" };
|
|
101
148
|
* const entries = objectToEntries(users);
|
|
102
149
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
150
|
+
* assertType<ReadonlyArray<[UserId, string]>, typeof entries>();
|
|
151
|
+
* assertEqual(entries, [[userId, "Alice"]]);
|
|
105
152
|
* ```
|
|
106
153
|
*/
|
|
107
154
|
export const objectToEntries = <T extends Record<string, any>>(
|
|
@@ -122,6 +169,8 @@ type StringKeyOf<T> = Extract<keyof T, string>;
|
|
|
122
169
|
*
|
|
123
170
|
* ```ts
|
|
124
171
|
* import {
|
|
172
|
+
* assertEqual,
|
|
173
|
+
* assertType,
|
|
125
174
|
* objectFromEntries,
|
|
126
175
|
* type Brand,
|
|
127
176
|
* type ReadonlyRecord,
|
|
@@ -133,8 +182,8 @@ type StringKeyOf<T> = Extract<keyof T, string>;
|
|
|
133
182
|
* ];
|
|
134
183
|
* const users = objectFromEntries(entries);
|
|
135
184
|
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
185
|
+
* assertType<ReadonlyRecord<UserId, string>, typeof users>();
|
|
186
|
+
* assertEqual(users, { u1: "Alice" });
|
|
138
187
|
* ```
|
|
139
188
|
*/
|
|
140
189
|
export const objectFromEntries = <K extends string, V>(
|
|
@@ -150,17 +199,20 @@ export const objectFromEntries = <K extends string, V>(
|
|
|
150
199
|
* ### Example
|
|
151
200
|
*
|
|
152
201
|
* ```ts
|
|
153
|
-
* import {
|
|
202
|
+
* import {
|
|
203
|
+
* assertEqual,
|
|
204
|
+
* assertType,
|
|
205
|
+
* objectFrom,
|
|
206
|
+
* type ReadonlyRecord,
|
|
207
|
+
* } from "@evolu/common";
|
|
154
208
|
*
|
|
155
209
|
* const translations = objectFrom(
|
|
156
210
|
* ["en", "fr"] as const,
|
|
157
211
|
* (locale): string => `Hello in ${locale}`,
|
|
158
212
|
* );
|
|
159
213
|
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* >();
|
|
163
|
-
* expect(translations).toEqual({
|
|
214
|
+
* assertType<ReadonlyRecord<"en" | "fr", string>, typeof translations>();
|
|
215
|
+
* assertEqual(translations, {
|
|
164
216
|
* en: "Hello in en",
|
|
165
217
|
* fr: "Hello in fr",
|
|
166
218
|
* });
|
|
@@ -228,7 +280,7 @@ export const excludeProp = <T extends object, K extends keyof T>(
|
|
|
228
280
|
* ### Example
|
|
229
281
|
*
|
|
230
282
|
* ```ts
|
|
231
|
-
* import { createMutableRecord } from "@evolu/common";
|
|
283
|
+
* import { assertEqual, createMutableRecord } from "@evolu/common";
|
|
232
284
|
*
|
|
233
285
|
* const createValuesByKey = (
|
|
234
286
|
* entries: ReadonlyArray<readonly [string, number]>,
|
|
@@ -242,12 +294,13 @@ export const excludeProp = <T extends object, K extends keyof T>(
|
|
|
242
294
|
* return valuesByKey;
|
|
243
295
|
* };
|
|
244
296
|
*
|
|
245
|
-
*
|
|
297
|
+
* assertEqual(
|
|
246
298
|
* createValuesByKey([
|
|
247
299
|
* ["a", 1],
|
|
248
300
|
* ["b", 2],
|
|
249
301
|
* ]),
|
|
250
|
-
*
|
|
302
|
+
* { a: 1, b: 2 },
|
|
303
|
+
* );
|
|
251
304
|
* ```
|
|
252
305
|
*
|
|
253
306
|
* Note that TypeScript does not model an object's runtime prototype. A plain
|
|
@@ -255,21 +308,34 @@ export const excludeProp = <T extends object, K extends keyof T>(
|
|
|
255
308
|
* object has a `null` prototype:
|
|
256
309
|
*
|
|
257
310
|
* ```ts
|
|
311
|
+
* import { assertErr, assertTrue, trySync } from "@evolu/common";
|
|
312
|
+
*
|
|
258
313
|
* const values = Object.create(null) as Record<string, number>;
|
|
259
314
|
*
|
|
260
315
|
* // TypeScript accepts the call, but `toString` is undefined at runtime.
|
|
261
|
-
*
|
|
316
|
+
* // oxlint-disable-next-line typescript/no-base-to-string -- Intentionally calls a method missing from the null-prototype value.
|
|
317
|
+
* const result = trySync(() => values.toString());
|
|
318
|
+
* assertErr(result);
|
|
319
|
+
* assertTrue(result.error instanceof TypeError);
|
|
262
320
|
* ```
|
|
263
321
|
*
|
|
264
322
|
* `createMutableRecord` uses the same TypeScript Record representation.
|
|
265
323
|
*
|
|
266
324
|
* ```ts
|
|
267
|
-
* import {
|
|
325
|
+
* import {
|
|
326
|
+
* assertErr,
|
|
327
|
+
* assertTrue,
|
|
328
|
+
* createMutableRecord,
|
|
329
|
+
* trySync,
|
|
330
|
+
* } from "@evolu/common";
|
|
268
331
|
*
|
|
269
332
|
* const values = createMutableRecord<string, number>();
|
|
270
333
|
*
|
|
271
334
|
* // TypeScript accepts the call, but `toString` is undefined at runtime.
|
|
272
|
-
*
|
|
335
|
+
* // oxlint-disable-next-line typescript/no-base-to-string -- Intentionally calls a method missing from the null-prototype value.
|
|
336
|
+
* const result = trySync(() => values.toString());
|
|
337
|
+
* assertErr(result);
|
|
338
|
+
* assertTrue(result.error instanceof TypeError);
|
|
273
339
|
* ```
|
|
274
340
|
*
|
|
275
341
|
* In other words, treat the returned object as string-keyed data rather than
|
|
@@ -318,7 +384,7 @@ export const emptyRecord: Readonly<Record<string, never>> =
|
|
|
318
384
|
* ### Example
|
|
319
385
|
*
|
|
320
386
|
* ```ts
|
|
321
|
-
* import { getOwnProp } from "@evolu/common";
|
|
387
|
+
* import { assertEqual, assertType, getOwnProp } from "@evolu/common";
|
|
322
388
|
*
|
|
323
389
|
* interface User {
|
|
324
390
|
* readonly name: string;
|
|
@@ -329,9 +395,9 @@ export const emptyRecord: Readonly<Record<string, never>> =
|
|
|
329
395
|
* };
|
|
330
396
|
* const user = getOwnProp(users, "bob");
|
|
331
397
|
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
398
|
+
* assertType<User | undefined, typeof user>();
|
|
399
|
+
* assertEqual(user, undefined);
|
|
400
|
+
* assertEqual(getOwnProp(users, "toString"), undefined);
|
|
335
401
|
* ```
|
|
336
402
|
*/
|
|
337
403
|
export const getOwnProp = <K extends string, V>(
|
|
@@ -347,12 +413,12 @@ export const getOwnProp = <K extends string, V>(
|
|
|
347
413
|
* ### Example
|
|
348
414
|
*
|
|
349
415
|
* ```ts
|
|
350
|
-
* import { createObjectURL } from "@evolu/common";
|
|
416
|
+
* import { assertTrue, createObjectURL } from "@evolu/common";
|
|
351
417
|
*
|
|
352
418
|
* const blob = new Blob(["hello"], { type: "text/plain" });
|
|
353
419
|
* using objectUrl = createObjectURL(blob);
|
|
354
420
|
*
|
|
355
|
-
*
|
|
421
|
+
* assertTrue(objectUrl.url.startsWith("blob:"));
|
|
356
422
|
* // URL.revokeObjectURL is automatically called when the scope ends.
|
|
357
423
|
* ```
|
|
358
424
|
*
|
package/src/Option.ts
CHANGED
|
@@ -9,7 +9,16 @@
|
|
|
9
9
|
* ### Example
|
|
10
10
|
*
|
|
11
11
|
* ```ts
|
|
12
|
-
* import {
|
|
12
|
+
* import {
|
|
13
|
+
* assert,
|
|
14
|
+
* assertSame,
|
|
15
|
+
* assertTrue,
|
|
16
|
+
* isNone,
|
|
17
|
+
* isSome,
|
|
18
|
+
* none,
|
|
19
|
+
* type Option,
|
|
20
|
+
* some,
|
|
21
|
+
* } from "@evolu/common";
|
|
13
22
|
*
|
|
14
23
|
* const cache = new Map<string, Option<unknown>>();
|
|
15
24
|
*
|
|
@@ -19,10 +28,10 @@
|
|
|
19
28
|
* cache.set("b", some(undefined));
|
|
20
29
|
*
|
|
21
30
|
* const a = get("a");
|
|
22
|
-
* assert(isSome(a));
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
31
|
+
* assert(isSome(a), "Expected Some.");
|
|
32
|
+
* assertSame(a.value, null);
|
|
33
|
+
* assertTrue(isSome(get("b")));
|
|
34
|
+
* assertTrue(isNone(get("c")));
|
|
26
35
|
* ```
|
|
27
36
|
*
|
|
28
37
|
* @module
|
package/src/Order.ts
CHANGED
|
@@ -33,12 +33,12 @@ export type Ordering = -1 | 0 | 1;
|
|
|
33
33
|
* ### Example
|
|
34
34
|
*
|
|
35
35
|
* ```ts
|
|
36
|
-
* import { createOrder } from "@evolu/common";
|
|
36
|
+
* import { assertEqual, createOrder } from "@evolu/common";
|
|
37
37
|
*
|
|
38
38
|
* const orderNumber = createOrder<number>((x, y) => x < y);
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* assertEqual(orderNumber(1, 2), -1);
|
|
40
|
+
* assertEqual(orderNumber(2, 1), 1);
|
|
41
|
+
* assertEqual(orderNumber(1, 1), 0);
|
|
42
42
|
* ```
|
|
43
43
|
*/
|
|
44
44
|
export const createOrder =
|
|
@@ -52,10 +52,10 @@ export const createOrder =
|
|
|
52
52
|
* ### Example
|
|
53
53
|
*
|
|
54
54
|
* ```ts
|
|
55
|
-
* import { orderNumber, reverseOrder } from "@evolu/common";
|
|
55
|
+
* import { assertEqual, orderNumber, reverseOrder } from "@evolu/common";
|
|
56
56
|
*
|
|
57
57
|
* const descendingOrderNumber = reverseOrder(orderNumber);
|
|
58
|
-
*
|
|
58
|
+
* assertEqual([3, 1, 2].toSorted(descendingOrderNumber), [3, 2, 1]);
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
61
|
export const reverseOrder =
|
|
@@ -69,9 +69,9 @@ export const reverseOrder =
|
|
|
69
69
|
* ### Example
|
|
70
70
|
*
|
|
71
71
|
* ```ts
|
|
72
|
-
* import { orderString } from "@evolu/common";
|
|
72
|
+
* import { assertEqual, orderString } from "@evolu/common";
|
|
73
73
|
*
|
|
74
|
-
*
|
|
74
|
+
* assertEqual(["c", "b", "a"].toSorted(orderString), ["a", "b", "c"]);
|
|
75
75
|
* ```
|
|
76
76
|
*/
|
|
77
77
|
export const orderString: Order<string> = /*#__PURE__*/ createOrder(
|
|
@@ -84,9 +84,9 @@ export const orderString: Order<string> = /*#__PURE__*/ createOrder(
|
|
|
84
84
|
* ### Example
|
|
85
85
|
*
|
|
86
86
|
* ```ts
|
|
87
|
-
* import { orderNumber } from "@evolu/common";
|
|
87
|
+
* import { assertEqual, orderNumber } from "@evolu/common";
|
|
88
88
|
*
|
|
89
|
-
*
|
|
89
|
+
* assertEqual([2, 1, 3].toSorted(orderNumber), [1, 2, 3]);
|
|
90
90
|
* ```
|
|
91
91
|
*/
|
|
92
92
|
export const orderNumber = /*#__PURE__*/ createOrder<number>((a, b) => a < b);
|
|
@@ -97,9 +97,9 @@ export const orderNumber = /*#__PURE__*/ createOrder<number>((a, b) => a < b);
|
|
|
97
97
|
* ### Example
|
|
98
98
|
*
|
|
99
99
|
* ```ts
|
|
100
|
-
* import { orderBigInt } from "@evolu/common";
|
|
100
|
+
* import { assertEqual, orderBigInt } from "@evolu/common";
|
|
101
101
|
*
|
|
102
|
-
*
|
|
102
|
+
* assertEqual([2n, 1n, 3n].toSorted(orderBigInt), [1n, 2n, 3n]);
|
|
103
103
|
* ```
|
|
104
104
|
*/
|
|
105
105
|
export const orderBigInt = /*#__PURE__*/ createOrder<bigint>((a, b) => a < b);
|
package/src/Platform.ts
CHANGED
|
@@ -82,8 +82,8 @@ export interface TestGlobalErrors extends Disposable {
|
|
|
82
82
|
* Platforms deliver global errors asynchronously and provide no hook for
|
|
83
83
|
* "nothing was reported", so settle emits a sentinel of the same kind and
|
|
84
84
|
* resolves when it arrives. Platform delivery is ordered, so all earlier
|
|
85
|
-
* errors are recorded by then.
|
|
86
|
-
* unhandledRejections.settle()
|
|
85
|
+
* errors are recorded by then. Assert absence with `assertEqual(await
|
|
86
|
+
* unhandledRejections.settle(), [])`.
|
|
87
87
|
*/
|
|
88
88
|
readonly settle: () => Promise<ReadonlyArray<unknown>>;
|
|
89
89
|
}
|
|
@@ -176,6 +176,7 @@ const createTestGlobalErrors = (
|
|
|
176
176
|
globalThis.removeEventListener(webEvent, listener);
|
|
177
177
|
});
|
|
178
178
|
} else {
|
|
179
|
+
// oxlint-disable-next-line unicorn/prefer-type-error -- An unsupported runtime environment is not an invalid argument type.
|
|
179
180
|
throw new Error(`Unsupported platform global ${errorType} reporting.`);
|
|
180
181
|
}
|
|
181
182
|
|
package/src/Random.ts
CHANGED
|
@@ -23,6 +23,9 @@ export type RandomNumber = number & Brand<"RandomNumber">;
|
|
|
23
23
|
*
|
|
24
24
|
* ```ts
|
|
25
25
|
* import {
|
|
26
|
+
* assertEqual,
|
|
27
|
+
* assertTrue,
|
|
28
|
+
* assertType,
|
|
26
29
|
* createRandom,
|
|
27
30
|
* testCreateRandom,
|
|
28
31
|
* type RandomNumber,
|
|
@@ -31,14 +34,14 @@ export type RandomNumber = number & Brand<"RandomNumber">;
|
|
|
31
34
|
* // For apps, use the Math.random-backed implementation.
|
|
32
35
|
* const random = createRandom();
|
|
33
36
|
* const value = random.next();
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
+
* assertType<RandomNumber, typeof value>();
|
|
38
|
+
* assertTrue(value >= 0);
|
|
39
|
+
* assertTrue(value < 1);
|
|
37
40
|
*
|
|
38
41
|
* // For tests, use a seed.
|
|
39
42
|
* const firstTestRandom = testCreateRandom("test");
|
|
40
43
|
* const secondTestRandom = testCreateRandom("test");
|
|
41
|
-
*
|
|
44
|
+
* assertEqual(firstTestRandom.next(), secondTestRandom.next());
|
|
42
45
|
* ```
|
|
43
46
|
*/
|
|
44
47
|
export interface Random {
|
package/src/Redacted.ts
CHANGED
|
@@ -30,8 +30,11 @@ import type { Eq } from "./Eq.ts";
|
|
|
30
30
|
*
|
|
31
31
|
* ```ts
|
|
32
32
|
* import {
|
|
33
|
+
* assertErr,
|
|
34
|
+
* assertEqual,
|
|
33
35
|
* createRedacted,
|
|
34
36
|
* revealRedacted,
|
|
37
|
+
* trySync,
|
|
35
38
|
* type Brand,
|
|
36
39
|
* type Redacted,
|
|
37
40
|
* } from "@evolu/common";
|
|
@@ -45,11 +48,13 @@ import type { Eq } from "./Eq.ts";
|
|
|
45
48
|
* using redactedKey: RedactedApiKey = createRedacted(apiKey);
|
|
46
49
|
* const fetchUser = (key: RedactedApiKey): ApiKey => revealRedacted(key);
|
|
47
50
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
51
|
+
* // oxlint-disable-next-line typescript/no-base-to-string -- Redacted intentionally implements a safe custom toString.
|
|
52
|
+
* assertEqual(redactedKey.toString(), "<redacted>");
|
|
53
|
+
* assertEqual(
|
|
54
|
+
* JSON.stringify({ apiKey: redactedKey }),
|
|
50
55
|
* '{"apiKey":"<redacted>"}',
|
|
51
56
|
* );
|
|
52
|
-
*
|
|
57
|
+
* assertEqual(fetchUser(redactedKey), apiKey);
|
|
53
58
|
*
|
|
54
59
|
* using password = createRedacted("password" as DbPassword);
|
|
55
60
|
* // @ts-expect-error Redacted secrets retain their distinct branded types.
|
|
@@ -60,7 +65,7 @@ import type { Eq } from "./Eq.ts";
|
|
|
60
65
|
* return key;
|
|
61
66
|
* })();
|
|
62
67
|
* // Leaving the `using` scope removes the value from memory.
|
|
63
|
-
*
|
|
68
|
+
* assertErr(trySync(() => revealRedacted(disposedKey)));
|
|
64
69
|
* ```
|
|
65
70
|
*/
|
|
66
71
|
export interface Redacted<A> extends Brand<"Redacted">, Disposable {
|
|
@@ -112,6 +117,8 @@ export const isRedacted = (value: unknown): value is Redacted<unknown> =>
|
|
|
112
117
|
*
|
|
113
118
|
* ```ts
|
|
114
119
|
* import {
|
|
120
|
+
* assertFalse,
|
|
121
|
+
* assertTrue,
|
|
115
122
|
* createEqRedacted,
|
|
116
123
|
* createRedacted,
|
|
117
124
|
* eqString,
|
|
@@ -126,8 +133,8 @@ export const isRedacted = (value: unknown): value is Redacted<unknown> =>
|
|
|
126
133
|
* using b = createRedacted("x" as ApiKey);
|
|
127
134
|
* using c = createRedacted("y" as ApiKey);
|
|
128
135
|
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
136
|
+
* assertTrue(eqRedactedApiKey(a, b));
|
|
137
|
+
* assertFalse(eqRedactedApiKey(a, c));
|
|
131
138
|
* ```
|
|
132
139
|
*/
|
|
133
140
|
export const createEqRedacted =
|
package/src/Ref.ts
CHANGED
|
@@ -21,18 +21,18 @@ import type { Store } from "./Store.ts";
|
|
|
21
21
|
* ### Example
|
|
22
22
|
*
|
|
23
23
|
* ```ts
|
|
24
|
-
* import { createRef } from "@evolu/common";
|
|
24
|
+
* import { assertEqual, createRef } from "@evolu/common";
|
|
25
25
|
*
|
|
26
26
|
* const count = createRef(0);
|
|
27
27
|
* count.set(1);
|
|
28
28
|
* count.update((n) => n + 1);
|
|
29
|
-
*
|
|
29
|
+
* assertEqual(count.get(), 2);
|
|
30
30
|
* ```
|
|
31
31
|
*
|
|
32
32
|
* ### As a dependency
|
|
33
33
|
*
|
|
34
34
|
* ```ts
|
|
35
|
-
* import { createRef, type Ref } from "@evolu/common";
|
|
35
|
+
* import { assertEqual, createRef, type Ref } from "@evolu/common";
|
|
36
36
|
*
|
|
37
37
|
* interface CounterRefDep {
|
|
38
38
|
* readonly counterRef: Ref<number>;
|
|
@@ -40,7 +40,7 @@ import type { Store } from "./Store.ts";
|
|
|
40
40
|
*
|
|
41
41
|
* const deps: CounterRefDep = { counterRef: createRef(0) };
|
|
42
42
|
* deps.counterRef.update((count) => count + 1);
|
|
43
|
-
*
|
|
43
|
+
* assertEqual(deps.counterRef.get(), 1);
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
46
|
export interface Ref<T> {
|
package/src/Relation.ts
CHANGED
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
* Use the default identity semantics.
|
|
57
57
|
*
|
|
58
58
|
* ```ts
|
|
59
|
-
* import { createRelation } from "@evolu/common";
|
|
59
|
+
* import { assertFalse, assertTrue, createRelation } from "@evolu/common";
|
|
60
60
|
*
|
|
61
61
|
* interface Socket {
|
|
62
62
|
* readonly id: string;
|
|
@@ -67,8 +67,8 @@ import {
|
|
|
67
67
|
*
|
|
68
68
|
* relation.add(socket, "owner-1");
|
|
69
69
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
70
|
+
* assertTrue(relation.has(socket, "owner-1"));
|
|
71
|
+
* assertFalse(relation.has({ id: "socket-1" }, "owner-1"));
|
|
72
72
|
* ```
|
|
73
73
|
*
|
|
74
74
|
* ### Lookup-derived equality
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
* Use lookup-derived equality.
|
|
77
77
|
*
|
|
78
78
|
* ```ts
|
|
79
|
-
* import { createRelation } from "@evolu/common";
|
|
79
|
+
* import { assertTrue, createRelation } from "@evolu/common";
|
|
80
80
|
*
|
|
81
81
|
* interface Person {
|
|
82
82
|
* readonly id: string;
|
|
@@ -90,9 +90,7 @@ import {
|
|
|
90
90
|
*
|
|
91
91
|
* relation.add({ id: "1", name: "Ada" }, { id: "admins" });
|
|
92
92
|
*
|
|
93
|
-
*
|
|
94
|
-
* true,
|
|
95
|
-
* );
|
|
93
|
+
* assertTrue(relation.has({ id: "1", name: "Grace" }, { id: "admins" }));
|
|
96
94
|
* ```
|
|
97
95
|
*
|
|
98
96
|
* @see {@link createRelation}
|
|
@@ -250,14 +248,14 @@ export function createRelation<A, B, LA = A, LB = B>({
|
|
|
250
248
|
removeByA: (a) => {
|
|
251
249
|
const relatedB = bByA.get(a);
|
|
252
250
|
if (!relatedB) return false;
|
|
253
|
-
for (const b of
|
|
251
|
+
for (const b of relatedB.keys()) removePair(a, b);
|
|
254
252
|
return true;
|
|
255
253
|
},
|
|
256
254
|
|
|
257
255
|
removeByB: (b) => {
|
|
258
256
|
const relatedA = aByB.get(b);
|
|
259
257
|
if (!relatedA) return false;
|
|
260
|
-
for (const a of
|
|
258
|
+
for (const a of relatedA.keys()) removePair(a, b);
|
|
261
259
|
return true;
|
|
262
260
|
},
|
|
263
261
|
|
|
@@ -306,7 +304,7 @@ export function createRelation<A, B, LA = A, LB = B>({
|
|
|
306
304
|
const assertRelationMappingConsistency: (
|
|
307
305
|
condition: unknown,
|
|
308
306
|
) => asserts condition = (condition) => {
|
|
309
|
-
assert(condition, "Relation mapping inconsistency");
|
|
307
|
+
assert(Boolean(condition), "Relation mapping inconsistency");
|
|
310
308
|
};
|
|
311
309
|
|
|
312
310
|
/**
|