@evolu/common 8.7.0 → 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/{Buffer.d.ts → Binary.d.ts} +85 -12
- package/dist/src/Binary.d.ts.map +1 -0
- package/dist/src/{Buffer.js → Binary.js} +206 -24
- 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 +14 -76
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +29 -206
- 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 -4
- 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/{Buffer.ts → Binary.ts} +273 -46
- 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 +58 -261
- 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.map +0 -1
|
@@ -180,18 +180,31 @@ import {
|
|
|
180
180
|
isNonEmptyArray,
|
|
181
181
|
type NonEmptyReadonlyArray,
|
|
182
182
|
} from "../Array.ts";
|
|
183
|
-
import {
|
|
183
|
+
import {
|
|
184
|
+
assert,
|
|
185
|
+
assertNonNullable,
|
|
186
|
+
assertNotUndefined,
|
|
187
|
+
assertSame,
|
|
188
|
+
} from "../Assert.ts";
|
|
184
189
|
import type { Brand } from "../Brand.ts";
|
|
185
190
|
import {
|
|
186
191
|
type Buffer,
|
|
187
|
-
bytesToHex,
|
|
188
|
-
bytesToUtf8,
|
|
189
192
|
createBuffer,
|
|
193
|
+
createRunLengthEncoder,
|
|
194
|
+
decodeFlags,
|
|
190
195
|
decodeJsonValue,
|
|
196
|
+
decodeLength,
|
|
197
|
+
decodeNonNegativeInt,
|
|
198
|
+
decodeNumber,
|
|
199
|
+
decodeRle,
|
|
200
|
+
decodeString,
|
|
201
|
+
encodeFlags,
|
|
191
202
|
encodeJsonValue,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
203
|
+
encodeLength,
|
|
204
|
+
encodeNonNegativeInt,
|
|
205
|
+
encodeNumber,
|
|
206
|
+
encodeString,
|
|
207
|
+
} from "../Binary.ts";
|
|
195
208
|
import type { ConsoleDep } from "../Console.ts";
|
|
196
209
|
import {
|
|
197
210
|
createPadmePadding,
|
|
@@ -208,10 +221,11 @@ import { eqArrayNumber } from "../Eq.ts";
|
|
|
208
221
|
import { computeBalancedBuckets } from "../Number.ts";
|
|
209
222
|
import { createMutableRecord, objectToEntries } from "../Object.ts";
|
|
210
223
|
import { err, ok, type Result } from "../Result.ts";
|
|
211
|
-
import { SqliteValue } from "../Sqlite.ts";
|
|
224
|
+
import type { SqliteValue } from "../Sqlite.ts";
|
|
212
225
|
import { AbortError, type Task } from "../Task.ts";
|
|
213
226
|
import { Millis } from "../Time.ts";
|
|
214
227
|
import {
|
|
228
|
+
assertType,
|
|
215
229
|
Base64Url,
|
|
216
230
|
base64UrlToUint8Array,
|
|
217
231
|
between,
|
|
@@ -263,6 +277,10 @@ import {
|
|
|
263
277
|
Counter,
|
|
264
278
|
eqTimestamp,
|
|
265
279
|
NodeId,
|
|
280
|
+
type NodeIdBytes,
|
|
281
|
+
nodeIdBytesLength,
|
|
282
|
+
nodeIdBytesToNodeId,
|
|
283
|
+
nodeIdToNodeIdBytes,
|
|
266
284
|
Timestamp,
|
|
267
285
|
TimestampBytes,
|
|
268
286
|
timestampBytesLength,
|
|
@@ -270,8 +288,6 @@ import {
|
|
|
270
288
|
timestampToTimestampBytes,
|
|
271
289
|
} from "./Timestamp.ts";
|
|
272
290
|
|
|
273
|
-
const jsonBuffer = createBuffer();
|
|
274
|
-
|
|
275
291
|
const minProtocolMessageMaxSize = 1_000_000;
|
|
276
292
|
const maxProtocolMessageMaxSize = 100_000_000;
|
|
277
293
|
|
|
@@ -427,7 +443,7 @@ export interface ProtocolVersionError
|
|
|
427
443
|
|
|
428
444
|
/** Error for invalid or corrupted protocol message data. */
|
|
429
445
|
export interface ProtocolInvalidDataError extends Typed<"ProtocolInvalidDataError"> {
|
|
430
|
-
readonly data:
|
|
446
|
+
readonly data: Uint8Array;
|
|
431
447
|
readonly error: unknown;
|
|
432
448
|
}
|
|
433
449
|
|
|
@@ -836,13 +852,13 @@ export const createTimestampsBuffer = (): TimestampsBuffer => {
|
|
|
836
852
|
encodeNonNegativeInt(buffer, value);
|
|
837
853
|
});
|
|
838
854
|
const nodeIdEncoder = createRunLengthEncoder<NodeId>((buffer, value) => {
|
|
839
|
-
|
|
855
|
+
buffer.extend(nodeIdToNodeIdBytes(value));
|
|
840
856
|
});
|
|
841
857
|
|
|
842
858
|
return {
|
|
843
859
|
add: (timestamp) => {
|
|
844
860
|
const delta = timestamp.millis - previousMillis;
|
|
845
|
-
|
|
861
|
+
assertType(NonNegativeInt, delta);
|
|
846
862
|
|
|
847
863
|
count++;
|
|
848
864
|
syncCount();
|
|
@@ -876,40 +892,6 @@ export const createTimestampsBuffer = (): TimestampsBuffer => {
|
|
|
876
892
|
};
|
|
877
893
|
};
|
|
878
894
|
|
|
879
|
-
interface RunLengthEncoder<T> {
|
|
880
|
-
add: (value: T) => void;
|
|
881
|
-
getLength: () => NonNegativeInt;
|
|
882
|
-
unwrap: () => Uint8Array;
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
const createRunLengthEncoder = <T>(
|
|
886
|
-
encodeValue: (buffer: Buffer, value: T) => void,
|
|
887
|
-
): RunLengthEncoder<T> => {
|
|
888
|
-
const buffer = createBuffer();
|
|
889
|
-
let previousLength = zeroNonNegativeInt;
|
|
890
|
-
let previousValue = null as T | null;
|
|
891
|
-
let runLength = zeroNonNegativeInt;
|
|
892
|
-
|
|
893
|
-
return {
|
|
894
|
-
add: (value) => {
|
|
895
|
-
if (value === previousValue) {
|
|
896
|
-
runLength++;
|
|
897
|
-
buffer.truncate(previousLength);
|
|
898
|
-
} else {
|
|
899
|
-
previousValue = value;
|
|
900
|
-
runLength = NonNegativeInt.orThrow(1);
|
|
901
|
-
}
|
|
902
|
-
previousLength = buffer.getLength();
|
|
903
|
-
encodeValue(buffer, value);
|
|
904
|
-
encodeNonNegativeInt(buffer, runLength);
|
|
905
|
-
},
|
|
906
|
-
|
|
907
|
-
getLength: () => buffer.getLength(),
|
|
908
|
-
|
|
909
|
-
unwrap: () => buffer.unwrap(),
|
|
910
|
-
};
|
|
911
|
-
};
|
|
912
|
-
|
|
913
895
|
export interface ApplyProtocolMessageAsClientOptions {
|
|
914
896
|
writeKey?: OwnerWriteKey;
|
|
915
897
|
|
|
@@ -1123,7 +1105,7 @@ export const applyProtocolMessageAsRelay =
|
|
|
1123
1105
|
}
|
|
1124
1106
|
|
|
1125
1107
|
const messageType = input.shift() as MessageType;
|
|
1126
|
-
|
|
1108
|
+
assertSame(messageType, MessageType.Request);
|
|
1127
1109
|
|
|
1128
1110
|
const hasWriteKey = input.shift();
|
|
1129
1111
|
let writeKey: OwnerWriteKey | undefined;
|
|
@@ -1715,7 +1697,9 @@ const decodeTimestamps = (
|
|
|
1715
1697
|
return counter.value;
|
|
1716
1698
|
});
|
|
1717
1699
|
|
|
1718
|
-
const nodeIds = decodeRle(buffer, length, (): NodeId =>
|
|
1700
|
+
const nodeIds = decodeRle(buffer, length, (): NodeId =>
|
|
1701
|
+
nodeIdBytesToNodeId(buffer.shiftN(nodeIdBytesLength) as NodeIdBytes),
|
|
1702
|
+
);
|
|
1719
1703
|
|
|
1720
1704
|
const timestamps = createMutableArray<Timestamp>(length);
|
|
1721
1705
|
for (let i = 0; i < length; i++) {
|
|
@@ -1729,118 +1713,11 @@ const decodeTimestamps = (
|
|
|
1729
1713
|
return timestamps;
|
|
1730
1714
|
};
|
|
1731
1715
|
|
|
1732
|
-
export const decodeRle = <T>(
|
|
1733
|
-
buffer: Buffer,
|
|
1734
|
-
length: NonNegativeInt,
|
|
1735
|
-
decodeValue: () => T,
|
|
1736
|
-
): ReadonlyArray<T> => {
|
|
1737
|
-
const values = createMutableArray<T>(length);
|
|
1738
|
-
let index = 0;
|
|
1739
|
-
while (index < length) {
|
|
1740
|
-
const value = decodeValue();
|
|
1741
|
-
const runLength = decodeNonNegativeInt(buffer);
|
|
1742
|
-
|
|
1743
|
-
// Prevent infinite loop on malformed input.
|
|
1744
|
-
if (runLength === 0) {
|
|
1745
|
-
throw new ProtocolDecodeError(
|
|
1746
|
-
"Invalid RLE encoding: runLength must be positive",
|
|
1747
|
-
);
|
|
1748
|
-
}
|
|
1749
|
-
const remaining = length - index;
|
|
1750
|
-
|
|
1751
|
-
// Prevent CPU/memory amplification via oversized runLength.
|
|
1752
|
-
if (runLength > remaining) {
|
|
1753
|
-
throw new ProtocolDecodeError(
|
|
1754
|
-
`Invalid RLE encoding: runLength ${runLength} exceeds remaining ${remaining}`,
|
|
1755
|
-
);
|
|
1756
|
-
}
|
|
1757
|
-
for (let i = 0; i < runLength; i++) {
|
|
1758
|
-
values[index] = value;
|
|
1759
|
-
index++;
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
return values;
|
|
1763
|
-
};
|
|
1764
|
-
|
|
1765
1716
|
const decodeId = (buffer: Buffer): Id => {
|
|
1766
1717
|
const bytes = buffer.shiftN(idBytesTypeValueLength);
|
|
1767
1718
|
return idBytesToId(bytes as IdBytes);
|
|
1768
1719
|
};
|
|
1769
1720
|
|
|
1770
|
-
/**
|
|
1771
|
-
* Evolu uses MessagePack to handle finite numbers except for NonNegativeInt.
|
|
1772
|
-
* For NonNegativeInt, Evolu provides more efficient encoding.
|
|
1773
|
-
*/
|
|
1774
|
-
export const encodeNumber = (buffer: Buffer, number: FiniteNumber): void => {
|
|
1775
|
-
encodeJsonValue(buffer, number);
|
|
1776
|
-
};
|
|
1777
|
-
|
|
1778
|
-
export const decodeNumber = (buffer: Buffer): FiniteNumber => {
|
|
1779
|
-
const numberResult = FiniteNumber.fromUnknown(decodeJsonValue(buffer));
|
|
1780
|
-
if (!numberResult.ok) throw new ProtocolDecodeError(numberResult.error.type);
|
|
1781
|
-
return numberResult.value;
|
|
1782
|
-
};
|
|
1783
|
-
|
|
1784
|
-
/**
|
|
1785
|
-
* Encodes an array of boolean flags into a single byte.
|
|
1786
|
-
*
|
|
1787
|
-
* Each element in the array corresponds to a bit (0-7). Array can have 0-8
|
|
1788
|
-
* elements.
|
|
1789
|
-
*
|
|
1790
|
-
* ### Example
|
|
1791
|
-
*
|
|
1792
|
-
* ```ts
|
|
1793
|
-
* import { assertEqual, createBuffer } from "@evolu/common";
|
|
1794
|
-
* import { encodeFlags } from "@evolu/common/local-first";
|
|
1795
|
-
*
|
|
1796
|
-
* const buffer = createBuffer();
|
|
1797
|
-
* encodeFlags(buffer, [true, false, true]);
|
|
1798
|
-
*
|
|
1799
|
-
* assertEqual(buffer.unwrap(), new Uint8Array([0b101]));
|
|
1800
|
-
* ```
|
|
1801
|
-
*/
|
|
1802
|
-
export const encodeFlags = (
|
|
1803
|
-
buffer: Buffer,
|
|
1804
|
-
flags: ReadonlyArray<boolean>,
|
|
1805
|
-
): void => {
|
|
1806
|
-
let byte = 0;
|
|
1807
|
-
for (let i = 0; i < flags.length && i < 8; i++) {
|
|
1808
|
-
if (flags[i]) {
|
|
1809
|
-
byte |= 1 << i;
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
buffer.extend([byte]);
|
|
1813
|
-
};
|
|
1814
|
-
|
|
1815
|
-
/**
|
|
1816
|
-
* Decodes a byte into an array of boolean flags.
|
|
1817
|
-
*
|
|
1818
|
-
* ### Example
|
|
1819
|
-
*
|
|
1820
|
-
* ```ts
|
|
1821
|
-
* import { assertEqual, createBuffer, PositiveInt } from "@evolu/common";
|
|
1822
|
-
* import { decodeFlags } from "@evolu/common/local-first";
|
|
1823
|
-
*
|
|
1824
|
-
* const buffer = createBuffer([0b101]);
|
|
1825
|
-
* const flags = decodeFlags(buffer, PositiveInt.orThrow(3));
|
|
1826
|
-
*
|
|
1827
|
-
* assertEqual(flags, [true, false, true]);
|
|
1828
|
-
* assertEqual(buffer.getLength(), 0);
|
|
1829
|
-
* ```
|
|
1830
|
-
*/
|
|
1831
|
-
export const decodeFlags = (
|
|
1832
|
-
buffer: Buffer,
|
|
1833
|
-
count: PositiveInt,
|
|
1834
|
-
): ReadonlyArray<boolean> => {
|
|
1835
|
-
const byte = buffer.shift();
|
|
1836
|
-
const length = globalThis.Math.min(count, 8);
|
|
1837
|
-
const flags = createMutableArray<boolean>(length);
|
|
1838
|
-
for (let i = 0; i < length; i++) {
|
|
1839
|
-
flags[i] = (byte & (1 << i)) !== 0;
|
|
1840
|
-
}
|
|
1841
|
-
return flags;
|
|
1842
|
-
};
|
|
1843
|
-
|
|
1844
1721
|
/**
|
|
1845
1722
|
* Encodes and encrypts a {@link DbChange} using the provided owner's encryption
|
|
1846
1723
|
* key. Returns an encrypted binary representation as {@link EncryptedDbChange}.
|
|
@@ -1972,91 +1849,30 @@ export const decryptAndDecodeDbChange = (
|
|
|
1972
1849
|
};
|
|
1973
1850
|
|
|
1974
1851
|
/**
|
|
1975
|
-
*
|
|
1976
|
-
* more efficient than encoding via {@link encodeNumber}.
|
|
1852
|
+
* Decodes a ProtocolMessage into a readable JSON object for debugging.
|
|
1977
1853
|
*
|
|
1978
|
-
*
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
if (int === 0) {
|
|
1985
|
-
buffer.extend([0]);
|
|
1986
|
-
return;
|
|
1987
|
-
}
|
|
1988
|
-
|
|
1989
|
-
let remaining = BigInt(int);
|
|
1990
|
-
const bytes: Array<number> = [];
|
|
1991
|
-
|
|
1992
|
-
while (remaining !== 0n) {
|
|
1993
|
-
const byte = globalThis.Number(remaining & 127n);
|
|
1994
|
-
bytes.push(byte);
|
|
1995
|
-
remaining >>= 7n;
|
|
1996
|
-
}
|
|
1997
|
-
|
|
1998
|
-
for (let i = 0; i < bytes.length - 1; i++) {
|
|
1999
|
-
bytes[i] |= 128;
|
|
2000
|
-
}
|
|
2001
|
-
|
|
2002
|
-
buffer.extend(bytes);
|
|
2003
|
-
};
|
|
2004
|
-
|
|
2005
|
-
/**
|
|
2006
|
-
* Decodes a non-negative integer from a variable-length integer format.
|
|
1854
|
+
* Note: This is a stub for future implementation. It should use:
|
|
1855
|
+
*
|
|
1856
|
+
* - DecodeVersionAndOwner
|
|
1857
|
+
* - DecodeError or decodeWriteKeys (depending on context)
|
|
1858
|
+
* - DecodeMessages
|
|
1859
|
+
* - DecodeRanges
|
|
2007
1860
|
*
|
|
2008
|
-
*
|
|
1861
|
+
* If you want to help, please contribute to this function.
|
|
2009
1862
|
*/
|
|
2010
|
-
export const
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
//
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
shift += 7n;
|
|
2021
|
-
}
|
|
2022
|
-
|
|
2023
|
-
const int = NonNegativeInt.fromUnknown(globalThis.Number(result));
|
|
2024
|
-
if (!int.ok) throw new ProtocolDecodeError(int.error.type);
|
|
2025
|
-
|
|
2026
|
-
return int.value;
|
|
2027
|
-
};
|
|
2028
|
-
|
|
2029
|
-
export const encodeLength = (buffer: Buffer, value: ArrayLike<any>): void => {
|
|
2030
|
-
encodeNonNegativeInt(buffer, NonNegativeInt.orThrow(value.length));
|
|
2031
|
-
};
|
|
2032
|
-
|
|
2033
|
-
export const decodeLength = decodeNonNegativeInt;
|
|
2034
|
-
|
|
2035
|
-
export const encodeString = (buffer: Buffer, value: string): void => {
|
|
2036
|
-
const bytes = utf8ToBytes(value);
|
|
2037
|
-
encodeLength(buffer, bytes);
|
|
2038
|
-
buffer.extend(bytes);
|
|
2039
|
-
};
|
|
2040
|
-
|
|
2041
|
-
export const decodeString = (buffer: Buffer): string => {
|
|
2042
|
-
const length = decodeLength(buffer);
|
|
2043
|
-
const bytes = buffer.shiftN(length);
|
|
2044
|
-
return bytesToUtf8(bytes);
|
|
2045
|
-
};
|
|
2046
|
-
|
|
2047
|
-
export const encodeNodeId = (buffer: Buffer, nodeId: NodeId): void => {
|
|
2048
|
-
buffer.extend(hexToBytes(nodeId));
|
|
2049
|
-
};
|
|
2050
|
-
|
|
2051
|
-
export const decodeNodeId = (buffer: Buffer): NodeId => {
|
|
2052
|
-
const bytes = buffer.shiftN(NonNegativeInt.orThrow(8));
|
|
2053
|
-
return bytesToHex(bytes) as NodeId;
|
|
1863
|
+
export const decodeProtocolMessageToJson = (
|
|
1864
|
+
_protocolMessage: ProtocolMessage,
|
|
1865
|
+
_isInitiator: boolean,
|
|
1866
|
+
): unknown => {
|
|
1867
|
+
// TODO: Implement using
|
|
1868
|
+
// - decodeVersionAndOwner
|
|
1869
|
+
// -- decodeError or decodeWriteKeys (should be refactored out),
|
|
1870
|
+
// -- decodeMessages, and decodeRanges.
|
|
1871
|
+
// This is a stub for PRs and community contributions.
|
|
1872
|
+
throw new Error("decodeProtocolMessageToJson is not implemented yet.");
|
|
2054
1873
|
};
|
|
2055
1874
|
|
|
2056
1875
|
// Small ints are encoded into ProtocolValueType, saving one byte per int.
|
|
2057
|
-
const isSmallInt: Predicate<number> = (value: number) =>
|
|
2058
|
-
value >= 0 && value < 20;
|
|
2059
|
-
|
|
2060
1876
|
export const ProtocolValueType = {
|
|
2061
1877
|
// 0-19 small ints
|
|
2062
1878
|
|
|
@@ -2163,7 +1979,7 @@ export const encodeSqliteValue = (buffer: Buffer, value: SqliteValue): void => {
|
|
|
2163
1979
|
case "number": {
|
|
2164
1980
|
// Negative zero is a non-negative integer in JavaScript, but integer
|
|
2165
1981
|
// encoding would lose its observable sign.
|
|
2166
|
-
if (!
|
|
1982
|
+
if (!Object.is(value, -0) && NonNegativeInt.is(value)) {
|
|
2167
1983
|
if (isSmallInt(value)) {
|
|
2168
1984
|
encodeNonNegativeInt(buffer, value);
|
|
2169
1985
|
return;
|
|
@@ -2213,9 +2029,9 @@ export const decodeSqliteValue = (buffer: Buffer): SqliteValue => {
|
|
|
2213
2029
|
|
|
2214
2030
|
case ProtocolValueType.Json: {
|
|
2215
2031
|
const length = decodeLength(buffer);
|
|
2216
|
-
const
|
|
2217
|
-
const value = decodeJsonValue(
|
|
2218
|
-
if (
|
|
2032
|
+
const jsonValueBuffer = createBuffer(buffer.shiftN(length));
|
|
2033
|
+
const value = decodeJsonValue(jsonValueBuffer);
|
|
2034
|
+
if (jsonValueBuffer.getLength() !== 0) {
|
|
2219
2035
|
throw new ProtocolDecodeError("Invalid JSON MessagePack length");
|
|
2220
2036
|
}
|
|
2221
2037
|
return JSON.stringify(value);
|
|
@@ -2246,26 +2062,7 @@ export const decodeSqliteValue = (buffer: Buffer): SqliteValue => {
|
|
|
2246
2062
|
}
|
|
2247
2063
|
};
|
|
2248
2064
|
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
*
|
|
2254
|
-
* - DecodeVersionAndOwner
|
|
2255
|
-
* - DecodeError or decodeWriteKeys (depending on context)
|
|
2256
|
-
* - DecodeMessages
|
|
2257
|
-
* - DecodeRanges
|
|
2258
|
-
*
|
|
2259
|
-
* If you want to help, please contribute to this function.
|
|
2260
|
-
*/
|
|
2261
|
-
export const decodeProtocolMessageToJson = (
|
|
2262
|
-
_protocolMessage: ProtocolMessage,
|
|
2263
|
-
_isInitiator: boolean,
|
|
2264
|
-
): unknown => {
|
|
2265
|
-
// TODO: Implement using
|
|
2266
|
-
// - decodeVersionAndOwner
|
|
2267
|
-
// -- decodeError or decodeWriteKeys (should be refactored out),
|
|
2268
|
-
// -- decodeMessages, and decodeRanges.
|
|
2269
|
-
// This is a stub for PRs and community contributions.
|
|
2270
|
-
throw new Error("decodeProtocolMessageToJson is not implemented yet.");
|
|
2271
|
-
};
|
|
2065
|
+
const jsonBuffer = createBuffer();
|
|
2066
|
+
|
|
2067
|
+
const isSmallInt: Predicate<number> = (value: number) =>
|
|
2068
|
+
value >= 0 && value < 20;
|