@laserdata/laser-sdk 0.1.1 → 0.2.1
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 +65 -5
- package/dist/agent/reliable-consumer.d.ts.map +1 -1
- package/dist/agent/reliable-consumer.js +1 -0
- package/dist/agent/reliable-consumer.js.map +1 -1
- package/dist/agent/workflow.d.ts +2 -0
- package/dist/agent/workflow.d.ts.map +1 -1
- package/dist/agent/workflow.js +114 -13
- package/dist/agent/workflow.js.map +1 -1
- package/dist/bridges/a2a.d.ts +1 -1
- package/dist/bridges/a2a.js +1 -1
- package/dist/client/capabilities.d.ts +14 -1
- package/dist/client/capabilities.d.ts.map +1 -1
- package/dist/client/capabilities.js +57 -23
- package/dist/client/capabilities.js.map +1 -1
- package/dist/client/errors.d.ts +6 -1
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +5 -0
- package/dist/client/errors.js.map +1 -1
- package/dist/client/laser.d.ts +8 -0
- package/dist/client/laser.d.ts.map +1 -1
- package/dist/client/laser.js +42 -10
- package/dist/client/laser.js.map +1 -1
- package/dist/client/managed.d.ts +3 -1
- package/dist/client/managed.d.ts.map +1 -1
- package/dist/client/managed.js +2 -2
- package/dist/client/managed.js.map +1 -1
- package/dist/full.d.ts +1 -0
- package/dist/full.d.ts.map +1 -1
- package/dist/full.js +1 -0
- package/dist/full.js.map +1 -1
- package/dist/iggy/apache-iggy.d.ts +6 -2
- package/dist/iggy/apache-iggy.d.ts.map +1 -1
- package/dist/iggy/apache-iggy.js +11 -10
- package/dist/iggy/apache-iggy.js.map +1 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/managed/batch.d.ts.map +1 -1
- package/dist/managed/batch.js +23 -2
- package/dist/managed/batch.js.map +1 -1
- package/dist/managed/destinations.d.ts +19 -0
- package/dist/managed/destinations.d.ts.map +1 -0
- package/dist/managed/destinations.js +90 -0
- package/dist/managed/destinations.js.map +1 -0
- package/dist/managed/kv.d.ts +33 -6
- package/dist/managed/kv.d.ts.map +1 -1
- package/dist/managed/kv.js +99 -17
- package/dist/managed/kv.js.map +1 -1
- package/dist/managed/query.d.ts +26 -19
- package/dist/managed/query.d.ts.map +1 -1
- package/dist/managed/query.js +97 -55
- package/dist/managed/query.js.map +1 -1
- package/dist/stream/publish.d.ts +3 -0
- package/dist/stream/publish.d.ts.map +1 -1
- package/dist/stream/publish.js +25 -0
- package/dist/stream/publish.js.map +1 -1
- package/dist/stream/record.d.ts +4 -1
- package/dist/stream/record.d.ts.map +1 -1
- package/dist/stream/record.js +34 -3
- package/dist/stream/record.js.map +1 -1
- package/dist/wire/arrow.d.ts +39 -0
- package/dist/wire/arrow.d.ts.map +1 -0
- package/dist/wire/arrow.js +133 -0
- package/dist/wire/arrow.js.map +1 -0
- package/dist/wire/authz.d.ts +2 -2
- package/dist/wire/authz.d.ts.map +1 -1
- package/dist/wire/authz.js +39 -20
- package/dist/wire/authz.js.map +1 -1
- package/dist/wire/cbor.d.ts +9 -1
- package/dist/wire/cbor.d.ts.map +1 -1
- package/dist/wire/cbor.js +45 -2
- package/dist/wire/cbor.js.map +1 -1
- package/dist/wire/checkpoint.d.ts +386 -0
- package/dist/wire/checkpoint.d.ts.map +1 -0
- package/dist/wire/checkpoint.js +1373 -0
- package/dist/wire/checkpoint.js.map +1 -0
- package/dist/wire/codes.d.ts +10 -0
- package/dist/wire/codes.d.ts.map +1 -1
- package/dist/wire/codes.js +14 -0
- package/dist/wire/codes.js.map +1 -1
- package/dist/wire/commands.d.ts +14 -5
- package/dist/wire/commands.d.ts.map +1 -1
- package/dist/wire/commands.js +75 -7
- package/dist/wire/commands.js.map +1 -1
- package/dist/wire/control.d.ts +3 -12
- package/dist/wire/control.d.ts.map +1 -1
- package/dist/wire/control.js +10 -43
- package/dist/wire/control.js.map +1 -1
- package/dist/wire/destination.d.ts +86 -0
- package/dist/wire/destination.d.ts.map +1 -0
- package/dist/wire/destination.js +251 -0
- package/dist/wire/destination.js.map +1 -0
- package/dist/wire/headers.d.ts +1 -0
- package/dist/wire/headers.d.ts.map +1 -1
- package/dist/wire/headers.js +1 -0
- package/dist/wire/headers.js.map +1 -1
- package/dist/wire/hello.d.ts +83 -11
- package/dist/wire/hello.d.ts.map +1 -1
- package/dist/wire/hello.js +292 -73
- package/dist/wire/hello.js.map +1 -1
- package/dist/wire/http.d.ts +153 -1
- package/dist/wire/http.d.ts.map +1 -1
- package/dist/wire/http.js +491 -10
- package/dist/wire/http.js.map +1 -1
- package/dist/wire/ids.d.ts +60 -0
- package/dist/wire/ids.d.ts.map +1 -1
- package/dist/wire/ids.js +143 -0
- package/dist/wire/ids.js.map +1 -1
- package/dist/wire/index.d.ts +5 -0
- package/dist/wire/index.d.ts.map +1 -1
- package/dist/wire/index.js +5 -0
- package/dist/wire/index.js.map +1 -1
- package/dist/wire/kv.d.ts +35 -0
- package/dist/wire/kv.d.ts.map +1 -1
- package/dist/wire/kv.js +178 -18
- package/dist/wire/kv.js.map +1 -1
- package/dist/wire/limits.d.ts +10 -0
- package/dist/wire/limits.d.ts.map +1 -1
- package/dist/wire/limits.js +10 -0
- package/dist/wire/limits.js.map +1 -1
- package/dist/wire/mutation.d.ts +10 -0
- package/dist/wire/mutation.d.ts.map +1 -1
- package/dist/wire/mutation.js +14 -0
- package/dist/wire/mutation.js.map +1 -1
- package/dist/wire/query.d.ts +192 -97
- package/dist/wire/query.d.ts.map +1 -1
- package/dist/wire/query.js +968 -443
- package/dist/wire/query.js.map +1 -1
- package/dist/wire/result.d.ts +6 -0
- package/dist/wire/result.d.ts.map +1 -1
- package/dist/wire/result.js +19 -2
- package/dist/wire/result.js.map +1 -1
- package/dist/wire/schema.d.ts +121 -0
- package/dist/wire/schema.d.ts.map +1 -0
- package/dist/wire/schema.js +778 -0
- package/dist/wire/schema.js.map +1 -0
- package/dist/wire/source.d.ts +35 -0
- package/dist/wire/source.d.ts.map +1 -0
- package/dist/wire/source.js +105 -0
- package/dist/wire/source.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
2
|
+
import { CodecError, InvalidError } from "../client/errors.js";
|
|
3
|
+
import { expectMap, field } from "./cbor.js";
|
|
4
|
+
import { LogicalSchemaId } from "./ids.js";
|
|
5
|
+
import { MAX_VALUE_BYTES } from "./limits.js";
|
|
6
|
+
export const MAX_LOGICAL_SCHEMA_DEPTH = 16;
|
|
7
|
+
export const MAX_LOGICAL_SCHEMA_FIELDS = 4096;
|
|
8
|
+
export const MAX_LOGICAL_SCHEMA_BYTES = 1_048_576;
|
|
9
|
+
export const MAX_FIELD_NAME_BYTES = 255;
|
|
10
|
+
export const MAX_FIELD_DOC_BYTES = 4096;
|
|
11
|
+
export const MAX_FIXED_BYTES = 1_048_576;
|
|
12
|
+
export const MAX_DECIMAL_PRECISION = 38;
|
|
13
|
+
export const MICROS_PER_DAY = 86400000000n;
|
|
14
|
+
export const PROVENANCE_FIELD_ID_START = 2_000_000_000;
|
|
15
|
+
export const PROVENANCE_FIELDS = [
|
|
16
|
+
[2_000_000_001, "__laser_cluster_incarnation"],
|
|
17
|
+
[2_000_000_002, "__laser_source_incarnation"],
|
|
18
|
+
[2_000_000_003, "__laser_stream_id"],
|
|
19
|
+
[2_000_000_004, "__laser_topic_id"],
|
|
20
|
+
[2_000_000_005, "__laser_partition_id"],
|
|
21
|
+
[2_000_000_006, "__laser_offset"],
|
|
22
|
+
[2_000_000_007, "__laser_row_ordinal"],
|
|
23
|
+
[2_000_000_008, "__laser_projection_id"],
|
|
24
|
+
[2_000_000_009, "__laser_projection_version"],
|
|
25
|
+
[2_000_000_010, "__laser_destination_id"],
|
|
26
|
+
[2_000_000_011, "__laser_destination_generation"],
|
|
27
|
+
[2_000_000_012, "__laser_original_payload"],
|
|
28
|
+
[2_000_000_013, "__laser_original_content_type"],
|
|
29
|
+
[2_000_000_014, "__laser_original_schema_id"]
|
|
30
|
+
];
|
|
31
|
+
export function encodeLogicalSchema(value) {
|
|
32
|
+
return new Map([
|
|
33
|
+
["schema", encodeLogicalSchemaRef(value.schema)],
|
|
34
|
+
["fields", value.fields.map(encodeLogicalField)]
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
export function decodeLogicalSchema(map, context) {
|
|
38
|
+
return {
|
|
39
|
+
schema: decodeLogicalSchemaRef(field.requiredMap(map, "schema", context), `${context}.schema`),
|
|
40
|
+
fields: field.requiredArray(map, "fields", context, (item, index) => decodeLogicalField(expectMap(item, `${context}.fields[${String(index)}]`), `${context}.fields[${String(index)}]`))
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function mapOf(entries) {
|
|
44
|
+
return new Map(entries);
|
|
45
|
+
}
|
|
46
|
+
export function encodeLogicalSchemaRef(value) {
|
|
47
|
+
return mapOf([
|
|
48
|
+
["id", value.id.toBytes()],
|
|
49
|
+
["version", value.version],
|
|
50
|
+
["fingerprint", value.fingerprint]
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
export function decodeLogicalSchemaRef(map, context) {
|
|
54
|
+
return {
|
|
55
|
+
id: LogicalSchemaId.fromBytes(field.requiredBytes(map, "id", context)),
|
|
56
|
+
version: field.requiredU32(map, "version", context),
|
|
57
|
+
fingerprint: fixedBytes(field.requiredBytes(map, "fingerprint", context), 32, `${context}.fingerprint`)
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function encodeLogicalField(value) {
|
|
61
|
+
const map = mapOf([
|
|
62
|
+
["id", value.id],
|
|
63
|
+
["name", value.name],
|
|
64
|
+
["required", value.required],
|
|
65
|
+
["field_type", encodeLogicalType(value.fieldType)]
|
|
66
|
+
]);
|
|
67
|
+
if (value.doc !== undefined)
|
|
68
|
+
map.set("doc", value.doc);
|
|
69
|
+
return map;
|
|
70
|
+
}
|
|
71
|
+
export function decodeLogicalField(map, context) {
|
|
72
|
+
const doc = field.optionalString(map, "doc", context);
|
|
73
|
+
return {
|
|
74
|
+
id: field.requiredU32(map, "id", context),
|
|
75
|
+
name: field.requiredString(map, "name", context),
|
|
76
|
+
required: field.requiredBoolean(map, "required", context),
|
|
77
|
+
fieldType: decodeLogicalType(field.requiredMap(map, "field_type", context), `${context}.field_type`),
|
|
78
|
+
...(doc === undefined ? {} : { doc })
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export function encodeLogicalType(value) {
|
|
82
|
+
const map = new Map([["kind", value.kind]]);
|
|
83
|
+
switch (value.kind) {
|
|
84
|
+
case "decimal":
|
|
85
|
+
map.set("precision", value.precision);
|
|
86
|
+
map.set("scale", value.scale);
|
|
87
|
+
break;
|
|
88
|
+
case "fixed":
|
|
89
|
+
map.set("length", value.length);
|
|
90
|
+
break;
|
|
91
|
+
case "struct":
|
|
92
|
+
map.set("fields", value.fields.map(encodeLogicalField));
|
|
93
|
+
break;
|
|
94
|
+
case "list":
|
|
95
|
+
map.set("element_id", value.elementId);
|
|
96
|
+
map.set("element_required", value.elementRequired);
|
|
97
|
+
map.set("element", encodeLogicalType(value.element));
|
|
98
|
+
break;
|
|
99
|
+
case "map":
|
|
100
|
+
map.set("key_id", value.keyId);
|
|
101
|
+
map.set("key", encodeLogicalType(value.key));
|
|
102
|
+
map.set("value_id", value.valueId);
|
|
103
|
+
map.set("value_required", value.valueRequired);
|
|
104
|
+
map.set("value", encodeLogicalType(value.value));
|
|
105
|
+
break;
|
|
106
|
+
case "boolean":
|
|
107
|
+
case "int":
|
|
108
|
+
case "long":
|
|
109
|
+
case "float":
|
|
110
|
+
case "double":
|
|
111
|
+
case "date":
|
|
112
|
+
case "time_micros":
|
|
113
|
+
case "timestamp_micros":
|
|
114
|
+
case "timestamp_tz_micros":
|
|
115
|
+
case "string":
|
|
116
|
+
case "uuid":
|
|
117
|
+
case "binary":
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
return map;
|
|
121
|
+
}
|
|
122
|
+
const PRIMITIVE_TYPES = new Set([
|
|
123
|
+
"boolean",
|
|
124
|
+
"int",
|
|
125
|
+
"long",
|
|
126
|
+
"float",
|
|
127
|
+
"double",
|
|
128
|
+
"date",
|
|
129
|
+
"time_micros",
|
|
130
|
+
"timestamp_micros",
|
|
131
|
+
"timestamp_tz_micros",
|
|
132
|
+
"string",
|
|
133
|
+
"uuid",
|
|
134
|
+
"binary"
|
|
135
|
+
]);
|
|
136
|
+
export function decodeLogicalType(map, context) {
|
|
137
|
+
const kind = field.requiredString(map, "kind", context);
|
|
138
|
+
if (PRIMITIVE_TYPES.has(kind))
|
|
139
|
+
return { kind };
|
|
140
|
+
switch (kind) {
|
|
141
|
+
case "decimal":
|
|
142
|
+
return {
|
|
143
|
+
kind,
|
|
144
|
+
precision: field.requiredU8(map, "precision", context),
|
|
145
|
+
scale: field.requiredU8(map, "scale", context)
|
|
146
|
+
};
|
|
147
|
+
case "fixed":
|
|
148
|
+
return { kind, length: field.requiredU32(map, "length", context) };
|
|
149
|
+
case "struct":
|
|
150
|
+
return {
|
|
151
|
+
kind,
|
|
152
|
+
fields: field.requiredArray(map, "fields", context, (item, index) => decodeLogicalField(expectMap(item, `${context}.fields[${String(index)}]`), `${context}.fields[${String(index)}]`))
|
|
153
|
+
};
|
|
154
|
+
case "list":
|
|
155
|
+
return {
|
|
156
|
+
kind,
|
|
157
|
+
elementId: field.requiredU32(map, "element_id", context),
|
|
158
|
+
elementRequired: field.requiredBoolean(map, "element_required", context),
|
|
159
|
+
element: decodeLogicalType(field.requiredMap(map, "element", context), `${context}.element`)
|
|
160
|
+
};
|
|
161
|
+
case "map":
|
|
162
|
+
return {
|
|
163
|
+
kind,
|
|
164
|
+
keyId: field.requiredU32(map, "key_id", context),
|
|
165
|
+
key: decodeLogicalType(field.requiredMap(map, "key", context), `${context}.key`),
|
|
166
|
+
valueId: field.requiredU32(map, "value_id", context),
|
|
167
|
+
valueRequired: field.requiredBoolean(map, "value_required", context),
|
|
168
|
+
value: decodeLogicalType(field.requiredMap(map, "value", context), `${context}.value`)
|
|
169
|
+
};
|
|
170
|
+
default:
|
|
171
|
+
throw new CodecError(`unknown logical type \`${kind}\``, context, "kind");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
export function encodeTypedValue(value) {
|
|
175
|
+
const map = new Map([["kind", value.kind]]);
|
|
176
|
+
if (value.kind === "null")
|
|
177
|
+
return map;
|
|
178
|
+
if (value.kind === "decimal")
|
|
179
|
+
map.set("value", mapOf([
|
|
180
|
+
["unscaled", value.value.unscaled],
|
|
181
|
+
["precision", value.value.precision],
|
|
182
|
+
["scale", value.value.scale]
|
|
183
|
+
]));
|
|
184
|
+
else if (value.kind === "struct")
|
|
185
|
+
map.set("value", value.value.map((entry) => mapOf([
|
|
186
|
+
["field_id", entry.fieldId],
|
|
187
|
+
["value", encodeTypedValue(entry.value)]
|
|
188
|
+
])));
|
|
189
|
+
else if (value.kind === "list")
|
|
190
|
+
map.set("value", value.value.map(encodeTypedValue));
|
|
191
|
+
else if (value.kind === "map")
|
|
192
|
+
map.set("value", value.value.map((entry) => mapOf([
|
|
193
|
+
["key", encodeTypedValue(entry.key)],
|
|
194
|
+
["value", encodeTypedValue(entry.value)]
|
|
195
|
+
])));
|
|
196
|
+
else
|
|
197
|
+
map.set("value", value.value);
|
|
198
|
+
return map;
|
|
199
|
+
}
|
|
200
|
+
export function decodeTypedValue(value, context) {
|
|
201
|
+
const map = expectMap(value, context);
|
|
202
|
+
const kind = field.requiredString(map, "kind", context);
|
|
203
|
+
switch (kind) {
|
|
204
|
+
case "null":
|
|
205
|
+
return { kind };
|
|
206
|
+
case "boolean":
|
|
207
|
+
return { kind, value: field.requiredBoolean(map, "value", context) };
|
|
208
|
+
case "int":
|
|
209
|
+
return { kind, value: field.requiredI32(map, "value", context) };
|
|
210
|
+
case "long":
|
|
211
|
+
case "time_micros":
|
|
212
|
+
case "timestamp_micros":
|
|
213
|
+
case "timestamp_tz_micros":
|
|
214
|
+
return { kind, value: field.requiredI64(map, "value", context) };
|
|
215
|
+
case "date":
|
|
216
|
+
return { kind, value: field.requiredI32(map, "value", context) };
|
|
217
|
+
case "float":
|
|
218
|
+
case "double": {
|
|
219
|
+
const number = map.get("value");
|
|
220
|
+
if (typeof number !== "number")
|
|
221
|
+
throw new CodecError("typed float value must be a number", context, "value");
|
|
222
|
+
return { kind, value: number };
|
|
223
|
+
}
|
|
224
|
+
case "string":
|
|
225
|
+
return { kind, value: field.requiredString(map, "value", context) };
|
|
226
|
+
case "uuid":
|
|
227
|
+
return { kind, value: fixedBytes(field.requiredBytes(map, "value", context), 16, context) };
|
|
228
|
+
case "fixed":
|
|
229
|
+
case "binary":
|
|
230
|
+
return { kind, value: field.requiredBytes(map, "value", context) };
|
|
231
|
+
case "decimal": {
|
|
232
|
+
const decimal = field.requiredMap(map, "value", context);
|
|
233
|
+
return {
|
|
234
|
+
kind,
|
|
235
|
+
value: {
|
|
236
|
+
unscaled: field.requiredBytes(decimal, "unscaled", context),
|
|
237
|
+
precision: field.requiredU8(decimal, "precision", context),
|
|
238
|
+
scale: field.requiredU8(decimal, "scale", context)
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
case "struct":
|
|
243
|
+
return {
|
|
244
|
+
kind,
|
|
245
|
+
value: field.requiredArray(map, "value", context, (item, index) => {
|
|
246
|
+
const entry = expectMap(item, `${context}.value[${String(index)}]`);
|
|
247
|
+
return {
|
|
248
|
+
fieldId: field.requiredU32(entry, "field_id", context),
|
|
249
|
+
value: decodeTypedValue(entry.get("value"), context)
|
|
250
|
+
};
|
|
251
|
+
})
|
|
252
|
+
};
|
|
253
|
+
case "list":
|
|
254
|
+
return {
|
|
255
|
+
kind,
|
|
256
|
+
value: field.requiredArray(map, "value", context, (item, index) => decodeTypedValue(item, `${context}.value[${String(index)}]`))
|
|
257
|
+
};
|
|
258
|
+
case "map":
|
|
259
|
+
return {
|
|
260
|
+
kind,
|
|
261
|
+
value: field.requiredArray(map, "value", context, (item, index) => {
|
|
262
|
+
const entry = expectMap(item, `${context}.value[${String(index)}]`);
|
|
263
|
+
return {
|
|
264
|
+
key: decodeTypedValue(entry.get("key"), context),
|
|
265
|
+
value: decodeTypedValue(entry.get("value"), context)
|
|
266
|
+
};
|
|
267
|
+
})
|
|
268
|
+
};
|
|
269
|
+
default:
|
|
270
|
+
throw new CodecError(`unknown typed value \`${kind}\``, context, "kind");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function hex(value) {
|
|
274
|
+
return [...value].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
275
|
+
}
|
|
276
|
+
export function typedValueDiagnosticText(value) {
|
|
277
|
+
switch (value.kind) {
|
|
278
|
+
case "null":
|
|
279
|
+
return "null";
|
|
280
|
+
case "boolean":
|
|
281
|
+
case "int":
|
|
282
|
+
case "float":
|
|
283
|
+
case "double":
|
|
284
|
+
case "date":
|
|
285
|
+
return String(value.value);
|
|
286
|
+
case "long":
|
|
287
|
+
case "time_micros":
|
|
288
|
+
case "timestamp_micros":
|
|
289
|
+
case "timestamp_tz_micros":
|
|
290
|
+
return value.value.toString();
|
|
291
|
+
case "string":
|
|
292
|
+
return value.value;
|
|
293
|
+
case "uuid": {
|
|
294
|
+
const text = hex(value.value);
|
|
295
|
+
return `${text.slice(0, 8)}-${text.slice(8, 12)}-${text.slice(12, 16)}-${text.slice(16, 20)}-${text.slice(20)}`;
|
|
296
|
+
}
|
|
297
|
+
case "decimal":
|
|
298
|
+
return `0x${hex(value.value.unscaled)} scale ${String(value.value.scale)}`;
|
|
299
|
+
case "fixed":
|
|
300
|
+
case "binary":
|
|
301
|
+
return `0x${hex(value.value)}`;
|
|
302
|
+
case "struct":
|
|
303
|
+
case "list":
|
|
304
|
+
case "map":
|
|
305
|
+
return JSON.stringify(diagnosticJsonValue(encodeTypedValue(value)));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function diagnosticJsonValue(value) {
|
|
309
|
+
if (typeof value === "bigint")
|
|
310
|
+
return value.toString();
|
|
311
|
+
if (value instanceof Uint8Array)
|
|
312
|
+
return Array.from(value);
|
|
313
|
+
if (value instanceof Map) {
|
|
314
|
+
const object = {};
|
|
315
|
+
for (const [key, item] of value)
|
|
316
|
+
object[String(key)] = diagnosticJsonValue(item);
|
|
317
|
+
return object;
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(value))
|
|
320
|
+
return value.map(diagnosticJsonValue);
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
export function validateTypedValue(value, depth = 1) {
|
|
324
|
+
if (depth > MAX_LOGICAL_SCHEMA_DEPTH)
|
|
325
|
+
throw new InvalidError("typed value depth exceeds cap");
|
|
326
|
+
switch (value.kind) {
|
|
327
|
+
case "int":
|
|
328
|
+
case "date":
|
|
329
|
+
if (!Number.isInteger(value.value) ||
|
|
330
|
+
value.value < -2_147_483_648 ||
|
|
331
|
+
value.value > 2_147_483_647) {
|
|
332
|
+
throw new InvalidError("32-bit signed value is outside its bound");
|
|
333
|
+
}
|
|
334
|
+
break;
|
|
335
|
+
case "long":
|
|
336
|
+
case "timestamp_micros":
|
|
337
|
+
case "timestamp_tz_micros":
|
|
338
|
+
validateI64(value.value);
|
|
339
|
+
break;
|
|
340
|
+
case "float":
|
|
341
|
+
case "double":
|
|
342
|
+
if (!Number.isFinite(value.value) || Object.is(value.value, -0))
|
|
343
|
+
throw new InvalidError("floating values must be finite and cannot be negative zero");
|
|
344
|
+
break;
|
|
345
|
+
case "time_micros":
|
|
346
|
+
validateI64(value.value);
|
|
347
|
+
if (value.value < 0n || value.value >= MICROS_PER_DAY)
|
|
348
|
+
throw new InvalidError("time value is outside one day in microseconds");
|
|
349
|
+
break;
|
|
350
|
+
case "uuid":
|
|
351
|
+
fixedBytes(value.value, 16, "UUID");
|
|
352
|
+
break;
|
|
353
|
+
case "decimal":
|
|
354
|
+
validateDecimal(value.value);
|
|
355
|
+
break;
|
|
356
|
+
case "string":
|
|
357
|
+
if (new TextEncoder().encode(value.value).length > MAX_VALUE_BYTES) {
|
|
358
|
+
throw new InvalidError("string value exceeds its byte bound");
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
case "fixed":
|
|
362
|
+
if (value.value.length > MAX_FIXED_BYTES) {
|
|
363
|
+
throw new InvalidError("fixed value exceeds its byte bound");
|
|
364
|
+
}
|
|
365
|
+
break;
|
|
366
|
+
case "binary":
|
|
367
|
+
if (value.value.length > MAX_VALUE_BYTES) {
|
|
368
|
+
throw new InvalidError("binary value exceeds its byte bound");
|
|
369
|
+
}
|
|
370
|
+
break;
|
|
371
|
+
case "struct": {
|
|
372
|
+
if (value.value.length > MAX_LOGICAL_SCHEMA_FIELDS) {
|
|
373
|
+
throw new InvalidError("struct value count exceeds cap");
|
|
374
|
+
}
|
|
375
|
+
let previous = 0;
|
|
376
|
+
for (const entry of value.value) {
|
|
377
|
+
if (entry.fieldId <= previous)
|
|
378
|
+
throw new InvalidError("struct field values must use increasing positive field ids");
|
|
379
|
+
previous = entry.fieldId;
|
|
380
|
+
validateTypedValue(entry.value, depth + 1);
|
|
381
|
+
}
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
case "list":
|
|
385
|
+
if (value.value.length > MAX_LOGICAL_SCHEMA_FIELDS) {
|
|
386
|
+
throw new InvalidError("list value count exceeds cap");
|
|
387
|
+
}
|
|
388
|
+
for (const item of value.value)
|
|
389
|
+
validateTypedValue(item, depth + 1);
|
|
390
|
+
break;
|
|
391
|
+
case "map": {
|
|
392
|
+
if (value.value.length > MAX_LOGICAL_SCHEMA_FIELDS) {
|
|
393
|
+
throw new InvalidError("map value count exceeds cap");
|
|
394
|
+
}
|
|
395
|
+
let previous;
|
|
396
|
+
for (const entry of value.value) {
|
|
397
|
+
validateTypedValue(entry.key, depth + 1);
|
|
398
|
+
validateTypedValue(entry.value, depth + 1);
|
|
399
|
+
const key = canonicalMapKey(entry.key);
|
|
400
|
+
if (previous !== undefined && compareBytes(previous, key) >= 0)
|
|
401
|
+
throw new InvalidError("map entries must be ordered by canonical key");
|
|
402
|
+
previous = key;
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
case "null":
|
|
407
|
+
case "boolean":
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
export function validateTypedValueAgainst(value, logicalType, required) {
|
|
412
|
+
if (value.kind === "null") {
|
|
413
|
+
if (required)
|
|
414
|
+
throw new InvalidError("required value is null");
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
validateTypedValue(value);
|
|
418
|
+
switch (logicalType.kind) {
|
|
419
|
+
case "boolean":
|
|
420
|
+
case "int":
|
|
421
|
+
case "long":
|
|
422
|
+
case "float":
|
|
423
|
+
case "double":
|
|
424
|
+
case "date":
|
|
425
|
+
case "time_micros":
|
|
426
|
+
case "timestamp_micros":
|
|
427
|
+
case "timestamp_tz_micros":
|
|
428
|
+
case "string":
|
|
429
|
+
case "uuid":
|
|
430
|
+
case "binary":
|
|
431
|
+
if (value.kind !== logicalType.kind)
|
|
432
|
+
throw new InvalidError("typed value does not match logical type");
|
|
433
|
+
return;
|
|
434
|
+
case "decimal":
|
|
435
|
+
if (value.kind !== "decimal" ||
|
|
436
|
+
value.value.precision !== logicalType.precision ||
|
|
437
|
+
value.value.scale !== logicalType.scale)
|
|
438
|
+
throw new InvalidError("decimal value does not match logical type");
|
|
439
|
+
return;
|
|
440
|
+
case "fixed":
|
|
441
|
+
if (value.kind !== "fixed" || value.value.length !== logicalType.length)
|
|
442
|
+
throw new InvalidError("fixed value does not match logical type length");
|
|
443
|
+
return;
|
|
444
|
+
case "struct":
|
|
445
|
+
if (value.kind !== "struct" || value.value.length !== logicalType.fields.length)
|
|
446
|
+
throw new InvalidError("struct value does not match logical type");
|
|
447
|
+
for (let index = 0; index < logicalType.fields.length; index += 1) {
|
|
448
|
+
const field = logicalType.fields[index];
|
|
449
|
+
const entry = value.value[index];
|
|
450
|
+
if (field === undefined || entry?.fieldId !== field.id)
|
|
451
|
+
throw new InvalidError("struct field ids do not match logical type");
|
|
452
|
+
validateTypedValueAgainst(entry.value, field.fieldType, field.required);
|
|
453
|
+
}
|
|
454
|
+
return;
|
|
455
|
+
case "list":
|
|
456
|
+
if (value.kind !== "list")
|
|
457
|
+
throw new InvalidError("typed value does not match logical type");
|
|
458
|
+
for (const item of value.value)
|
|
459
|
+
validateTypedValueAgainst(item, logicalType.element, logicalType.elementRequired);
|
|
460
|
+
return;
|
|
461
|
+
case "map":
|
|
462
|
+
if (value.kind !== "map")
|
|
463
|
+
throw new InvalidError("typed value does not match logical type");
|
|
464
|
+
for (const entry of value.value) {
|
|
465
|
+
validateTypedValueAgainst(entry.key, logicalType.key, true);
|
|
466
|
+
validateTypedValueAgainst(entry.value, logicalType.value, logicalType.valueRequired);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
export function createLogicalSchema(id, version, fields) {
|
|
471
|
+
validateSchemaShape(id, version, fields);
|
|
472
|
+
const withoutFingerprint = {
|
|
473
|
+
schema: { id, version, fingerprint: new Uint8Array(32) },
|
|
474
|
+
fields
|
|
475
|
+
};
|
|
476
|
+
return {
|
|
477
|
+
...withoutFingerprint,
|
|
478
|
+
schema: { id, version, fingerprint: sha256(canonicalSchemaBytes(withoutFingerprint)) }
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
export function validateLogicalSchema(schema) {
|
|
482
|
+
validateSchemaShape(schema.schema.id, schema.schema.version, schema.fields);
|
|
483
|
+
const expected = sha256(canonicalSchemaBytes(schema));
|
|
484
|
+
if (!equalBytes(expected, schema.schema.fingerprint))
|
|
485
|
+
throw new InvalidError("logical schema fingerprint does not match canonical bytes");
|
|
486
|
+
}
|
|
487
|
+
export function validateResultFields(fields) {
|
|
488
|
+
if (fields.length === 0)
|
|
489
|
+
throw new InvalidError("query result schema must not be empty");
|
|
490
|
+
validateFieldShape(fields, true);
|
|
491
|
+
}
|
|
492
|
+
export function canonicalSchemaBytes(schema) {
|
|
493
|
+
validateSchemaShape(schema.schema.id, schema.schema.version, schema.fields);
|
|
494
|
+
const encoder = new SchemaEncoder();
|
|
495
|
+
encoder.bytes(new TextEncoder().encode("AGDX-SCHEMA-V1\0"));
|
|
496
|
+
encoder.bytes(schema.schema.id.toBytes());
|
|
497
|
+
encoder.u32(schema.schema.version);
|
|
498
|
+
encodeFingerprintFields(encoder, schema.fields);
|
|
499
|
+
const bytes = encoder.finish();
|
|
500
|
+
if (bytes.length > MAX_LOGICAL_SCHEMA_BYTES) {
|
|
501
|
+
throw new InvalidError("logical schema canonical bytes exceed cap");
|
|
502
|
+
}
|
|
503
|
+
return bytes;
|
|
504
|
+
}
|
|
505
|
+
function validateSchemaShape(id, version, fields) {
|
|
506
|
+
if (id.asU128() === 0n || version === 0 || fields.length === 0)
|
|
507
|
+
throw new InvalidError("logical schema identity, version, and fields must be nonzero");
|
|
508
|
+
validateFieldShape(fields, false);
|
|
509
|
+
}
|
|
510
|
+
function validateFieldShape(fields, allowTopLevelProvenance) {
|
|
511
|
+
const ids = new Set();
|
|
512
|
+
let count = 0;
|
|
513
|
+
let estimatedSize = 0;
|
|
514
|
+
const visit = (items, depth, allowProvenance) => {
|
|
515
|
+
if (depth > MAX_LOGICAL_SCHEMA_DEPTH)
|
|
516
|
+
throw new InvalidError("logical schema depth exceeds cap");
|
|
517
|
+
const names = new Set();
|
|
518
|
+
for (const item of items) {
|
|
519
|
+
const provenancePair = PROVENANCE_FIELDS.some(([reservedId, reservedName]) => reservedId === item.id && reservedName === item.name);
|
|
520
|
+
if (item.id <= 0 ||
|
|
521
|
+
ids.has(item.id) ||
|
|
522
|
+
(item.id >= PROVENANCE_FIELD_ID_START && !(allowProvenance && provenancePair)))
|
|
523
|
+
throw new InvalidError(`field id ${String(item.id)} is invalid or duplicated`);
|
|
524
|
+
if (item.name.length === 0 ||
|
|
525
|
+
new TextEncoder().encode(item.name).length > MAX_FIELD_NAME_BYTES ||
|
|
526
|
+
item.name.trim() !== item.name ||
|
|
527
|
+
hasControlCharacter(item.name) ||
|
|
528
|
+
names.has(item.name) ||
|
|
529
|
+
(PROVENANCE_FIELDS.some((entry) => entry[1] === item.name) &&
|
|
530
|
+
!(allowProvenance && provenancePair)))
|
|
531
|
+
throw new InvalidError(`field name \`${item.name}\` is invalid, duplicated, or reserved`);
|
|
532
|
+
if (item.doc !== undefined && new TextEncoder().encode(item.doc).length > MAX_FIELD_DOC_BYTES)
|
|
533
|
+
throw new InvalidError("field documentation exceeds cap");
|
|
534
|
+
estimatedSize +=
|
|
535
|
+
new TextEncoder().encode(item.name).length +
|
|
536
|
+
(item.doc === undefined ? 0 : new TextEncoder().encode(item.doc).length) +
|
|
537
|
+
16;
|
|
538
|
+
if (estimatedSize > MAX_LOGICAL_SCHEMA_BYTES)
|
|
539
|
+
throw new InvalidError("logical schema exceeds its byte cap");
|
|
540
|
+
ids.add(item.id);
|
|
541
|
+
names.add(item.name);
|
|
542
|
+
count += 1;
|
|
543
|
+
if (count > MAX_LOGICAL_SCHEMA_FIELDS)
|
|
544
|
+
throw new InvalidError("logical schema field count exceeds cap");
|
|
545
|
+
visitType(item.fieldType, depth);
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
const nestedId = (value) => {
|
|
549
|
+
if (value <= 0 || value >= PROVENANCE_FIELD_ID_START || ids.has(value))
|
|
550
|
+
throw new InvalidError("nested field id is invalid or duplicated");
|
|
551
|
+
ids.add(value);
|
|
552
|
+
count += 1;
|
|
553
|
+
if (count > MAX_LOGICAL_SCHEMA_FIELDS) {
|
|
554
|
+
throw new InvalidError("logical schema field count exceeds cap");
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
const visitType = (type, depth) => {
|
|
558
|
+
if (type.kind === "decimal" &&
|
|
559
|
+
(type.precision < 1 || type.precision > MAX_DECIMAL_PRECISION || type.scale > type.precision))
|
|
560
|
+
throw new InvalidError("decimal precision or scale is invalid");
|
|
561
|
+
if (type.kind === "fixed" && (type.length < 1 || type.length > MAX_FIXED_BYTES))
|
|
562
|
+
throw new InvalidError("fixed length is invalid");
|
|
563
|
+
if (type.kind === "struct")
|
|
564
|
+
visit(type.fields, depth + 1, false);
|
|
565
|
+
if (type.kind === "list") {
|
|
566
|
+
nestedId(type.elementId);
|
|
567
|
+
visitType(type.element, depth + 1);
|
|
568
|
+
}
|
|
569
|
+
if (type.kind === "map") {
|
|
570
|
+
nestedId(type.keyId);
|
|
571
|
+
nestedId(type.valueId);
|
|
572
|
+
if (![
|
|
573
|
+
"boolean",
|
|
574
|
+
"int",
|
|
575
|
+
"long",
|
|
576
|
+
"decimal",
|
|
577
|
+
"date",
|
|
578
|
+
"time_micros",
|
|
579
|
+
"timestamp_micros",
|
|
580
|
+
"timestamp_tz_micros",
|
|
581
|
+
"string",
|
|
582
|
+
"uuid",
|
|
583
|
+
"fixed",
|
|
584
|
+
"binary"
|
|
585
|
+
].includes(type.key.kind))
|
|
586
|
+
throw new InvalidError("map key type is not supported");
|
|
587
|
+
visitType(type.key, depth + 1);
|
|
588
|
+
visitType(type.value, depth + 1);
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
visit(fields, 1, allowTopLevelProvenance);
|
|
592
|
+
}
|
|
593
|
+
function encodeFingerprintFields(encoder, fields) {
|
|
594
|
+
encoder.u32(fields.length);
|
|
595
|
+
for (const item of fields) {
|
|
596
|
+
encoder.u32(item.id);
|
|
597
|
+
encoder.u8(item.required ? 1 : 0);
|
|
598
|
+
encoder.text(item.name);
|
|
599
|
+
encoder.u8(item.doc === undefined ? 0 : 1);
|
|
600
|
+
if (item.doc !== undefined)
|
|
601
|
+
encoder.text(item.doc);
|
|
602
|
+
encodeFingerprintType(encoder, item.fieldType);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function encodeFingerprintType(encoder, type) {
|
|
606
|
+
const tags = {
|
|
607
|
+
boolean: 0,
|
|
608
|
+
int: 1,
|
|
609
|
+
long: 2,
|
|
610
|
+
float: 3,
|
|
611
|
+
double: 4,
|
|
612
|
+
decimal: 5,
|
|
613
|
+
date: 6,
|
|
614
|
+
time_micros: 7,
|
|
615
|
+
timestamp_micros: 8,
|
|
616
|
+
timestamp_tz_micros: 9,
|
|
617
|
+
string: 10,
|
|
618
|
+
uuid: 11,
|
|
619
|
+
fixed: 12,
|
|
620
|
+
binary: 13,
|
|
621
|
+
struct: 14,
|
|
622
|
+
list: 15,
|
|
623
|
+
map: 16
|
|
624
|
+
};
|
|
625
|
+
encoder.u8(tags[type.kind] ?? 255);
|
|
626
|
+
if (type.kind === "decimal") {
|
|
627
|
+
encoder.u8(type.precision);
|
|
628
|
+
encoder.u8(type.scale);
|
|
629
|
+
}
|
|
630
|
+
if (type.kind === "fixed")
|
|
631
|
+
encoder.u32(type.length);
|
|
632
|
+
if (type.kind === "struct")
|
|
633
|
+
encodeFingerprintFields(encoder, type.fields);
|
|
634
|
+
if (type.kind === "list") {
|
|
635
|
+
encoder.u32(type.elementId);
|
|
636
|
+
encoder.u8(type.elementRequired ? 1 : 0);
|
|
637
|
+
encodeFingerprintType(encoder, type.element);
|
|
638
|
+
}
|
|
639
|
+
if (type.kind === "map") {
|
|
640
|
+
encoder.u32(type.keyId);
|
|
641
|
+
encodeFingerprintType(encoder, type.key);
|
|
642
|
+
encoder.u32(type.valueId);
|
|
643
|
+
encoder.u8(type.valueRequired ? 1 : 0);
|
|
644
|
+
encodeFingerprintType(encoder, type.value);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
class SchemaEncoder {
|
|
648
|
+
chunks = [];
|
|
649
|
+
u8(value) {
|
|
650
|
+
this.chunks.push(Uint8Array.of(value));
|
|
651
|
+
}
|
|
652
|
+
u32(value) {
|
|
653
|
+
const bytes = new Uint8Array(4);
|
|
654
|
+
new DataView(bytes.buffer).setUint32(0, value, false);
|
|
655
|
+
this.chunks.push(bytes);
|
|
656
|
+
}
|
|
657
|
+
bytes(value) {
|
|
658
|
+
this.chunks.push(value);
|
|
659
|
+
}
|
|
660
|
+
text(value) {
|
|
661
|
+
const bytes = new TextEncoder().encode(value);
|
|
662
|
+
this.u32(bytes.length);
|
|
663
|
+
this.bytes(bytes);
|
|
664
|
+
}
|
|
665
|
+
finish() {
|
|
666
|
+
const size = this.chunks.reduce((total, chunk) => total + chunk.length, 0);
|
|
667
|
+
const output = new Uint8Array(size);
|
|
668
|
+
let offset = 0;
|
|
669
|
+
for (const chunk of this.chunks) {
|
|
670
|
+
output.set(chunk, offset);
|
|
671
|
+
offset += chunk.length;
|
|
672
|
+
}
|
|
673
|
+
return output;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
function fixedBytes(value, length, context) {
|
|
677
|
+
if (value.length !== length)
|
|
678
|
+
throw new CodecError(`${context} must contain ${String(length)} bytes`, context, "bytes");
|
|
679
|
+
return value;
|
|
680
|
+
}
|
|
681
|
+
function equalBytes(left, right) {
|
|
682
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
683
|
+
}
|
|
684
|
+
function compareBytes(left, right) {
|
|
685
|
+
for (let index = 0; index < Math.min(left.length, right.length); index += 1) {
|
|
686
|
+
const delta = (left[index] ?? 0) - (right[index] ?? 0);
|
|
687
|
+
if (delta !== 0)
|
|
688
|
+
return delta;
|
|
689
|
+
}
|
|
690
|
+
return left.length - right.length;
|
|
691
|
+
}
|
|
692
|
+
function validateDecimal(value) {
|
|
693
|
+
if (value.precision < 1 ||
|
|
694
|
+
value.precision > MAX_DECIMAL_PRECISION ||
|
|
695
|
+
value.scale > value.precision ||
|
|
696
|
+
value.unscaled.length < 1 ||
|
|
697
|
+
value.unscaled.length > 16 ||
|
|
698
|
+
(value.unscaled.length > 1 &&
|
|
699
|
+
((value.unscaled[0] === 0 && (value.unscaled[1] ?? 0) < 0x80) ||
|
|
700
|
+
(value.unscaled[0] === 0xff && (value.unscaled[1] ?? 0) >= 0x80))))
|
|
701
|
+
throw new InvalidError("decimal value is not canonical");
|
|
702
|
+
let unscaled = 0n;
|
|
703
|
+
for (const byte of value.unscaled)
|
|
704
|
+
unscaled = (unscaled << 8n) | BigInt(byte);
|
|
705
|
+
if ((value.unscaled[0] ?? 0) >= 0x80) {
|
|
706
|
+
unscaled -= 1n << BigInt(value.unscaled.length * 8);
|
|
707
|
+
}
|
|
708
|
+
const digits = (unscaled < 0n ? -unscaled : unscaled).toString().length;
|
|
709
|
+
if (digits > value.precision) {
|
|
710
|
+
throw new InvalidError("decimal value exceeds its declared precision");
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
function validateI64(value) {
|
|
714
|
+
if (value < -9223372036854775808n || value > 9223372036854775807n) {
|
|
715
|
+
throw new InvalidError("64-bit signed value is outside its bound");
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
function canonicalMapKey(value) {
|
|
719
|
+
validateTypedValue(value);
|
|
720
|
+
switch (value.kind) {
|
|
721
|
+
case "boolean":
|
|
722
|
+
return Uint8Array.of(0, value.value ? 1 : 0);
|
|
723
|
+
case "int":
|
|
724
|
+
return prefixedSigned(1, value.value, 4);
|
|
725
|
+
case "long":
|
|
726
|
+
return prefixedSigned(2, value.value, 8);
|
|
727
|
+
case "decimal":
|
|
728
|
+
return concatBytes(Uint8Array.of(3, value.value.precision, value.value.scale), value.value.unscaled);
|
|
729
|
+
case "date":
|
|
730
|
+
return prefixedSigned(4, value.value, 4);
|
|
731
|
+
case "time_micros":
|
|
732
|
+
return prefixedSigned(5, value.value, 8);
|
|
733
|
+
case "timestamp_micros":
|
|
734
|
+
return prefixedSigned(6, value.value, 8);
|
|
735
|
+
case "timestamp_tz_micros":
|
|
736
|
+
return prefixedSigned(7, value.value, 8);
|
|
737
|
+
case "string":
|
|
738
|
+
return concatBytes(Uint8Array.of(8), new TextEncoder().encode(value.value));
|
|
739
|
+
case "uuid":
|
|
740
|
+
return concatBytes(Uint8Array.of(9), value.value);
|
|
741
|
+
case "fixed":
|
|
742
|
+
return concatBytes(Uint8Array.of(10), value.value);
|
|
743
|
+
case "binary":
|
|
744
|
+
return concatBytes(Uint8Array.of(11), value.value);
|
|
745
|
+
case "float":
|
|
746
|
+
case "double":
|
|
747
|
+
case "struct":
|
|
748
|
+
case "list":
|
|
749
|
+
case "map":
|
|
750
|
+
case "null":
|
|
751
|
+
throw new InvalidError("map key must be a deterministic non-floating primitive");
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
function prefixedSigned(tag, value, width) {
|
|
755
|
+
const bytes = new Uint8Array(width + 1);
|
|
756
|
+
bytes[0] = tag;
|
|
757
|
+
const view = new DataView(bytes.buffer);
|
|
758
|
+
if (width === 4)
|
|
759
|
+
view.setInt32(1, Number(value), false);
|
|
760
|
+
else
|
|
761
|
+
view.setBigInt64(1, BigInt(value), false);
|
|
762
|
+
return bytes;
|
|
763
|
+
}
|
|
764
|
+
function concatBytes(left, right) {
|
|
765
|
+
const bytes = new Uint8Array(left.length + right.length);
|
|
766
|
+
bytes.set(left);
|
|
767
|
+
bytes.set(right, left.length);
|
|
768
|
+
return bytes;
|
|
769
|
+
}
|
|
770
|
+
function hasControlCharacter(value) {
|
|
771
|
+
for (const character of value) {
|
|
772
|
+
const code = character.codePointAt(0) ?? 0;
|
|
773
|
+
if (code < 32 || code === 127)
|
|
774
|
+
return true;
|
|
775
|
+
}
|
|
776
|
+
return false;
|
|
777
|
+
}
|
|
778
|
+
//# sourceMappingURL=schema.js.map
|