@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
|
@@ -10,7 +10,11 @@ import {
|
|
|
10
10
|
isNonEmptyArray,
|
|
11
11
|
type NonEmptyReadonlyArray,
|
|
12
12
|
} from "../Array.ts";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
assertNonNullable,
|
|
15
|
+
assertNotSame,
|
|
16
|
+
assertNotUndefined,
|
|
17
|
+
} from "../Assert.ts";
|
|
14
18
|
import type { Brand } from "../Brand.ts";
|
|
15
19
|
import { createCallbacks } from "../Callbacks.ts";
|
|
16
20
|
import type { ConsoleEntry, ConsoleLevel } from "../Console.ts";
|
|
@@ -495,7 +499,7 @@ const createEvoluTenant =
|
|
|
495
499
|
|
|
496
500
|
const initDbWorker = (): void => {
|
|
497
501
|
const tabLeaderPort = deps.tabLeaderPortStore.get();
|
|
498
|
-
|
|
502
|
+
assertNonNullable(tabLeaderPort);
|
|
499
503
|
|
|
500
504
|
const dbWorkerChannel = deps.createMessageChannel<
|
|
501
505
|
DbWorkerOutput,
|
|
@@ -506,10 +510,7 @@ const createEvoluTenant =
|
|
|
506
510
|
currentDbWorkerPort.onMessage = (message) => {
|
|
507
511
|
switch (message.type) {
|
|
508
512
|
case "LeaderAcquired": {
|
|
509
|
-
|
|
510
|
-
dbWorkerPort !== currentDbWorkerPort,
|
|
511
|
-
"Expected a new DbWorker port.",
|
|
512
|
-
);
|
|
513
|
+
assertNotSame(dbWorkerPort, currentDbWorkerPort);
|
|
513
514
|
dbWorkerPort?.[Symbol.dispose]();
|
|
514
515
|
dbWorkerPort = currentDbWorkerPort;
|
|
515
516
|
queueRequestInFlight = false;
|
|
@@ -775,9 +776,9 @@ const createEvoluTenant =
|
|
|
775
776
|
} else {
|
|
776
777
|
instance.usedSyncOwners.decrement(syncOwner);
|
|
777
778
|
const claimLeases = instance.claimLeasesBySyncOwner.get(syncOwner);
|
|
778
|
-
|
|
779
|
+
assertNotUndefined(claimLeases);
|
|
779
780
|
const claimLease = claimLeases.pop();
|
|
780
|
-
|
|
781
|
+
assertNotUndefined(claimLease);
|
|
781
782
|
claimLease.release();
|
|
782
783
|
if (claimLeases.length === 0) {
|
|
783
784
|
instance.claimLeasesBySyncOwner.delete(syncOwner);
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
8
8
|
import type { NonEmptyReadonlyArray } from "../Array.ts";
|
|
9
9
|
import { firstInArray, isNonEmptyArray } from "../Array.ts";
|
|
10
|
-
import { assert } from "../Assert.ts";
|
|
10
|
+
import { assert, assertNonNullable } from "../Assert.ts";
|
|
11
11
|
import type { Brand } from "../Brand.ts";
|
|
12
|
-
import { concatBytes } from "../
|
|
12
|
+
import { concatBytes } from "../Binary.ts";
|
|
13
13
|
import { decrement } from "../Number.ts";
|
|
14
14
|
import type { RandomDep } from "../Random.ts";
|
|
15
15
|
import { err, ok } from "../Result.ts";
|
|
@@ -1602,8 +1602,8 @@ export const readOwnerUsageOrDefault =
|
|
|
1602
1602
|
}
|
|
1603
1603
|
|
|
1604
1604
|
const row = firstInArray(result.rows);
|
|
1605
|
-
|
|
1606
|
-
|
|
1605
|
+
assertNonNullable(row.firstTimestamp);
|
|
1606
|
+
assertNonNullable(row.lastTimestamp);
|
|
1607
1607
|
|
|
1608
1608
|
return {
|
|
1609
1609
|
storedBytes: row.storedBytes,
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import { describe, it, test } from "node:test";
|
|
2
|
+
import {
|
|
3
|
+
assertEqual,
|
|
4
|
+
assertErr,
|
|
5
|
+
assertFalse,
|
|
6
|
+
assertOk,
|
|
7
|
+
assertTrue,
|
|
8
|
+
} from "../Assert.ts";
|
|
9
|
+
import { increment } from "../Number.ts";
|
|
10
|
+
import { orderNumber } from "../Order.ts";
|
|
11
|
+
import type { Result } from "../Result.ts";
|
|
12
|
+
import { ok } from "../Result.ts";
|
|
13
|
+
import { testCreateDeps } from "../Task.ts";
|
|
14
|
+
import type { Time, TimeDep } from "../Time.ts";
|
|
15
|
+
import { maxMillis, Millis, minMillis, testCreateTime } from "../Time.ts";
|
|
16
|
+
import type {
|
|
17
|
+
Timestamp,
|
|
18
|
+
TimestampBytes,
|
|
19
|
+
TimestampConfigDep,
|
|
20
|
+
TimestampCounterOverflowError,
|
|
21
|
+
TimestampDriftError,
|
|
22
|
+
TimestampTimeOutOfRangeError,
|
|
23
|
+
} from "./Timestamp.ts";
|
|
24
|
+
import {
|
|
25
|
+
Counter,
|
|
26
|
+
createInitialTimestamp,
|
|
27
|
+
createTimestamp,
|
|
28
|
+
defaultTimestampMaxDrift,
|
|
29
|
+
maxCounter,
|
|
30
|
+
minCounter,
|
|
31
|
+
NodeId,
|
|
32
|
+
nodeIdBytesToNodeId,
|
|
33
|
+
nodeIdToNodeIdBytes,
|
|
34
|
+
orderTimestampBytes,
|
|
35
|
+
receiveTimestamp,
|
|
36
|
+
sendTimestamp,
|
|
37
|
+
timestampBytesToTimestamp,
|
|
38
|
+
timestampToDateIso,
|
|
39
|
+
timestampToTimestampBytes,
|
|
40
|
+
} from "./Timestamp.ts";
|
|
41
|
+
|
|
42
|
+
test("validates Millis", () => {
|
|
43
|
+
assertFalse(Millis.fromUnknown(-1).ok);
|
|
44
|
+
assertTrue(Millis.fromUnknown(0).ok);
|
|
45
|
+
assertTrue(Millis.fromUnknown(maxMillis).ok);
|
|
46
|
+
assertFalse(Millis.fromUnknown(maxMillis + 1).ok);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("validates Counter", () => {
|
|
50
|
+
assertFalse(Counter.fromUnknown(-1).ok);
|
|
51
|
+
assertTrue(Counter.fromUnknown(0).ok);
|
|
52
|
+
assertTrue(Counter.fromUnknown(maxCounter).ok);
|
|
53
|
+
assertFalse(Counter.fromUnknown(maxCounter + 1).ok);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("validates NodeId", () => {
|
|
57
|
+
assertFalse(NodeId.fromUnknown("").ok);
|
|
58
|
+
assertTrue(NodeId.fromUnknown("0000000000000000").ok);
|
|
59
|
+
assertTrue(NodeId.fromUnknown("aaaaaaaaaaaaaaaa").ok);
|
|
60
|
+
assertFalse(NodeId.fromUnknown("Aaaaaaaaaaaaaaaa").ok);
|
|
61
|
+
assertFalse(NodeId.fromUnknown("aaaaaaaaaaaaaaaaa").ok);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("NodeId bytes", () => {
|
|
65
|
+
it("round-trips NodeId", () => {
|
|
66
|
+
const deps = testCreateDeps();
|
|
67
|
+
const nodeIds = Array.from(
|
|
68
|
+
{ length: 100 },
|
|
69
|
+
() => createInitialTimestamp(deps).nodeId,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
for (const nodeId of nodeIds) {
|
|
73
|
+
assertEqual(nodeIdBytesToNodeId(nodeIdToNodeIdBytes(nodeId)), nodeId);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("creates the minimum Timestamp by default", () => {
|
|
79
|
+
assertEqual(createTimestamp(), {
|
|
80
|
+
counter: 0,
|
|
81
|
+
millis: 0,
|
|
82
|
+
nodeId: "0000000000000000",
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("creates an initial Timestamp", () => {
|
|
87
|
+
const timestamp = createInitialTimestamp(testCreateDeps());
|
|
88
|
+
|
|
89
|
+
assertEqual(timestamp, {
|
|
90
|
+
counter: 0,
|
|
91
|
+
millis: 0,
|
|
92
|
+
nodeId: "9dca8c435bb0779f",
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const makeMillis = (millis: number): Millis => Millis.orThrow(millis);
|
|
97
|
+
|
|
98
|
+
const deps0: TimeDep & TimestampConfigDep = {
|
|
99
|
+
time: testCreateTime({ startAt: minMillis }),
|
|
100
|
+
timestampConfig: { maxDrift: defaultTimestampMaxDrift },
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const deps1: TimeDep & TimestampConfigDep = {
|
|
104
|
+
time: testCreateTime({ startAt: (minMillis + 1) as Millis }),
|
|
105
|
+
timestampConfig: { maxDrift: defaultTimestampMaxDrift },
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
describe("sendTimestamp", () => {
|
|
109
|
+
it("sends monotonically with a monotonic clock", () => {
|
|
110
|
+
assertOk(sendTimestamp(deps1)(createTimestamp()), {
|
|
111
|
+
counter: 0,
|
|
112
|
+
millis: 1,
|
|
113
|
+
nodeId: "0000000000000000",
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("sends monotonically with a stuttering clock", () => {
|
|
118
|
+
assertOk(sendTimestamp(deps0)(createTimestamp()), {
|
|
119
|
+
counter: 1,
|
|
120
|
+
millis: 0,
|
|
121
|
+
nodeId: "0000000000000000",
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("sends monotonically with a regressing clock", () => {
|
|
126
|
+
assertOk(
|
|
127
|
+
sendTimestamp(deps0)(
|
|
128
|
+
createTimestamp({ millis: makeMillis(minMillis + 1) }),
|
|
129
|
+
),
|
|
130
|
+
{
|
|
131
|
+
counter: 1,
|
|
132
|
+
millis: 1,
|
|
133
|
+
nodeId: "0000000000000000",
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("returns TimestampCounterOverflowError for counter overflow", () => {
|
|
139
|
+
let timestamp: Result<
|
|
140
|
+
Timestamp,
|
|
141
|
+
| TimestampDriftError
|
|
142
|
+
| TimestampCounterOverflowError
|
|
143
|
+
| TimestampTimeOutOfRangeError
|
|
144
|
+
> = ok(createTimestamp());
|
|
145
|
+
|
|
146
|
+
// Note +1 in 65536.
|
|
147
|
+
for (let i = 0; i < 65536; i++) {
|
|
148
|
+
if (timestamp.ok) timestamp = sendTimestamp(deps0)(timestamp.value);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
assertErr(timestamp, { type: "TimestampCounterOverflowError" });
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("returns TimestampDriftError for excessive clock drift", () => {
|
|
155
|
+
assertErr(
|
|
156
|
+
sendTimestamp(deps0)(
|
|
157
|
+
createTimestamp({
|
|
158
|
+
millis: makeMillis(minMillis + defaultTimestampMaxDrift + 1),
|
|
159
|
+
}),
|
|
160
|
+
),
|
|
161
|
+
{
|
|
162
|
+
next: 300001,
|
|
163
|
+
now: 0,
|
|
164
|
+
type: "TimestampDriftError",
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("returns TimestampTimeOutOfRangeError for an invalid clock", () => {
|
|
170
|
+
const time = testCreateTime();
|
|
171
|
+
const invalidTime: Time = {
|
|
172
|
+
...time,
|
|
173
|
+
now: (() => -1) as Time["now"],
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
assertErr(
|
|
177
|
+
sendTimestamp({
|
|
178
|
+
time: invalidTime,
|
|
179
|
+
timestampConfig: { maxDrift: defaultTimestampMaxDrift },
|
|
180
|
+
})(createTimestamp()),
|
|
181
|
+
{ type: "TimestampTimeOutOfRangeError" },
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe("receiveTimestamp", () => {
|
|
187
|
+
const makeNode1Timestamp = (
|
|
188
|
+
millis = 0,
|
|
189
|
+
counter = 0,
|
|
190
|
+
nodeId = "0000000000000001",
|
|
191
|
+
): Timestamp =>
|
|
192
|
+
({
|
|
193
|
+
millis: makeMillis(minMillis + millis),
|
|
194
|
+
counter,
|
|
195
|
+
nodeId,
|
|
196
|
+
}) as Timestamp;
|
|
197
|
+
|
|
198
|
+
const makeNode2Timestamp = (millis = 0, counter = 0): Timestamp =>
|
|
199
|
+
makeNode1Timestamp(millis, counter, "0000000000000002");
|
|
200
|
+
|
|
201
|
+
it("uses a wall clock later than both timestamps", () => {
|
|
202
|
+
assertOk(
|
|
203
|
+
receiveTimestamp(deps1)(makeNode1Timestamp(), makeNode2Timestamp()),
|
|
204
|
+
{
|
|
205
|
+
counter: 0,
|
|
206
|
+
millis: 1,
|
|
207
|
+
nodeId: "0000000000000001",
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
describe("wall clock is behind", () => {
|
|
213
|
+
it("increments the maximum counter when millis are equal", () => {
|
|
214
|
+
assertOk(
|
|
215
|
+
receiveTimestamp(deps1)(
|
|
216
|
+
makeNode1Timestamp(1, 0),
|
|
217
|
+
makeNode2Timestamp(1, 1),
|
|
218
|
+
),
|
|
219
|
+
{
|
|
220
|
+
counter: 2,
|
|
221
|
+
millis: 1,
|
|
222
|
+
nodeId: "0000000000000001",
|
|
223
|
+
},
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
assertOk(
|
|
227
|
+
receiveTimestamp(deps0)(
|
|
228
|
+
makeNode1Timestamp(1, 1),
|
|
229
|
+
makeNode2Timestamp(1, 0),
|
|
230
|
+
),
|
|
231
|
+
{
|
|
232
|
+
counter: 2,
|
|
233
|
+
millis: 1,
|
|
234
|
+
nodeId: "0000000000000001",
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("increments the counter when local millis is later", () => {
|
|
240
|
+
assertOk(
|
|
241
|
+
receiveTimestamp(deps0)(makeNode1Timestamp(2), makeNode2Timestamp(1)),
|
|
242
|
+
{
|
|
243
|
+
counter: 1,
|
|
244
|
+
millis: 2,
|
|
245
|
+
nodeId: "0000000000000001",
|
|
246
|
+
},
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it("increments the counter when remote millis is later", () => {
|
|
251
|
+
assertOk(
|
|
252
|
+
receiveTimestamp(deps0)(makeNode1Timestamp(1), makeNode2Timestamp(2)),
|
|
253
|
+
{
|
|
254
|
+
counter: 1,
|
|
255
|
+
millis: 2,
|
|
256
|
+
nodeId: "0000000000000001",
|
|
257
|
+
},
|
|
258
|
+
);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("returns TimestampDriftError for excessive clock drift", () => {
|
|
262
|
+
const expected = {
|
|
263
|
+
next: 300001,
|
|
264
|
+
now: 0,
|
|
265
|
+
type: "TimestampDriftError",
|
|
266
|
+
} as const;
|
|
267
|
+
|
|
268
|
+
assertErr(
|
|
269
|
+
receiveTimestamp(deps0)(
|
|
270
|
+
createTimestamp({
|
|
271
|
+
millis: makeMillis(minMillis + defaultTimestampMaxDrift + 1),
|
|
272
|
+
}),
|
|
273
|
+
makeNode2Timestamp(),
|
|
274
|
+
),
|
|
275
|
+
expected,
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
assertErr(
|
|
279
|
+
receiveTimestamp(deps0)(
|
|
280
|
+
makeNode2Timestamp(),
|
|
281
|
+
createTimestamp({
|
|
282
|
+
millis: makeMillis(minMillis + defaultTimestampMaxDrift + 1),
|
|
283
|
+
}),
|
|
284
|
+
),
|
|
285
|
+
expected,
|
|
286
|
+
);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("returns TimestampCounterOverflowError for counter overflow", () => {
|
|
290
|
+
assertErr(
|
|
291
|
+
receiveTimestamp(deps0)(
|
|
292
|
+
makeNode1Timestamp(0, maxCounter),
|
|
293
|
+
makeNode2Timestamp(0, maxCounter),
|
|
294
|
+
),
|
|
295
|
+
{ type: "TimestampCounterOverflowError" },
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe("TimestampBytes", () => {
|
|
302
|
+
it("round-trips and preserves Timestamp order", () => {
|
|
303
|
+
const decodeFromEncoded = (timestamp: TimestampBytes) =>
|
|
304
|
+
timestampBytesToTimestamp(timestamp);
|
|
305
|
+
|
|
306
|
+
const timestamp = createTimestamp();
|
|
307
|
+
assertEqual(
|
|
308
|
+
decodeFromEncoded(timestampToTimestampBytes(timestamp)),
|
|
309
|
+
timestamp,
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
const lastSafeTimestampEncodedDecoded = decodeFromEncoded(
|
|
313
|
+
timestampToTimestampBytes(createTimestamp({ millis: maxMillis })),
|
|
314
|
+
);
|
|
315
|
+
assertEqual(lastSafeTimestampEncodedDecoded.millis, maxMillis);
|
|
316
|
+
|
|
317
|
+
const t1 = timestampToTimestampBytes(
|
|
318
|
+
createTimestamp({ millis: minMillis }),
|
|
319
|
+
);
|
|
320
|
+
const t2 = timestampToTimestampBytes(
|
|
321
|
+
createTimestamp({
|
|
322
|
+
millis: Millis.orThrow(increment(minMillis)),
|
|
323
|
+
}),
|
|
324
|
+
);
|
|
325
|
+
assertEqual(orderTimestampBytes(t1, t2), -1);
|
|
326
|
+
assertEqual(orderTimestampBytes(t2, t1), 1);
|
|
327
|
+
assertEqual(orderTimestampBytes(t1, t1), 0);
|
|
328
|
+
|
|
329
|
+
const t3 = timestampToTimestampBytes(
|
|
330
|
+
createTimestamp({ counter: minCounter }),
|
|
331
|
+
);
|
|
332
|
+
const t4 = timestampToTimestampBytes(
|
|
333
|
+
createTimestamp({
|
|
334
|
+
counter: Counter.orThrow(increment(minCounter)),
|
|
335
|
+
}),
|
|
336
|
+
);
|
|
337
|
+
assertEqual(orderTimestampBytes(t3, t4), -1);
|
|
338
|
+
assertEqual(orderTimestampBytes(t4, t3), 1);
|
|
339
|
+
assertEqual(orderTimestampBytes(t3, t3), 0);
|
|
340
|
+
|
|
341
|
+
const t5 = timestampToTimestampBytes(
|
|
342
|
+
createTimestamp({ nodeId: "0000000000000000" as NodeId }),
|
|
343
|
+
);
|
|
344
|
+
const t6 = timestampToTimestampBytes(
|
|
345
|
+
createTimestamp({ nodeId: "0000000000000001" as NodeId }),
|
|
346
|
+
);
|
|
347
|
+
assertEqual(orderTimestampBytes(t5, t6), -1);
|
|
348
|
+
assertEqual(orderTimestampBytes(t6, t5), 1);
|
|
349
|
+
assertEqual(orderTimestampBytes(t5, t5), 0);
|
|
350
|
+
|
|
351
|
+
const deps = testCreateDeps();
|
|
352
|
+
const randomMillis = new Set<Millis>();
|
|
353
|
+
for (let i = 0; i < 1000; i++) {
|
|
354
|
+
randomMillis.add(deps.randomLib.int(0, 10000) as Millis);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const sortedMillis = [...randomMillis].toSorted(orderNumber);
|
|
358
|
+
const sortedEncodedMillis = [...randomMillis]
|
|
359
|
+
.map((millis) => createTimestamp({ millis }))
|
|
360
|
+
.map(timestampToTimestampBytes)
|
|
361
|
+
.toSorted(orderTimestampBytes)
|
|
362
|
+
.map(decodeFromEncoded)
|
|
363
|
+
.map(({ millis }) => millis);
|
|
364
|
+
|
|
365
|
+
assertEqual(sortedEncodedMillis, sortedMillis);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
test("converts Timestamp to DateIso", () => {
|
|
370
|
+
assertEqual(
|
|
371
|
+
timestampToDateIso(createTimestamp()),
|
|
372
|
+
"1970-01-01T00:00:00.000Z",
|
|
373
|
+
);
|
|
374
|
+
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { bytesToHex } from "../
|
|
7
|
+
import { bytesToHex, hexToBytes } from "../Binary.ts";
|
|
8
8
|
import type { RandomBytesDep } from "../Crypto.ts";
|
|
9
9
|
import { createEqObject, eqNumber, eqString } from "../Eq.ts";
|
|
10
10
|
import { increment } from "../Number.ts";
|
|
@@ -99,6 +99,24 @@ export type NodeId = typeof NodeId.Output;
|
|
|
99
99
|
export const minNodeId = "0000000000000000" as NodeId;
|
|
100
100
|
export const maxNodeId = "ffffffffffffffff" as NodeId;
|
|
101
101
|
|
|
102
|
+
/** Binary representation of {@link NodeId}. */
|
|
103
|
+
export const NodeIdBytes = /*#__PURE__*/ brand(
|
|
104
|
+
"NodeIdBytes",
|
|
105
|
+
/*#__PURE__*/ length(8)(Uint8Array),
|
|
106
|
+
);
|
|
107
|
+
export type NodeIdBytes = typeof NodeIdBytes.Output;
|
|
108
|
+
|
|
109
|
+
/** Length of {@link NodeIdBytes}. */
|
|
110
|
+
export const nodeIdBytesLength = /*#__PURE__*/ NonNegativeInt.orThrow(8);
|
|
111
|
+
|
|
112
|
+
/** Converts {@link NodeId} to {@link NodeIdBytes}. */
|
|
113
|
+
export const nodeIdToNodeIdBytes = (nodeId: NodeId): NodeIdBytes =>
|
|
114
|
+
hexToBytes(nodeId) as NodeIdBytes;
|
|
115
|
+
|
|
116
|
+
/** Converts {@link NodeIdBytes} to {@link NodeId}. */
|
|
117
|
+
export const nodeIdBytesToNodeId = (nodeIdBytes: NodeIdBytes): NodeId =>
|
|
118
|
+
bytesToHex(nodeIdBytes) as NodeId;
|
|
119
|
+
|
|
102
120
|
/**
|
|
103
121
|
* Hybrid Logical Clock timestamp.
|
|
104
122
|
*
|
|
@@ -303,11 +321,8 @@ export const timestampToTimestampBytes = (
|
|
|
303
321
|
value[6] = (counter >> 8) & 0xff;
|
|
304
322
|
value[7] = counter & 0xff;
|
|
305
323
|
|
|
306
|
-
// Encode `nodeId`
|
|
307
|
-
|
|
308
|
-
const byte = parseInt(nodeId.slice(i * 2, i * 2 + 2), 16);
|
|
309
|
-
value[8 + i] = byte;
|
|
310
|
-
}
|
|
324
|
+
// Encode `nodeId` into the next 8 bytes.
|
|
325
|
+
value.set(nodeIdToNodeIdBytes(nodeId), 8);
|
|
311
326
|
|
|
312
327
|
return value as TimestampBytes;
|
|
313
328
|
};
|
|
@@ -328,10 +343,7 @@ export const timestampBytesToTimestamp = (
|
|
|
328
343
|
const counter = (timestamp[6] << 8) | timestamp[7];
|
|
329
344
|
|
|
330
345
|
// Decode `nodeId` from the last 8 bytes.
|
|
331
|
-
|
|
332
|
-
for (let i = 8; i < 16; i++) {
|
|
333
|
-
nodeId += timestamp[i].toString(16).padStart(2, "0");
|
|
334
|
-
}
|
|
346
|
+
const nodeId = nodeIdBytesToNodeId(timestamp.subarray(8) as NodeIdBytes);
|
|
335
347
|
|
|
336
348
|
return { millis: Number(millis), counter, nodeId } as Timestamp;
|
|
337
349
|
};
|
package/dist/src/Buffer.d.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Binary data handling and byte array utilities.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
import { NonNegativeInt } from "./Type.ts";
|
|
7
|
-
export { bytesToHex, bytesToUtf8, concatBytes, hexToBytes, utf8ToBytes, } from "@noble/ciphers/utils.js";
|
|
8
|
-
/**
|
|
9
|
-
* Custom error for {@link Buffer}-related failures like premature end of data.
|
|
10
|
-
* Provides better stack traces for debugging binary protocol issues.
|
|
11
|
-
*/
|
|
12
|
-
export declare class BufferError extends Error {
|
|
13
|
-
constructor(message: string);
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* A Buffer is a dynamic, resizable container for binary data, optimized for
|
|
17
|
-
* scenarios where the final size is unknown. It grows exponentially (doubling
|
|
18
|
-
* its capacity) to minimize memory reallocations and uses `subarray` for
|
|
19
|
-
* efficient, copy-free data access in methods like `unwrap` and `shift`.
|
|
20
|
-
*
|
|
21
|
-
* ## Recommended Usage
|
|
22
|
-
*
|
|
23
|
-
* Create as few Buffers as possible—typically one main Buffer for the final
|
|
24
|
-
* output. Temporary Buffers are allowed when necessary (e.g., for
|
|
25
|
-
* variable-length headers), but avoid excessive allocations. Buffers can be
|
|
26
|
-
* reused within functions by leveraging `reset` to clear contents while
|
|
27
|
-
* preserving capacity, or `truncate` to adjust the length to a specific size,
|
|
28
|
-
* reducing the need for new allocations. Pass Buffers to `encode*` functions to
|
|
29
|
-
* append serialized data and use `decode*` functions to extract data. Both
|
|
30
|
-
* `shift` and `shiftN` throw an {@link BufferError} with message "Buffer parse
|
|
31
|
-
* ended prematurely" on failure, as do higher-level `decode*` functions,
|
|
32
|
-
* providing stack traces for debugging instead of using {@link Result}. This
|
|
33
|
-
* avoids allocation overhead in success cases and leverages exceptions'
|
|
34
|
-
* diagnostic benefits.
|
|
35
|
-
*
|
|
36
|
-
* ### Example
|
|
37
|
-
*
|
|
38
|
-
* ```ts
|
|
39
|
-
* import {
|
|
40
|
-
* assert,
|
|
41
|
-
* assertEqual,
|
|
42
|
-
* assertErr,
|
|
43
|
-
* createBuffer,
|
|
44
|
-
* createIdFromString,
|
|
45
|
-
* IdBytes,
|
|
46
|
-
* idBytesToId,
|
|
47
|
-
* idBytesTypeValueLength,
|
|
48
|
-
* idToIdBytes,
|
|
49
|
-
* NonNegativeInt,
|
|
50
|
-
* trySync,
|
|
51
|
-
* } from "@evolu/common";
|
|
52
|
-
* import {
|
|
53
|
-
* decodeNonNegativeInt,
|
|
54
|
-
* encodeNonNegativeInt,
|
|
55
|
-
* } from "@evolu/common/local-first";
|
|
56
|
-
*
|
|
57
|
-
* const buffer = createBuffer();
|
|
58
|
-
* const id = createIdFromString("buffer-example");
|
|
59
|
-
* encodeNonNegativeInt(buffer, NonNegativeInt.orThrow(300));
|
|
60
|
-
* buffer.extend(idToIdBytes(id));
|
|
61
|
-
*
|
|
62
|
-
* const decoder = createBuffer(buffer.unwrap());
|
|
63
|
-
* assertEqual(decodeNonNegativeInt(decoder), 300);
|
|
64
|
-
* const decodedId = idBytesToId(
|
|
65
|
-
* IdBytes.orThrow(decoder.shiftN(idBytesTypeValueLength)),
|
|
66
|
-
* );
|
|
67
|
-
* assertEqual(decodedId, id);
|
|
68
|
-
* const result = trySync(() => decodeNonNegativeInt(decoder));
|
|
69
|
-
* assertErr(result);
|
|
70
|
-
* assert(
|
|
71
|
-
* result.error instanceof Error &&
|
|
72
|
-
* result.error.message === "Buffer parse ended prematurely",
|
|
73
|
-
* "Expected the premature-buffer-end error.",
|
|
74
|
-
* );
|
|
75
|
-
* ```
|
|
76
|
-
*
|
|
77
|
-
* For more on exponential growth, see:
|
|
78
|
-
* https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially
|
|
79
|
-
*/
|
|
80
|
-
export interface Buffer {
|
|
81
|
-
/** Returns the current capacity of the buffer. */
|
|
82
|
-
getCapacity: () => NonNegativeInt;
|
|
83
|
-
/** Returns the current number of bytes stored in the buffer. */
|
|
84
|
-
getLength: () => NonNegativeInt;
|
|
85
|
-
/**
|
|
86
|
-
* Appends binary data to the buffer, resizing if necessary. Throws if
|
|
87
|
-
* `arg.length` is not a non-negative integer.
|
|
88
|
-
*/
|
|
89
|
-
extend: (arg: Uint8Array | ArrayLike<number>) => void;
|
|
90
|
-
/**
|
|
91
|
-
* Removes and returns the first byte. Throws an `Error` with message "Buffer
|
|
92
|
-
* parse ended prematurely" if the buffer is empty.
|
|
93
|
-
*/
|
|
94
|
-
shift: () => NonNegativeInt;
|
|
95
|
-
/**
|
|
96
|
-
* Removes and returns the first `n` bytes. Throws an `Error` with message
|
|
97
|
-
* "Buffer parse ended prematurely" if fewer than `n` bytes remain.
|
|
98
|
-
*/
|
|
99
|
-
shiftN: (n: NonNegativeInt) => Uint8Array;
|
|
100
|
-
/**
|
|
101
|
-
* Truncates the buffer to the specified length, discarding data from the end.
|
|
102
|
-
* Throws if the new length is greater than the current length.
|
|
103
|
-
*/
|
|
104
|
-
truncate: (length: NonNegativeInt) => void;
|
|
105
|
-
/**
|
|
106
|
-
* Resets the buffer to its initial empty state, preserving its capacity.
|
|
107
|
-
*
|
|
108
|
-
* This allows efficient buffer reuse without reallocating memory. Use this
|
|
109
|
-
* when you want to clear the buffer and write new data, avoiding unnecessary
|
|
110
|
-
* allocations.
|
|
111
|
-
*/
|
|
112
|
-
reset: () => void;
|
|
113
|
-
/**
|
|
114
|
-
* Returns a view of the buffer’s current data. Do not modify this array, as
|
|
115
|
-
* it directly alters the buffer’s internal state, potentially breaking
|
|
116
|
-
* subsequent operations.
|
|
117
|
-
*/
|
|
118
|
-
unwrap: () => Uint8Array;
|
|
119
|
-
}
|
|
120
|
-
/** Creates a {@link Buffer} for efficient byte operations. */
|
|
121
|
-
export declare const createBuffer: (arrayLike?: Uint8Array | ArrayLike<number>) => Buffer;
|
|
122
|
-
//# sourceMappingURL=Buffer.d.ts.map
|
package/dist/src/Buffer.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Buffer.d.ts","sourceRoot":"","sources":["../../src/Buffer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAsB,MAAM,WAAW,CAAC;AAC/D,OAAO,EACL,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,GACZ,MAAM,yBAAyB,CAAC;AAEjC;;;GAGG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAO,EAAE,MAAM,EAK1B;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AACH,MAAM,WAAW,MAAM;IACrB,kDAAkD;IAClD,WAAW,EAAE,MAAM,cAAc,CAAC;IAElC,gEAAgE;IAChE,SAAS,EAAE,MAAM,cAAc,CAAC;IAEhC;;;OAGG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAEtD;;;OAGG;IACH,KAAK,EAAE,MAAM,cAAc,CAAC;IAE5B;;;OAGG;IACH,MAAM,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,UAAU,CAAC;IAE1C;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAE3C;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB;;;;OAIG;IACH,MAAM,EAAE,MAAM,UAAU,CAAC;CAC1B;AAED,8DAA8D;AAC9D,eAAO,MAAM,YAAY,eACX,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,KACzC,MA4DF,CAAC"}
|
package/dist/src/Buffer.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Binary data handling and byte array utilities.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
import { NonNegativeInt, zeroNonNegativeInt } from "./Type.js";
|
|
7
|
-
export { bytesToHex, bytesToUtf8, concatBytes, hexToBytes, utf8ToBytes, } from "@noble/ciphers/utils.js";
|
|
8
|
-
/**
|
|
9
|
-
* Custom error for {@link Buffer}-related failures like premature end of data.
|
|
10
|
-
* Provides better stack traces for debugging binary protocol issues.
|
|
11
|
-
*/
|
|
12
|
-
export class BufferError extends Error {
|
|
13
|
-
constructor(message) {
|
|
14
|
-
super(message);
|
|
15
|
-
this.name = this.constructor.name;
|
|
16
|
-
Error.captureStackTrace(this, this.constructor);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
/** Creates a {@link Buffer} for efficient byte operations. */
|
|
20
|
-
export const createBuffer = (arrayLike) => {
|
|
21
|
-
let value = arrayLike
|
|
22
|
-
? new globalThis.Uint8Array(arrayLike)
|
|
23
|
-
: new globalThis.Uint8Array(512);
|
|
24
|
-
let length = NonNegativeInt.orThrow(arrayLike ? arrayLike.length : 0);
|
|
25
|
-
const buffer = {
|
|
26
|
-
getCapacity: () => NonNegativeInt.orThrow(value.length),
|
|
27
|
-
getLength: () => length,
|
|
28
|
-
extend: (arg) => {
|
|
29
|
-
const targetSize = length + arg.length;
|
|
30
|
-
if (value.length < targetSize) {
|
|
31
|
-
const oldValue = value;
|
|
32
|
-
const newCapacity = Math.max(value.length * 2, targetSize);
|
|
33
|
-
value = new globalThis.Uint8Array(newCapacity);
|
|
34
|
-
value.set(oldValue);
|
|
35
|
-
}
|
|
36
|
-
value.set(arg, length);
|
|
37
|
-
length = NonNegativeInt.orThrow(length + arg.length);
|
|
38
|
-
},
|
|
39
|
-
shift: () => {
|
|
40
|
-
if (length === 0) {
|
|
41
|
-
throw new BufferError("Buffer parse ended prematurely");
|
|
42
|
-
}
|
|
43
|
-
const first = value[0];
|
|
44
|
-
value = value.subarray(1);
|
|
45
|
-
length--;
|
|
46
|
-
return NonNegativeInt.orThrow(first);
|
|
47
|
-
},
|
|
48
|
-
shiftN: (n) => {
|
|
49
|
-
if (length < n) {
|
|
50
|
-
throw new BufferError("Buffer parse ended prematurely");
|
|
51
|
-
}
|
|
52
|
-
const subarray = value.subarray(0, n);
|
|
53
|
-
value = value.subarray(n);
|
|
54
|
-
length = NonNegativeInt.orThrow(length - n);
|
|
55
|
-
return subarray;
|
|
56
|
-
},
|
|
57
|
-
truncate: (newLength) => {
|
|
58
|
-
if (newLength > length) {
|
|
59
|
-
throw new BufferError("Cannot truncate to a length greater than current");
|
|
60
|
-
}
|
|
61
|
-
length = newLength;
|
|
62
|
-
},
|
|
63
|
-
reset: () => {
|
|
64
|
-
length = zeroNonNegativeInt;
|
|
65
|
-
},
|
|
66
|
-
unwrap: () => value.subarray(0, length),
|
|
67
|
-
};
|
|
68
|
-
return buffer;
|
|
69
|
-
};
|