@evolu/common 8.6.2 → 8.8.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 +21 -21
- package/dist/src/Array.js +5 -5
- package/dist/src/Assert.d.ts +478 -141
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +644 -99
- package/dist/src/Binary.d.ts +254 -0
- package/dist/src/Binary.d.ts.map +1 -0
- package/dist/src/Binary.js +958 -0
- package/dist/src/Console.d.ts +2 -10
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +6 -12
- package/dist/src/Crypto.d.ts +5 -5
- package/dist/src/Crypto.js +1 -1
- package/dist/src/Eq.d.ts +35 -40
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +51 -87
- package/dist/src/Function.d.ts +9 -14
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +7 -9
- package/dist/src/Http.d.ts +6 -7
- package/dist/src/Http.d.ts.map +1 -1
- package/dist/src/LeakDetector.d.ts.map +1 -1
- package/dist/src/LeakDetector.js +1 -0
- package/dist/src/LockManager.d.ts +1 -1
- package/dist/src/LockManager.js +1 -1
- package/dist/src/Lookup.d.ts +3 -2
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +4 -3
- package/dist/src/Number.d.ts +1 -1
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +1 -1
- package/dist/src/Object.d.ts +4 -4
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +5 -4
- package/dist/src/Option.d.ts +1 -2
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +1 -2
- package/dist/src/Platform.js +2 -0
- package/dist/src/Polyfills.js +4 -1
- package/dist/src/Random.d.ts +1 -1
- package/dist/src/Result.d.ts +49 -54
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +17 -22
- package/dist/src/Set.d.ts +6 -6
- package/dist/src/Set.js +2 -2
- package/dist/src/Sqlite.js +1 -1
- package/dist/src/String.js +3 -2
- package/dist/src/Task.d.ts +32 -32
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +20 -22
- package/dist/src/Test.d.ts +31 -3
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +46 -3
- package/dist/src/Time.d.ts +3 -11
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +10 -18
- package/dist/src/Type.d.ts +87 -85
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +70 -63
- package/dist/src/Types.d.ts +12 -12
- package/dist/src/Types.js +1 -1
- package/dist/src/WebSocket.d.ts +4 -7
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/Worker.d.ts +1 -1
- package/dist/src/Worker.js +7 -7
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/intl/_en.d.ts.map +1 -1
- package/dist/src/intl/_en.js +1 -1
- package/dist/src/intl/ar.d.ts.map +1 -1
- package/dist/src/intl/ar.js +1 -1
- package/dist/src/intl/bn.d.ts.map +1 -1
- package/dist/src/intl/bn.js +1 -1
- package/dist/src/intl/ca.d.ts.map +1 -1
- package/dist/src/intl/ca.js +1 -1
- package/dist/src/intl/cs.d.ts.map +1 -1
- package/dist/src/intl/cs.js +1 -1
- package/dist/src/intl/da.d.ts.map +1 -1
- package/dist/src/intl/da.js +1 -1
- package/dist/src/intl/de.d.ts.map +1 -1
- package/dist/src/intl/de.js +1 -1
- package/dist/src/intl/el.d.ts.map +1 -1
- package/dist/src/intl/el.js +1 -1
- package/dist/src/intl/es.d.ts.map +1 -1
- package/dist/src/intl/es.js +1 -1
- package/dist/src/intl/fa.d.ts.map +1 -1
- package/dist/src/intl/fa.js +1 -1
- package/dist/src/intl/fi.d.ts.map +1 -1
- package/dist/src/intl/fi.js +1 -1
- package/dist/src/intl/fil.d.ts.map +1 -1
- package/dist/src/intl/fil.js +1 -1
- package/dist/src/intl/fr.d.ts.map +1 -1
- package/dist/src/intl/fr.js +1 -1
- package/dist/src/intl/he.d.ts.map +1 -1
- package/dist/src/intl/he.js +1 -1
- package/dist/src/intl/hi.d.ts.map +1 -1
- package/dist/src/intl/hi.js +1 -1
- package/dist/src/intl/hr.d.ts.map +1 -1
- package/dist/src/intl/hr.js +1 -1
- package/dist/src/intl/hu.d.ts.map +1 -1
- package/dist/src/intl/hu.js +1 -1
- package/dist/src/intl/id.d.ts.map +1 -1
- package/dist/src/intl/id.js +1 -1
- package/dist/src/intl/it.d.ts.map +1 -1
- package/dist/src/intl/it.js +1 -1
- package/dist/src/intl/ja.d.ts.map +1 -1
- package/dist/src/intl/ja.js +1 -1
- package/dist/src/intl/ko.d.ts.map +1 -1
- package/dist/src/intl/ko.js +1 -1
- package/dist/src/intl/ml.d.ts.map +1 -1
- package/dist/src/intl/ml.js +1 -1
- package/dist/src/intl/mr.d.ts.map +1 -1
- package/dist/src/intl/mr.js +1 -1
- package/dist/src/intl/ms.d.ts.map +1 -1
- package/dist/src/intl/ms.js +1 -1
- package/dist/src/intl/nb.d.ts.map +1 -1
- package/dist/src/intl/nb.js +1 -1
- package/dist/src/intl/nl.d.ts.map +1 -1
- package/dist/src/intl/nl.js +1 -1
- package/dist/src/intl/pa.d.ts.map +1 -1
- package/dist/src/intl/pa.js +1 -1
- package/dist/src/intl/pl.d.ts.map +1 -1
- package/dist/src/intl/pl.js +1 -1
- package/dist/src/intl/pt-BR.d.ts.map +1 -1
- package/dist/src/intl/pt-BR.js +1 -1
- package/dist/src/intl/pt.d.ts.map +1 -1
- package/dist/src/intl/pt.js +1 -1
- package/dist/src/intl/ro.d.ts.map +1 -1
- package/dist/src/intl/ro.js +1 -1
- package/dist/src/intl/sk.d.ts.map +1 -1
- package/dist/src/intl/sk.js +1 -1
- package/dist/src/intl/sl.d.ts.map +1 -1
- package/dist/src/intl/sl.js +1 -1
- package/dist/src/intl/sv.d.ts.map +1 -1
- package/dist/src/intl/sv.js +1 -1
- package/dist/src/intl/sw.d.ts.map +1 -1
- package/dist/src/intl/sw.js +1 -1
- package/dist/src/intl/ta.d.ts.map +1 -1
- package/dist/src/intl/ta.js +1 -1
- package/dist/src/intl/te.d.ts.map +1 -1
- package/dist/src/intl/te.js +1 -1
- package/dist/src/intl/th.d.ts.map +1 -1
- package/dist/src/intl/th.js +1 -1
- package/dist/src/intl/tr.d.ts.map +1 -1
- package/dist/src/intl/tr.js +1 -1
- package/dist/src/intl/uk.d.ts.map +1 -1
- package/dist/src/intl/uk.js +1 -1
- package/dist/src/intl/ur.d.ts.map +1 -1
- package/dist/src/intl/ur.js +1 -1
- package/dist/src/intl/vi.d.ts.map +1 -1
- package/dist/src/intl/vi.js +1 -1
- package/dist/src/intl/zh-CN.d.ts.map +1 -1
- package/dist/src/intl/zh-CN.js +1 -1
- package/dist/src/intl/zh-TW.d.ts.map +1 -1
- package/dist/src/intl/zh-TW.js +1 -1
- package/dist/src/local-first/Evolu.d.ts +12 -12
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +2 -2
- package/dist/src/local-first/Protocol.d.ts +28 -76
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +45 -229
- package/dist/src/local-first/Query.d.ts +11 -11
- package/dist/src/local-first/Query.js +6 -6
- package/dist/src/local-first/Relay.d.ts +2 -2
- package/dist/src/local-first/Schema.d.ts +3 -5
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +2 -4
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +5 -5
- package/dist/src/local-first/Storage.js +4 -4
- package/dist/src/local-first/Timestamp.d.ts +9 -0
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +13 -10
- package/package.json +7 -5
- package/src/Array.test.ts +809 -0
- package/src/Array.ts +21 -21
- package/src/Assert.test.ts +1181 -0
- package/src/Assert.ts +971 -227
- package/src/BigInt.test.ts +28 -0
- package/src/Binary.test.ts +1128 -0
- package/src/Binary.ts +1377 -0
- package/src/Brand.test.ts +90 -0
- package/src/Cache.test.ts +183 -0
- package/src/Callbacks.test.ts +66 -0
- package/src/Console.test.ts +809 -0
- package/src/Console.ts +9 -17
- package/src/Crypto.test.ts +138 -0
- package/src/Crypto.ts +5 -5
- package/src/Eq.test.ts +333 -0
- package/src/Eq.ts +110 -176
- package/src/Error.test.ts +118 -0
- package/src/Function.test.ts +204 -0
- package/src/Function.ts +10 -15
- package/src/Http.test.ts +816 -0
- package/src/Http.ts +6 -7
- package/src/LeakDetector.test.ts +210 -0
- package/src/LeakDetector.ts +1 -0
- package/src/LockManager.ts +2 -2
- package/src/Lookup.test.ts +418 -0
- package/src/Lookup.ts +4 -3
- package/src/Microtask.test.ts +140 -0
- package/src/Number.test.ts +218 -0
- package/src/Number.ts +2 -2
- package/src/Object.test.ts +293 -0
- package/src/Object.ts +5 -4
- package/src/Option.test.ts +104 -0
- package/src/Option.ts +1 -2
- package/src/Order.test.ts +56 -0
- package/src/Platform.ts +2 -0
- package/src/Polyfills.ts +3 -4
- package/src/Random.test.ts +89 -0
- package/src/Random.ts +1 -1
- package/src/Ref.test.ts +139 -0
- package/src/RefCount.test.ts +184 -0
- package/src/Relation.test.ts +505 -0
- package/src/Resource.test.ts +4623 -0
- package/src/Result.test.ts +1829 -0
- package/src/Result.ts +49 -54
- package/src/Schedule.test.ts +1554 -0
- package/src/Set.test.ts +279 -0
- package/src/Set.ts +6 -6
- package/src/Sqlite.ts +1 -1
- package/src/Store.test.ts +288 -0
- package/src/String.test.ts +54 -0
- package/src/String.ts +3 -3
- package/src/Task.test.ts +10820 -0
- package/src/Task.ts +38 -43
- package/src/Test.test.ts +88 -0
- package/src/Test.ts +49 -3
- package/src/Time.test.ts +926 -0
- package/src/Time.ts +13 -21
- package/src/Type.base64.test.ts +88 -0
- package/src/Type.test.ts +20465 -0
- package/src/Type.ts +114 -111
- package/src/Types.test.ts +324 -0
- package/src/Types.ts +13 -13
- package/src/WebSocket.ts +4 -7
- package/src/Worker.test.ts +755 -0
- package/src/Worker.ts +13 -18
- package/src/index.ts +1 -1
- package/src/intl/_en.ts +1 -1
- package/src/intl/ar.ts +1 -1
- package/src/intl/bn.ts +1 -1
- package/src/intl/ca.ts +1 -1
- package/src/intl/cs.ts +1 -1
- package/src/intl/da.ts +1 -1
- package/src/intl/de.ts +1 -1
- package/src/intl/el.ts +1 -1
- package/src/intl/es.ts +1 -1
- package/src/intl/fa.ts +1 -1
- package/src/intl/fi.ts +1 -1
- package/src/intl/fil.ts +1 -1
- package/src/intl/fr.ts +1 -1
- package/src/intl/he.ts +1 -1
- package/src/intl/hi.ts +1 -1
- package/src/intl/hr.ts +1 -1
- package/src/intl/hu.ts +1 -1
- package/src/intl/id.ts +1 -1
- package/src/intl/intl.test.ts +3106 -0
- package/src/intl/it.ts +1 -1
- package/src/intl/ja.ts +1 -1
- package/src/intl/ko.ts +1 -1
- package/src/intl/ml.ts +1 -1
- package/src/intl/mr.ts +1 -1
- package/src/intl/ms.ts +1 -1
- package/src/intl/nb.ts +1 -1
- package/src/intl/nl.ts +1 -1
- package/src/intl/pa.ts +1 -1
- package/src/intl/pl.ts +1 -1
- package/src/intl/pt-BR.ts +1 -1
- package/src/intl/pt.ts +1 -1
- package/src/intl/ro.ts +1 -1
- package/src/intl/sk.ts +1 -1
- package/src/intl/sl.ts +1 -1
- package/src/intl/sv.ts +1 -1
- package/src/intl/sw.ts +1 -1
- package/src/intl/ta.ts +1 -1
- package/src/intl/te.ts +1 -1
- package/src/intl/th.ts +1 -1
- package/src/intl/tr.ts +1 -1
- package/src/intl/uk.ts +1 -1
- package/src/intl/ur.ts +1 -1
- package/src/intl/vi.ts +1 -1
- package/src/intl/zh-CN.ts +1 -1
- package/src/intl/zh-TW.ts +1 -1
- package/src/local-first/Evolu.test.ts +1921 -0
- package/src/local-first/Evolu.ts +18 -14
- package/src/local-first/Owner.test.ts +83 -0
- package/src/local-first/Protocol.test.ts +1037 -0
- package/src/local-first/Protocol.ts +75 -290
- package/src/local-first/Query.test.ts +349 -0
- package/src/local-first/Query.ts +11 -11
- package/src/local-first/Relay.ts +2 -2
- package/src/local-first/Schema.ts +3 -5
- package/src/local-first/Shared.test.ts +1828 -0
- package/src/local-first/Shared.ts +9 -8
- package/src/local-first/Storage.ts +4 -4
- package/src/local-first/Timestamp.test.ts +374 -0
- package/src/local-first/Timestamp.ts +22 -10
- package/dist/src/Buffer.d.ts +0 -122
- package/dist/src/Buffer.d.ts.map +0 -1
- package/dist/src/Buffer.js +0 -69
- package/src/Buffer.ts +0 -206
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
|
|
3
|
+
import type { Brand, IsBranded } from "./Brand.ts";
|
|
4
|
+
import { constVoid } from "./Function.ts";
|
|
5
|
+
import { assertType } from "./Type.ts";
|
|
6
|
+
|
|
7
|
+
test("Brand", () => {
|
|
8
|
+
type UserId = string & Brand<"UserId">;
|
|
9
|
+
type ProductId = number & Brand<"ProductId">;
|
|
10
|
+
|
|
11
|
+
const validUserId: UserId = "user123" as UserId;
|
|
12
|
+
assertType<typeof validUserId, string & Brand<"UserId">>();
|
|
13
|
+
|
|
14
|
+
const validProductId: ProductId = 42 as ProductId;
|
|
15
|
+
assertType<typeof validProductId, number & Brand<"ProductId">>();
|
|
16
|
+
|
|
17
|
+
// Invalid assignment (string to ProductId)
|
|
18
|
+
// @ts-expect-error - Should not allow a string to be assigned to ProductId
|
|
19
|
+
const invalidProductId: ProductId = "not-a-number";
|
|
20
|
+
|
|
21
|
+
// Invalid assignment (unbranded string to UserId)
|
|
22
|
+
// @ts-expect-error - Should not allow unbranded string to be assigned to UserId
|
|
23
|
+
const invalidUserId: UserId = "user123";
|
|
24
|
+
|
|
25
|
+
// Invalid assignment (mixing different brands)
|
|
26
|
+
// @ts-expect-error - Should not allow assigning a ProductId to a UserId
|
|
27
|
+
const mismatchedId: UserId = validProductId;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("Brand - multiple brands", () => {
|
|
31
|
+
type Min1 = string & Brand<"Min1">;
|
|
32
|
+
type Max100 = string & Brand<"Max100">;
|
|
33
|
+
type Min1Max100 = string & Brand<"Min1" | "Max100">;
|
|
34
|
+
|
|
35
|
+
const requiresMin1 = (_value: Min1) => constVoid;
|
|
36
|
+
const requiresMax100 = (_value: Max100) => constVoid;
|
|
37
|
+
|
|
38
|
+
const min1Value: Min1 = "hello" as Min1;
|
|
39
|
+
const max100Value: Max100 = "world" as Max100;
|
|
40
|
+
const min1Max100Value: Min1Max100 = "typescript" as Min1Max100;
|
|
41
|
+
|
|
42
|
+
requiresMin1(min1Value);
|
|
43
|
+
requiresMax100(max100Value);
|
|
44
|
+
requiresMin1(min1Max100Value);
|
|
45
|
+
requiresMax100(min1Max100Value);
|
|
46
|
+
|
|
47
|
+
// @ts-expect-error: brands works
|
|
48
|
+
requiresMin1("hello");
|
|
49
|
+
// @ts-expect-error: brands works
|
|
50
|
+
requiresMin1(max100Value);
|
|
51
|
+
// @ts-expect-error: brands works
|
|
52
|
+
requiresMax100("world");
|
|
53
|
+
// @ts-expect-error: brands works
|
|
54
|
+
requiresMax100(min1Value);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("IsBranded", () => {
|
|
58
|
+
type UnbrandedString = string;
|
|
59
|
+
type BrandedString = string & Brand<"UserId">;
|
|
60
|
+
type BrandedNumber = number & Brand<"ProductId">;
|
|
61
|
+
type DoubleBranded = string & Brand<"Min"> & Brand<"Max">;
|
|
62
|
+
|
|
63
|
+
assertType<IsBranded<UnbrandedString>, false>();
|
|
64
|
+
assertType<IsBranded<BrandedString>, true>();
|
|
65
|
+
assertType<IsBranded<BrandedNumber>, true>();
|
|
66
|
+
assertType<IsBranded<DoubleBranded>, true>();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("Brand - standalone (nominal type)", () => {
|
|
70
|
+
// Brand can be used alone without a base type for purely nominal typing.
|
|
71
|
+
// Useful for platform-specific values where type identity is based on name only.
|
|
72
|
+
type NativePort = Brand<"NativePort">;
|
|
73
|
+
|
|
74
|
+
const requiresNativePort = (_port: NativePort) => constVoid;
|
|
75
|
+
|
|
76
|
+
// Only branded values can be passed
|
|
77
|
+
const nativePort: NativePort = {} as NativePort;
|
|
78
|
+
requiresNativePort(nativePort);
|
|
79
|
+
|
|
80
|
+
// @ts-expect-error: plain unknown cannot be passed
|
|
81
|
+
requiresNativePort({} as unknown);
|
|
82
|
+
|
|
83
|
+
// @ts-expect-error: other types cannot be passed
|
|
84
|
+
requiresNativePort({});
|
|
85
|
+
|
|
86
|
+
// @ts-expect-error: null cannot be passed
|
|
87
|
+
requiresNativePort(null);
|
|
88
|
+
|
|
89
|
+
assertType<IsBranded<NativePort>, true>();
|
|
90
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { assertEqual, assertFalse, assertSame, assertTrue } from "./Assert.ts";
|
|
3
|
+
|
|
4
|
+
import { createLruCache } from "./Cache.ts";
|
|
5
|
+
import { onePositiveInt, PositiveInt } from "./Type.ts";
|
|
6
|
+
|
|
7
|
+
test("LRU cache - basic set and get", () => {
|
|
8
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(3));
|
|
9
|
+
|
|
10
|
+
cache.set("a", 1);
|
|
11
|
+
cache.set("b", 2);
|
|
12
|
+
cache.set("c", 3);
|
|
13
|
+
|
|
14
|
+
assertEqual(cache.get("a"), 1);
|
|
15
|
+
assertEqual(cache.get("b"), 2);
|
|
16
|
+
assertEqual(cache.get("c"), 3);
|
|
17
|
+
assertSame(cache.get("d"), undefined);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("LRU cache - has method", () => {
|
|
21
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
22
|
+
|
|
23
|
+
cache.set("a", 1);
|
|
24
|
+
cache.set("b", 2);
|
|
25
|
+
|
|
26
|
+
assertTrue(cache.has("a"));
|
|
27
|
+
assertTrue(cache.has("b"));
|
|
28
|
+
assertFalse(cache.has("c"));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("LRU cache - delete method", () => {
|
|
32
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
33
|
+
|
|
34
|
+
cache.set("a", 1);
|
|
35
|
+
cache.set("b", 2);
|
|
36
|
+
|
|
37
|
+
assertTrue(cache.has("a"));
|
|
38
|
+
cache.delete("a");
|
|
39
|
+
assertFalse(cache.has("a"));
|
|
40
|
+
assertSame(cache.get("a"), undefined);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("LRU cache - evicts least recently used on capacity", () => {
|
|
44
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
45
|
+
|
|
46
|
+
cache.set("a", 1);
|
|
47
|
+
cache.set("b", 2);
|
|
48
|
+
// Should evict "a"
|
|
49
|
+
cache.set("c", 3);
|
|
50
|
+
|
|
51
|
+
assertFalse(cache.has("a"));
|
|
52
|
+
assertTrue(cache.has("b"));
|
|
53
|
+
assertTrue(cache.has("c"));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("LRU cache - get updates access order", () => {
|
|
57
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
58
|
+
|
|
59
|
+
cache.set("a", 1);
|
|
60
|
+
cache.set("b", 2);
|
|
61
|
+
// Access "a", making it most recent
|
|
62
|
+
cache.get("a");
|
|
63
|
+
// Should evict "b", not "a"
|
|
64
|
+
cache.set("c", 3);
|
|
65
|
+
|
|
66
|
+
assertTrue(cache.has("a"));
|
|
67
|
+
assertFalse(cache.has("b"));
|
|
68
|
+
assertTrue(cache.has("c"));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("LRU cache - set updates access order for existing key", () => {
|
|
72
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
73
|
+
|
|
74
|
+
cache.set("a", 1);
|
|
75
|
+
cache.set("b", 2);
|
|
76
|
+
// Update "a", making it most recent
|
|
77
|
+
cache.set("a", 10);
|
|
78
|
+
// Should evict "b", not "a"
|
|
79
|
+
cache.set("c", 3);
|
|
80
|
+
|
|
81
|
+
assertEqual(cache.get("a"), 10);
|
|
82
|
+
assertFalse(cache.has("b"));
|
|
83
|
+
assertTrue(cache.has("c"));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("LRU cache - readonly map view", () => {
|
|
87
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(3));
|
|
88
|
+
|
|
89
|
+
cache.set("a", 1);
|
|
90
|
+
cache.set("b", 2);
|
|
91
|
+
cache.set("c", 3);
|
|
92
|
+
|
|
93
|
+
assertEqual(cache.map.size, 3);
|
|
94
|
+
assertEqual(cache.map.get("a"), 1);
|
|
95
|
+
assertEqual(cache.map.get("b"), 2);
|
|
96
|
+
assertEqual(cache.map.get("c"), 3);
|
|
97
|
+
assertTrue(cache.map.has("a"));
|
|
98
|
+
assertFalse(cache.map.has("d"));
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("LRU cache - map view reflects cache changes", () => {
|
|
102
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(2));
|
|
103
|
+
|
|
104
|
+
cache.set("a", 1);
|
|
105
|
+
assertEqual(cache.map.size, 1);
|
|
106
|
+
|
|
107
|
+
cache.set("b", 2);
|
|
108
|
+
assertEqual(cache.map.size, 2);
|
|
109
|
+
|
|
110
|
+
// Evicts "a"
|
|
111
|
+
cache.set("c", 3);
|
|
112
|
+
assertEqual(cache.map.size, 2);
|
|
113
|
+
assertFalse(cache.map.has("a"));
|
|
114
|
+
assertTrue(cache.map.has("b"));
|
|
115
|
+
assertTrue(cache.map.has("c"));
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("LRU cache - iteration over map", () => {
|
|
119
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(3));
|
|
120
|
+
|
|
121
|
+
cache.set("a", 1);
|
|
122
|
+
cache.set("b", 2);
|
|
123
|
+
cache.set("c", 3);
|
|
124
|
+
|
|
125
|
+
const entries = Array.from(cache.map.entries());
|
|
126
|
+
assertEqual(entries, [
|
|
127
|
+
["a", 1],
|
|
128
|
+
["b", 2],
|
|
129
|
+
["c", 3],
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
const keys = Array.from(cache.map.keys());
|
|
133
|
+
assertEqual(keys, ["a", "b", "c"]);
|
|
134
|
+
|
|
135
|
+
const values = Array.from(cache.map.values());
|
|
136
|
+
assertEqual(values, [1, 2, 3]);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("LRU cache - forEach on map", () => {
|
|
140
|
+
const cache = createLruCache<string, number>(PositiveInt.orThrow(3));
|
|
141
|
+
|
|
142
|
+
cache.set("a", 1);
|
|
143
|
+
cache.set("b", 2);
|
|
144
|
+
cache.set("c", 3);
|
|
145
|
+
|
|
146
|
+
const collected: Array<[string, number]> = [];
|
|
147
|
+
cache.map.forEach((value, key) => {
|
|
148
|
+
collected.push([key, value]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
assertEqual(collected, [
|
|
152
|
+
["a", 1],
|
|
153
|
+
["b", 2],
|
|
154
|
+
["c", 3],
|
|
155
|
+
]);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("LRU cache - reference-based key comparison", () => {
|
|
159
|
+
const cache = createLruCache<object, number>(PositiveInt.orThrow(2));
|
|
160
|
+
|
|
161
|
+
const key1 = { id: 1 };
|
|
162
|
+
// Different object, same structure
|
|
163
|
+
const key2 = { id: 1 };
|
|
164
|
+
|
|
165
|
+
cache.set(key1, 100);
|
|
166
|
+
cache.set(key2, 200);
|
|
167
|
+
|
|
168
|
+
assertEqual(cache.get(key1), 100);
|
|
169
|
+
assertEqual(cache.get(key2), 200);
|
|
170
|
+
assertTrue(cache.has(key1));
|
|
171
|
+
assertTrue(cache.has(key2));
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("LRU cache - capacity of 1", () => {
|
|
175
|
+
const cache = createLruCache<string, number>(onePositiveInt);
|
|
176
|
+
|
|
177
|
+
cache.set("a", 1);
|
|
178
|
+
assertTrue(cache.has("a"));
|
|
179
|
+
|
|
180
|
+
cache.set("b", 2);
|
|
181
|
+
assertFalse(cache.has("a"));
|
|
182
|
+
assertTrue(cache.has("b"));
|
|
183
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { assertEqual, assertFalse, assertSame, assertTrue } from "./Assert.ts";
|
|
3
|
+
|
|
4
|
+
import { createCallbacks } from "./Callbacks.ts";
|
|
5
|
+
import { testCreateDeps } from "./Task.ts";
|
|
6
|
+
|
|
7
|
+
test("Callbacks with no argument", () => {
|
|
8
|
+
const deps = testCreateDeps();
|
|
9
|
+
const callbacks = createCallbacks(deps);
|
|
10
|
+
|
|
11
|
+
let called = false;
|
|
12
|
+
const id = callbacks.register(() => {
|
|
13
|
+
called = true;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
callbacks.execute(id);
|
|
17
|
+
assertTrue(called);
|
|
18
|
+
|
|
19
|
+
called = false;
|
|
20
|
+
callbacks.execute(id);
|
|
21
|
+
assertFalse(called);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("Callbacks with string type", () => {
|
|
25
|
+
const deps = testCreateDeps();
|
|
26
|
+
const callbacks = createCallbacks<string>(deps);
|
|
27
|
+
|
|
28
|
+
let receivedValue: string | null = null;
|
|
29
|
+
const id = callbacks.register((value) => {
|
|
30
|
+
receivedValue = value;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
callbacks.execute(id, "test value");
|
|
34
|
+
assertEqual(receivedValue, "test value");
|
|
35
|
+
|
|
36
|
+
receivedValue = null;
|
|
37
|
+
callbacks.execute(id, "should not execute");
|
|
38
|
+
assertSame(receivedValue, null);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("Callbacks with Promise.withResolvers pattern", async () => {
|
|
42
|
+
const deps = testCreateDeps();
|
|
43
|
+
const callbacks = createCallbacks<string>(deps);
|
|
44
|
+
|
|
45
|
+
const { promise, resolve } = Promise.withResolvers<string>();
|
|
46
|
+
const id = callbacks.register(resolve);
|
|
47
|
+
|
|
48
|
+
callbacks.execute(id, "resolved value");
|
|
49
|
+
|
|
50
|
+
assertEqual(await promise, "resolved value");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("Callbacks dispose clears pending callbacks", () => {
|
|
54
|
+
const deps = testCreateDeps();
|
|
55
|
+
const callbacks = createCallbacks<string>(deps);
|
|
56
|
+
|
|
57
|
+
let called = false;
|
|
58
|
+
const id = callbacks.register(() => {
|
|
59
|
+
called = true;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
callbacks[Symbol.dispose]();
|
|
63
|
+
callbacks.execute(id, "ignored");
|
|
64
|
+
|
|
65
|
+
assertFalse(called);
|
|
66
|
+
});
|