@syncular/core 0.1.2 → 0.2.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/README.md +5 -19
- package/dist/blob-ref.d.ts +21 -0
- package/dist/blob-ref.js +97 -0
- package/dist/bytes.d.ts +45 -0
- package/dist/bytes.js +242 -0
- package/dist/canonical-json.d.ts +10 -0
- package/dist/canonical-json.js +18 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +5 -0
- package/dist/crypto.d.ts +60 -0
- package/dist/crypto.js +251 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +17 -0
- package/dist/frames.d.ts +24 -0
- package/dist/frames.js +42 -0
- package/dist/index.d.ts +18 -26
- package/dist/index.js +18 -43
- package/dist/message.d.ts +157 -0
- package/dist/message.js +786 -0
- package/dist/realtime.d.ts +92 -0
- package/dist/realtime.js +222 -0
- package/dist/render.d.ts +22 -0
- package/dist/render.js +273 -0
- package/dist/row-codec.d.ts +39 -0
- package/dist/row-codec.js +176 -0
- package/dist/segment.d.ts +18 -0
- package/dist/segment.js +105 -0
- package/dist/stream.d.ts +20 -0
- package/dist/stream.js +102 -0
- package/package.json +7 -59
- package/src/blob-ref.ts +135 -0
- package/src/bytes.ts +301 -0
- package/src/canonical-json.ts +20 -0
- package/src/constants.ts +7 -0
- package/src/crypto.ts +335 -0
- package/src/errors.ts +18 -0
- package/src/frames.ts +47 -0
- package/src/index.ts +18 -43
- package/src/message.ts +1024 -0
- package/src/realtime.ts +340 -0
- package/src/render.ts +325 -0
- package/src/row-codec.ts +265 -0
- package/src/segment.ts +150 -0
- package/src/stream.ts +128 -0
- package/dist/blobs.d.ts +0 -153
- package/dist/blobs.d.ts.map +0 -1
- package/dist/blobs.js +0 -47
- package/dist/blobs.js.map +0 -1
- package/dist/column-codecs.d.ts +0 -59
- package/dist/column-codecs.d.ts.map +0 -1
- package/dist/column-codecs.js +0 -159
- package/dist/column-codecs.js.map +0 -1
- package/dist/conflict.d.ts +0 -22
- package/dist/conflict.d.ts.map +0 -1
- package/dist/conflict.js +0 -81
- package/dist/conflict.js.map +0 -1
- package/dist/database.d.ts +0 -7
- package/dist/database.d.ts.map +0 -1
- package/dist/database.js +0 -14
- package/dist/database.js.map +0 -1
- package/dist/dialect.d.ts +0 -7
- package/dist/dialect.d.ts.map +0 -1
- package/dist/dialect.js +0 -2
- package/dist/dialect.js.map +0 -1
- package/dist/error-responses.d.ts +0 -393
- package/dist/error-responses.d.ts.map +0 -1
- package/dist/error-responses.js +0 -393
- package/dist/error-responses.js.map +0 -1
- package/dist/http/api-client.d.ts +0 -11
- package/dist/http/api-client.d.ts.map +0 -1
- package/dist/http/api-client.js +0 -30
- package/dist/http/api-client.js.map +0 -1
- package/dist/http/blob.d.ts +0 -6
- package/dist/http/blob.d.ts.map +0 -1
- package/dist/http/blob.js +0 -46
- package/dist/http/blob.js.map +0 -1
- package/dist/http/generated/api.d.ts +0 -5241
- package/dist/http/generated/api.d.ts.map +0 -1
- package/dist/http/generated/api.js +0 -6
- package/dist/http/generated/api.js.map +0 -1
- package/dist/http/index.d.ts +0 -18
- package/dist/http/index.d.ts.map +0 -1
- package/dist/http/index.js +0 -212
- package/dist/http/index.js.map +0 -1
- package/dist/http/shared.d.ts +0 -45
- package/dist/http/shared.d.ts.map +0 -1
- package/dist/http/shared.js +0 -122
- package/dist/http/shared.js.map +0 -1
- package/dist/http/transport-client.d.ts +0 -31
- package/dist/http/transport-client.d.ts.map +0 -1
- package/dist/http/transport-client.js +0 -193
- package/dist/http/transport-client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/kysely-column-codecs.d.ts +0 -31
- package/dist/kysely-column-codecs.d.ts.map +0 -1
- package/dist/kysely-column-codecs.js +0 -452
- package/dist/kysely-column-codecs.js.map +0 -1
- package/dist/logger.d.ts +0 -29
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -26
- package/dist/logger.js.map +0 -1
- package/dist/proxy/index.d.ts +0 -54
- package/dist/proxy/index.d.ts.map +0 -1
- package/dist/proxy/index.js +0 -7
- package/dist/proxy/index.js.map +0 -1
- package/dist/schemas/blobs.d.ts +0 -82
- package/dist/schemas/blobs.d.ts.map +0 -1
- package/dist/schemas/blobs.js +0 -64
- package/dist/schemas/blobs.js.map +0 -1
- package/dist/schemas/common.d.ts +0 -100
- package/dist/schemas/common.d.ts.map +0 -1
- package/dist/schemas/common.js +0 -64
- package/dist/schemas/common.js.map +0 -1
- package/dist/schemas/index.d.ts +0 -7
- package/dist/schemas/index.d.ts.map +0 -1
- package/dist/schemas/index.js +0 -7
- package/dist/schemas/index.js.map +0 -1
- package/dist/schemas/sync.d.ts +0 -1065
- package/dist/schemas/sync.d.ts.map +0 -1
- package/dist/schemas/sync.js +0 -361
- package/dist/schemas/sync.js.map +0 -1
- package/dist/scopes/index.d.ts +0 -113
- package/dist/scopes/index.d.ts.map +0 -1
- package/dist/scopes/index.js +0 -103
- package/dist/scopes/index.js.map +0 -1
- package/dist/sentry.d.ts +0 -31
- package/dist/sentry.d.ts.map +0 -1
- package/dist/sentry.js +0 -147
- package/dist/sentry.js.map +0 -1
- package/dist/snapshot-chunks.d.ts +0 -110
- package/dist/snapshot-chunks.d.ts.map +0 -1
- package/dist/snapshot-chunks.js +0 -682
- package/dist/snapshot-chunks.js.map +0 -1
- package/dist/sync-packs.d.ts +0 -33
- package/dist/sync-packs.d.ts.map +0 -1
- package/dist/sync-packs.js +0 -821
- package/dist/sync-packs.js.map +0 -1
- package/dist/telemetry.d.ts +0 -114
- package/dist/telemetry.d.ts.map +0 -1
- package/dist/telemetry.js +0 -114
- package/dist/telemetry.js.map +0 -1
- package/dist/transforms.d.ts +0 -146
- package/dist/transforms.d.ts.map +0 -1
- package/dist/transforms.js +0 -155
- package/dist/transforms.js.map +0 -1
- package/dist/types.d.ts +0 -210
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -20
- package/dist/types.js.map +0 -1
- package/dist/utils/bytes.d.ts +0 -4
- package/dist/utils/bytes.d.ts.map +0 -1
- package/dist/utils/bytes.js +0 -66
- package/dist/utils/bytes.js.map +0 -1
- package/dist/utils/compression.d.ts +0 -22
- package/dist/utils/compression.d.ts.map +0 -1
- package/dist/utils/compression.js +0 -129
- package/dist/utils/compression.js.map +0 -1
- package/dist/utils/crypto.d.ts +0 -13
- package/dist/utils/crypto.d.ts.map +0 -1
- package/dist/utils/crypto.js +0 -107
- package/dist/utils/crypto.js.map +0 -1
- package/dist/utils/id.d.ts +0 -3
- package/dist/utils/id.d.ts.map +0 -1
- package/dist/utils/id.js +0 -25
- package/dist/utils/id.js.map +0 -1
- package/dist/utils/index.d.ts +0 -10
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -10
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/internal-runtime.d.ts +0 -16
- package/dist/utils/internal-runtime.d.ts.map +0 -1
- package/dist/utils/internal-runtime.js +0 -14
- package/dist/utils/internal-runtime.js.map +0 -1
- package/dist/utils/object.d.ts +0 -2
- package/dist/utils/object.d.ts.map +0 -1
- package/dist/utils/object.js +0 -4
- package/dist/utils/object.js.map +0 -1
- package/dist/utils/realtime-change-index.d.ts +0 -9
- package/dist/utils/realtime-change-index.d.ts.map +0 -1
- package/dist/utils/realtime-change-index.js +0 -36
- package/dist/utils/realtime-change-index.js.map +0 -1
- package/dist/utils/realtime-connection-registry.d.ts +0 -40
- package/dist/utils/realtime-connection-registry.d.ts.map +0 -1
- package/dist/utils/realtime-connection-registry.js +0 -237
- package/dist/utils/realtime-connection-registry.js.map +0 -1
- package/dist/utils/table-registry.d.ts +0 -10
- package/dist/utils/table-registry.d.ts.map +0 -1
- package/dist/utils/table-registry.js +0 -54
- package/dist/utils/table-registry.js.map +0 -1
- package/dist/utils/url.d.ts +0 -3
- package/dist/utils/url.d.ts.map +0 -1
- package/dist/utils/url.js +0 -20
- package/dist/utils/url.js.map +0 -1
- package/src/blobs.ts +0 -219
- package/src/column-codecs.ts +0 -262
- package/src/conflict.ts +0 -92
- package/src/database.ts +0 -21
- package/src/dialect.ts +0 -8
- package/src/error-responses.ts +0 -423
- package/src/http/api-client.ts +0 -39
- package/src/http/blob.ts +0 -95
- package/src/http/generated/api.ts +0 -5241
- package/src/http/index.ts +0 -365
- package/src/http/shared.ts +0 -220
- package/src/http/transport-client.ts +0 -314
- package/src/kysely-column-codecs.ts +0 -585
- package/src/logger.ts +0 -38
- package/src/proxy/index.ts +0 -57
- package/src/schemas/blobs.ts +0 -110
- package/src/schemas/common.ts +0 -89
- package/src/schemas/index.ts +0 -7
- package/src/schemas/sync.ts +0 -517
- package/src/scopes/index.ts +0 -237
- package/src/sentry.ts +0 -200
- package/src/snapshot-chunks.ts +0 -964
- package/src/sync-packs.ts +0 -1096
- package/src/telemetry.ts +0 -243
- package/src/transforms.ts +0 -256
- package/src/types.ts +0 -267
- package/src/utils/bytes.ts +0 -75
- package/src/utils/compression.ts +0 -187
- package/src/utils/crypto.ts +0 -146
- package/src/utils/id.ts +0 -34
- package/src/utils/index.ts +0 -9
- package/src/utils/internal-runtime.ts +0 -39
- package/src/utils/object.ts +0 -3
- package/src/utils/realtime-change-index.ts +0 -44
- package/src/utils/realtime-connection-registry.ts +0 -286
- package/src/utils/table-registry.ts +0 -67
- package/src/utils/url.ts +0 -29
package/dist/sync-packs.js
DELETED
|
@@ -1,821 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Binary sync-pack helpers.
|
|
3
|
-
*
|
|
4
|
-
* `binary-sync-pack-v1` removes the repeated JSON field-name envelope around
|
|
5
|
-
* combined sync responses. Commit/subscription/snapshot protocol metadata is
|
|
6
|
-
* encoded positionally, and incremental row bodies can be grouped into
|
|
7
|
-
* generated binary table payloads when table encoders are available.
|
|
8
|
-
*
|
|
9
|
-
* Wire versions:
|
|
10
|
-
* - v7: positional envelope with refs-only snapshot chunks, per-pack table and
|
|
11
|
-
* scope dictionaries, and grouped generated binary row payloads for
|
|
12
|
-
* incremental changes.
|
|
13
|
-
* - v8: variant-tagged push and operation result records.
|
|
14
|
-
* - v9: per-snapshot `bootstrapStateAfter` checkpoints for partial resume.
|
|
15
|
-
* - v10: optional per-commit digest and chain-root verification metadata.
|
|
16
|
-
* - v11: per-snapshot manifest metadata for chunk ordering/integrity.
|
|
17
|
-
* - v12: per-commit partition id and previous chain root for canonical wire
|
|
18
|
-
* commit verification.
|
|
19
|
-
* - v13: subscription-level integrity roots replace repeated per-commit root
|
|
20
|
-
* metadata.
|
|
21
|
-
* - v14: snapshots can advertise scoped artifact refs.
|
|
22
|
-
*/
|
|
23
|
-
import { decodeBinarySnapshotTable, } from './snapshot-chunks.js';
|
|
24
|
-
export const SYNC_PACK_ENCODING_BINARY_V1 = 'binary-sync-pack-v1';
|
|
25
|
-
export const SYNC_PACK_CONTENT_TYPE = 'application/vnd.syncular.sync-pack.v1';
|
|
26
|
-
const MAGIC = new Uint8Array([0x53, 0x53, 0x50, 0x31]); // "SSP1"
|
|
27
|
-
const VERSION = 14;
|
|
28
|
-
const FLAG_NONE = 0;
|
|
29
|
-
// Row-group framing carries table/schema overhead; small commits are
|
|
30
|
-
// cheaper inline.
|
|
31
|
-
const MIN_BINARY_CHANGE_ROW_GROUP_ROWS = 8;
|
|
32
|
-
const textEncoder = new TextEncoder();
|
|
33
|
-
const textDecoder = new TextDecoder();
|
|
34
|
-
export function isBinarySyncPackContentType(value) {
|
|
35
|
-
return value?.split(';', 1)[0]?.trim() === SYNC_PACK_CONTENT_TYPE;
|
|
36
|
-
}
|
|
37
|
-
export function encodeBinarySyncPack(response, options = {}) {
|
|
38
|
-
const writer = new BinarySyncPackWriter();
|
|
39
|
-
writer.bytes(MAGIC);
|
|
40
|
-
writer.u16(VERSION);
|
|
41
|
-
writer.u16(FLAG_NONE);
|
|
42
|
-
writer.bool(response.ok);
|
|
43
|
-
writer.optionalI32(response.requiredSchemaVersion);
|
|
44
|
-
writer.optionalI32(response.latestSchemaVersion);
|
|
45
|
-
writer.optionalValue(response.push, writePushResponse);
|
|
46
|
-
writer.optionalValue(response.pull, (nextWriter, pull) => writePullResponse(nextWriter, pull, options));
|
|
47
|
-
return writer.finish();
|
|
48
|
-
}
|
|
49
|
-
export function decodeBinarySyncPack(bytes) {
|
|
50
|
-
const reader = new BinarySyncPackReader(bytes);
|
|
51
|
-
reader.expectMagic(MAGIC, 'binary sync pack');
|
|
52
|
-
const version = reader.u16('binary sync pack version');
|
|
53
|
-
if (version !== VERSION) {
|
|
54
|
-
throw new Error(`Unsupported binary sync pack version: ${version}`);
|
|
55
|
-
}
|
|
56
|
-
const flags = reader.u16('binary sync pack flags');
|
|
57
|
-
if (flags !== FLAG_NONE) {
|
|
58
|
-
throw new Error(`Unsupported binary sync pack flags: ${flags}`);
|
|
59
|
-
}
|
|
60
|
-
const response = {
|
|
61
|
-
ok: reader.bool('combined response ok'),
|
|
62
|
-
};
|
|
63
|
-
const requiredSchemaVersion = reader.optionalI32('required schema version');
|
|
64
|
-
if (requiredSchemaVersion !== undefined) {
|
|
65
|
-
response.requiredSchemaVersion = requiredSchemaVersion;
|
|
66
|
-
}
|
|
67
|
-
const latestSchemaVersion = reader.optionalI32('latest schema version');
|
|
68
|
-
if (latestSchemaVersion !== undefined) {
|
|
69
|
-
response.latestSchemaVersion = latestSchemaVersion;
|
|
70
|
-
}
|
|
71
|
-
const push = reader.optionalValue(readPushResponse);
|
|
72
|
-
if (push)
|
|
73
|
-
response.push = push;
|
|
74
|
-
const pull = reader.optionalValue(readPullResponse);
|
|
75
|
-
if (pull)
|
|
76
|
-
response.pull = pull;
|
|
77
|
-
reader.assertDone();
|
|
78
|
-
return response;
|
|
79
|
-
}
|
|
80
|
-
function writePushResponse(writer, push) {
|
|
81
|
-
writer.bool(push.ok);
|
|
82
|
-
writer.array(push.commits, writePushCommitResponse);
|
|
83
|
-
}
|
|
84
|
-
function readPushResponse(reader) {
|
|
85
|
-
return {
|
|
86
|
-
ok: reader.bool('push response ok'),
|
|
87
|
-
commits: reader.array('push commits', readPushCommitResponse),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
function writePushCommitResponse(writer, commit) {
|
|
91
|
-
writer.bool(commit.ok);
|
|
92
|
-
writer.string32(commit.clientCommitId);
|
|
93
|
-
writer.u8(pushCommitStatusByte(commit.status));
|
|
94
|
-
writer.optionalI64(commit.commitSeq);
|
|
95
|
-
writer.array(commit.results, writeOperationResult);
|
|
96
|
-
}
|
|
97
|
-
function readPushCommitResponse(reader) {
|
|
98
|
-
const commit = {
|
|
99
|
-
ok: reader.bool('push commit ok'),
|
|
100
|
-
clientCommitId: reader.string32('push client commit id'),
|
|
101
|
-
status: readPushCommitStatus(reader),
|
|
102
|
-
results: [],
|
|
103
|
-
};
|
|
104
|
-
const commitSeq = reader.optionalI64('push commit seq');
|
|
105
|
-
if (commitSeq !== undefined)
|
|
106
|
-
commit.commitSeq = commitSeq;
|
|
107
|
-
commit.results = reader.array('push operation results', readOperationResult);
|
|
108
|
-
return commit;
|
|
109
|
-
}
|
|
110
|
-
function pushCommitStatusByte(status) {
|
|
111
|
-
switch (status) {
|
|
112
|
-
case 'applied':
|
|
113
|
-
return 1;
|
|
114
|
-
case 'cached':
|
|
115
|
-
return 2;
|
|
116
|
-
case 'rejected':
|
|
117
|
-
return 3;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function readPushCommitStatus(reader) {
|
|
121
|
-
const status = reader.u8('push commit status');
|
|
122
|
-
switch (status) {
|
|
123
|
-
case 1:
|
|
124
|
-
return 'applied';
|
|
125
|
-
case 2:
|
|
126
|
-
return 'cached';
|
|
127
|
-
case 3:
|
|
128
|
-
return 'rejected';
|
|
129
|
-
default:
|
|
130
|
-
throw new Error(`Unsupported push commit status byte: ${status}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function operationResultStatusByte(status) {
|
|
134
|
-
switch (status) {
|
|
135
|
-
case 'applied':
|
|
136
|
-
return 1;
|
|
137
|
-
case 'conflict':
|
|
138
|
-
return 2;
|
|
139
|
-
case 'error':
|
|
140
|
-
return 3;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
function writeOperationResult(writer, result) {
|
|
144
|
-
writer.i32(result.opIndex);
|
|
145
|
-
writer.u8(operationResultStatusByte(result.status));
|
|
146
|
-
switch (result.status) {
|
|
147
|
-
case 'applied':
|
|
148
|
-
return;
|
|
149
|
-
case 'conflict':
|
|
150
|
-
writer.string32(result.message);
|
|
151
|
-
writer.optionalString32(result.code);
|
|
152
|
-
writer.i64(result.server_version);
|
|
153
|
-
writer.json(result.server_row);
|
|
154
|
-
return;
|
|
155
|
-
case 'error':
|
|
156
|
-
writer.string32(result.error);
|
|
157
|
-
writer.optionalString32(result.code);
|
|
158
|
-
writer.optionalBool(result.retriable);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function readOperationResult(reader) {
|
|
163
|
-
const opIndex = reader.i32('operation result index');
|
|
164
|
-
const status = reader.u8('operation result status');
|
|
165
|
-
switch (status) {
|
|
166
|
-
case 1:
|
|
167
|
-
return { opIndex, status: 'applied' };
|
|
168
|
-
case 2: {
|
|
169
|
-
const message = reader.string32('operation result conflict message');
|
|
170
|
-
const code = reader.optionalString32('operation result conflict code');
|
|
171
|
-
const serverVersion = reader.i64('operation result conflict server version');
|
|
172
|
-
const serverRow = reader.json('operation result conflict server row');
|
|
173
|
-
return {
|
|
174
|
-
opIndex,
|
|
175
|
-
status: 'conflict',
|
|
176
|
-
message,
|
|
177
|
-
...(code !== undefined ? { code } : {}),
|
|
178
|
-
server_version: serverVersion,
|
|
179
|
-
server_row: serverRow,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
case 3: {
|
|
183
|
-
const error = reader.string32('operation result error message');
|
|
184
|
-
const code = reader.optionalString32('operation result error code');
|
|
185
|
-
const retriable = reader.optionalBool('operation result error retriable');
|
|
186
|
-
return {
|
|
187
|
-
opIndex,
|
|
188
|
-
status: 'error',
|
|
189
|
-
error,
|
|
190
|
-
...(code !== undefined ? { code } : {}),
|
|
191
|
-
...(retriable !== undefined ? { retriable } : {}),
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
default:
|
|
195
|
-
throw new Error(`Unsupported operation result status byte: ${status}`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
function writePullResponse(writer, pull, options) {
|
|
199
|
-
writer.bool(pull.ok);
|
|
200
|
-
writer.array(pull.subscriptions, (nextWriter, subscription) => writeSubscriptionResponse(nextWriter, subscription, options));
|
|
201
|
-
}
|
|
202
|
-
function readPullResponse(reader) {
|
|
203
|
-
return {
|
|
204
|
-
ok: reader.bool('pull response ok'),
|
|
205
|
-
subscriptions: reader.array('pull subscriptions', readSubscriptionResponse),
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
function writeSubscriptionResponse(writer, subscription, options) {
|
|
209
|
-
writer.string32(subscription.id);
|
|
210
|
-
writer.string16(subscription.status);
|
|
211
|
-
writer.json(subscription.scopes);
|
|
212
|
-
writer.bool(subscription.bootstrap);
|
|
213
|
-
writer.optionalJson(subscription.bootstrapState ?? undefined);
|
|
214
|
-
writer.i64(subscription.nextCursor);
|
|
215
|
-
writer.optionalValue(subscription.integrity, writeSubscriptionIntegrity);
|
|
216
|
-
writer.array(subscription.commits, (nextWriter, commit) => writeCommit(nextWriter, commit, options));
|
|
217
|
-
writer.optionalArray(subscription.snapshots, writeSnapshot);
|
|
218
|
-
}
|
|
219
|
-
function readSubscriptionResponse(reader) {
|
|
220
|
-
const subscription = {
|
|
221
|
-
id: reader.string32('subscription id'),
|
|
222
|
-
status: reader.string16('subscription status'),
|
|
223
|
-
scopes: reader.json('subscription scopes'),
|
|
224
|
-
bootstrap: reader.bool('subscription bootstrap'),
|
|
225
|
-
nextCursor: 0,
|
|
226
|
-
commits: [],
|
|
227
|
-
};
|
|
228
|
-
const bootstrapState = reader.optionalJson('subscription bootstrap state');
|
|
229
|
-
subscription.bootstrapState =
|
|
230
|
-
bootstrapState ?? null;
|
|
231
|
-
subscription.nextCursor = reader.i64('subscription next cursor');
|
|
232
|
-
const integrity = reader.optionalValue(readSubscriptionIntegrity);
|
|
233
|
-
if (integrity)
|
|
234
|
-
subscription.integrity = integrity;
|
|
235
|
-
subscription.commits = reader.array('subscription commits', readCommit);
|
|
236
|
-
const snapshots = reader.optionalArray('subscription snapshots', readSnapshot);
|
|
237
|
-
if (snapshots)
|
|
238
|
-
subscription.snapshots = snapshots;
|
|
239
|
-
return subscription;
|
|
240
|
-
}
|
|
241
|
-
function writeSubscriptionIntegrity(writer, integrity) {
|
|
242
|
-
writer.string32(integrity.partitionId);
|
|
243
|
-
writer.string32(integrity.previousChainRoot);
|
|
244
|
-
writer.string32(integrity.commitChainRoot);
|
|
245
|
-
writer.i64(integrity.commitSeq);
|
|
246
|
-
}
|
|
247
|
-
function readSubscriptionIntegrity(reader) {
|
|
248
|
-
return {
|
|
249
|
-
partitionId: reader.string32('subscription integrity partitionId'),
|
|
250
|
-
previousChainRoot: reader.string32('subscription integrity previous chain root'),
|
|
251
|
-
commitChainRoot: reader.string32('subscription integrity chain root'),
|
|
252
|
-
commitSeq: reader.i64('subscription integrity commit seq'),
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
function writeCommit(writer, commit, options) {
|
|
256
|
-
writer.i64(commit.commitSeq);
|
|
257
|
-
writer.string32(commit.createdAt);
|
|
258
|
-
writer.string32(commit.actorId);
|
|
259
|
-
writeChanges(writer, commit.changes, options);
|
|
260
|
-
}
|
|
261
|
-
function readCommit(reader) {
|
|
262
|
-
const commit = {
|
|
263
|
-
commitSeq: reader.i64('commit seq'),
|
|
264
|
-
createdAt: reader.string32('commit createdAt'),
|
|
265
|
-
actorId: reader.string32('commit actorId'),
|
|
266
|
-
changes: [],
|
|
267
|
-
};
|
|
268
|
-
commit.changes = readChangesV8(reader);
|
|
269
|
-
return commit;
|
|
270
|
-
}
|
|
271
|
-
function writeChanges(writer, changes, options) {
|
|
272
|
-
const encodedRowCountsByTable = new Map();
|
|
273
|
-
const tableIndexesByName = new Map();
|
|
274
|
-
const tableNames = [];
|
|
275
|
-
const scopeIndexesByKey = new Map();
|
|
276
|
-
const singleScopeIndexesByName = new Map();
|
|
277
|
-
const scopeValuesByIndex = [];
|
|
278
|
-
const tableIndexFor = (table) => {
|
|
279
|
-
let tableIndex = tableIndexesByName.get(table);
|
|
280
|
-
if (tableIndex !== undefined)
|
|
281
|
-
return tableIndex;
|
|
282
|
-
tableIndex = tableNames.length;
|
|
283
|
-
tableIndexesByName.set(table, tableIndex);
|
|
284
|
-
tableNames.push(table);
|
|
285
|
-
return tableIndex;
|
|
286
|
-
};
|
|
287
|
-
const scopeIndexFor = (scopes) => {
|
|
288
|
-
const entries = Object.entries(scopes);
|
|
289
|
-
if (entries.length === 1) {
|
|
290
|
-
const [scopeName, scopeValue] = entries[0];
|
|
291
|
-
let indexesByValue = singleScopeIndexesByName.get(scopeName);
|
|
292
|
-
if (!indexesByValue) {
|
|
293
|
-
indexesByValue = new Map();
|
|
294
|
-
singleScopeIndexesByName.set(scopeName, indexesByValue);
|
|
295
|
-
}
|
|
296
|
-
let scopeIndex = indexesByValue.get(scopeValue);
|
|
297
|
-
if (scopeIndex !== undefined)
|
|
298
|
-
return scopeIndex;
|
|
299
|
-
scopeIndex = scopeValuesByIndex.length;
|
|
300
|
-
indexesByValue.set(scopeValue, scopeIndex);
|
|
301
|
-
scopeValuesByIndex.push(scopes);
|
|
302
|
-
return scopeIndex;
|
|
303
|
-
}
|
|
304
|
-
const key = scopeDictionaryKey(entries);
|
|
305
|
-
let scopeIndex = scopeIndexesByKey.get(key);
|
|
306
|
-
if (scopeIndex !== undefined)
|
|
307
|
-
return scopeIndex;
|
|
308
|
-
scopeIndex = scopeValuesByIndex.length;
|
|
309
|
-
scopeIndexesByKey.set(key, scopeIndex);
|
|
310
|
-
scopeValuesByIndex.push(scopes);
|
|
311
|
-
return scopeIndex;
|
|
312
|
-
};
|
|
313
|
-
const tableIndexesByChange = [];
|
|
314
|
-
const scopeIndexesByChange = [];
|
|
315
|
-
for (let index = 0; index < changes.length; index += 1) {
|
|
316
|
-
const change = changes[index];
|
|
317
|
-
tableIndexesByChange[index] = tableIndexFor(change.table);
|
|
318
|
-
scopeIndexesByChange[index] = scopeIndexFor(change.scopes);
|
|
319
|
-
if (change.op === 'delete' || change.row_json == null)
|
|
320
|
-
continue;
|
|
321
|
-
if (!options.changeRowEncoders?.[change.table])
|
|
322
|
-
continue;
|
|
323
|
-
encodedRowCountsByTable.set(change.table, (encodedRowCountsByTable.get(change.table) ?? 0) + 1);
|
|
324
|
-
}
|
|
325
|
-
const rowRefs = new Map();
|
|
326
|
-
const groups = [];
|
|
327
|
-
const groupIndexesByTable = new Map();
|
|
328
|
-
for (let index = 0; index < changes.length; index += 1) {
|
|
329
|
-
const change = changes[index];
|
|
330
|
-
if (change.op === 'delete' || change.row_json == null)
|
|
331
|
-
continue;
|
|
332
|
-
const encoder = options.changeRowEncoders?.[change.table];
|
|
333
|
-
if (!encoder)
|
|
334
|
-
continue;
|
|
335
|
-
if ((encodedRowCountsByTable.get(change.table) ?? 0) <
|
|
336
|
-
MIN_BINARY_CHANGE_ROW_GROUP_ROWS) {
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
let groupIndex = groupIndexesByTable.get(change.table);
|
|
340
|
-
if (groupIndex === undefined) {
|
|
341
|
-
groupIndex = groups.length;
|
|
342
|
-
groupIndexesByTable.set(change.table, groupIndex);
|
|
343
|
-
groups.push({
|
|
344
|
-
table: change.table,
|
|
345
|
-
tableIndex: tableIndexesByChange[index],
|
|
346
|
-
encoder,
|
|
347
|
-
rows: [],
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
const group = groups[groupIndex];
|
|
351
|
-
const rowIndex = group.rows.length;
|
|
352
|
-
group.rows.push(change.row_json);
|
|
353
|
-
rowRefs.set(index, { groupIndex, rowIndex });
|
|
354
|
-
}
|
|
355
|
-
writer.array(tableNames, (nextWriter, table) => nextWriter.string16(table));
|
|
356
|
-
writer.array(scopeValuesByIndex, (nextWriter, scopes) => nextWriter.stringMap(scopes));
|
|
357
|
-
writer.u32(changes.length);
|
|
358
|
-
for (let index = 0; index < changes.length; index += 1) {
|
|
359
|
-
const change = changes[index];
|
|
360
|
-
writeChangeMetadataV8(writer, change, tableIndexesByChange[index], scopeIndexesByChange[index], rowRefs.get(index));
|
|
361
|
-
}
|
|
362
|
-
writer.u32(groups.length);
|
|
363
|
-
for (const group of groups) {
|
|
364
|
-
writer.u16(group.tableIndex);
|
|
365
|
-
writer.bytes32(group.encoder(group.rows));
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
function writeChangeMetadataV8(writer, change, tableIndex, scopeIndex, rowRef) {
|
|
369
|
-
writer.u16(tableIndex);
|
|
370
|
-
writer.string32(change.row_id);
|
|
371
|
-
writer.u8(change.op === 'upsert' ? 1 : 2);
|
|
372
|
-
if (change.row_json == null) {
|
|
373
|
-
writer.u8(0);
|
|
374
|
-
}
|
|
375
|
-
else if (rowRef) {
|
|
376
|
-
writer.u8(2);
|
|
377
|
-
writer.u32(rowRef.groupIndex);
|
|
378
|
-
writer.u32(rowRef.rowIndex);
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
writer.u8(1);
|
|
382
|
-
writer.json(change.row_json);
|
|
383
|
-
}
|
|
384
|
-
writer.optionalI64(change.row_version ?? undefined);
|
|
385
|
-
writer.u32(scopeIndex);
|
|
386
|
-
}
|
|
387
|
-
function readChangesV8(reader) {
|
|
388
|
-
const tableNames = reader.array('commit change table dictionary', (reader) => reader.string16('commit change table'));
|
|
389
|
-
const scopeValuesByIndex = reader.array('commit change scope dictionary', (reader) => reader.stringMap('commit change scopes'));
|
|
390
|
-
const changeCount = reader.u32('commit changes length');
|
|
391
|
-
const changes = [];
|
|
392
|
-
const rowRefs = [];
|
|
393
|
-
for (let index = 0; index < changeCount; index += 1) {
|
|
394
|
-
const change = readChangeMetadataV8(reader, index, tableNames, scopeValuesByIndex, rowRefs);
|
|
395
|
-
changes.push(change);
|
|
396
|
-
}
|
|
397
|
-
const groupCount = reader.u32('binary change row group count');
|
|
398
|
-
const groupRows = new Map();
|
|
399
|
-
for (let groupIndex = 0; groupIndex < groupCount; groupIndex += 1) {
|
|
400
|
-
const table = tableNameAt(tableNames, reader.u16('binary change row group table index'));
|
|
401
|
-
const decoded = decodeBinarySnapshotTable(reader.bytes32('binary change row group payload'));
|
|
402
|
-
if (decoded.table !== table) {
|
|
403
|
-
throw new Error(`Binary sync pack row group table mismatch: expected ${table}, got ${decoded.table}`);
|
|
404
|
-
}
|
|
405
|
-
groupRows.set(groupIndex, decoded.rows);
|
|
406
|
-
}
|
|
407
|
-
for (const ref of rowRefs) {
|
|
408
|
-
const rows = groupRows.get(ref.groupIndex);
|
|
409
|
-
const row = rows?.[ref.rowIndex];
|
|
410
|
-
if (!row) {
|
|
411
|
-
throw new Error(`Binary sync pack change row ref is invalid: group=${ref.groupIndex}, row=${ref.rowIndex}`);
|
|
412
|
-
}
|
|
413
|
-
if (changes[ref.changeIndex]?.table !== ref.table) {
|
|
414
|
-
throw new Error('Binary sync pack row ref table mismatch');
|
|
415
|
-
}
|
|
416
|
-
changes[ref.changeIndex].row_json = row;
|
|
417
|
-
}
|
|
418
|
-
return changes;
|
|
419
|
-
}
|
|
420
|
-
function readChangeMetadataV8(reader, changeIndex, tableNames, scopeValuesByIndex, rowRefs) {
|
|
421
|
-
const table = tableNameAt(tableNames, reader.u16('change table index'));
|
|
422
|
-
const rowId = reader.string32('change row id');
|
|
423
|
-
const opByte = reader.u8('change op');
|
|
424
|
-
if (opByte !== 1 && opByte !== 2) {
|
|
425
|
-
throw new Error(`Unsupported binary sync pack change op byte: ${opByte}`);
|
|
426
|
-
}
|
|
427
|
-
let rowJson = null;
|
|
428
|
-
const rowPayloadKind = reader.u8('change row payload kind');
|
|
429
|
-
if (rowPayloadKind === 1) {
|
|
430
|
-
rowJson = reader.json('change row json');
|
|
431
|
-
}
|
|
432
|
-
else if (rowPayloadKind === 2) {
|
|
433
|
-
rowRefs.push({
|
|
434
|
-
changeIndex,
|
|
435
|
-
table,
|
|
436
|
-
groupIndex: reader.u32('change row group index'),
|
|
437
|
-
rowIndex: reader.u32('change row group row index'),
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
else if (rowPayloadKind !== 0) {
|
|
441
|
-
throw new Error(`Unsupported binary sync pack change row payload kind: ${rowPayloadKind}`);
|
|
442
|
-
}
|
|
443
|
-
return {
|
|
444
|
-
table,
|
|
445
|
-
row_id: rowId,
|
|
446
|
-
op: opByte === 1 ? 'upsert' : 'delete',
|
|
447
|
-
row_json: rowJson,
|
|
448
|
-
row_version: reader.optionalI64('change row version') ?? null,
|
|
449
|
-
scopes: scopeValuesAt(scopeValuesByIndex, reader.u32('change scopes index')),
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
function tableNameAt(tableNames, index) {
|
|
453
|
-
const table = tableNames[index];
|
|
454
|
-
if (table === undefined) {
|
|
455
|
-
throw new Error(`Binary sync pack table index is invalid: ${index}`);
|
|
456
|
-
}
|
|
457
|
-
return table;
|
|
458
|
-
}
|
|
459
|
-
function scopeValuesAt(scopeValuesByIndex, index) {
|
|
460
|
-
const scopes = scopeValuesByIndex[index];
|
|
461
|
-
if (scopes === undefined) {
|
|
462
|
-
throw new Error(`Binary sync pack scope index is invalid: ${index}`);
|
|
463
|
-
}
|
|
464
|
-
return { ...scopes };
|
|
465
|
-
}
|
|
466
|
-
function scopeDictionaryKey(entries) {
|
|
467
|
-
let count = 0;
|
|
468
|
-
let body = '';
|
|
469
|
-
for (const [scopeName, scopeValue] of entries) {
|
|
470
|
-
count += 1;
|
|
471
|
-
body += `${scopeName.length}:${scopeName}${scopeValue.length}:${scopeValue}`;
|
|
472
|
-
}
|
|
473
|
-
return `${count}|${body}`;
|
|
474
|
-
}
|
|
475
|
-
function writeSnapshot(writer, snapshot) {
|
|
476
|
-
writer.string16(snapshot.table);
|
|
477
|
-
writer.array(snapshot.rows, (nextWriter, row) => nextWriter.json(row));
|
|
478
|
-
writer.optionalArray(snapshot.chunks, writeSnapshotChunkRef);
|
|
479
|
-
writer.bool(snapshot.isFirstPage);
|
|
480
|
-
writer.bool(snapshot.isLastPage);
|
|
481
|
-
writer.optionalJson(snapshot.bootstrapStateAfter ?? undefined);
|
|
482
|
-
writer.optionalJson(snapshot.manifest ?? undefined);
|
|
483
|
-
writer.optionalJson(snapshot.artifacts ?? undefined);
|
|
484
|
-
}
|
|
485
|
-
function readSnapshot(reader) {
|
|
486
|
-
const snapshot = {
|
|
487
|
-
table: reader.string16('snapshot table'),
|
|
488
|
-
rows: reader.array('snapshot rows', (nextReader) => nextReader.json('snapshot row')),
|
|
489
|
-
isFirstPage: false,
|
|
490
|
-
isLastPage: false,
|
|
491
|
-
};
|
|
492
|
-
const chunks = reader.optionalArray('snapshot chunks', readSnapshotChunkRef);
|
|
493
|
-
if (chunks)
|
|
494
|
-
snapshot.chunks = chunks;
|
|
495
|
-
snapshot.isFirstPage = reader.bool('snapshot first page');
|
|
496
|
-
snapshot.isLastPage = reader.bool('snapshot last page');
|
|
497
|
-
snapshot.bootstrapStateAfter =
|
|
498
|
-
reader.optionalJson('snapshot bootstrap state after') ?? null;
|
|
499
|
-
const manifest = reader.optionalJson('snapshot manifest');
|
|
500
|
-
if (manifest !== undefined)
|
|
501
|
-
snapshot.manifest = manifest;
|
|
502
|
-
const artifacts = reader.optionalJson('snapshot artifacts');
|
|
503
|
-
if (artifacts !== undefined)
|
|
504
|
-
snapshot.artifacts = artifacts;
|
|
505
|
-
return snapshot;
|
|
506
|
-
}
|
|
507
|
-
function writeSnapshotChunkRef(writer, chunk) {
|
|
508
|
-
writer.string32(chunk.id);
|
|
509
|
-
writer.i64(chunk.byteLength);
|
|
510
|
-
writer.string16(chunk.sha256);
|
|
511
|
-
writer.string16(chunk.encoding);
|
|
512
|
-
writer.string16(chunk.compression);
|
|
513
|
-
}
|
|
514
|
-
function readSnapshotChunkRef(reader) {
|
|
515
|
-
return {
|
|
516
|
-
id: reader.string32('snapshot chunk id'),
|
|
517
|
-
byteLength: reader.i64('snapshot chunk byte length'),
|
|
518
|
-
sha256: reader.string16('snapshot chunk sha256'),
|
|
519
|
-
encoding: reader.string16('snapshot chunk encoding'),
|
|
520
|
-
compression: reader.string16('snapshot chunk compression'),
|
|
521
|
-
};
|
|
522
|
-
}
|
|
523
|
-
class BinarySyncPackWriter {
|
|
524
|
-
bytesOut;
|
|
525
|
-
view;
|
|
526
|
-
offset = 0;
|
|
527
|
-
constructor(initialCapacity = 1024) {
|
|
528
|
-
this.bytesOut = new Uint8Array(Math.max(64, initialCapacity));
|
|
529
|
-
this.view = new DataView(this.bytesOut.buffer, this.bytesOut.byteOffset, this.bytesOut.length);
|
|
530
|
-
}
|
|
531
|
-
finish() {
|
|
532
|
-
return this.bytesOut.subarray(0, this.offset);
|
|
533
|
-
}
|
|
534
|
-
bytes(value) {
|
|
535
|
-
this.ensure(value.length);
|
|
536
|
-
this.bytesOut.set(value, this.offset);
|
|
537
|
-
this.offset += value.length;
|
|
538
|
-
}
|
|
539
|
-
bool(value) {
|
|
540
|
-
this.u8(value ? 1 : 0);
|
|
541
|
-
}
|
|
542
|
-
optionalBool(value) {
|
|
543
|
-
this.optionalValue(value, (writer, nextValue) => writer.bool(nextValue));
|
|
544
|
-
}
|
|
545
|
-
u8(value) {
|
|
546
|
-
this.ensure(1);
|
|
547
|
-
this.view.setUint8(this.offset, value);
|
|
548
|
-
this.offset += 1;
|
|
549
|
-
}
|
|
550
|
-
u16(value) {
|
|
551
|
-
assertUnsigned(value, 0xffff, 'uint16');
|
|
552
|
-
this.ensure(2);
|
|
553
|
-
this.view.setUint16(this.offset, value, true);
|
|
554
|
-
this.offset += 2;
|
|
555
|
-
}
|
|
556
|
-
u32(value) {
|
|
557
|
-
assertUnsigned(value, 0xffff_ffff, 'uint32');
|
|
558
|
-
this.ensure(4);
|
|
559
|
-
this.view.setUint32(this.offset, value, true);
|
|
560
|
-
this.offset += 4;
|
|
561
|
-
}
|
|
562
|
-
i32(value) {
|
|
563
|
-
assertSigned(value, -0x8000_0000, 0x7fff_ffff, 'int32');
|
|
564
|
-
this.ensure(4);
|
|
565
|
-
this.view.setInt32(this.offset, value, true);
|
|
566
|
-
this.offset += 4;
|
|
567
|
-
}
|
|
568
|
-
optionalI32(value) {
|
|
569
|
-
this.optionalValue(value, (writer, nextValue) => writer.i32(nextValue));
|
|
570
|
-
}
|
|
571
|
-
i64(value) {
|
|
572
|
-
if (!Number.isSafeInteger(value)) {
|
|
573
|
-
throw new Error('int64 value must be a safe integer');
|
|
574
|
-
}
|
|
575
|
-
this.ensure(8);
|
|
576
|
-
if (value >= 0) {
|
|
577
|
-
this.view.setUint32(this.offset, value >>> 0, true);
|
|
578
|
-
this.view.setUint32(this.offset + 4, Math.floor(value / 0x1_0000_0000), true);
|
|
579
|
-
}
|
|
580
|
-
else {
|
|
581
|
-
this.view.setBigInt64(this.offset, BigInt(value), true);
|
|
582
|
-
}
|
|
583
|
-
this.offset += 8;
|
|
584
|
-
}
|
|
585
|
-
optionalI64(value) {
|
|
586
|
-
this.optionalValue(value ?? undefined, (writer, nextValue) => writer.i64(nextValue));
|
|
587
|
-
}
|
|
588
|
-
string16(value) {
|
|
589
|
-
if (this.writeAsciiString16(value))
|
|
590
|
-
return;
|
|
591
|
-
const bytes = textEncoder.encode(value);
|
|
592
|
-
this.u16(bytes.length);
|
|
593
|
-
this.bytes(bytes);
|
|
594
|
-
}
|
|
595
|
-
string32(value) {
|
|
596
|
-
if (this.writeAsciiString32(value))
|
|
597
|
-
return;
|
|
598
|
-
const bytes = textEncoder.encode(value);
|
|
599
|
-
this.u32(bytes.length);
|
|
600
|
-
this.bytes(bytes);
|
|
601
|
-
}
|
|
602
|
-
optionalString32(value) {
|
|
603
|
-
this.optionalValue(value, (writer, nextValue) => writer.string32(nextValue));
|
|
604
|
-
}
|
|
605
|
-
bytes32(value) {
|
|
606
|
-
this.u32(value.length);
|
|
607
|
-
this.bytes(value);
|
|
608
|
-
}
|
|
609
|
-
json(value) {
|
|
610
|
-
this.string32(JSON.stringify(value) ?? 'null');
|
|
611
|
-
}
|
|
612
|
-
stringMap(value) {
|
|
613
|
-
const entries = Object.entries(value);
|
|
614
|
-
this.u32(entries.length);
|
|
615
|
-
for (const [key, nextValue] of entries) {
|
|
616
|
-
this.string16(key);
|
|
617
|
-
this.string32(nextValue);
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
optionalJson(value) {
|
|
621
|
-
this.optionalValue(value, (writer, nextValue) => writer.json(nextValue));
|
|
622
|
-
}
|
|
623
|
-
array(values, write) {
|
|
624
|
-
this.u32(values.length);
|
|
625
|
-
for (const value of values) {
|
|
626
|
-
write(this, value);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
optionalArray(values, write) {
|
|
630
|
-
this.optionalValue(values, (writer, nextValues) => writer.array(nextValues, write));
|
|
631
|
-
}
|
|
632
|
-
optionalValue(value, write) {
|
|
633
|
-
if (value === undefined) {
|
|
634
|
-
this.u8(0);
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
this.u8(1);
|
|
638
|
-
write(this, value);
|
|
639
|
-
}
|
|
640
|
-
ensure(length) {
|
|
641
|
-
const required = this.offset + length;
|
|
642
|
-
if (required <= this.bytesOut.length)
|
|
643
|
-
return;
|
|
644
|
-
let nextLength = this.bytesOut.length;
|
|
645
|
-
while (nextLength < required) {
|
|
646
|
-
nextLength *= 2;
|
|
647
|
-
}
|
|
648
|
-
const next = new Uint8Array(nextLength);
|
|
649
|
-
next.set(this.bytesOut, 0);
|
|
650
|
-
this.bytesOut = next;
|
|
651
|
-
this.view = new DataView(this.bytesOut.buffer, this.bytesOut.byteOffset, this.bytesOut.length);
|
|
652
|
-
}
|
|
653
|
-
writeAsciiString16(value) {
|
|
654
|
-
assertUnsigned(value.length, 0xffff, 'uint16');
|
|
655
|
-
const start = this.offset;
|
|
656
|
-
this.u16(value.length);
|
|
657
|
-
return this.tryWriteAsciiBytes(value, start);
|
|
658
|
-
}
|
|
659
|
-
writeAsciiString32(value) {
|
|
660
|
-
assertUnsigned(value.length, 0xffff_ffff, 'uint32');
|
|
661
|
-
const start = this.offset;
|
|
662
|
-
this.u32(value.length);
|
|
663
|
-
return this.tryWriteAsciiBytes(value, start);
|
|
664
|
-
}
|
|
665
|
-
tryWriteAsciiBytes(value, rollbackOffset) {
|
|
666
|
-
this.ensure(value.length);
|
|
667
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
668
|
-
const code = value.charCodeAt(index);
|
|
669
|
-
if (code > 0x7f) {
|
|
670
|
-
this.offset = rollbackOffset;
|
|
671
|
-
return false;
|
|
672
|
-
}
|
|
673
|
-
this.bytesOut[this.offset + index] = code;
|
|
674
|
-
}
|
|
675
|
-
this.offset += value.length;
|
|
676
|
-
return true;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
class BinarySyncPackReader {
|
|
680
|
-
bytes;
|
|
681
|
-
view;
|
|
682
|
-
offset = 0;
|
|
683
|
-
constructor(bytes) {
|
|
684
|
-
this.bytes = bytes;
|
|
685
|
-
this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.length);
|
|
686
|
-
}
|
|
687
|
-
expectMagic(magic, label) {
|
|
688
|
-
const actual = this.bytesSlice(magic.length, `${label} magic`);
|
|
689
|
-
for (let index = 0; index < magic.length; index += 1) {
|
|
690
|
-
if (actual[index] !== magic[index]) {
|
|
691
|
-
throw new Error(`Unexpected ${label} magic`);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
bool(label) {
|
|
696
|
-
const value = this.u8(label);
|
|
697
|
-
if (value !== 0 && value !== 1) {
|
|
698
|
-
throw new Error(`${label} expected boolean byte`);
|
|
699
|
-
}
|
|
700
|
-
return value === 1;
|
|
701
|
-
}
|
|
702
|
-
optionalBool(label) {
|
|
703
|
-
return this.optionalValue((reader) => reader.bool(label));
|
|
704
|
-
}
|
|
705
|
-
u8(label) {
|
|
706
|
-
this.require(1, label);
|
|
707
|
-
const value = this.view.getUint8(this.offset);
|
|
708
|
-
this.offset += 1;
|
|
709
|
-
return value;
|
|
710
|
-
}
|
|
711
|
-
u16(label) {
|
|
712
|
-
this.require(2, label);
|
|
713
|
-
const value = this.view.getUint16(this.offset, true);
|
|
714
|
-
this.offset += 2;
|
|
715
|
-
return value;
|
|
716
|
-
}
|
|
717
|
-
u32(label) {
|
|
718
|
-
this.require(4, label);
|
|
719
|
-
const value = this.view.getUint32(this.offset, true);
|
|
720
|
-
this.offset += 4;
|
|
721
|
-
return value;
|
|
722
|
-
}
|
|
723
|
-
i32(label) {
|
|
724
|
-
this.require(4, label);
|
|
725
|
-
const value = this.view.getInt32(this.offset, true);
|
|
726
|
-
this.offset += 4;
|
|
727
|
-
return value;
|
|
728
|
-
}
|
|
729
|
-
optionalI32(label) {
|
|
730
|
-
return this.optionalValue((reader) => reader.i32(label));
|
|
731
|
-
}
|
|
732
|
-
i64(label) {
|
|
733
|
-
this.require(8, label);
|
|
734
|
-
const value = this.view.getBigInt64(this.offset, true);
|
|
735
|
-
this.offset += 8;
|
|
736
|
-
const asNumber = Number(value);
|
|
737
|
-
if (!Number.isSafeInteger(asNumber) || BigInt(asNumber) !== value) {
|
|
738
|
-
throw new Error(`${label} exceeds JavaScript safe integer bounds`);
|
|
739
|
-
}
|
|
740
|
-
return asNumber;
|
|
741
|
-
}
|
|
742
|
-
optionalI64(label) {
|
|
743
|
-
return this.optionalValue((reader) => reader.i64(label));
|
|
744
|
-
}
|
|
745
|
-
string16(label) {
|
|
746
|
-
const length = this.u16(`${label} length`);
|
|
747
|
-
return textDecoder.decode(this.bytesSlice(length, label));
|
|
748
|
-
}
|
|
749
|
-
string32(label) {
|
|
750
|
-
const length = this.u32(`${label} length`);
|
|
751
|
-
return textDecoder.decode(this.bytesSlice(length, label));
|
|
752
|
-
}
|
|
753
|
-
optionalString32(label) {
|
|
754
|
-
return this.optionalValue((reader) => reader.string32(label));
|
|
755
|
-
}
|
|
756
|
-
bytes32(label) {
|
|
757
|
-
const length = this.u32(`${label} length`);
|
|
758
|
-
return this.bytesSlice(length, label);
|
|
759
|
-
}
|
|
760
|
-
json(label) {
|
|
761
|
-
return JSON.parse(this.string32(label));
|
|
762
|
-
}
|
|
763
|
-
stringMap(label) {
|
|
764
|
-
const length = this.u32(`${label} length`);
|
|
765
|
-
const out = {};
|
|
766
|
-
for (let index = 0; index < length; index += 1) {
|
|
767
|
-
out[this.string16(`${label} key`)] = this.string32(`${label} value`);
|
|
768
|
-
}
|
|
769
|
-
return out;
|
|
770
|
-
}
|
|
771
|
-
optionalJson(label) {
|
|
772
|
-
return this.optionalValue((reader) => reader.json(label));
|
|
773
|
-
}
|
|
774
|
-
array(label, read) {
|
|
775
|
-
const length = this.u32(`${label} length`);
|
|
776
|
-
const values = [];
|
|
777
|
-
for (let index = 0; index < length; index += 1) {
|
|
778
|
-
values.push(read(this));
|
|
779
|
-
}
|
|
780
|
-
return values;
|
|
781
|
-
}
|
|
782
|
-
optionalArray(label, read) {
|
|
783
|
-
return this.optionalValue((reader) => reader.array(label, read));
|
|
784
|
-
}
|
|
785
|
-
optionalValue(read) {
|
|
786
|
-
const present = this.u8('optional value present');
|
|
787
|
-
if (present === 0)
|
|
788
|
-
return undefined;
|
|
789
|
-
if (present !== 1) {
|
|
790
|
-
throw new Error(`Optional value marker must be 0 or 1, got ${present}`);
|
|
791
|
-
}
|
|
792
|
-
return read(this);
|
|
793
|
-
}
|
|
794
|
-
bytesSlice(length, label) {
|
|
795
|
-
this.require(length, label);
|
|
796
|
-
const value = this.bytes.subarray(this.offset, this.offset + length);
|
|
797
|
-
this.offset += length;
|
|
798
|
-
return value;
|
|
799
|
-
}
|
|
800
|
-
assertDone() {
|
|
801
|
-
if (this.offset !== this.bytes.length) {
|
|
802
|
-
throw new Error('Binary sync pack has trailing bytes');
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
require(length, label) {
|
|
806
|
-
if (this.offset + length > this.bytes.length) {
|
|
807
|
-
throw new Error(`${label} exceeds binary sync pack bounds`);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
function assertUnsigned(value, max, label) {
|
|
812
|
-
if (!Number.isInteger(value) || value < 0 || value > max) {
|
|
813
|
-
throw new Error(`${label} value is out of range`);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
function assertSigned(value, min, max, label) {
|
|
817
|
-
if (!Number.isInteger(value) || value < min || value > max) {
|
|
818
|
-
throw new Error(`${label} value is out of range`);
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
//# sourceMappingURL=sync-packs.js.map
|