@syncular/core 0.1.3 → 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/src/row-codec.ts
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema-IR row codec (SPEC.md §2.4).
|
|
3
|
+
*
|
|
4
|
+
* A row is a null bitmap of ceil(columnCount / 8) bytes (bit i set =
|
|
5
|
+
* column i is NULL; LSB-first within each byte, byte i/8), followed by the
|
|
6
|
+
* non-null values encoded positionally in schema-IR declaration order.
|
|
7
|
+
* Used for `COMMIT` change payloads, rows-segment row data, push operation
|
|
8
|
+
* payloads, and conflict `serverRow` values.
|
|
9
|
+
*/
|
|
10
|
+
import { parseBlobRef } from './blob-ref';
|
|
11
|
+
import { ByteReader, ByteWriter } from './bytes';
|
|
12
|
+
import { DecodeError } from './errors';
|
|
13
|
+
|
|
14
|
+
export type ColumnType =
|
|
15
|
+
| 'string'
|
|
16
|
+
| 'integer'
|
|
17
|
+
| 'float'
|
|
18
|
+
| 'boolean'
|
|
19
|
+
| 'json'
|
|
20
|
+
| 'bytes'
|
|
21
|
+
| 'blob_ref'
|
|
22
|
+
| 'crdt';
|
|
23
|
+
|
|
24
|
+
export interface RowColumn {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly type: ColumnType;
|
|
27
|
+
readonly nullable: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* For a `crdt` column (§2.4 tag 8, §5.10.1): the named merger the server
|
|
30
|
+
* selects (this rung defines exactly `'yjs-doc'`). Schema-IR metadata
|
|
31
|
+
* ONLY — never on the wire (the SSG2 column table carries name/type/
|
|
32
|
+
* nullable, and `crdt` shares the `bytes` tag). Ignored for other types.
|
|
33
|
+
*/
|
|
34
|
+
readonly crdtType?: string;
|
|
35
|
+
/**
|
|
36
|
+
* §5.11: this column is encrypted end-to-end. When set, `type` is `bytes`
|
|
37
|
+
* (the wire/stored type — the ciphertext envelope rides the bytes machinery)
|
|
38
|
+
* and `declaredType` is the pre-flip app type. Both are schema-IR metadata,
|
|
39
|
+
* never on the wire (like `crdtType`). The row codec ignores these — it
|
|
40
|
+
* only ever sees a `bytes` value; encryption/decryption is the client
|
|
41
|
+
* encode/apply seam (§5.11).
|
|
42
|
+
*/
|
|
43
|
+
readonly encrypted?: boolean;
|
|
44
|
+
/** §5.11: the app-side type of an encrypted column (its type before the
|
|
45
|
+
* wire flip to `bytes`). Present iff `encrypted` is set. */
|
|
46
|
+
readonly declaredType?: ColumnType;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* `integer` is `i64` within the ±(2^53−1) contract; `json` is the raw JSON
|
|
51
|
+
* document string, preserved byte-for-byte on round-trip.
|
|
52
|
+
*/
|
|
53
|
+
export type RowValue = string | number | boolean | Uint8Array | null;
|
|
54
|
+
|
|
55
|
+
/** Wire tags, unchanged from v1's binary-table-v1 assignment (SPEC.md §2.4). */
|
|
56
|
+
const TYPE_TO_TAG: Readonly<Record<ColumnType, number>> = {
|
|
57
|
+
string: 1,
|
|
58
|
+
integer: 2,
|
|
59
|
+
float: 3,
|
|
60
|
+
boolean: 4,
|
|
61
|
+
json: 5,
|
|
62
|
+
bytes: 6,
|
|
63
|
+
blob_ref: 7,
|
|
64
|
+
crdt: 8,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const TAG_TO_TYPE = new Map<number, ColumnType>(
|
|
68
|
+
Object.entries(TYPE_TO_TAG).map(([type, tag]) => [tag, type as ColumnType]),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export function columnTypeTag(type: ColumnType): number {
|
|
72
|
+
return TYPE_TO_TAG[type];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function columnTypeFromTag(tag: number): ColumnType {
|
|
76
|
+
const type = TAG_TO_TYPE.get(tag);
|
|
77
|
+
if (type === undefined) {
|
|
78
|
+
throw new DecodeError(
|
|
79
|
+
'sync.invalid_request',
|
|
80
|
+
`unknown column type tag ${tag}`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return type;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function writeValue(
|
|
87
|
+
writer: ByteWriter,
|
|
88
|
+
column: RowColumn,
|
|
89
|
+
value: Exclude<RowValue, null>,
|
|
90
|
+
): void {
|
|
91
|
+
switch (column.type) {
|
|
92
|
+
case 'string':
|
|
93
|
+
case 'json':
|
|
94
|
+
case 'blob_ref':
|
|
95
|
+
if (typeof value !== 'string') {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`column ${column.name} (${column.type}) requires a string value`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
writer.str(value);
|
|
101
|
+
return;
|
|
102
|
+
case 'integer':
|
|
103
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`column ${column.name} (integer) requires a safe integer value`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
writer.i64(value);
|
|
109
|
+
return;
|
|
110
|
+
case 'float':
|
|
111
|
+
if (typeof value !== 'number') {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`column ${column.name} (float) requires a number value`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
writer.f64(value);
|
|
117
|
+
return;
|
|
118
|
+
case 'boolean':
|
|
119
|
+
if (typeof value !== 'boolean') {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`column ${column.name} (boolean) requires a boolean value`,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
writer.bool(value);
|
|
125
|
+
return;
|
|
126
|
+
case 'bytes':
|
|
127
|
+
case 'crdt':
|
|
128
|
+
// §2.4 tag 8: a `crdt` value is byte-for-byte a `bytes` value —
|
|
129
|
+
// opaque CRDT bytes (§5.10), no structural validation. `crdtType`
|
|
130
|
+
// selects the server merger and never touches the codec.
|
|
131
|
+
if (!(value instanceof Uint8Array)) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`column ${column.name} (${column.type}) requires a Uint8Array value`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
writer.bytes(value);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function readValue(reader: ByteReader, column: RowColumn): RowValue {
|
|
142
|
+
switch (column.type) {
|
|
143
|
+
case 'string':
|
|
144
|
+
return reader.str();
|
|
145
|
+
case 'json': {
|
|
146
|
+
// Conventions `json` MUST, applied at row-codec decode (SPEC.md §2.4
|
|
147
|
+
// tag 5): the value must parse as a JSON document; the raw string is
|
|
148
|
+
// preserved verbatim for round-trip fidelity.
|
|
149
|
+
const raw = reader.str();
|
|
150
|
+
try {
|
|
151
|
+
JSON.parse(raw);
|
|
152
|
+
} catch {
|
|
153
|
+
throw new DecodeError(
|
|
154
|
+
'sync.invalid_request',
|
|
155
|
+
`json column ${column.name} does not parse as a JSON document`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return raw;
|
|
159
|
+
}
|
|
160
|
+
case 'blob_ref': {
|
|
161
|
+
// §2.4 tag 7: the value is a canonical BlobRef JSON document
|
|
162
|
+
// (§5.9.1). Validated at decode, same class as tag-5 json; the raw
|
|
163
|
+
// string is preserved verbatim for re-encoding.
|
|
164
|
+
const raw = reader.str();
|
|
165
|
+
parseBlobRef(raw);
|
|
166
|
+
return raw;
|
|
167
|
+
}
|
|
168
|
+
case 'integer':
|
|
169
|
+
return reader.i64();
|
|
170
|
+
case 'float':
|
|
171
|
+
return reader.f64();
|
|
172
|
+
case 'boolean':
|
|
173
|
+
return reader.bool();
|
|
174
|
+
case 'bytes':
|
|
175
|
+
case 'crdt':
|
|
176
|
+
// §2.4 tag 8: opaque bytes, decoded exactly like tag 6 (no parse).
|
|
177
|
+
return reader.bytes();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function writeRow(
|
|
182
|
+
writer: ByteWriter,
|
|
183
|
+
columns: readonly RowColumn[],
|
|
184
|
+
values: readonly RowValue[],
|
|
185
|
+
): void {
|
|
186
|
+
if (values.length !== columns.length) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`row value count ${values.length} does not match column count ${columns.length}`,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
const bitmapLength = Math.ceil(columns.length / 8);
|
|
192
|
+
const bitmap = new Uint8Array(bitmapLength);
|
|
193
|
+
for (let i = 0; i < columns.length; i++) {
|
|
194
|
+
const column = columns[i];
|
|
195
|
+
if (column === undefined) continue;
|
|
196
|
+
if (values[i] === null) {
|
|
197
|
+
if (!column.nullable) {
|
|
198
|
+
throw new Error(`column ${column.name} is not nullable`);
|
|
199
|
+
}
|
|
200
|
+
bitmap[i >> 3] = (bitmap[i >> 3] ?? 0) | (1 << (i & 7));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
writer.raw(bitmap);
|
|
204
|
+
for (let i = 0; i < columns.length; i++) {
|
|
205
|
+
const column = columns[i];
|
|
206
|
+
const value = values[i];
|
|
207
|
+
if (column === undefined || value === null || value === undefined) continue;
|
|
208
|
+
writeValue(writer, column, value);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function readRow(
|
|
213
|
+
reader: ByteReader,
|
|
214
|
+
columns: readonly RowColumn[],
|
|
215
|
+
): RowValue[] {
|
|
216
|
+
const bitmapLength = Math.ceil(columns.length / 8);
|
|
217
|
+
const bitmap = reader.raw(bitmapLength);
|
|
218
|
+
for (let i = columns.length; i < bitmapLength * 8; i++) {
|
|
219
|
+
if ((((bitmap[i >> 3] ?? 0) >> (i & 7)) & 1) !== 0) {
|
|
220
|
+
throw new DecodeError(
|
|
221
|
+
'sync.invalid_request',
|
|
222
|
+
'non-zero padding bit in row null bitmap',
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const values: RowValue[] = [];
|
|
227
|
+
for (let i = 0; i < columns.length; i++) {
|
|
228
|
+
const column = columns[i];
|
|
229
|
+
if (column === undefined) continue;
|
|
230
|
+
const isNull = (((bitmap[i >> 3] ?? 0) >> (i & 7)) & 1) !== 0;
|
|
231
|
+
if (isNull) {
|
|
232
|
+
if (!column.nullable) {
|
|
233
|
+
throw new DecodeError(
|
|
234
|
+
'sync.invalid_request',
|
|
235
|
+
`null bit set for non-nullable column ${column.name}`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
values.push(null);
|
|
239
|
+
} else {
|
|
240
|
+
values.push(readValue(reader, column));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return values;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Encode one standalone row (e.g. a push payload or conflict serverRow). */
|
|
247
|
+
export function encodeRow(
|
|
248
|
+
columns: readonly RowColumn[],
|
|
249
|
+
values: readonly RowValue[],
|
|
250
|
+
): Uint8Array {
|
|
251
|
+
const writer = new ByteWriter();
|
|
252
|
+
writeRow(writer, columns, values);
|
|
253
|
+
return writer.finish();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Decode one standalone row; the bytes must contain exactly one row. */
|
|
257
|
+
export function decodeRow(
|
|
258
|
+
columns: readonly RowColumn[],
|
|
259
|
+
bytes: Uint8Array,
|
|
260
|
+
): RowValue[] {
|
|
261
|
+
const reader = new ByteReader(bytes);
|
|
262
|
+
const values = readRow(reader, columns);
|
|
263
|
+
reader.expectFullyConsumed('row payload');
|
|
264
|
+
return values;
|
|
265
|
+
}
|
package/src/segment.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSG2 rows segments (SPEC.md §5.2) — the mandatory bootstrap format.
|
|
3
|
+
*
|
|
4
|
+
* A standalone binary container: magic, format version, flags, a column
|
|
5
|
+
* descriptor header (validation checksum, never inference), then
|
|
6
|
+
* self-delimiting row blocks terminated by a mandatory `rowCount = 0` end
|
|
7
|
+
* marker. Each row record carries the row's current `server_version`
|
|
8
|
+
* (`serverVersion`, ≥ 1) ahead of the row-codec bytes, so segment-applied
|
|
9
|
+
* rows participate in §6.2 conflict detection (§5.6).
|
|
10
|
+
*/
|
|
11
|
+
import { ByteReader, ByteWriter, utf8Encode } from './bytes';
|
|
12
|
+
import { DecodeError } from './errors';
|
|
13
|
+
import {
|
|
14
|
+
columnTypeFromTag,
|
|
15
|
+
columnTypeTag,
|
|
16
|
+
type RowColumn,
|
|
17
|
+
type RowValue,
|
|
18
|
+
readRow,
|
|
19
|
+
writeRow,
|
|
20
|
+
} from './row-codec';
|
|
21
|
+
|
|
22
|
+
export const ROWS_SEGMENT_MAGIC = 'SSG2';
|
|
23
|
+
export const ROWS_SEGMENT_FORMAT_VERSION = 1;
|
|
24
|
+
|
|
25
|
+
const MAGIC_BYTES = utf8Encode(ROWS_SEGMENT_MAGIC);
|
|
26
|
+
|
|
27
|
+
/** One §5.2 row record: the row's `server_version` plus its values. */
|
|
28
|
+
export interface SegmentRow {
|
|
29
|
+
/** The row's `server_version` at `asOfCommitSeq` (§2.2); always ≥ 1. */
|
|
30
|
+
readonly serverVersion: number;
|
|
31
|
+
readonly values: readonly RowValue[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface RowsSegment {
|
|
35
|
+
readonly table: string;
|
|
36
|
+
readonly schemaVersion: number;
|
|
37
|
+
readonly columns: readonly RowColumn[];
|
|
38
|
+
/** Row blocks in wire order; each block is applied in one transaction. */
|
|
39
|
+
readonly blocks: readonly (readonly SegmentRow[])[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function encodeRowsSegment(segment: RowsSegment): Uint8Array {
|
|
43
|
+
const writer = new ByteWriter();
|
|
44
|
+
writer.raw(MAGIC_BYTES);
|
|
45
|
+
writer.u16(ROWS_SEGMENT_FORMAT_VERSION);
|
|
46
|
+
writer.u16(0);
|
|
47
|
+
writer.str(segment.table);
|
|
48
|
+
writer.i32(segment.schemaVersion);
|
|
49
|
+
writer.u16(segment.columns.length);
|
|
50
|
+
for (const column of segment.columns) {
|
|
51
|
+
writer.str(column.name);
|
|
52
|
+
writer.u8(columnTypeTag(column.type));
|
|
53
|
+
writer.u8(column.nullable ? 1 : 0);
|
|
54
|
+
}
|
|
55
|
+
for (const block of segment.blocks) {
|
|
56
|
+
if (block.length === 0) {
|
|
57
|
+
throw new Error('a rows-segment block must contain at least one row');
|
|
58
|
+
}
|
|
59
|
+
const rowsWriter = new ByteWriter();
|
|
60
|
+
for (const row of block) {
|
|
61
|
+
if (row.serverVersion < 1) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`a rows-segment row serverVersion must be >= 1, got ${row.serverVersion}`,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
rowsWriter.i64(row.serverVersion);
|
|
67
|
+
writeRow(rowsWriter, segment.columns, row.values);
|
|
68
|
+
}
|
|
69
|
+
const rows = rowsWriter.finish();
|
|
70
|
+
writer.u32(block.length);
|
|
71
|
+
writer.u32(rows.length);
|
|
72
|
+
writer.raw(rows);
|
|
73
|
+
}
|
|
74
|
+
writer.u32(0);
|
|
75
|
+
return writer.finish();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function decodeRowsSegment(bytes: Uint8Array): RowsSegment {
|
|
79
|
+
const reader = new ByteReader(bytes);
|
|
80
|
+
const magic = reader.raw(4);
|
|
81
|
+
if (
|
|
82
|
+
magic[0] !== MAGIC_BYTES[0] ||
|
|
83
|
+
magic[1] !== MAGIC_BYTES[1] ||
|
|
84
|
+
magic[2] !== MAGIC_BYTES[2] ||
|
|
85
|
+
magic[3] !== MAGIC_BYTES[3]
|
|
86
|
+
) {
|
|
87
|
+
throw new DecodeError('sync.invalid_request', 'bad rows segment magic');
|
|
88
|
+
}
|
|
89
|
+
const formatVersion = reader.u16();
|
|
90
|
+
if (formatVersion !== ROWS_SEGMENT_FORMAT_VERSION) {
|
|
91
|
+
throw new DecodeError(
|
|
92
|
+
'sync.invalid_request',
|
|
93
|
+
`unsupported rows segment format version ${formatVersion}`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const flags = reader.u16();
|
|
97
|
+
if (flags !== 0) {
|
|
98
|
+
throw new DecodeError(
|
|
99
|
+
'sync.invalid_request',
|
|
100
|
+
`non-zero rows segment flags 0x${flags.toString(16)}`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const table = reader.str();
|
|
104
|
+
const schemaVersion = reader.i32();
|
|
105
|
+
const columnCount = reader.u16();
|
|
106
|
+
const columns: RowColumn[] = [];
|
|
107
|
+
for (let i = 0; i < columnCount; i++) {
|
|
108
|
+
const name = reader.str();
|
|
109
|
+
const type = columnTypeFromTag(reader.u8());
|
|
110
|
+
const columnFlags = reader.u8();
|
|
111
|
+
if ((columnFlags & 0xfe) !== 0) {
|
|
112
|
+
throw new DecodeError(
|
|
113
|
+
'sync.invalid_request',
|
|
114
|
+
`reserved column flag bits set for column ${name}`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
columns.push({ name, type, nullable: columnFlags === 1 });
|
|
118
|
+
}
|
|
119
|
+
const blocks: SegmentRow[][] = [];
|
|
120
|
+
for (;;) {
|
|
121
|
+
if (reader.remaining < 4) {
|
|
122
|
+
throw new DecodeError(
|
|
123
|
+
'sync.invalid_request',
|
|
124
|
+
'rows segment truncated: missing end marker',
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
const rowCount = reader.u32();
|
|
128
|
+
if (rowCount === 0) {
|
|
129
|
+
reader.expectFullyConsumed('rows segment end marker');
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
const byteLength = reader.u32();
|
|
133
|
+
const rowBytes = reader.raw(byteLength);
|
|
134
|
+
const blockReader = new ByteReader(rowBytes);
|
|
135
|
+
const block: SegmentRow[] = [];
|
|
136
|
+
for (let i = 0; i < rowCount; i++) {
|
|
137
|
+
const serverVersion = blockReader.i64();
|
|
138
|
+
if (serverVersion < 1) {
|
|
139
|
+
throw new DecodeError(
|
|
140
|
+
'sync.invalid_request',
|
|
141
|
+
`rows segment row serverVersion must be >= 1, got ${serverVersion}`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
block.push({ serverVersion, values: readRow(blockReader, columns) });
|
|
145
|
+
}
|
|
146
|
+
blockReader.expectFullyConsumed('rows block');
|
|
147
|
+
blocks.push(block);
|
|
148
|
+
}
|
|
149
|
+
return { table, schemaVersion, columns, blocks };
|
|
150
|
+
}
|
package/src/stream.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental SSP2 message-stream scanner (SPEC.md §1.4, §8.7).
|
|
3
|
+
*
|
|
4
|
+
* The envelope grammar is self-delimiting — an 8-byte header, then
|
|
5
|
+
* length-prefixed frames until `END` — so a byte stream split across
|
|
6
|
+
* arbitrary chunk boundaries (WebSocket messages, §8.7) needs no
|
|
7
|
+
* reassembly protocol beyond concatenation plus this scanner: feed
|
|
8
|
+
* chunks, learn exactly where one complete envelope ends. Used by the
|
|
9
|
+
* server session (request assembly, pipelining detection), the client
|
|
10
|
+
* (response assembly), and the conformance harness (round attribution).
|
|
11
|
+
*
|
|
12
|
+
* The scanner validates only the 8-byte header (a stream whose header is
|
|
13
|
+
* not a valid SSP2 envelope has no findable end, §8.7 connection-fatal
|
|
14
|
+
* rule) and walks frame length prefixes; full decoding stays with
|
|
15
|
+
* `decodeMessage`.
|
|
16
|
+
*/
|
|
17
|
+
import { utf8Encode } from './bytes';
|
|
18
|
+
import { PROTOCOL_WIRE_VERSION, SYNC_PACK_MAGIC } from './constants';
|
|
19
|
+
import { DecodeError } from './errors';
|
|
20
|
+
|
|
21
|
+
const MAGIC = utf8Encode(SYNC_PACK_MAGIC);
|
|
22
|
+
/** `END` frame type byte (§1.2). */
|
|
23
|
+
const END_FRAME_TYPE = 0x00;
|
|
24
|
+
|
|
25
|
+
export interface ScannedMessage {
|
|
26
|
+
/** The complete envelope bytes (header through the END frame). */
|
|
27
|
+
readonly message: Uint8Array;
|
|
28
|
+
/** Byte count buffered PAST the END frame — a §8.7 stream MUST end
|
|
29
|
+
* exactly at the END frame's last byte, so any excess is a protocol
|
|
30
|
+
* violation (pipelining) for the caller to act on. */
|
|
31
|
+
readonly excess: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class MessageStreamScanner {
|
|
35
|
+
#buffer = new Uint8Array(1024);
|
|
36
|
+
#length = 0;
|
|
37
|
+
/** Parse cursor: start of the next frame header; -1 while the 8-byte
|
|
38
|
+
* envelope header is still incomplete. */
|
|
39
|
+
#offset = -1;
|
|
40
|
+
#complete = false;
|
|
41
|
+
|
|
42
|
+
/** True once any bytes were fed. */
|
|
43
|
+
get started(): boolean {
|
|
44
|
+
return this.#length > 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Feed one chunk. Returns the completed message once the END frame is
|
|
49
|
+
* fully buffered, `undefined` while more bytes are needed. Throws
|
|
50
|
+
* `DecodeError` on an invalid envelope header (connection-fatal per
|
|
51
|
+
* §8.7) and plain `Error` on use after completion.
|
|
52
|
+
*/
|
|
53
|
+
push(chunk: Uint8Array): ScannedMessage | undefined {
|
|
54
|
+
if (this.#complete) {
|
|
55
|
+
throw new Error('MessageStreamScanner: message already complete');
|
|
56
|
+
}
|
|
57
|
+
this.#append(chunk);
|
|
58
|
+
if (this.#offset < 0) {
|
|
59
|
+
if (this.#length < 8) return undefined;
|
|
60
|
+
this.#checkHeader();
|
|
61
|
+
this.#offset = 8;
|
|
62
|
+
}
|
|
63
|
+
for (;;) {
|
|
64
|
+
if (this.#length - this.#offset < 5) return undefined;
|
|
65
|
+
const frameType = this.#buffer[this.#offset] as number;
|
|
66
|
+
const view = new DataView(
|
|
67
|
+
this.#buffer.buffer,
|
|
68
|
+
this.#buffer.byteOffset + this.#offset + 1,
|
|
69
|
+
4,
|
|
70
|
+
);
|
|
71
|
+
const frameLength = view.getUint32(0, true);
|
|
72
|
+
const frameEnd = this.#offset + 5 + frameLength;
|
|
73
|
+
if (this.#length < frameEnd) return undefined;
|
|
74
|
+
this.#offset = frameEnd;
|
|
75
|
+
if (frameType === END_FRAME_TYPE) {
|
|
76
|
+
this.#complete = true;
|
|
77
|
+
return {
|
|
78
|
+
message: this.#buffer.subarray(0, frameEnd),
|
|
79
|
+
excess: this.#length - frameEnd,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#append(chunk: Uint8Array): void {
|
|
86
|
+
const needed = this.#length + chunk.length;
|
|
87
|
+
if (needed > this.#buffer.length) {
|
|
88
|
+
let capacity = this.#buffer.length;
|
|
89
|
+
while (capacity < needed) capacity *= 2;
|
|
90
|
+
const grown = new Uint8Array(capacity);
|
|
91
|
+
grown.set(this.#buffer.subarray(0, this.#length));
|
|
92
|
+
this.#buffer = grown;
|
|
93
|
+
}
|
|
94
|
+
this.#buffer.set(chunk, this.#length);
|
|
95
|
+
this.#length = needed;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#checkHeader(): void {
|
|
99
|
+
const b = this.#buffer;
|
|
100
|
+
if (
|
|
101
|
+
b[0] !== MAGIC[0] ||
|
|
102
|
+
b[1] !== MAGIC[1] ||
|
|
103
|
+
b[2] !== MAGIC[2] ||
|
|
104
|
+
b[3] !== MAGIC[3]
|
|
105
|
+
) {
|
|
106
|
+
throw new DecodeError('sync.invalid_request', 'bad envelope magic');
|
|
107
|
+
}
|
|
108
|
+
const wireVersion = (b[4] as number) | ((b[5] as number) << 8);
|
|
109
|
+
if (wireVersion !== PROTOCOL_WIRE_VERSION) {
|
|
110
|
+
throw new DecodeError(
|
|
111
|
+
'sync.invalid_request',
|
|
112
|
+
`unsupported wireVersion ${wireVersion}`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
if (b[6] !== 0x01 && b[6] !== 0x02) {
|
|
116
|
+
throw new DecodeError(
|
|
117
|
+
'sync.invalid_request',
|
|
118
|
+
`unknown msgKind byte 0x${(b[6] as number).toString(16)}`,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
if (b[7] !== 0x00) {
|
|
122
|
+
throw new DecodeError(
|
|
123
|
+
'sync.invalid_request',
|
|
124
|
+
`non-zero envelope flags 0x${(b[7] as number).toString(16)}`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
package/dist/blobs.d.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @syncular/core - Blob types for media/binary handling
|
|
3
|
-
*
|
|
4
|
-
* Content-addressable blob storage with presigned URL support.
|
|
5
|
-
* Protocol types (BlobRef, BlobMetadata, etc.) live in ./schemas/blobs.ts
|
|
6
|
-
*/
|
|
7
|
-
import type { BlobRef } from './schemas/blobs';
|
|
8
|
-
/**
|
|
9
|
-
* Transport interface for client-server blob communication.
|
|
10
|
-
* This is used by the client blob manager to communicate with the server.
|
|
11
|
-
*/
|
|
12
|
-
export interface BlobTransport {
|
|
13
|
-
/**
|
|
14
|
-
* Initiate a blob upload.
|
|
15
|
-
* Returns presigned URL info or indicates blob already exists (dedup).
|
|
16
|
-
*/
|
|
17
|
-
initiateUpload(args: {
|
|
18
|
-
hash: string;
|
|
19
|
-
size: number;
|
|
20
|
-
mimeType: string;
|
|
21
|
-
}): Promise<{
|
|
22
|
-
exists: boolean;
|
|
23
|
-
uploadUrl?: string;
|
|
24
|
-
uploadMethod?: 'PUT' | 'POST';
|
|
25
|
-
uploadHeaders?: Record<string, string>;
|
|
26
|
-
}>;
|
|
27
|
-
/**
|
|
28
|
-
* Complete a blob upload.
|
|
29
|
-
* Call this after uploading to the presigned URL.
|
|
30
|
-
*/
|
|
31
|
-
completeUpload(hash: string): Promise<{
|
|
32
|
-
ok: boolean;
|
|
33
|
-
error?: string;
|
|
34
|
-
}>;
|
|
35
|
-
/**
|
|
36
|
-
* Get a presigned download URL.
|
|
37
|
-
*/
|
|
38
|
-
getDownloadUrl(hash: string): Promise<{
|
|
39
|
-
url: string;
|
|
40
|
-
expiresAt: string;
|
|
41
|
-
}>;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Options for signing an upload URL.
|
|
45
|
-
*/
|
|
46
|
-
export interface BlobSignUploadOptions {
|
|
47
|
-
/** SHA-256 hash (for naming and checksum validation) */
|
|
48
|
-
hash: string;
|
|
49
|
-
/** Optional tenant/partition namespace for storage lookups */
|
|
50
|
-
partitionId?: string;
|
|
51
|
-
/** Content size in bytes */
|
|
52
|
-
size: number;
|
|
53
|
-
/** MIME type */
|
|
54
|
-
mimeType: string;
|
|
55
|
-
/** URL expiration in seconds */
|
|
56
|
-
expiresIn: number;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Result of signing an upload URL.
|
|
60
|
-
*/
|
|
61
|
-
export interface BlobSignedUpload {
|
|
62
|
-
/** The URL to upload to */
|
|
63
|
-
url: string;
|
|
64
|
-
/** HTTP method */
|
|
65
|
-
method: 'PUT' | 'POST';
|
|
66
|
-
/** Required headers */
|
|
67
|
-
headers?: Record<string, string>;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Options for signing a download URL.
|
|
71
|
-
*/
|
|
72
|
-
export interface BlobSignDownloadOptions {
|
|
73
|
-
/** SHA-256 hash */
|
|
74
|
-
hash: string;
|
|
75
|
-
/** Optional tenant/partition namespace for storage lookups */
|
|
76
|
-
partitionId?: string;
|
|
77
|
-
/** URL expiration in seconds */
|
|
78
|
-
expiresIn: number;
|
|
79
|
-
}
|
|
80
|
-
export interface BlobStoragePartitionOptions {
|
|
81
|
-
partitionId?: string;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Adapter for blob storage backends (S3, R2, custom).
|
|
85
|
-
* Implementations handle actual storage; the sync server orchestrates.
|
|
86
|
-
*/
|
|
87
|
-
export interface BlobStorageAdapter {
|
|
88
|
-
/** Adapter name for logging/debugging */
|
|
89
|
-
readonly name: string;
|
|
90
|
-
/**
|
|
91
|
-
* Generate a presigned URL for uploading a blob.
|
|
92
|
-
* The URL should enforce checksum validation if the backend supports it.
|
|
93
|
-
*/
|
|
94
|
-
signUpload(options: BlobSignUploadOptions): Promise<BlobSignedUpload>;
|
|
95
|
-
/**
|
|
96
|
-
* Generate a presigned URL for downloading a blob.
|
|
97
|
-
*/
|
|
98
|
-
signDownload(options: BlobSignDownloadOptions): Promise<string>;
|
|
99
|
-
/**
|
|
100
|
-
* Check if a blob exists in storage.
|
|
101
|
-
*/
|
|
102
|
-
exists(hash: string, options?: BlobStoragePartitionOptions): Promise<boolean>;
|
|
103
|
-
/**
|
|
104
|
-
* Delete a blob (for garbage collection).
|
|
105
|
-
*/
|
|
106
|
-
delete(hash: string, options?: BlobStoragePartitionOptions): Promise<void>;
|
|
107
|
-
/**
|
|
108
|
-
* Get blob metadata from storage (optional).
|
|
109
|
-
* Used to verify uploads completed successfully.
|
|
110
|
-
*/
|
|
111
|
-
getMetadata?(hash: string, options?: BlobStoragePartitionOptions): Promise<{
|
|
112
|
-
size: number;
|
|
113
|
-
mimeType?: string;
|
|
114
|
-
} | null>;
|
|
115
|
-
/**
|
|
116
|
-
* Store blob data directly (for adapters that support direct storage).
|
|
117
|
-
* Used for snapshot chunks and other internal data.
|
|
118
|
-
*/
|
|
119
|
-
put?(hash: string, data: Uint8Array, metadata?: Record<string, unknown>, options?: BlobStoragePartitionOptions): Promise<void>;
|
|
120
|
-
/**
|
|
121
|
-
* Store blob data directly from a stream.
|
|
122
|
-
* Preferred for large payloads to avoid full buffering in memory.
|
|
123
|
-
*/
|
|
124
|
-
putStream?(hash: string, stream: ReadableStream<Uint8Array>, metadata?: Record<string, unknown>, options?: BlobStoragePartitionOptions): Promise<void>;
|
|
125
|
-
/**
|
|
126
|
-
* Get blob data directly (for adapters that support direct retrieval).
|
|
127
|
-
*/
|
|
128
|
-
get?(hash: string, options?: BlobStoragePartitionOptions): Promise<Uint8Array | null>;
|
|
129
|
-
/**
|
|
130
|
-
* Get blob data directly as a stream (for adapters that support stream retrieval).
|
|
131
|
-
*/
|
|
132
|
-
getStream?(hash: string, options?: BlobStoragePartitionOptions): Promise<ReadableStream<Uint8Array> | null>;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Create a BlobRef from upload metadata.
|
|
136
|
-
*/
|
|
137
|
-
export declare function createBlobRef(args: {
|
|
138
|
-
hash: string;
|
|
139
|
-
size: number;
|
|
140
|
-
mimeType: string;
|
|
141
|
-
encrypted?: boolean;
|
|
142
|
-
keyId?: string;
|
|
143
|
-
}): BlobRef;
|
|
144
|
-
/**
|
|
145
|
-
* Parse a blob hash, validating format.
|
|
146
|
-
* @returns The hex hash without prefix, or null if invalid.
|
|
147
|
-
*/
|
|
148
|
-
export declare function parseBlobHash(hash: string): string | null;
|
|
149
|
-
/**
|
|
150
|
-
* Create a blob hash string from hex.
|
|
151
|
-
*/
|
|
152
|
-
export declare function createBlobHash(hexHash: string): string;
|
|
153
|
-
//# sourceMappingURL=blobs.d.ts.map
|
package/dist/blobs.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"blobs.d.ts","sourceRoot":"","sources":["../src/blobs.ts"],"names":[],"mappings":"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"}
|