@evolu/common 8.6.2 → 8.7.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/Buffer.d.ts +67 -8
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Buffer.js +722 -15
- package/dist/src/local-first/Protocol.d.ts +14 -0
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +24 -31
- package/package.json +1 -2
- package/src/Buffer.ts +966 -22
- package/src/local-first/Protocol.ts +24 -36
|
@@ -170,14 +170,11 @@
|
|
|
170
170
|
* initiator/non-initiator terminology instead, and consolidate into a single
|
|
171
171
|
* `applyProtocolMessage` function with conditional arguments to reduce code
|
|
172
172
|
* duplication.
|
|
173
|
-
* - Replace try-catch with Result + new Error (to preserve stacktraces). Measure
|
|
174
|
-
* Result overhead, it should be super small.
|
|
175
173
|
* - Allow clients to broadcast messages that are not persisted by relays. This
|
|
176
174
|
* would enable real-time ephemeral data (like cursor positions, typing
|
|
177
175
|
* indicators) to be forwarded by relays without storage overhead.
|
|
178
176
|
*/
|
|
179
177
|
|
|
180
|
-
import { Packr } from "msgpackr";
|
|
181
178
|
import {
|
|
182
179
|
createMutableArray,
|
|
183
180
|
isNonEmptyArray,
|
|
@@ -190,6 +187,8 @@ import {
|
|
|
190
187
|
bytesToHex,
|
|
191
188
|
bytesToUtf8,
|
|
192
189
|
createBuffer,
|
|
190
|
+
decodeJsonValue,
|
|
191
|
+
encodeJsonValue,
|
|
193
192
|
hexToBytes,
|
|
194
193
|
utf8ToBytes,
|
|
195
194
|
} from "../Buffer.ts";
|
|
@@ -271,13 +270,7 @@ import {
|
|
|
271
270
|
timestampToTimestampBytes,
|
|
272
271
|
} from "./Timestamp.ts";
|
|
273
272
|
|
|
274
|
-
|
|
275
|
-
* Evolu uses MessagePack for numbers and JSONs.
|
|
276
|
-
*
|
|
277
|
-
* - `variableMapSize: true` - More compact maps, ~5-10% slower encoding
|
|
278
|
-
* - `useRecords: false` - Standard MessagePack without extensions
|
|
279
|
-
*/
|
|
280
|
-
const packr = new Packr({ variableMapSize: true, useRecords: false });
|
|
273
|
+
const jsonBuffer = createBuffer();
|
|
281
274
|
|
|
282
275
|
const minProtocolMessageMaxSize = 1_000_000;
|
|
283
276
|
const maxProtocolMessageMaxSize = 100_000_000;
|
|
@@ -1779,29 +1772,12 @@ const decodeId = (buffer: Buffer): Id => {
|
|
|
1779
1772
|
* For NonNegativeInt, Evolu provides more efficient encoding.
|
|
1780
1773
|
*/
|
|
1781
1774
|
export const encodeNumber = (buffer: Buffer, number: FiniteNumber): void => {
|
|
1782
|
-
buffer
|
|
1775
|
+
encodeJsonValue(buffer, number);
|
|
1783
1776
|
};
|
|
1784
1777
|
|
|
1785
1778
|
export const decodeNumber = (buffer: Buffer): FiniteNumber => {
|
|
1786
|
-
|
|
1787
|
-
let end: unknown;
|
|
1788
|
-
|
|
1789
|
-
packr.unpackMultiple(
|
|
1790
|
-
buffer.unwrap(),
|
|
1791
|
-
(n: unknown, _: unknown, e: unknown) => {
|
|
1792
|
-
number = n;
|
|
1793
|
-
end = e;
|
|
1794
|
-
return false;
|
|
1795
|
-
},
|
|
1796
|
-
);
|
|
1797
|
-
|
|
1798
|
-
const endResult = NonNegativeInt.fromUnknown(end);
|
|
1799
|
-
if (!endResult.ok) throw new ProtocolDecodeError(endResult.error.type);
|
|
1800
|
-
|
|
1801
|
-
const numberResult = FiniteNumber.fromUnknown(number);
|
|
1779
|
+
const numberResult = FiniteNumber.fromUnknown(decodeJsonValue(buffer));
|
|
1802
1780
|
if (!numberResult.ok) throw new ProtocolDecodeError(numberResult.error.type);
|
|
1803
|
-
|
|
1804
|
-
buffer.shiftN(endResult.value);
|
|
1805
1781
|
return numberResult.value;
|
|
1806
1782
|
};
|
|
1807
1783
|
|
|
@@ -2157,10 +2133,16 @@ export const encodeSqliteValue = (buffer: Buffer, value: SqliteValue): void => {
|
|
|
2157
2133
|
// Some valid JSON strings like "-0E0" get normalized to "0" during parsing,
|
|
2158
2134
|
// which would cause data corruption if we don't verify round-trip safety.
|
|
2159
2135
|
if (json.ok && JSON.stringify(jsonToJsonValue(json.value)) === value) {
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2136
|
+
jsonBuffer.reset();
|
|
2137
|
+
try {
|
|
2138
|
+
encodeJsonValue(jsonBuffer, jsonToJsonValue(json.value));
|
|
2139
|
+
const jsonBytes = jsonBuffer.unwrap();
|
|
2140
|
+
encodeNonNegativeInt(buffer, ProtocolValueType.Json);
|
|
2141
|
+
encodeLength(buffer, jsonBytes);
|
|
2142
|
+
buffer.extend(jsonBytes);
|
|
2143
|
+
} finally {
|
|
2144
|
+
jsonBuffer.reset();
|
|
2145
|
+
}
|
|
2164
2146
|
return;
|
|
2165
2147
|
}
|
|
2166
2148
|
|
|
@@ -2179,7 +2161,9 @@ export const encodeSqliteValue = (buffer: Buffer, value: SqliteValue): void => {
|
|
|
2179
2161
|
}
|
|
2180
2162
|
|
|
2181
2163
|
case "number": {
|
|
2182
|
-
|
|
2164
|
+
// Negative zero is a non-negative integer in JavaScript, but integer
|
|
2165
|
+
// encoding would lose its observable sign.
|
|
2166
|
+
if (!globalThis.Object.is(value, -0) && NonNegativeInt.is(value)) {
|
|
2183
2167
|
if (isSmallInt(value)) {
|
|
2184
2168
|
encodeNonNegativeInt(buffer, value);
|
|
2185
2169
|
return;
|
|
@@ -2229,8 +2213,12 @@ export const decodeSqliteValue = (buffer: Buffer): SqliteValue => {
|
|
|
2229
2213
|
|
|
2230
2214
|
case ProtocolValueType.Json: {
|
|
2231
2215
|
const length = decodeLength(buffer);
|
|
2232
|
-
const
|
|
2233
|
-
|
|
2216
|
+
const lengthBeforeDecoding = buffer.getLength();
|
|
2217
|
+
const value = decodeJsonValue(buffer);
|
|
2218
|
+
if (lengthBeforeDecoding - buffer.getLength() !== length) {
|
|
2219
|
+
throw new ProtocolDecodeError("Invalid JSON MessagePack length");
|
|
2220
|
+
}
|
|
2221
|
+
return JSON.stringify(value);
|
|
2234
2222
|
}
|
|
2235
2223
|
|
|
2236
2224
|
case ProtocolValueType.DateIsoWithNonNegativeTime:
|