@evolu/common 8.0.0-next.4 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/Array.d.ts +279 -173
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +105 -101
- package/dist/src/Assert.d.ts +44 -44
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +44 -32
- package/dist/src/BigInt.d.ts +6 -3
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -2
- package/dist/src/Brand.d.ts +27 -40
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Buffer.d.ts +27 -11
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +9 -4
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +30 -19
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +145 -66
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +91 -43
- package/dist/src/Crypto.d.ts +85 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +44 -20
- package/dist/src/Eq.d.ts +87 -21
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +67 -19
- package/dist/src/Error.d.ts +5 -3
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +16 -0
- package/dist/src/Function.d.ts +119 -58
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +86 -43
- package/dist/src/Http.d.ts +394 -0
- package/dist/src/Http.d.ts.map +1 -0
- package/dist/src/Http.js +102 -0
- package/dist/src/Identicon.d.ts +16 -7
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +14 -5
- package/dist/src/LeakDetector.d.ts +88 -0
- package/dist/src/LeakDetector.d.ts.map +1 -0
- package/dist/src/LeakDetector.js +86 -0
- package/dist/src/LockManager.d.ts +18 -9
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +7 -8
- package/dist/src/Lookup.d.ts +43 -13
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +28 -8
- package/dist/src/Microtask.d.ts +1 -1
- package/dist/src/Microtask.d.ts.map +1 -1
- package/dist/src/Microtask.js +3 -7
- package/dist/src/Number.d.ts +49 -13
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +34 -5
- package/dist/src/Object.d.ts +160 -40
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +92 -46
- package/dist/src/Option.d.ts +10 -7
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +9 -6
- package/dist/src/Order.d.ts +21 -21
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +18 -21
- package/dist/src/Platform.d.ts +31 -0
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +98 -0
- package/dist/src/Random.d.ts +32 -17
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +12 -8
- package/dist/src/Redacted.d.ts +43 -29
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +14 -3
- package/dist/src/Ref.d.ts +11 -3
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +2 -2
- package/dist/src/RefCount.d.ts +2 -6
- package/dist/src/RefCount.d.ts.map +1 -1
- package/dist/src/RefCount.js +33 -90
- package/dist/src/Relation.d.ts +70 -5
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +77 -2
- package/dist/src/Resource.d.ts +590 -155
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +592 -343
- package/dist/src/Result.d.ts +838 -191
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +163 -102
- package/dist/src/Schedule.d.ts +684 -231
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +766 -295
- package/dist/src/Set.d.ts +89 -40
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +50 -29
- package/dist/src/Sqlite.d.ts +29 -72
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +41 -46
- package/dist/src/StackTrace.d.ts +40 -0
- package/dist/src/StackTrace.d.ts.map +1 -0
- package/dist/src/StackTrace.js +140 -0
- package/dist/src/Store.d.ts +5 -4
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +5 -4
- package/dist/src/String.d.ts +7 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +20 -7
- package/dist/src/Task.d.ts +3572 -1770
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1879 -1274
- package/dist/src/Test.d.ts +17 -125
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +17 -68
- package/dist/src/Time.d.ts +108 -49
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +172 -73
- package/dist/src/Type.d.ts +3542 -1926
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +3070 -1784
- package/dist/src/Types.d.ts +200 -108
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +39 -8
- package/dist/src/WebSocket.d.ts +48 -23
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +15 -6
- package/dist/src/Worker.d.ts +94 -36
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +58 -24
- package/dist/src/index.d.ts +55 -52
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/intl/cs.d.ts +94 -0
- package/dist/src/intl/cs.d.ts.map +1 -0
- package/dist/src/intl/cs.js +220 -0
- package/dist/src/intl/index.d.ts +7 -0
- package/dist/src/intl/index.d.ts.map +1 -0
- package/dist/src/intl/index.js +6 -0
- package/dist/src/local-first/Db.d.ts +12 -8
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +109 -132
- package/dist/src/local-first/Error.d.ts +4 -4
- package/dist/src/local-first/Evolu.d.ts +338 -92
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +47 -55
- package/dist/src/local-first/LocalAuth.d.ts +4 -4
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +61 -24
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +45 -8
- package/dist/src/local-first/Protocol.d.ts +44 -31
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +36 -13
- package/dist/src/local-first/Query.d.ts +147 -62
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +112 -58
- package/dist/src/local-first/Relay.d.ts +44 -14
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +92 -41
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +25 -8
- package/dist/src/local-first/Shared.d.ts +23 -21
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +100 -57
- package/dist/src/local-first/Storage.d.ts +53 -32
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +194 -234
- package/dist/src/local-first/Timestamp.d.ts +21 -21
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +2 -2
- package/dist/src/local-first/index.d.ts +11 -11
- package/package.json +14 -13
- package/src/Array.ts +306 -205
- package/src/Assert.ts +54 -69
- package/src/BigInt.ts +6 -3
- package/src/Brand.ts +27 -40
- package/src/Buffer.ts +28 -12
- package/src/Cache.ts +9 -4
- package/src/Callbacks.ts +30 -19
- package/src/Console.ts +156 -84
- package/src/Crypto.ts +83 -41
- package/src/Eq.ts +95 -22
- package/src/Error.ts +8 -4
- package/src/Function.ts +167 -59
- package/src/Http.ts +549 -0
- package/src/Identicon.ts +16 -7
- package/src/LeakDetector.ts +182 -0
- package/src/LockManager.ts +43 -39
- package/src/Lookup.ts +62 -28
- package/src/Microtask.ts +19 -23
- package/src/Number.ts +64 -12
- package/src/Object.ts +173 -49
- package/src/Option.ts +10 -7
- package/src/Order.ts +23 -21
- package/src/Platform.ts +136 -0
- package/src/Polyfills.ts +6 -12
- package/src/Random.ts +32 -19
- package/src/Redacted.ts +44 -30
- package/src/Ref.ts +14 -6
- package/src/RefCount.ts +38 -80
- package/src/Relation.ts +202 -10
- package/src/Resource.ts +1199 -591
- package/src/Result.ts +930 -271
- package/src/Schedule.ts +859 -343
- package/src/Set.ts +89 -40
- package/src/Sqlite.ts +144 -138
- package/src/StackTrace.ts +230 -0
- package/src/Store.ts +8 -7
- package/src/String.ts +22 -5
- package/src/Task.ts +5101 -2832
- package/src/Test.ts +20 -168
- package/src/Time.ts +293 -90
- package/src/Type.ts +10034 -4117
- package/src/Types.ts +227 -110
- package/src/WebSocket.ts +64 -36
- package/src/Worker.ts +180 -72
- package/src/index.ts +55 -52
- package/src/intl/cs.ts +388 -0
- package/src/intl/index.ts +7 -0
- package/src/local-first/Db.ts +152 -179
- package/src/local-first/Error.ts +4 -4
- package/src/local-first/Evolu.ts +495 -250
- package/src/local-first/LocalAuth.ts +6 -12
- package/src/local-first/Owner.ts +58 -21
- package/src/local-first/Protocol.ts +49 -31
- package/src/local-first/Query.ts +146 -61
- package/src/local-first/Relay.ts +51 -21
- package/src/local-first/Schema.ts +109 -51
- package/src/local-first/Shared.ts +266 -226
- package/src/local-first/Storage.ts +266 -264
- package/src/local-first/Timestamp.ts +25 -18
- package/src/local-first/index.ts +11 -11
- package/dist/src/Skiplist.d.ts +0 -28
- package/dist/src/Skiplist.d.ts.map +0 -1
- package/dist/src/Skiplist.js +0 -64
- package/dist/src/Tracer.d.ts +0 -48
- package/dist/src/Tracer.d.ts.map +0 -1
- package/dist/src/Tracer.js +0 -6
- package/src/Skiplist.ts +0 -108
- package/src/Tracer.ts +0 -54
package/dist/src/RefCount.js
CHANGED
|
@@ -55,87 +55,40 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
55
55
|
var e = new Error(message);
|
|
56
56
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
57
57
|
});
|
|
58
|
-
import { assert
|
|
59
|
-
import { identity } from "./Function.js";
|
|
58
|
+
import { assert } from "./Assert.js";
|
|
59
|
+
import { disposable, identity } from "./Function.js";
|
|
60
60
|
import { createLookupMap } from "./Lookup.js";
|
|
61
61
|
import { NonNegativeInt, PositiveInt, zeroNonNegativeInt } from "./Type.js";
|
|
62
62
|
/** Creates {@link RefCount}. */
|
|
63
63
|
export const createRefCount = () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
assertNotDisposed(disposables);
|
|
79
|
-
assert(count > 0, "RefCount must not be decremented below zero.");
|
|
80
|
-
count = NonNegativeInt.orThrow(count - 1);
|
|
81
|
-
return count;
|
|
82
|
-
},
|
|
83
|
-
getCount: () => {
|
|
84
|
-
assertNotDisposed(disposables);
|
|
85
|
-
return count;
|
|
86
|
-
},
|
|
87
|
-
[Symbol.dispose]: () => disposables.dispose(),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
catch (e_1) {
|
|
91
|
-
env_1.error = e_1;
|
|
92
|
-
env_1.hasError = true;
|
|
93
|
-
}
|
|
94
|
-
finally {
|
|
95
|
-
__disposeResources(env_1);
|
|
96
|
-
}
|
|
64
|
+
let count = zeroNonNegativeInt;
|
|
65
|
+
return disposable({
|
|
66
|
+
increment: () => {
|
|
67
|
+
const nextCount = PositiveInt.orThrow(count + 1);
|
|
68
|
+
count = nextCount;
|
|
69
|
+
return nextCount;
|
|
70
|
+
},
|
|
71
|
+
decrement: () => {
|
|
72
|
+
assert(count > 0, "RefCount must not be decremented below zero.");
|
|
73
|
+
count = NonNegativeInt.orThrow(count - 1);
|
|
74
|
+
return count;
|
|
75
|
+
},
|
|
76
|
+
getCount: () => count,
|
|
77
|
+
});
|
|
97
78
|
};
|
|
98
79
|
export function createRefCountByKey({ lookup = identity, } = {}) {
|
|
99
|
-
const
|
|
80
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
100
81
|
try {
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
try {
|
|
106
|
-
const disposer = __addDisposableResource(env_3, new DisposableStack(), false);
|
|
107
|
-
disposer.defer(() => {
|
|
108
|
-
refCountByKey.clear();
|
|
109
|
-
});
|
|
110
|
-
for (const refCount of refCountByKey.values()) {
|
|
111
|
-
disposer.use(refCount);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
catch (e_3) {
|
|
115
|
-
env_3.error = e_3;
|
|
116
|
-
env_3.hasError = true;
|
|
117
|
-
}
|
|
118
|
-
finally {
|
|
119
|
-
__disposeResources(env_3);
|
|
120
|
-
}
|
|
82
|
+
const disposer = __addDisposableResource(env_1, new DisposableStack(), false);
|
|
83
|
+
const refCountByKey = createLookupMap({ lookup });
|
|
84
|
+
disposer.defer(() => {
|
|
85
|
+
refCountByKey.clear();
|
|
121
86
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
let refCount = refCountByKey.get(key);
|
|
125
|
-
if (!refCount) {
|
|
126
|
-
refCount = createRefCount();
|
|
127
|
-
refCountByKey.set(key, refCount);
|
|
128
|
-
}
|
|
129
|
-
return refCount;
|
|
130
|
-
};
|
|
131
|
-
return {
|
|
132
|
-
increment: (key) => {
|
|
133
|
-
assertNotDisposed(disposables);
|
|
134
|
-
return getRefCount(key).increment();
|
|
135
|
-
},
|
|
87
|
+
return disposable({
|
|
88
|
+
increment: (key) => refCountByKey.getOrInsertComputed(key, createRefCount).increment(),
|
|
136
89
|
decrement: (key) => {
|
|
137
|
-
|
|
138
|
-
|
|
90
|
+
const refCount = refCountByKey.get(key);
|
|
91
|
+
assert(refCount, "RefCount must not be decremented for an untracked key.");
|
|
139
92
|
const nextCount = refCount.decrement();
|
|
140
93
|
if (nextCount === 0) {
|
|
141
94
|
refCountByKey.delete(key);
|
|
@@ -143,26 +96,16 @@ export function createRefCountByKey({ lookup = identity, } = {}) {
|
|
|
143
96
|
}
|
|
144
97
|
return nextCount;
|
|
145
98
|
},
|
|
146
|
-
getCount: (key) =>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
has: (key) => {
|
|
151
|
-
assertNotDisposed(disposables);
|
|
152
|
-
return refCountByKey.has(key);
|
|
153
|
-
},
|
|
154
|
-
keys: () => {
|
|
155
|
-
assertNotDisposed(disposables);
|
|
156
|
-
return new Set(refCountByKey.keys());
|
|
157
|
-
},
|
|
158
|
-
[Symbol.dispose]: () => disposables.dispose(),
|
|
159
|
-
};
|
|
99
|
+
getCount: (key) => refCountByKey.get(key)?.getCount() ?? zeroNonNegativeInt,
|
|
100
|
+
has: (key) => refCountByKey.has(key),
|
|
101
|
+
keys: () => new Set(refCountByKey.keys()),
|
|
102
|
+
}, disposer);
|
|
160
103
|
}
|
|
161
|
-
catch (
|
|
162
|
-
|
|
163
|
-
|
|
104
|
+
catch (e_1) {
|
|
105
|
+
env_1.error = e_1;
|
|
106
|
+
env_1.hasError = true;
|
|
164
107
|
}
|
|
165
108
|
finally {
|
|
166
|
-
__disposeResources(
|
|
109
|
+
__disposeResources(env_1);
|
|
167
110
|
}
|
|
168
111
|
}
|
package/dist/src/Relation.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
-
import { type Lookup } from "./Lookup.
|
|
6
|
+
import { type Lookup } from "./Lookup.ts";
|
|
7
|
+
import { NonNegativeInt, PositiveInt } from "./Type.ts";
|
|
7
8
|
/**
|
|
8
9
|
* Bidirectional relation between two types.
|
|
9
10
|
*
|
|
@@ -34,20 +35,33 @@ import { type Lookup } from "./Lookup.js";
|
|
|
34
35
|
* The input parameter types of `lookupA` and `lookupB` determine which values
|
|
35
36
|
* the returned relation accepts on each side.
|
|
36
37
|
*
|
|
37
|
-
* ###
|
|
38
|
+
* ### Reference identity
|
|
38
39
|
*
|
|
39
40
|
* Use the default identity semantics.
|
|
40
41
|
*
|
|
41
42
|
* ```ts
|
|
42
|
-
*
|
|
43
|
+
* import { createRelation } from "@evolu/common";
|
|
44
|
+
*
|
|
45
|
+
* interface Socket {
|
|
46
|
+
* readonly id: string;
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* const relation = createRelation<Socket, string>();
|
|
50
|
+
* const socket = { id: "socket-1" };
|
|
51
|
+
*
|
|
43
52
|
* relation.add(socket, "owner-1");
|
|
53
|
+
*
|
|
54
|
+
* expect(relation.has(socket, "owner-1")).toBe(true);
|
|
55
|
+
* expect(relation.has({ id: "socket-1" }, "owner-1")).toBe(false);
|
|
44
56
|
* ```
|
|
45
57
|
*
|
|
46
|
-
* ###
|
|
58
|
+
* ### Lookup-derived equality
|
|
47
59
|
*
|
|
48
60
|
* Use lookup-derived equality.
|
|
49
61
|
*
|
|
50
62
|
* ```ts
|
|
63
|
+
* import { createRelation } from "@evolu/common";
|
|
64
|
+
*
|
|
51
65
|
* interface Person {
|
|
52
66
|
* readonly id: string;
|
|
53
67
|
* readonly name: string;
|
|
@@ -59,7 +73,10 @@ import { type Lookup } from "./Lookup.js";
|
|
|
59
73
|
* });
|
|
60
74
|
*
|
|
61
75
|
* relation.add({ id: "1", name: "Ada" }, { id: "admins" });
|
|
62
|
-
*
|
|
76
|
+
*
|
|
77
|
+
* expect(relation.has({ id: "1", name: "Grace" }, { id: "admins" })).toBe(
|
|
78
|
+
* true,
|
|
79
|
+
* );
|
|
63
80
|
* ```
|
|
64
81
|
*
|
|
65
82
|
* @see {@link createRelation}
|
|
@@ -131,4 +148,52 @@ export interface CreateRelationOptions<A, B, LA = A, LB = B> {
|
|
|
131
148
|
/** Creates a {@link Relation}. */
|
|
132
149
|
export declare function createRelation<A, B>(): Relation<A, B>;
|
|
133
150
|
export declare function createRelation<A, B, LA, LB>(options: CreateRelationOptions<A, B, LA, LB>): Relation<A, B>;
|
|
151
|
+
/**
|
|
152
|
+
* Bidirectional relation with a positive retain count for every active pair.
|
|
153
|
+
*
|
|
154
|
+
* Logical equality and canonical representatives follow the same lookup rules
|
|
155
|
+
* as {@link Relation}. The first active representative on each side remains
|
|
156
|
+
* canonical until that value has no active pairs. Increment and decrement
|
|
157
|
+
* return those representatives so callers can reliably handle pair transitions
|
|
158
|
+
* without repeating lookup or canonicalization logic.
|
|
159
|
+
*
|
|
160
|
+
* Unlike {@link Relation}'s live iterators, directional and entry reads return
|
|
161
|
+
* snapshots so callers can mutate this relation while iterating. Their order
|
|
162
|
+
* follows first insertion of the current canonical representatives and pairs.
|
|
163
|
+
*/
|
|
164
|
+
export interface RefCountedRelation<A, B> {
|
|
165
|
+
/** Increments a pair count and returns its canonical values and new count. */
|
|
166
|
+
readonly increment: (a: A, b: B) => {
|
|
167
|
+
readonly a: A;
|
|
168
|
+
readonly b: B;
|
|
169
|
+
readonly count: PositiveInt;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Decrements a pair count and returns its canonical values and new count.
|
|
173
|
+
* Decrementing a missing pair is a programmer error checked with
|
|
174
|
+
* {@link assert}.
|
|
175
|
+
*/
|
|
176
|
+
readonly decrement: (a: A, b: B) => {
|
|
177
|
+
readonly a: A;
|
|
178
|
+
readonly b: B;
|
|
179
|
+
readonly count: NonNegativeInt;
|
|
180
|
+
};
|
|
181
|
+
/** Returns the pair count, or zero when the pair is absent. */
|
|
182
|
+
readonly getCount: (a: A, b: B) => NonNegativeInt;
|
|
183
|
+
/** Returns a snapshot of canonical A values related to `b`. */
|
|
184
|
+
readonly getAs: (b: B) => ReadonlyArray<A>;
|
|
185
|
+
/** Returns a snapshot of canonical B values related to `a`. */
|
|
186
|
+
readonly getBs: (a: A) => ReadonlyArray<B>;
|
|
187
|
+
/** Returns whether an A value has at least one active pair. */
|
|
188
|
+
readonly hasA: (a: A) => boolean;
|
|
189
|
+
/** Returns whether a B value has at least one active pair. */
|
|
190
|
+
readonly hasB: (b: B) => boolean;
|
|
191
|
+
/** Returns a snapshot of every canonical pair and its positive count. */
|
|
192
|
+
readonly getEntries: () => ReadonlyArray<readonly [a: A, b: B, count: PositiveInt]>;
|
|
193
|
+
/** Removes all pair counts and both directional indexes. */
|
|
194
|
+
readonly clear: () => void;
|
|
195
|
+
}
|
|
196
|
+
/** Creates a {@link RefCountedRelation}. */
|
|
197
|
+
export declare function createRefCountedRelation<A, B>(): RefCountedRelation<A, B>;
|
|
198
|
+
export declare function createRefCountedRelation<A, B, LA, LB>(options: CreateRelationOptions<A, B, LA, LB>): RefCountedRelation<A, B>;
|
|
134
199
|
//# sourceMappingURL=Relation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Relation.d.ts","sourceRoot":"","sources":["../../src/Relation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAGL,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"Relation.d.ts","sourceRoot":"","sources":["../../src/Relation.ts"],"names":[],"mappings":"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"}
|
package/dist/src/Relation.js
CHANGED
|
@@ -7,13 +7,13 @@ import { emptyArray } from "./Array.js";
|
|
|
7
7
|
import { assert } from "./Assert.js";
|
|
8
8
|
import { identity } from "./Function.js";
|
|
9
9
|
import { createLookupMap, createLookupSet, } from "./Lookup.js";
|
|
10
|
+
import { NonNegativeInt, onePositiveInt, PositiveInt, zeroNonNegativeInt, } from "./Type.js";
|
|
10
11
|
export function createRelation({ lookupA = identity, lookupB = identity, } = {}) {
|
|
11
12
|
const bByA = createLookupMap({ lookup: lookupA });
|
|
12
13
|
const aByB = createLookupMap({ lookup: lookupB });
|
|
13
14
|
let sizeInternal = 0;
|
|
14
15
|
const removePair = (a, b) => {
|
|
15
16
|
const relatedB = bByA.get(a);
|
|
16
|
-
// This should only fail if a leaked view was mutated via an unsafe cast.
|
|
17
17
|
assertRelationMappingConsistency(relatedB);
|
|
18
18
|
assertRelationMappingConsistency(relatedB.has(b));
|
|
19
19
|
relatedB.delete(b);
|
|
@@ -21,7 +21,6 @@ export function createRelation({ lookupA = identity, lookupB = identity, } = {})
|
|
|
21
21
|
bByA.delete(a);
|
|
22
22
|
}
|
|
23
23
|
const relatedA = aByB.get(b);
|
|
24
|
-
// This should only fail if a leaked view was mutated via an unsafe cast.
|
|
25
24
|
assertRelationMappingConsistency(relatedA);
|
|
26
25
|
assertRelationMappingConsistency(relatedA.has(a));
|
|
27
26
|
relatedA.delete(a);
|
|
@@ -100,6 +99,82 @@ export function createRelation({ lookupA = identity, lookupB = identity, } = {})
|
|
|
100
99
|
size: () => sizeInternal,
|
|
101
100
|
};
|
|
102
101
|
}
|
|
102
|
+
// This can fail if a lookup function violates its pure and stable contract.
|
|
103
103
|
const assertRelationMappingConsistency = (condition) => {
|
|
104
104
|
assert(condition, "Relation mapping inconsistency");
|
|
105
105
|
};
|
|
106
|
+
export function createRefCountedRelation({ lookupA = identity, lookupB = identity, } = {}) {
|
|
107
|
+
const relatedBsByA = createLookupMap({ lookup: lookupA });
|
|
108
|
+
const relatedAsByB = createLookupMap({ lookup: lookupB });
|
|
109
|
+
return {
|
|
110
|
+
increment: (a, b) => {
|
|
111
|
+
let relatedBs = relatedBsByA.get(a);
|
|
112
|
+
const canonicalA = relatedBs ? relatedBs.a : a;
|
|
113
|
+
const relatedAs = relatedAsByB.get(b);
|
|
114
|
+
const canonicalB = relatedAs ? relatedAs.b : b;
|
|
115
|
+
if (!relatedBs) {
|
|
116
|
+
relatedBs = {
|
|
117
|
+
a: canonicalA,
|
|
118
|
+
countsByB: createLookupMap({ lookup: lookupB }),
|
|
119
|
+
};
|
|
120
|
+
relatedBsByA.set(canonicalA, relatedBs);
|
|
121
|
+
}
|
|
122
|
+
const count = relatedBs.countsByB.get(canonicalB);
|
|
123
|
+
if (count) {
|
|
124
|
+
const nextCount = PositiveInt.orThrow(count + 1);
|
|
125
|
+
relatedBs.countsByB.set(canonicalB, nextCount);
|
|
126
|
+
return { a: canonicalA, b: canonicalB, count: nextCount };
|
|
127
|
+
}
|
|
128
|
+
relatedBs.countsByB.set(canonicalB, onePositiveInt);
|
|
129
|
+
if (relatedAs) {
|
|
130
|
+
relatedAs.as.add(canonicalA);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
relatedAsByB.set(canonicalB, {
|
|
134
|
+
b: canonicalB,
|
|
135
|
+
as: createLookupSet({
|
|
136
|
+
lookup: lookupA,
|
|
137
|
+
values: [canonicalA],
|
|
138
|
+
}),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return { a: canonicalA, b: canonicalB, count: onePositiveInt };
|
|
142
|
+
},
|
|
143
|
+
decrement: (a, b) => {
|
|
144
|
+
const relatedBs = relatedBsByA.get(a);
|
|
145
|
+
const relatedAs = relatedAsByB.get(b);
|
|
146
|
+
const count = relatedBs?.countsByB.get(b);
|
|
147
|
+
assert(relatedBs && relatedAs && count, "RefCountedRelation pair must exist before decrement.");
|
|
148
|
+
const nextCount = NonNegativeInt.orThrow(count - 1);
|
|
149
|
+
if (nextCount > 0) {
|
|
150
|
+
relatedBs.countsByB.set(relatedAs.b, PositiveInt.orThrow(nextCount));
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
relatedBs.countsByB.delete(relatedAs.b);
|
|
154
|
+
if (relatedBs.countsByB.size === 0)
|
|
155
|
+
relatedBsByA.delete(relatedBs.a);
|
|
156
|
+
relatedAs.as.delete(relatedBs.a);
|
|
157
|
+
if (relatedAs.as.size === 0)
|
|
158
|
+
relatedAsByB.delete(relatedAs.b);
|
|
159
|
+
}
|
|
160
|
+
return { a: relatedBs.a, b: relatedAs.b, count: nextCount };
|
|
161
|
+
},
|
|
162
|
+
getCount: (a, b) => relatedBsByA.get(a)?.countsByB.get(b) ?? zeroNonNegativeInt,
|
|
163
|
+
getAs: (b) => [...(relatedAsByB.get(b)?.as ?? emptyArray)],
|
|
164
|
+
getBs: (a) => [...(relatedBsByA.get(a)?.countsByB.keys() ?? emptyArray)],
|
|
165
|
+
hasA: (a) => relatedBsByA.has(a),
|
|
166
|
+
hasB: (b) => relatedAsByB.has(b),
|
|
167
|
+
getEntries: () => {
|
|
168
|
+
const entries = [];
|
|
169
|
+
for (const { a, countsByB } of relatedBsByA.values()) {
|
|
170
|
+
for (const [b, count] of countsByB)
|
|
171
|
+
entries.push([a, b, count]);
|
|
172
|
+
}
|
|
173
|
+
return entries;
|
|
174
|
+
},
|
|
175
|
+
clear: () => {
|
|
176
|
+
relatedBsByA.clear();
|
|
177
|
+
relatedAsByB.clear();
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|