atchara 0.1.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.
@@ -0,0 +1,2119 @@
1
+ 'use strict';
2
+
3
+ var core = require('@atcharajs/core');
4
+ var buffer = require('buffer');
5
+ var native = require('@atcharajs/native');
6
+
7
+ // src/index.ts
8
+
9
+ // src/decoder/reader.ts
10
+ var ByteReader = class {
11
+ constructor(bytes) {
12
+ this.bytes = bytes;
13
+ this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
14
+ this.offset = 0;
15
+ this.textDecoder = new TextDecoder("utf-8");
16
+ }
17
+ view;
18
+ offset;
19
+ textDecoder;
20
+ /**
21
+ * Reset with new bytes and reset position to start.
22
+ * Avoids allocation overhead by reusing the reader instance.
23
+ */
24
+ reset(bytes) {
25
+ this.bytes = bytes;
26
+ this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
27
+ this.offset = 0;
28
+ }
29
+ /** Seek to a specific offset in the byte stream */
30
+ seek(offset) {
31
+ this.offset = offset;
32
+ }
33
+ /** Get current read position */
34
+ getOffset() {
35
+ return this.offset;
36
+ }
37
+ /** Get number of bytes remaining */
38
+ getRemainingBytes() {
39
+ return this.bytes.length - this.offset;
40
+ }
41
+ /** Get the underlying bytes */
42
+ getBytes() {
43
+ return this.bytes;
44
+ }
45
+ /** Get the DataView for direct access when needed */
46
+ getView() {
47
+ return this.view;
48
+ }
49
+ // ============================================================================
50
+ // Primitive Reads (all big-endian)
51
+ // ============================================================================
52
+ readU8() {
53
+ const value = this.view.getUint8(this.offset);
54
+ this.offset += 1;
55
+ return value;
56
+ }
57
+ readU16() {
58
+ const value = this.view.getUint16(this.offset, false);
59
+ this.offset += 2;
60
+ return value;
61
+ }
62
+ readU32() {
63
+ const value = this.view.getUint32(this.offset, false);
64
+ this.offset += 4;
65
+ return value;
66
+ }
67
+ /** Read u32 at specific offset without advancing position */
68
+ readU32At(offset) {
69
+ return this.view.getUint32(offset, false);
70
+ }
71
+ /** Read u16 at specific offset without advancing position */
72
+ readU16At(offset) {
73
+ return this.view.getUint16(offset, false);
74
+ }
75
+ /** Read u8 at specific offset without advancing position */
76
+ readU8At(offset) {
77
+ return this.view.getUint8(offset);
78
+ }
79
+ readF64() {
80
+ const value = this.view.getFloat64(this.offset, false);
81
+ this.offset += 8;
82
+ return value;
83
+ }
84
+ readBoolean() {
85
+ const value = this.view.getUint8(this.offset);
86
+ this.offset += 1;
87
+ return value !== 0;
88
+ }
89
+ /**
90
+ * Read a length-prefixed string (u32 length + UTF-8 bytes).
91
+ * Uses zero-copy subarray view for efficiency.
92
+ */
93
+ readString() {
94
+ const length = this.view.getUint32(this.offset, false);
95
+ this.offset += 4;
96
+ const stringBytes = this.bytes.subarray(this.offset, this.offset + length);
97
+ this.offset += length;
98
+ return this.textDecoder.decode(stringBytes);
99
+ }
100
+ /** Skip past a length-prefixed string without decoding */
101
+ skipString() {
102
+ const length = this.view.getUint32(this.offset, false);
103
+ this.offset += 4 + length;
104
+ }
105
+ /** Skip n bytes */
106
+ skip(n) {
107
+ this.offset += n;
108
+ }
109
+ /**
110
+ * Read raw bytes as a subarray (zero-copy view).
111
+ * Advances position by length.
112
+ */
113
+ readBytes(length) {
114
+ const bytes = this.bytes.subarray(this.offset, this.offset + length);
115
+ this.offset += length;
116
+ return bytes;
117
+ }
118
+ /**
119
+ * Decode a string from bytes at specific offset with given length.
120
+ * Does not advance position.
121
+ */
122
+ decodeStringAt(offset, length) {
123
+ const stringBytes = this.bytes.subarray(offset, offset + length);
124
+ return this.textDecoder.decode(stringBytes);
125
+ }
126
+ };
127
+
128
+ // src/decoder/buffer.ts
129
+ var BufferDecoder = class {
130
+ reader;
131
+ defs;
132
+ constructor(bytes, defs = []) {
133
+ this.reader = new ByteReader(bytes);
134
+ this.defs = defs;
135
+ }
136
+ /**
137
+ * Reset the decoder with new bytes and reset state.
138
+ * Avoids allocation overhead by reusing the decoder instance.
139
+ */
140
+ reset(bytes) {
141
+ this.reader.reset(bytes);
142
+ }
143
+ /** Seek to a specific offset in the byte stream */
144
+ seek(offset) {
145
+ this.reader.seek(offset);
146
+ }
147
+ getOffset() {
148
+ return this.reader.getOffset();
149
+ }
150
+ getRemainingBytes() {
151
+ return this.reader.getRemainingBytes();
152
+ }
153
+ // ==========================================================================
154
+ // Primitives (BufferDecoder interface)
155
+ // ==========================================================================
156
+ /** Read null flag (0x00 = null, 0x01 = present) */
157
+ readNullFlag() {
158
+ return this.reader.readU8() === native.NULL_FLAG;
159
+ }
160
+ /** Read a boolean value */
161
+ readBoolean() {
162
+ return this.reader.readBoolean();
163
+ }
164
+ /** Read a number value (f64) */
165
+ readNumber() {
166
+ return this.reader.readF64();
167
+ }
168
+ /** Read a length-prefixed string */
169
+ readString() {
170
+ return this.reader.readString();
171
+ }
172
+ /** Read union variant index (u8) */
173
+ readVariantIndex() {
174
+ return this.reader.readU8();
175
+ }
176
+ // ==========================================================================
177
+ // Schema-driven read
178
+ // ==========================================================================
179
+ /**
180
+ * Read and deserialize based on schema type
181
+ */
182
+ read(schema) {
183
+ switch (schema.kind) {
184
+ case "string":
185
+ return this.reader.readString();
186
+ case "number":
187
+ case "integer":
188
+ return this.reader.readF64();
189
+ case "boolean":
190
+ return this.reader.readBoolean();
191
+ case "literal":
192
+ return this.readLiteral(schema);
193
+ case "object":
194
+ return this.readObject(schema);
195
+ case "array":
196
+ return this.readArray(schema);
197
+ case "tuple":
198
+ return this.readTuple(schema);
199
+ case "nullable":
200
+ return this.readNullable(schema);
201
+ case "optional":
202
+ return this.read(schema.inner);
203
+ case "record":
204
+ return this.readRecord(schema);
205
+ case "union":
206
+ return this.readUnion(schema);
207
+ case "ref":
208
+ return this.read(this.defs[schema.defId]);
209
+ default: {
210
+ const exhaustiveCheck = schema;
211
+ throw new Error(`Unknown schema type: ${String(exhaustiveCheck)}`);
212
+ }
213
+ }
214
+ }
215
+ /** Read array length at current position without decoding elements */
216
+ readArrayLength() {
217
+ return this.reader.readU32At(this.reader.getOffset());
218
+ }
219
+ /** Read record keys at current position, skipping values */
220
+ readRecordKeys(valueSchema) {
221
+ const offset = this.reader.getOffset();
222
+ const keyCount = this.reader.readU32At(offset);
223
+ if (keyCount === 0) {
224
+ this.reader.seek(offset + 8);
225
+ return [];
226
+ }
227
+ this.reader.seek(offset + 8);
228
+ const keys = new Array(keyCount);
229
+ for (let i = 0; i < keyCount; i++) {
230
+ const keyLen = this.reader.readU16();
231
+ keys[i] = this.reader.decodeStringAt(this.reader.getOffset(), keyLen);
232
+ this.reader.skip(keyLen);
233
+ this.skip(valueSchema);
234
+ }
235
+ this.reader.skip(keyCount * 12);
236
+ return keys;
237
+ }
238
+ // ============================================================================
239
+ // Array Operations (at specific offset)
240
+ // ============================================================================
241
+ /** Read array length at a specific offset without modifying decoder position */
242
+ getArrayLengthAt(arrayOffset) {
243
+ return this.reader.readU32At(arrayOffset);
244
+ }
245
+ /**
246
+ * Get offset of array element at index by skipping preceding elements.
247
+ * Returns undefined if index is out of bounds.
248
+ */
249
+ getArrayElementOffset(arrayOffset, index, elementSchema) {
250
+ const length = this.reader.readU32At(arrayOffset);
251
+ if (index >= length) return void 0;
252
+ this.reader.seek(arrayOffset + 4);
253
+ for (let i = 0; i < index; i++) {
254
+ this.skip(elementSchema);
255
+ }
256
+ return this.reader.getOffset();
257
+ }
258
+ /** Read array element at index */
259
+ readArrayElementAt(arrayOffset, index, elementSchema) {
260
+ const length = this.reader.readU32At(arrayOffset);
261
+ if (index >= length) return void 0;
262
+ this.reader.seek(arrayOffset + 4);
263
+ for (let i = 0; i < index; i++) {
264
+ this.skip(elementSchema);
265
+ }
266
+ return this.read(elementSchema);
267
+ }
268
+ // ============================================================================
269
+ // Record Operations (hash-based O(log n) lookup)
270
+ // ============================================================================
271
+ /** Read record key count at a specific offset */
272
+ getRecordKeyCountAt(recordOffset) {
273
+ return this.reader.readU32At(recordOffset);
274
+ }
275
+ /**
276
+ * Find offset of record value by key using hash-based binary search.
277
+ * Returns the offset where the value begins, or undefined if key not found.
278
+ */
279
+ findRecordValueOffset(recordOffset, key) {
280
+ const view = this.reader.getView();
281
+ const keyCount = view.getUint32(recordOffset, false);
282
+ if (keyCount === 0) return void 0;
283
+ const kvDataSize = view.getUint32(recordOffset + 4, false);
284
+ const targetHash = native.fnv1A64(key);
285
+ const indexStart = recordOffset + 8 + kvDataSize;
286
+ let lo = 0;
287
+ let hi = keyCount - 1;
288
+ while (lo <= hi) {
289
+ const mid = lo + hi >>> 1;
290
+ const entryOffset = indexStart + mid * 12;
291
+ const hashHigh = view.getUint32(entryOffset, false);
292
+ const hashLow = view.getUint32(entryOffset + 4, false);
293
+ const entryHash = BigInt(hashHigh) << 32n | BigInt(hashLow);
294
+ if (targetHash === entryHash) {
295
+ const kvOffset = view.getUint32(entryOffset + 8, false);
296
+ const keyLen = view.getUint16(kvOffset, false);
297
+ return kvOffset + 2 + keyLen;
298
+ } else if (targetHash < entryHash) {
299
+ hi = mid - 1;
300
+ } else {
301
+ lo = mid + 1;
302
+ }
303
+ }
304
+ return void 0;
305
+ }
306
+ /** Read record value by key using hash-based binary search */
307
+ readRecordValueAt(recordOffset, key, valueSchema) {
308
+ const valueOffset = this.findRecordValueOffset(recordOffset, key);
309
+ if (valueOffset === void 0) return void 0;
310
+ this.reader.seek(valueOffset);
311
+ return this.read(valueSchema);
312
+ }
313
+ // ============================================================================
314
+ // Object Operations (O(1) offset table lookup)
315
+ // ============================================================================
316
+ /** Check if object contains a field by reading offset table entry - O(1) */
317
+ hasObjectFieldAt(objectOffset, fieldIndex, _schema) {
318
+ const relativeOffset = this.reader.readU32At(objectOffset + fieldIndex * 4);
319
+ return relativeOffset !== native.ABSENT_FIELD_MARKER;
320
+ }
321
+ /**
322
+ * Find offset of object field value by field index - O(1).
323
+ * Returns undefined if field is not present.
324
+ */
325
+ findObjectFieldOffset(objectOffset, fieldIndex, schema) {
326
+ const fieldCount = schema.objectFields.length;
327
+ const relativeOffset = this.reader.readU32At(objectOffset + fieldIndex * 4);
328
+ if (relativeOffset === native.ABSENT_FIELD_MARKER) return void 0;
329
+ const valuesStart = objectOffset + fieldCount * 4;
330
+ return valuesStart + relativeOffset;
331
+ }
332
+ /** Read object field value by field index - O(1) */
333
+ readObjectFieldAt(objectOffset, fieldIndex, schema) {
334
+ const fieldOffset = this.findObjectFieldOffset(objectOffset, fieldIndex, schema);
335
+ if (fieldOffset === void 0) return void 0;
336
+ const field = schema.objectFields[fieldIndex];
337
+ if (!field) return void 0;
338
+ this.reader.seek(fieldOffset);
339
+ return this.read(field.schema);
340
+ }
341
+ /**
342
+ * Advance past a value without materializing it.
343
+ * Used for efficient iteration when only partial data is needed.
344
+ */
345
+ skip(schema) {
346
+ switch (schema.kind) {
347
+ case "string":
348
+ this.reader.skipString();
349
+ break;
350
+ case "number":
351
+ case "integer":
352
+ this.reader.skip(8);
353
+ break;
354
+ case "boolean":
355
+ this.reader.skip(1);
356
+ break;
357
+ case "literal":
358
+ this.skipLiteral(schema);
359
+ break;
360
+ case "object":
361
+ this.skipObject(schema);
362
+ break;
363
+ case "array":
364
+ this.skipArray(schema);
365
+ break;
366
+ case "tuple":
367
+ this.skipTuple(schema);
368
+ break;
369
+ case "nullable":
370
+ this.skipNullable(schema);
371
+ break;
372
+ case "optional":
373
+ this.skip(schema.inner);
374
+ break;
375
+ case "record":
376
+ this.skipRecord();
377
+ break;
378
+ case "union":
379
+ this.skipUnion(schema);
380
+ break;
381
+ case "ref":
382
+ this.skip(this.defs[schema.defId]);
383
+ break;
384
+ default: {
385
+ const exhaustiveCheck = schema;
386
+ throw new Error(`Unknown schema type: ${String(exhaustiveCheck)}`);
387
+ }
388
+ }
389
+ }
390
+ // ============================================================================
391
+ // Private Read Methods
392
+ // ============================================================================
393
+ readLiteral(schema) {
394
+ if (schema.value === null) {
395
+ return null;
396
+ }
397
+ switch (typeof schema.value) {
398
+ case "string":
399
+ return this.reader.readString();
400
+ case "number":
401
+ return this.reader.readF64();
402
+ case "boolean":
403
+ return this.reader.readBoolean();
404
+ default:
405
+ throw new Error(`Unknown literal type: ${typeof schema.value}`);
406
+ }
407
+ }
408
+ readNullable(schema) {
409
+ const flag = this.reader.readU8();
410
+ return flag === native.NULL_FLAG ? null : this.read(schema.inner);
411
+ }
412
+ readArray(schema) {
413
+ const length = this.reader.readU32();
414
+ const array2 = new Array(length);
415
+ for (let i = 0; i < length; i++) {
416
+ array2[i] = this.read(schema.elements);
417
+ }
418
+ return array2;
419
+ }
420
+ readTuple(schema) {
421
+ const elements = schema.elements;
422
+ const result = new Array(elements.length);
423
+ for (let i = 0; i < elements.length; i++) {
424
+ result[i] = this.read(elements[i]);
425
+ }
426
+ return result;
427
+ }
428
+ readRecord(schema) {
429
+ const keyCount = this.reader.readU32();
430
+ if (keyCount === 0) {
431
+ this.reader.skip(4);
432
+ return {};
433
+ }
434
+ this.reader.skip(4);
435
+ const result = {};
436
+ for (let i = 0; i < keyCount; i++) {
437
+ const keyLen = this.reader.readU16();
438
+ const key = this.reader.decodeStringAt(this.reader.getOffset(), keyLen);
439
+ this.reader.skip(keyLen);
440
+ result[key] = this.read(schema.valueSchema);
441
+ }
442
+ this.reader.skip(keyCount * 12);
443
+ return result;
444
+ }
445
+ readObject(schema) {
446
+ const result = {};
447
+ const fieldCount = schema.objectFields.length;
448
+ const objectStart = this.reader.getOffset();
449
+ const valuesStart = objectStart + fieldCount * 4;
450
+ let maxEnd = valuesStart;
451
+ for (let i = 0; i < fieldCount; i++) {
452
+ const relativeOffset = this.reader.readU32At(objectStart + i * 4);
453
+ if (relativeOffset === native.ABSENT_FIELD_MARKER) continue;
454
+ const field = schema.objectFields[i];
455
+ if (!field) {
456
+ throw new Error(`Invalid field index: ${i}`);
457
+ }
458
+ this.reader.seek(valuesStart + relativeOffset);
459
+ result[field.key] = this.read(field.schema);
460
+ const currentOffset = this.reader.getOffset();
461
+ if (currentOffset > maxEnd) maxEnd = currentOffset;
462
+ }
463
+ this.reader.seek(maxEnd);
464
+ return result;
465
+ }
466
+ readUnion(schema) {
467
+ const variantIndex = this.reader.readU8();
468
+ const variantSchema = schema.variants[variantIndex];
469
+ if (variantSchema === void 0) {
470
+ throw new Error(`Invalid union variant index: ${variantIndex}`);
471
+ }
472
+ return this.read(variantSchema);
473
+ }
474
+ // ============================================================================
475
+ // Private Skip Methods
476
+ // ============================================================================
477
+ skipLiteral(schema) {
478
+ if (schema.value === null) return;
479
+ if (typeof schema.value === "string") this.reader.skipString();
480
+ else if (typeof schema.value === "number") this.reader.skip(8);
481
+ else if (typeof schema.value === "boolean") this.reader.skip(1);
482
+ }
483
+ skipNullable(schema) {
484
+ const flag = this.reader.readU8();
485
+ if (flag !== native.NULL_FLAG) this.skip(schema.inner);
486
+ }
487
+ skipArray(schema) {
488
+ const length = this.reader.readU32();
489
+ for (let i = 0; i < length; i++) {
490
+ this.skip(schema.elements);
491
+ }
492
+ }
493
+ skipTuple(schema) {
494
+ for (const element of schema.elements) {
495
+ this.skip(element);
496
+ }
497
+ }
498
+ skipRecord() {
499
+ const offset = this.reader.getOffset();
500
+ const keyCount = this.reader.readU32At(offset);
501
+ const kvDataSize = this.reader.readU32At(offset + 4);
502
+ this.reader.seek(offset + 8 + kvDataSize + keyCount * 12);
503
+ }
504
+ skipObject(schema) {
505
+ const fieldCount = schema.objectFields.length;
506
+ const objectStart = this.reader.getOffset();
507
+ const valuesStart = objectStart + fieldCount * 4;
508
+ let maxEnd = valuesStart;
509
+ for (let i = 0; i < fieldCount; i++) {
510
+ const relativeOffset = this.reader.readU32At(objectStart + i * 4);
511
+ if (relativeOffset === native.ABSENT_FIELD_MARKER) continue;
512
+ const field = schema.objectFields[i];
513
+ if (!field) throw new Error(`Invalid field index: ${i}`);
514
+ this.reader.seek(valuesStart + relativeOffset);
515
+ this.skip(field.schema);
516
+ const currentOffset = this.reader.getOffset();
517
+ if (currentOffset > maxEnd) maxEnd = currentOffset;
518
+ }
519
+ this.reader.seek(maxEnd);
520
+ }
521
+ skipUnion(schema) {
522
+ const variantIndex = this.reader.readU8();
523
+ const variantSchema = schema.variants[variantIndex];
524
+ if (variantSchema === void 0) {
525
+ throw new Error(`Invalid union variant index: ${variantIndex}`);
526
+ }
527
+ this.skip(variantSchema);
528
+ }
529
+ };
530
+
531
+ // src/decoder/offset.ts
532
+ var OffsetIndex = class {
533
+ view;
534
+ tableCount;
535
+ tableStartOffset;
536
+ valueDataLength;
537
+ cache;
538
+ // schema_index → offset cache
539
+ constructor(binary) {
540
+ this.view = new DataView(binary.buffer, binary.byteOffset, binary.byteLength);
541
+ this.cache = /* @__PURE__ */ new Map();
542
+ this.tableCount = this.view.getUint32(binary.length - 4, false);
543
+ this.tableStartOffset = binary.length - 4 - this.tableCount * 4;
544
+ this.valueDataLength = this.tableStartOffset;
545
+ }
546
+ /**
547
+ * Get the offset for a given schema index.
548
+ * Uses lazy reading and caching for performance.
549
+ */
550
+ getOffset(schemaIndex) {
551
+ if (this.cache.has(schemaIndex)) {
552
+ return this.cache.get(schemaIndex);
553
+ }
554
+ if (schemaIndex >= this.tableCount || schemaIndex < 0) {
555
+ return void 0;
556
+ }
557
+ const offsetPos = this.tableStartOffset + schemaIndex * 4;
558
+ const offset = this.view.getUint32(offsetPos, false);
559
+ this.cache.set(schemaIndex, offset);
560
+ return offset;
561
+ }
562
+ /**
563
+ * Get the length of the value data (before offset table)
564
+ */
565
+ getValueDataLength() {
566
+ return this.valueDataLength;
567
+ }
568
+ /**
569
+ * Get the total number of offsets in the table
570
+ */
571
+ getCount() {
572
+ return this.tableCount;
573
+ }
574
+ };
575
+
576
+ // src/path.ts
577
+ function encodePath(path) {
578
+ return path.map((p) => p + "\0").join("");
579
+ }
580
+
581
+ // src/store/memory.ts
582
+ var MemoryStore = class {
583
+ defs;
584
+ decoder;
585
+ offsetIndex;
586
+ schema;
587
+ indexMap;
588
+ schemaCache = /* @__PURE__ */ new Map();
589
+ getDefs() {
590
+ return this.defs;
591
+ }
592
+ constructor(bytes, schema, indexMap, defs = []) {
593
+ this.defs = defs;
594
+ this.schema = schema;
595
+ this.indexMap = indexMap;
596
+ this.offsetIndex = new OffsetIndex(bytes);
597
+ const valueDataLength = this.offsetIndex.getValueDataLength();
598
+ const valueData = bytes.subarray(0, valueDataLength);
599
+ this.decoder = new BufferDecoder(valueData, defs);
600
+ }
601
+ get(path) {
602
+ const pathKey = encodePath(path);
603
+ const offsetIdx = this.indexMap.get(pathKey);
604
+ if (offsetIdx === void 0) {
605
+ if (path.length > 0) {
606
+ const parentPath = path.slice(0, -1);
607
+ const parentSchema = core.resolveRef(
608
+ path.length === 1 ? this.schema : core.schemaAtPath(this.schema, parentPath, this.defs),
609
+ this.defs
610
+ );
611
+ const key = path[path.length - 1];
612
+ if (parentSchema.kind === "array" && key !== void 0) {
613
+ const index = parseInt(key, 10);
614
+ if (isNaN(index) || index < 0) return void 0;
615
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
616
+ if (parentOffset === void 0) return void 0;
617
+ return this.decoder.readArrayElementAt(parentOffset, index, parentSchema.elements);
618
+ }
619
+ if (parentSchema.kind === "record" && key !== void 0) {
620
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
621
+ if (parentOffset === void 0) return void 0;
622
+ return this.decoder.readRecordValueAt(parentOffset, key, parentSchema.valueSchema);
623
+ }
624
+ if (parentSchema.kind === "object" && key !== void 0) {
625
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
626
+ if (parentOffset === void 0) return void 0;
627
+ const fieldDef = parentSchema.objectFields.find((f) => f.key === key);
628
+ if (!fieldDef) return void 0;
629
+ return this.decoder.readObjectFieldAt(parentOffset, fieldDef.index, parentSchema);
630
+ }
631
+ }
632
+ return void 0;
633
+ }
634
+ const offset = this.offsetIndex.getOffset(offsetIdx);
635
+ if (offset === void 0) return void 0;
636
+ this.decoder.seek(offset);
637
+ const schema = this.getCachedSchema(path);
638
+ return this.decoder.read(schema);
639
+ }
640
+ has(path) {
641
+ if (path.length === 0) {
642
+ return true;
643
+ }
644
+ const parentPath = path.slice(0, -1);
645
+ const parentSchema = core.resolveRef(
646
+ path.length === 1 ? this.schema : core.schemaAtPath(this.schema, parentPath, this.defs),
647
+ this.defs
648
+ );
649
+ const key = path[path.length - 1];
650
+ if (key === void 0) return false;
651
+ if (parentSchema.kind === "object") {
652
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
653
+ if (parentOffset === void 0) return false;
654
+ const fieldDef = parentSchema.objectFields.find((f) => f.key === key);
655
+ if (!fieldDef) return false;
656
+ return this.decoder.hasObjectFieldAt(parentOffset, fieldDef.index, parentSchema);
657
+ }
658
+ if (parentSchema.kind === "array") {
659
+ const index = parseInt(key, 10);
660
+ if (isNaN(index) || index < 0) return false;
661
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
662
+ if (parentOffset === void 0) return false;
663
+ const length = this.decoder.getArrayLengthAt(parentOffset);
664
+ return index < length;
665
+ }
666
+ if (parentSchema.kind === "record") {
667
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
668
+ if (parentOffset === void 0) return false;
669
+ return this.decoder.findRecordValueOffset(parentOffset, key) !== void 0;
670
+ }
671
+ return false;
672
+ }
673
+ getFieldMetadata(path, key) {
674
+ const fullPath = [...path, key];
675
+ const pathKey = encodePath(fullPath);
676
+ const exists = this.indexMap.has(pathKey);
677
+ return {
678
+ exists,
679
+ schema: exists ? this.getCachedSchema(fullPath) : { kind: "string" }
680
+ };
681
+ }
682
+ getArrayLength(path) {
683
+ const offset = this.getOffsetForDynamicPath(path);
684
+ if (offset === void 0) return 0;
685
+ this.decoder.seek(offset);
686
+ return this.decoder.readArrayLength();
687
+ }
688
+ getRecordKeys(path) {
689
+ const offset = this.getOffsetForDynamicPath(path);
690
+ if (offset === void 0) return [];
691
+ const schema = this.getCachedSchema(path);
692
+ if (schema.kind !== "record") return [];
693
+ this.decoder.seek(offset);
694
+ return this.decoder.readRecordKeys(schema.valueSchema);
695
+ }
696
+ getOffsetForPath(path) {
697
+ const pathKey = encodePath(path);
698
+ const offsetIdx = this.indexMap.get(pathKey);
699
+ if (offsetIdx === void 0) return void 0;
700
+ return this.offsetIndex.getOffset(offsetIdx);
701
+ }
702
+ /**
703
+ * Get offset for a path that may contain dynamic segments (array indices, record keys, object fields).
704
+ * Recursively resolves each path segment, handling both schema-indexed and dynamic paths.
705
+ */
706
+ getOffsetForDynamicPath(path) {
707
+ const directOffset = this.getOffsetForPath(path);
708
+ if (directOffset !== void 0) return directOffset;
709
+ if (path.length === 0) return void 0;
710
+ const parentPath = path.slice(0, -1);
711
+ const parentOffset = this.getOffsetForDynamicPath(parentPath);
712
+ if (parentOffset === void 0) return void 0;
713
+ const parentSchema = core.resolveRef(
714
+ path.length === 1 ? this.schema : core.schemaAtPath(this.schema, parentPath, this.defs),
715
+ this.defs
716
+ );
717
+ const key = path[path.length - 1];
718
+ if (key === void 0) return void 0;
719
+ if (parentSchema.kind === "array") {
720
+ const index = parseInt(key, 10);
721
+ if (isNaN(index) || index < 0) return void 0;
722
+ return this.decoder.getArrayElementOffset(parentOffset, index, parentSchema.elements);
723
+ }
724
+ if (parentSchema.kind === "record") {
725
+ return this.decoder.findRecordValueOffset(parentOffset, key);
726
+ }
727
+ if (parentSchema.kind === "object") {
728
+ const fieldDef = parentSchema.objectFields.find((f) => f.key === key);
729
+ if (!fieldDef) return void 0;
730
+ return this.decoder.findObjectFieldOffset(parentOffset, fieldDef.index, parentSchema);
731
+ }
732
+ return void 0;
733
+ }
734
+ /**
735
+ * Get schema at path with caching for repeated access
736
+ */
737
+ getCachedSchema(path) {
738
+ if (path.length === 0) {
739
+ return core.resolveRef(this.schema, this.defs);
740
+ }
741
+ const pathKey = encodePath(path);
742
+ let schema = this.schemaCache.get(pathKey);
743
+ if (schema === void 0) {
744
+ schema = core.schemaAtPath(this.schema, path, this.defs);
745
+ this.schemaCache.set(pathKey, schema);
746
+ }
747
+ return schema;
748
+ }
749
+ };
750
+ var ErrorDecoder = class {
751
+ reader;
752
+ constructor(bytes) {
753
+ this.reader = new ByteReader(bytes);
754
+ }
755
+ /**
756
+ * Decode the binary error and return an AtcharaError ready to be thrown.
757
+ */
758
+ decode() {
759
+ const code = this.reader.readU8();
760
+ switch (code) {
761
+ case native.ERROR_CODE_UNEXPECTED_EOF:
762
+ return core.createAtcharaError("Unexpected end of input", {
763
+ code: "UNEXPECTED_EOF"
764
+ });
765
+ case native.ERROR_CODE_INVALID_UTF8: {
766
+ const line = this.reader.readU32();
767
+ const column = this.reader.readU32();
768
+ const rawMessage = this.reader.readString();
769
+ return core.createAtcharaError(
770
+ `Invalid UTF-8 at line ${line}, column ${column}: ${rawMessage}`,
771
+ {
772
+ code: "INVALID_UTF8",
773
+ position: { line, column },
774
+ details: { rawMessage }
775
+ }
776
+ );
777
+ }
778
+ case native.ERROR_CODE_UNEXPECTED_CHARACTER: {
779
+ const line = this.reader.readU32();
780
+ const column = this.reader.readU32();
781
+ const character = this.reader.readString();
782
+ return core.createAtcharaError(
783
+ `Unexpected character '${character}' at line ${line}, column ${column}`,
784
+ {
785
+ code: "UNEXPECTED_CHARACTER",
786
+ position: { line, column },
787
+ details: { character }
788
+ }
789
+ );
790
+ }
791
+ case native.ERROR_CODE_VALIDATION_ERROR: {
792
+ const line = this.reader.readU32();
793
+ const column = this.reader.readU32();
794
+ const expected = this.reader.readString();
795
+ const found = this.reader.readString();
796
+ return core.createAtcharaError(
797
+ `Expected ${expected}, found ${found} at line ${line}, column ${column}`,
798
+ {
799
+ code: "VALIDATION_ERROR",
800
+ position: { line, column },
801
+ details: { expected, found }
802
+ }
803
+ );
804
+ }
805
+ case native.ERROR_CODE_MISSING_REQUIRED: {
806
+ const line = this.reader.readU32();
807
+ const column = this.reader.readU32();
808
+ const field = this.reader.readString();
809
+ return core.createAtcharaError(
810
+ `Missing required field '${field}' in object at line ${line}, column ${column}`,
811
+ {
812
+ code: "MISSING_REQUIRED",
813
+ position: { line, column },
814
+ details: { field }
815
+ }
816
+ );
817
+ }
818
+ case native.ERROR_CODE_UNEXPECTED_FIELD: {
819
+ const line = this.reader.readU32();
820
+ const column = this.reader.readU32();
821
+ const field = this.reader.readString();
822
+ return core.createAtcharaError(
823
+ `Unexpected field '${field}' at line ${line}, column ${column}`,
824
+ {
825
+ code: "UNEXPECTED_FIELD",
826
+ position: { line, column },
827
+ details: { field }
828
+ }
829
+ );
830
+ }
831
+ case native.ERROR_CODE_UNION_NO_MATCH: {
832
+ const line = this.reader.readU32();
833
+ const column = this.reader.readU32();
834
+ const count = this.reader.readU32();
835
+ const variantErrors = [];
836
+ for (let i = 0; i < count; i++) {
837
+ variantErrors.push(this.decode());
838
+ }
839
+ const variantSummary = variantErrors.map((e, i) => `[${i}] ${e.message}`).join("; ");
840
+ return core.createAtcharaError(
841
+ `No union variant matched at line ${line}, column ${column}. Variant errors: ${variantSummary}`,
842
+ {
843
+ code: "UNION_NO_MATCH",
844
+ position: { line, column },
845
+ details: { variantErrors }
846
+ }
847
+ );
848
+ }
849
+ case native.ERROR_CODE_INVALID_SCHEMA: {
850
+ const message = this.reader.readString();
851
+ return core.createAtcharaError(`Invalid schema: ${message}`, {
852
+ code: "INVALID_SCHEMA"
853
+ });
854
+ }
855
+ default:
856
+ throw new Error(`Unknown error code: ${code}`);
857
+ }
858
+ }
859
+ };
860
+ function unwrapSchema(schema, defs) {
861
+ if (schema.kind === "ref" && defs) {
862
+ return unwrapSchema(defs[schema.defId], defs);
863
+ }
864
+ if (schema.kind === "optional" || schema.kind === "nullable") {
865
+ return unwrapSchema(schema.inner, defs);
866
+ }
867
+ return schema;
868
+ }
869
+ function isPackable(schema, defs) {
870
+ const inner = unwrapSchema(schema, defs);
871
+ switch (inner.kind) {
872
+ case "string":
873
+ case "number":
874
+ case "integer":
875
+ case "boolean":
876
+ case "literal":
877
+ return true;
878
+ default:
879
+ return false;
880
+ }
881
+ }
882
+ function decodePackedBlob(blob, objectFields) {
883
+ const result = /* @__PURE__ */ new Map();
884
+ const view = new DataView(blob.buffer, blob.byteOffset, blob.byteLength);
885
+ let offset = 0;
886
+ const entryCount = view.getUint16(offset);
887
+ offset += 2;
888
+ const decoder = new TextDecoder();
889
+ for (let i = 0; i < entryCount; i++) {
890
+ const fieldIndex = view.getUint16(offset);
891
+ offset += 2;
892
+ const tag = blob[offset++];
893
+ if (tag === 2) {
894
+ result.set(fieldIndex, null);
895
+ continue;
896
+ }
897
+ if (tag !== 1) {
898
+ result.set(fieldIndex, void 0);
899
+ continue;
900
+ }
901
+ const field = objectFields.find((f) => f.index === fieldIndex);
902
+ if (!field) continue;
903
+ const innerSchema = unwrapSchema(field.schema);
904
+ switch (innerSchema.kind) {
905
+ case "boolean": {
906
+ result.set(fieldIndex, blob[offset++] === 1);
907
+ break;
908
+ }
909
+ case "number":
910
+ case "integer": {
911
+ result.set(fieldIndex, view.getFloat64(offset));
912
+ offset += 8;
913
+ break;
914
+ }
915
+ case "string": {
916
+ const len = view.getUint32(offset);
917
+ offset += 4;
918
+ result.set(fieldIndex, decoder.decode(blob.subarray(offset, offset + len)));
919
+ offset += len;
920
+ break;
921
+ }
922
+ case "literal": {
923
+ if (innerSchema.value === null) {
924
+ result.set(fieldIndex, null);
925
+ } else if (typeof innerSchema.value === "boolean") {
926
+ result.set(fieldIndex, blob[offset++] === 1);
927
+ } else if (typeof innerSchema.value === "number") {
928
+ result.set(fieldIndex, view.getFloat64(offset));
929
+ offset += 8;
930
+ } else if (typeof innerSchema.value === "string") {
931
+ const len = view.getUint32(offset);
932
+ offset += 4;
933
+ result.set(fieldIndex, decoder.decode(blob.subarray(offset, offset + len)));
934
+ offset += len;
935
+ }
936
+ break;
937
+ }
938
+ }
939
+ }
940
+ return result;
941
+ }
942
+ var RedbStore = class {
943
+ constructor(session, schema, indexMap, defs = []) {
944
+ this.session = session;
945
+ this.schema = schema;
946
+ this.indexMap = indexMap;
947
+ this.defs = defs;
948
+ }
949
+ schemaCache = /* @__PURE__ */ new Map();
950
+ closed = false;
951
+ defs;
952
+ getDefs() {
953
+ return this.defs;
954
+ }
955
+ get isClosed() {
956
+ return this.closed;
957
+ }
958
+ close() {
959
+ if (!this.closed) {
960
+ this.session.close();
961
+ this.closed = true;
962
+ }
963
+ }
964
+ ensureOpen() {
965
+ if (this.closed) {
966
+ throw new Error("RedbStore is closed");
967
+ }
968
+ }
969
+ /**
970
+ * Check if data exists at a path based on the schema type.
971
+ * For primitives: check d:{path}
972
+ * For objects/arrays/tuples/records: check m:{path}:len
973
+ * For unions: check m:{path}:var
974
+ * For nullable: check m:{path}:nul
975
+ * For optional: recursively check inner schema
976
+ */
977
+ hasDataAtPath(path, schema) {
978
+ const resolved = core.resolveRef(schema, this.defs);
979
+ const innerSchema = resolved.kind === "optional" ? resolved.inner : resolved;
980
+ switch (innerSchema.kind) {
981
+ case "object": {
982
+ const dataKey = this.pathToKey(path);
983
+ if (this.session.get(dataKey) !== null) return true;
984
+ const objMetaKey = this.pathToMetaKey(path, "len");
985
+ return this.session.get(objMetaKey) !== null;
986
+ }
987
+ case "array":
988
+ case "tuple":
989
+ case "record": {
990
+ const metaKey = this.pathToMetaKey(path, "len");
991
+ return this.session.get(metaKey) !== null;
992
+ }
993
+ case "union": {
994
+ const metaKey = this.pathToMetaKey(path, "var");
995
+ return this.session.get(metaKey) !== null;
996
+ }
997
+ case "nullable": {
998
+ const metaKey = this.pathToMetaKey(path, "nul");
999
+ return this.session.get(metaKey) !== null;
1000
+ }
1001
+ default: {
1002
+ const dataKey = this.pathToKey(path);
1003
+ return this.session.get(dataKey) !== null;
1004
+ }
1005
+ }
1006
+ }
1007
+ /**
1008
+ * Convert a user path to a metadata key with given suffix.
1009
+ * Reuses pathToKey logic but produces m:{path}:{suffix} format.
1010
+ */
1011
+ pathToMetaKey(path, suffix) {
1012
+ const dataKey = this.pathToKey(path);
1013
+ if (dataKey === "d:") {
1014
+ return `m::${suffix}`;
1015
+ }
1016
+ return `m:${dataKey.slice(2)}:${suffix}`;
1017
+ }
1018
+ /**
1019
+ * Convert a user path to a storage key.
1020
+ * Handles record keys by adding k: prefix.
1021
+ */
1022
+ pathToKey(path) {
1023
+ if (path.length === 0) return "d:";
1024
+ const parts = [];
1025
+ let currentSchema = core.resolveRef(this.schema, this.defs);
1026
+ for (const segment of path) {
1027
+ currentSchema = core.resolveRef(currentSchema, this.defs);
1028
+ switch (currentSchema.kind) {
1029
+ case "object": {
1030
+ parts.push(segment);
1031
+ const field = currentSchema.objectFields.find(
1032
+ (f) => f.key === segment
1033
+ );
1034
+ if (field) {
1035
+ currentSchema = field.schema;
1036
+ }
1037
+ break;
1038
+ }
1039
+ case "array":
1040
+ parts.push(segment);
1041
+ currentSchema = currentSchema.elements;
1042
+ break;
1043
+ case "tuple": {
1044
+ parts.push(segment);
1045
+ const idx = parseInt(segment, 10);
1046
+ const elem = currentSchema.elements[idx];
1047
+ if (elem) {
1048
+ currentSchema = elem;
1049
+ }
1050
+ break;
1051
+ }
1052
+ case "record":
1053
+ parts.push(`k:${segment}`);
1054
+ currentSchema = currentSchema.valueSchema;
1055
+ break;
1056
+ case "union": {
1057
+ parts.push(segment);
1058
+ if (segment.startsWith("v")) {
1059
+ const variantIdx = parseInt(segment.slice(1), 10);
1060
+ const variant = currentSchema.variants[variantIdx];
1061
+ if (variant) {
1062
+ currentSchema = variant;
1063
+ }
1064
+ }
1065
+ break;
1066
+ }
1067
+ case "nullable":
1068
+ case "optional":
1069
+ currentSchema = currentSchema.inner;
1070
+ return this.pathToKeyWithSchema(path, this.schema);
1071
+ default:
1072
+ parts.push(segment);
1073
+ }
1074
+ }
1075
+ return `d:${parts.join(":")}`;
1076
+ }
1077
+ /**
1078
+ * Convert path to storage key with explicit schema tracking for nullable/optional handling.
1079
+ */
1080
+ pathToKeyWithSchema(path, rootSchema) {
1081
+ if (path.length === 0) return "d:";
1082
+ const parts = [];
1083
+ let currentSchema = rootSchema;
1084
+ currentSchema = core.resolveRef(currentSchema, this.defs);
1085
+ while (currentSchema.kind === "nullable" || currentSchema.kind === "optional") {
1086
+ currentSchema = core.resolveRef(currentSchema.inner, this.defs);
1087
+ }
1088
+ for (const segment of path) {
1089
+ currentSchema = core.resolveRef(currentSchema, this.defs);
1090
+ while (currentSchema.kind === "nullable" || currentSchema.kind === "optional") {
1091
+ currentSchema = core.resolveRef(currentSchema.inner, this.defs);
1092
+ }
1093
+ switch (currentSchema.kind) {
1094
+ case "object": {
1095
+ parts.push(segment);
1096
+ const field = currentSchema.objectFields.find(
1097
+ (f) => f.key === segment
1098
+ );
1099
+ if (field) {
1100
+ currentSchema = field.schema;
1101
+ }
1102
+ break;
1103
+ }
1104
+ case "array":
1105
+ parts.push(segment);
1106
+ currentSchema = currentSchema.elements;
1107
+ break;
1108
+ case "tuple": {
1109
+ parts.push(segment);
1110
+ const idx = parseInt(segment, 10);
1111
+ const elem = currentSchema.elements[idx];
1112
+ if (elem) {
1113
+ currentSchema = elem;
1114
+ }
1115
+ break;
1116
+ }
1117
+ case "record":
1118
+ parts.push(`k:${segment}`);
1119
+ currentSchema = currentSchema.valueSchema;
1120
+ break;
1121
+ default:
1122
+ parts.push(segment);
1123
+ }
1124
+ }
1125
+ return `d:${parts.join(":")}`;
1126
+ }
1127
+ get(path) {
1128
+ this.ensureOpen();
1129
+ if (path.length > 0) {
1130
+ const parentPath = path.slice(0, -1);
1131
+ const parentSchema = this.getUnwrappedSchemaAtPath(parentPath);
1132
+ if (parentSchema.kind === "object") {
1133
+ const fieldKey = path[path.length - 1];
1134
+ const field = parentSchema.objectFields.find((f) => f.key === fieldKey);
1135
+ if (field && isPackable(field.schema, this.defs)) {
1136
+ return this.readPackedField(parentPath, parentSchema, field);
1137
+ }
1138
+ }
1139
+ }
1140
+ const schema = this.getCachedSchema(path);
1141
+ return this.readValue(path, schema);
1142
+ }
1143
+ /**
1144
+ * Recursively read and materialize a value from storage.
1145
+ * This fully materializes complex types (objects, arrays, records).
1146
+ */
1147
+ readValue(path, schema) {
1148
+ const key = this.pathToKey(path);
1149
+ switch (schema.kind) {
1150
+ case "string": {
1151
+ const bytes = this.session.get(key);
1152
+ if (!bytes) return void 0;
1153
+ return new TextDecoder().decode(bytes);
1154
+ }
1155
+ case "number":
1156
+ case "integer": {
1157
+ const bytes = this.session.get(key);
1158
+ if (!bytes) return void 0;
1159
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1160
+ return view.getFloat64(0);
1161
+ }
1162
+ case "boolean": {
1163
+ const bytes = this.session.get(key);
1164
+ if (!bytes) return void 0;
1165
+ return bytes[0] === 1;
1166
+ }
1167
+ case "literal": {
1168
+ if (schema.value === null) {
1169
+ return null;
1170
+ }
1171
+ const bytes = this.session.get(key);
1172
+ if (!bytes) return schema.value;
1173
+ if (typeof schema.value === "string") {
1174
+ return new TextDecoder().decode(bytes);
1175
+ }
1176
+ if (typeof schema.value === "number") {
1177
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1178
+ return view.getFloat64(0);
1179
+ }
1180
+ if (typeof schema.value === "boolean") {
1181
+ return bytes[0] === 1;
1182
+ }
1183
+ return schema.value;
1184
+ }
1185
+ case "nullable": {
1186
+ const metaKey = this.pathToMetaKey(path, "nul");
1187
+ const bytes = this.session.get(metaKey);
1188
+ if (!bytes) return void 0;
1189
+ const isNull = bytes[0] === 1;
1190
+ if (isNull) return null;
1191
+ return this.readValue(path, schema.inner);
1192
+ }
1193
+ case "optional":
1194
+ return this.readValue(path, schema.inner);
1195
+ case "union": {
1196
+ const metaKey = this.pathToMetaKey(path, "var");
1197
+ const bytes = this.session.get(metaKey);
1198
+ if (!bytes) return void 0;
1199
+ const variantIndex = bytes[0];
1200
+ if (variantIndex === void 0 || variantIndex >= schema.variants.length) {
1201
+ return void 0;
1202
+ }
1203
+ const variantSchema = schema.variants[variantIndex];
1204
+ if (!variantSchema) return void 0;
1205
+ const variantPath = [...path, `v${variantIndex}`];
1206
+ return this.readValue(variantPath, variantSchema);
1207
+ }
1208
+ case "object": {
1209
+ const result = {};
1210
+ const blobKey = this.pathToKey(path);
1211
+ const blob = this.session.get(blobKey);
1212
+ let packedData = null;
1213
+ if (blob) {
1214
+ packedData = decodePackedBlob(new Uint8Array(blob), schema.objectFields);
1215
+ }
1216
+ for (const field of schema.objectFields) {
1217
+ const fieldSchema = field.schema;
1218
+ if (packedData && isPackable(fieldSchema, this.defs)) {
1219
+ const entry = packedData.get(field.index);
1220
+ result[field.key] = entry;
1221
+ } else {
1222
+ const fieldPath = [...path, field.key];
1223
+ const isOptional = fieldSchema.kind === "optional";
1224
+ if (isOptional) {
1225
+ const hasField = this.hasDataAtPath(fieldPath, fieldSchema);
1226
+ if (hasField) {
1227
+ result[field.key] = this.readValue(fieldPath, fieldSchema);
1228
+ } else {
1229
+ result[field.key] = void 0;
1230
+ }
1231
+ } else {
1232
+ result[field.key] = this.readValue(fieldPath, fieldSchema);
1233
+ }
1234
+ }
1235
+ }
1236
+ return result;
1237
+ }
1238
+ case "array": {
1239
+ const length = this.getArrayLength(path);
1240
+ const result = new Array(length);
1241
+ for (let i = 0; i < length; i++) {
1242
+ const elemPath = [...path, String(i)];
1243
+ result[i] = this.readValue(elemPath, schema.elements);
1244
+ }
1245
+ return result;
1246
+ }
1247
+ case "tuple": {
1248
+ const result = new Array(schema.elements.length);
1249
+ for (let i = 0; i < schema.elements.length; i++) {
1250
+ const elemPath = [...path, String(i)];
1251
+ const elemSchema = schema.elements[i];
1252
+ if (elemSchema) {
1253
+ result[i] = this.readValue(elemPath, elemSchema);
1254
+ }
1255
+ }
1256
+ return result;
1257
+ }
1258
+ case "record": {
1259
+ const keys = this.getRecordKeys(path);
1260
+ const result = {};
1261
+ for (const k of keys) {
1262
+ const valuePath = [...path, k];
1263
+ result[k] = this.readValue(valuePath, schema.valueSchema);
1264
+ }
1265
+ return result;
1266
+ }
1267
+ case "ref":
1268
+ return this.readValue(path, this.defs[schema.defId]);
1269
+ }
1270
+ }
1271
+ has(path) {
1272
+ this.ensureOpen();
1273
+ if (path.length === 0) {
1274
+ return true;
1275
+ }
1276
+ const parentPath = path.slice(0, -1);
1277
+ const parentSchema = path.length === 1 ? this.schema : core.schemaAtPath(this.schema, parentPath, this.defs);
1278
+ const key = path[path.length - 1];
1279
+ if (key === void 0) return false;
1280
+ if (parentSchema.kind === "object") {
1281
+ const field = parentSchema.objectFields.find((f) => f.key === key);
1282
+ if (!field) return false;
1283
+ if (isPackable(field.schema, this.defs)) {
1284
+ const blobKey = this.pathToKey(parentPath);
1285
+ const blob = this.session.get(blobKey);
1286
+ if (blob) {
1287
+ const packedData = decodePackedBlob(new Uint8Array(blob), parentSchema.objectFields);
1288
+ return packedData.has(field.index) && packedData.get(field.index) !== void 0;
1289
+ }
1290
+ return false;
1291
+ }
1292
+ return this.hasDataAtPath(path, field.schema);
1293
+ }
1294
+ if (parentSchema.kind === "array") {
1295
+ const index = parseInt(key, 10);
1296
+ if (isNaN(index) || index < 0) return false;
1297
+ const length = this.getArrayLength(parentPath);
1298
+ return index < length;
1299
+ }
1300
+ if (parentSchema.kind === "record") {
1301
+ const recordKey = parentPath.length === 0 ? `d:k:${key}` : `d:${parentPath.join(":")}:k:${key}`;
1302
+ return this.session.get(recordKey) !== null;
1303
+ }
1304
+ return false;
1305
+ }
1306
+ getFieldMetadata(path, key) {
1307
+ const fullPath = [...path, key];
1308
+ const pathKey = encodePath(fullPath);
1309
+ const exists = this.indexMap.has(pathKey);
1310
+ return {
1311
+ exists,
1312
+ schema: exists ? this.getCachedSchema(fullPath) : { kind: "string" }
1313
+ };
1314
+ }
1315
+ getArrayLength(path) {
1316
+ this.ensureOpen();
1317
+ const metaKey = this.pathToMetaKey(path, "len");
1318
+ const bytes = this.session.get(metaKey);
1319
+ if (!bytes) return 0;
1320
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1321
+ return view.getUint32(0);
1322
+ }
1323
+ getRecordKeys(path) {
1324
+ this.ensureOpen();
1325
+ const dataKey = this.pathToKey(path);
1326
+ const dataPrefix = dataKey === "d:" ? "d:k:" : `${dataKey}:k:`;
1327
+ const metaPrefix = dataKey === "d:" ? "m:k:" : `m:${dataKey.slice(2)}:k:`;
1328
+ const keys = /* @__PURE__ */ new Set();
1329
+ for (const k of this.session.keysWithPrefix(dataPrefix)) {
1330
+ const keyPart = k.slice(dataPrefix.length);
1331
+ const colonIdx = keyPart.indexOf(":");
1332
+ const immediateKey = colonIdx === -1 ? keyPart : keyPart.slice(0, colonIdx);
1333
+ keys.add(immediateKey);
1334
+ }
1335
+ for (const k of this.session.keysWithPrefix(metaPrefix)) {
1336
+ const keyPart = k.slice(metaPrefix.length);
1337
+ const colonIdx = keyPart.indexOf(":");
1338
+ const immediateKey = colonIdx === -1 ? keyPart : keyPart.slice(0, colonIdx);
1339
+ keys.add(immediateKey);
1340
+ }
1341
+ return Array.from(keys);
1342
+ }
1343
+ /**
1344
+ * Navigate to a path and unwrap any nullable/optional wrappers on the result.
1345
+ */
1346
+ getUnwrappedSchemaAtPath(path) {
1347
+ let schema = path.length === 0 ? this.schema : core.schemaAtPath(this.schema, path, this.defs);
1348
+ schema = core.resolveRef(schema, this.defs);
1349
+ while (schema.kind === "nullable" || schema.kind === "optional") {
1350
+ schema = core.resolveRef(schema.inner, this.defs);
1351
+ }
1352
+ return schema;
1353
+ }
1354
+ /**
1355
+ * Read a single packable field from the parent object's packed blob.
1356
+ */
1357
+ readPackedField(parentPath, parentSchema, field) {
1358
+ const blobKey = this.pathToKey(parentPath);
1359
+ const blob = this.session.get(blobKey);
1360
+ if (!blob) return void 0;
1361
+ const packedData = decodePackedBlob(new Uint8Array(blob), parentSchema.objectFields);
1362
+ return packedData.get(field.index);
1363
+ }
1364
+ /**
1365
+ * Get schema at path with caching
1366
+ */
1367
+ getCachedSchema(path) {
1368
+ if (path.length === 0) {
1369
+ return this.schema;
1370
+ }
1371
+ const pathKey = encodePath(path);
1372
+ let schema = this.schemaCache.get(pathKey);
1373
+ if (schema === void 0) {
1374
+ schema = core.schemaAtPath(this.schema, path, this.defs);
1375
+ this.schemaCache.set(pathKey, schema);
1376
+ }
1377
+ return schema;
1378
+ }
1379
+ };
1380
+
1381
+ // src/native.ts
1382
+ var NativeParser = class {
1383
+ constructor(schema) {
1384
+ this.schema = schema;
1385
+ const counter = { value: 0 };
1386
+ const lazy2 = { seen: /* @__PURE__ */ new Map(), defs: [] };
1387
+ this.root = schema.serializeSchema(counter, lazy2);
1388
+ if (lazy2.defs.some((d) => d === void 0)) {
1389
+ throw new Error(
1390
+ "Incomplete lazy defs: some definitions were not resolved during serialization"
1391
+ );
1392
+ }
1393
+ this.defs = lazy2.defs;
1394
+ this.native = new native.Atchara(this.root, this.defs.length > 0 ? this.defs : void 0);
1395
+ this.indexMap = buildIndexMap(this.root, this.defs);
1396
+ }
1397
+ root;
1398
+ defs;
1399
+ native;
1400
+ indexMap;
1401
+ parse(input) {
1402
+ const [isError, bytes] = this.native.parse(input);
1403
+ if (isError) {
1404
+ const errorDecoder = new ErrorDecoder(bytes);
1405
+ throw errorDecoder.decode();
1406
+ }
1407
+ const store = new MemoryStore(bytes, this.root, this.indexMap, this.defs);
1408
+ return core.wrapDeferred(store, [], this.root);
1409
+ }
1410
+ /**
1411
+ * Parse a JSON array from a stream, yielding each element as it is parsed.
1412
+ * Only valid when the root schema is an array.
1413
+ * Yielded deferreds become invalid after the iterator completes.
1414
+ */
1415
+ async *parseEach(stream) {
1416
+ const [session, redbClient] = this.native.createIteratingSession();
1417
+ const arraySchema = this.root;
1418
+ const store = new RedbStore(redbClient, this.root, this.indexMap, this.defs);
1419
+ try {
1420
+ let complete = false;
1421
+ for await (const chunk of stream) {
1422
+ const bytes = buffer.Buffer.isBuffer(chunk) ? chunk : buffer.Buffer.from(chunk);
1423
+ const result = session.feed(bytes);
1424
+ for (const index of result.readyIndices) {
1425
+ yield core.wrapDeferred(store, [String(index)], arraySchema.elements);
1426
+ }
1427
+ if (result.status === -1) {
1428
+ const errorDecoder = new ErrorDecoder(result.errorBytes);
1429
+ throw errorDecoder.decode();
1430
+ }
1431
+ if (result.status === 0) {
1432
+ complete = true;
1433
+ break;
1434
+ }
1435
+ }
1436
+ if (!complete) {
1437
+ const result = session.finish();
1438
+ for (const index of result.readyIndices) {
1439
+ yield core.wrapDeferred(store, [String(index)], arraySchema.elements);
1440
+ }
1441
+ if (result.status === -1) {
1442
+ const errorDecoder = new ErrorDecoder(result.errorBytes);
1443
+ throw errorDecoder.decode();
1444
+ }
1445
+ }
1446
+ } finally {
1447
+ session.abort();
1448
+ store.close();
1449
+ }
1450
+ }
1451
+ /**
1452
+ * Parse large JSON documents incrementally from a readable stream.
1453
+ * Parses and stores to redb as chunks arrive - never buffers the entire document.
1454
+ * Enables parsing files larger than available RAM.
1455
+ * Returns a result object with explicit close() for resource management.
1456
+ */
1457
+ async parseLarge(stream) {
1458
+ const session = this.native.createStreamingSession();
1459
+ try {
1460
+ for await (const chunk of stream) {
1461
+ const bytes = buffer.Buffer.isBuffer(chunk) ? chunk : buffer.Buffer.from(chunk);
1462
+ const [status, errorBytes2] = session.feed(bytes);
1463
+ if (status === -1) {
1464
+ const errorDecoder = new ErrorDecoder(errorBytes2);
1465
+ throw errorDecoder.decode();
1466
+ }
1467
+ if (status === 0) break;
1468
+ }
1469
+ const [isError, errorBytes, redbClient] = session.finish();
1470
+ if (isError || !redbClient) {
1471
+ const errorDecoder = new ErrorDecoder(errorBytes);
1472
+ throw errorDecoder.decode();
1473
+ }
1474
+ const store = new RedbStore(redbClient, this.root, this.indexMap, this.defs);
1475
+ const deferred = core.wrapDeferred(store, [], this.root);
1476
+ return {
1477
+ data: deferred,
1478
+ close: () => store.close(),
1479
+ get isClosed() {
1480
+ return store.isClosed;
1481
+ }
1482
+ };
1483
+ } catch (error) {
1484
+ session.abort();
1485
+ throw error;
1486
+ }
1487
+ }
1488
+ };
1489
+ function buildIndexMap(schema, defs) {
1490
+ const map = /* @__PURE__ */ new Map();
1491
+ const visited = /* @__PURE__ */ new Set();
1492
+ const traverse = (s, pathParts) => {
1493
+ if (s.schemaIndex !== void 0) {
1494
+ const pathKey = encodePath(pathParts);
1495
+ map.set(pathKey, s.schemaIndex);
1496
+ }
1497
+ switch (s.kind) {
1498
+ case "optional":
1499
+ case "nullable":
1500
+ break;
1501
+ case "object":
1502
+ for (const field of s.objectFields) {
1503
+ const fieldPath = [...pathParts, field.key];
1504
+ traverse(field.schema, fieldPath);
1505
+ }
1506
+ break;
1507
+ case "array":
1508
+ break;
1509
+ case "tuple":
1510
+ for (let i = 0; i < s.elements.length; i++) {
1511
+ const element = s.elements[i];
1512
+ if (!element) continue;
1513
+ const elementPath = [...pathParts, String(i)];
1514
+ traverse(element, elementPath);
1515
+ }
1516
+ break;
1517
+ case "record":
1518
+ break;
1519
+ case "union":
1520
+ break;
1521
+ case "ref": {
1522
+ if (!visited.has(s.defId)) {
1523
+ visited.add(s.defId);
1524
+ const target = defs[s.defId];
1525
+ if (target) {
1526
+ traverse(target, pathParts);
1527
+ }
1528
+ }
1529
+ break;
1530
+ }
1531
+ }
1532
+ };
1533
+ traverse(schema, []);
1534
+ return map;
1535
+ }
1536
+
1537
+ // src/schema/string.ts
1538
+ var StringSchema = class _StringSchema {
1539
+ _output;
1540
+ _input;
1541
+ _deferred;
1542
+ _constraints;
1543
+ _parser;
1544
+ get schema() {
1545
+ return this;
1546
+ }
1547
+ get constraints() {
1548
+ return this._constraints;
1549
+ }
1550
+ min(n) {
1551
+ const s = new _StringSchema();
1552
+ s._constraints = { ...this._constraints, min: n };
1553
+ return s;
1554
+ }
1555
+ max(n) {
1556
+ const s = new _StringSchema();
1557
+ s._constraints = { ...this._constraints, max: n };
1558
+ return s;
1559
+ }
1560
+ pattern(regex) {
1561
+ const s = new _StringSchema();
1562
+ s._constraints = {
1563
+ ...this._constraints,
1564
+ pattern: typeof regex === "string" ? regex : regex.source
1565
+ };
1566
+ return s;
1567
+ }
1568
+ parse(input) {
1569
+ return this.getParser().parse(input);
1570
+ }
1571
+ parseLarge(stream) {
1572
+ return this.getParser().parseLarge(stream);
1573
+ }
1574
+ getParser() {
1575
+ if (!this._parser) {
1576
+ this._parser = new NativeParser(this);
1577
+ }
1578
+ return this._parser;
1579
+ }
1580
+ serializeSchema(counter, _lazy) {
1581
+ return {
1582
+ kind: "string",
1583
+ schemaIndex: counter ? counter.value++ : void 0,
1584
+ ...this._constraints && { constraints: this._constraints }
1585
+ };
1586
+ }
1587
+ };
1588
+
1589
+ // src/schema/object.ts
1590
+ var ObjectSchema = class {
1591
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1592
+ constructor(_shape) {
1593
+ this._shape = _shape;
1594
+ }
1595
+ _output;
1596
+ _input;
1597
+ _deferred;
1598
+ serializeSchema(counter, lazy2) {
1599
+ return {
1600
+ kind: "object",
1601
+ schemaIndex: counter ? counter.value++ : void 0,
1602
+ objectFields: Object.entries(this._shape).map(([key, parser], index) => ({
1603
+ key,
1604
+ index,
1605
+ schema: parser.schema.serializeSchema(counter, lazy2)
1606
+ }))
1607
+ };
1608
+ }
1609
+ };
1610
+
1611
+ // src/schema/number.ts
1612
+ var NumberSchema = class _NumberSchema {
1613
+ _output;
1614
+ _input;
1615
+ _deferred;
1616
+ _constraints;
1617
+ _parser;
1618
+ get schema() {
1619
+ return this;
1620
+ }
1621
+ get constraints() {
1622
+ return this._constraints;
1623
+ }
1624
+ min(n) {
1625
+ const s = new _NumberSchema();
1626
+ s._constraints = { ...this._constraints, min: n };
1627
+ return s;
1628
+ }
1629
+ max(n) {
1630
+ const s = new _NumberSchema();
1631
+ s._constraints = { ...this._constraints, max: n };
1632
+ return s;
1633
+ }
1634
+ gt(n) {
1635
+ const s = new _NumberSchema();
1636
+ s._constraints = { ...this._constraints, gt: n };
1637
+ return s;
1638
+ }
1639
+ lt(n) {
1640
+ const s = new _NumberSchema();
1641
+ s._constraints = { ...this._constraints, lt: n };
1642
+ return s;
1643
+ }
1644
+ multipleOf(n) {
1645
+ const s = new _NumberSchema();
1646
+ s._constraints = { ...this._constraints, multipleOf: n };
1647
+ return s;
1648
+ }
1649
+ parse(input) {
1650
+ return this.getParser().parse(input);
1651
+ }
1652
+ parseLarge(stream) {
1653
+ return this.getParser().parseLarge(stream);
1654
+ }
1655
+ getParser() {
1656
+ if (!this._parser) {
1657
+ this._parser = new NativeParser(this);
1658
+ }
1659
+ return this._parser;
1660
+ }
1661
+ serializeSchema(counter, _lazy) {
1662
+ return {
1663
+ kind: "number",
1664
+ schemaIndex: counter ? counter.value++ : void 0,
1665
+ ...this._constraints && { constraints: this._constraints }
1666
+ };
1667
+ }
1668
+ };
1669
+
1670
+ // src/schema/integer.ts
1671
+ var IntegerSchema = class _IntegerSchema {
1672
+ _output;
1673
+ _input;
1674
+ _deferred;
1675
+ _constraints;
1676
+ _parser;
1677
+ get schema() {
1678
+ return this;
1679
+ }
1680
+ get constraints() {
1681
+ return this._constraints;
1682
+ }
1683
+ min(n) {
1684
+ const s = new _IntegerSchema();
1685
+ s._constraints = { ...this._constraints, min: n };
1686
+ return s;
1687
+ }
1688
+ max(n) {
1689
+ const s = new _IntegerSchema();
1690
+ s._constraints = { ...this._constraints, max: n };
1691
+ return s;
1692
+ }
1693
+ gt(n) {
1694
+ const s = new _IntegerSchema();
1695
+ s._constraints = { ...this._constraints, gt: n };
1696
+ return s;
1697
+ }
1698
+ lt(n) {
1699
+ const s = new _IntegerSchema();
1700
+ s._constraints = { ...this._constraints, lt: n };
1701
+ return s;
1702
+ }
1703
+ multipleOf(n) {
1704
+ const s = new _IntegerSchema();
1705
+ s._constraints = { ...this._constraints, multipleOf: n };
1706
+ return s;
1707
+ }
1708
+ parse(input) {
1709
+ return this.getParser().parse(input);
1710
+ }
1711
+ parseLarge(stream) {
1712
+ return this.getParser().parseLarge(stream);
1713
+ }
1714
+ getParser() {
1715
+ if (!this._parser) {
1716
+ this._parser = new NativeParser(this);
1717
+ }
1718
+ return this._parser;
1719
+ }
1720
+ serializeSchema(counter, _lazy) {
1721
+ return {
1722
+ kind: "integer",
1723
+ schemaIndex: counter ? counter.value++ : void 0,
1724
+ ...this._constraints && { constraints: this._constraints }
1725
+ };
1726
+ }
1727
+ };
1728
+
1729
+ // src/schema/boolean.ts
1730
+ var BooleanSchema = class {
1731
+ _output;
1732
+ _input;
1733
+ _deferred;
1734
+ serializeSchema(counter, _lazy) {
1735
+ return { kind: "boolean", schemaIndex: counter ? counter.value++ : void 0 };
1736
+ }
1737
+ };
1738
+
1739
+ // src/schema/nullable.ts
1740
+ var NullableSchema = class {
1741
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1742
+ constructor(_valueParser) {
1743
+ this._valueParser = _valueParser;
1744
+ }
1745
+ _output;
1746
+ _input;
1747
+ _deferred;
1748
+ // Brand to distinguish from OptionalSchema (which has identical structure)
1749
+ _brand = "nullable";
1750
+ serializeSchema(counter, lazy2) {
1751
+ return {
1752
+ kind: "nullable",
1753
+ schemaIndex: counter ? counter.value++ : void 0,
1754
+ inner: this._valueParser.schema.serializeSchema(null, lazy2)
1755
+ };
1756
+ }
1757
+ };
1758
+
1759
+ // src/schema/optional.ts
1760
+ var OptionalSchema = class {
1761
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1762
+ constructor(_valueParser) {
1763
+ this._valueParser = _valueParser;
1764
+ }
1765
+ _output;
1766
+ _input;
1767
+ _deferred;
1768
+ // Brand to distinguish from NullableSchema (which has identical structure)
1769
+ _brand = "optional";
1770
+ serializeSchema(counter, lazy2) {
1771
+ return {
1772
+ kind: "optional",
1773
+ schemaIndex: counter ? counter.value++ : void 0,
1774
+ inner: this._valueParser.schema.serializeSchema(null, lazy2)
1775
+ };
1776
+ }
1777
+ };
1778
+
1779
+ // src/schema/literal.ts
1780
+ var LiteralSchema = class {
1781
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1782
+ constructor(_value) {
1783
+ this._value = _value;
1784
+ }
1785
+ _output;
1786
+ _input;
1787
+ _deferred;
1788
+ serializeSchema(counter, _lazy) {
1789
+ return {
1790
+ kind: "literal",
1791
+ value: this._value,
1792
+ schemaIndex: counter ? counter.value++ : void 0
1793
+ };
1794
+ }
1795
+ };
1796
+
1797
+ // src/schema/tuple.ts
1798
+ var TupleSchema = class {
1799
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1800
+ constructor(_elements) {
1801
+ this._elements = _elements;
1802
+ }
1803
+ _output;
1804
+ _input;
1805
+ _deferred;
1806
+ serializeSchema(counter, lazy2) {
1807
+ return {
1808
+ kind: "tuple",
1809
+ schemaIndex: counter ? counter.value++ : void 0,
1810
+ elements: this._elements.map((e) => e.schema.serializeSchema(counter, lazy2))
1811
+ };
1812
+ }
1813
+ };
1814
+
1815
+ // src/schema/record.ts
1816
+ var RecordSchema = class _RecordSchema {
1817
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1818
+ constructor(_valueSchema) {
1819
+ this._valueSchema = _valueSchema;
1820
+ }
1821
+ _output;
1822
+ _input;
1823
+ _deferred;
1824
+ _constraints;
1825
+ _parser;
1826
+ get schema() {
1827
+ return this;
1828
+ }
1829
+ get constraints() {
1830
+ return this._constraints;
1831
+ }
1832
+ min(n) {
1833
+ const s = new _RecordSchema(this._valueSchema);
1834
+ s._constraints = { ...this._constraints, min: n };
1835
+ return s;
1836
+ }
1837
+ max(n) {
1838
+ const s = new _RecordSchema(this._valueSchema);
1839
+ s._constraints = { ...this._constraints, max: n };
1840
+ return s;
1841
+ }
1842
+ parse(input) {
1843
+ return this.getParser().parse(input);
1844
+ }
1845
+ parseLarge(stream) {
1846
+ return this.getParser().parseLarge(stream);
1847
+ }
1848
+ getParser() {
1849
+ if (!this._parser) {
1850
+ this._parser = new NativeParser(this);
1851
+ }
1852
+ return this._parser;
1853
+ }
1854
+ serializeSchema(counter, lazy2) {
1855
+ return {
1856
+ kind: "record",
1857
+ schemaIndex: counter ? counter.value++ : void 0,
1858
+ valueSchema: this._valueSchema.schema.serializeSchema(null, lazy2),
1859
+ ...this._constraints && { constraints: this._constraints }
1860
+ };
1861
+ }
1862
+ };
1863
+ var UnionSchema = class {
1864
+ constructor(_variants) {
1865
+ this._variants = _variants;
1866
+ for (const variant of _variants) {
1867
+ if (variant.schema instanceof OptionalSchema) {
1868
+ throw core.createAtcharaError(
1869
+ "optional() cannot be used as a union variant. optional() is for object fields that may be absent. Use nullable() if you want a value that can be null.",
1870
+ {
1871
+ code: "INVALID_SCHEMA"
1872
+ }
1873
+ );
1874
+ }
1875
+ }
1876
+ }
1877
+ _output;
1878
+ _input;
1879
+ _deferred;
1880
+ serializeSchema(counter, lazy2) {
1881
+ return {
1882
+ kind: "union",
1883
+ schemaIndex: counter ? counter.value++ : void 0,
1884
+ variants: this._variants.map((v) => v.schema.serializeSchema(null, lazy2))
1885
+ };
1886
+ }
1887
+ };
1888
+
1889
+ // src/schema/array.ts
1890
+ var ArraySchema = class _ArraySchema {
1891
+ // can't make it private: https://github.com/microsoft/TypeScript/issues/35822
1892
+ constructor(_elements) {
1893
+ this._elements = _elements;
1894
+ }
1895
+ _output;
1896
+ _input;
1897
+ _deferred;
1898
+ _constraints;
1899
+ _parser;
1900
+ get schema() {
1901
+ return this;
1902
+ }
1903
+ get constraints() {
1904
+ return this._constraints;
1905
+ }
1906
+ min(n) {
1907
+ const s = new _ArraySchema(this._elements);
1908
+ s._constraints = { ...this._constraints, min: n };
1909
+ return s;
1910
+ }
1911
+ max(n) {
1912
+ const s = new _ArraySchema(this._elements);
1913
+ s._constraints = { ...this._constraints, max: n };
1914
+ return s;
1915
+ }
1916
+ parse(input) {
1917
+ return this.getParser().parse(input);
1918
+ }
1919
+ parseLarge(stream) {
1920
+ return this.getParser().parseLarge(stream);
1921
+ }
1922
+ /**
1923
+ * Parse a JSON array from a stream, yielding each element's deferred wrapper as it is parsed.
1924
+ * Yielded deferreds become invalid after the iterator completes.
1925
+ */
1926
+ parseEach(stream) {
1927
+ return this.getParser().parseEach(stream);
1928
+ }
1929
+ getParser() {
1930
+ if (!this._parser) {
1931
+ this._parser = new NativeParser(this);
1932
+ }
1933
+ return this._parser;
1934
+ }
1935
+ serializeSchema(counter, lazy2) {
1936
+ return {
1937
+ kind: "array",
1938
+ schemaIndex: counter ? counter.value++ : void 0,
1939
+ elements: this._elements.schema.serializeSchema(null, lazy2),
1940
+ ...this._constraints && { constraints: this._constraints }
1941
+ };
1942
+ }
1943
+ };
1944
+
1945
+ // src/schema/lazy.ts
1946
+ var LazySchema = class {
1947
+ constructor(_thunk) {
1948
+ this._thunk = _thunk;
1949
+ }
1950
+ _output;
1951
+ _input;
1952
+ _deferred;
1953
+ _resolved;
1954
+ _parser;
1955
+ // Guards against re-entrant thunk resolution (e.g., object() inside thunk
1956
+ // eagerly creates NativeParser which re-enters serializeSchema)
1957
+ _resolving = false;
1958
+ get schema() {
1959
+ return this;
1960
+ }
1961
+ parse(input) {
1962
+ return this.getParser().parse(input);
1963
+ }
1964
+ parseLarge(stream) {
1965
+ return this.getParser().parseLarge(stream);
1966
+ }
1967
+ getParser() {
1968
+ if (!this._parser) {
1969
+ this._parser = new NativeParser(this);
1970
+ }
1971
+ return this._parser;
1972
+ }
1973
+ resolve() {
1974
+ if (!this._resolved) {
1975
+ this._resolved = this._thunk();
1976
+ }
1977
+ return this._resolved;
1978
+ }
1979
+ serializeSchema(counter, lazy2) {
1980
+ if (lazy2?.seen.has(this)) {
1981
+ return { kind: "ref", defId: lazy2.seen.get(this) };
1982
+ }
1983
+ if (this._resolving) {
1984
+ return { kind: "ref", defId: 0 };
1985
+ }
1986
+ let defId;
1987
+ if (lazy2) {
1988
+ defId = lazy2.defs.length;
1989
+ lazy2.seen.set(this, defId);
1990
+ lazy2.defs.push(void 0);
1991
+ }
1992
+ this._resolving = true;
1993
+ const resolved = this.resolve();
1994
+ this._resolving = false;
1995
+ const inner = resolved.schema.serializeSchema(counter, lazy2);
1996
+ if (lazy2 && defId !== void 0) {
1997
+ lazy2.defs[defId] = inner;
1998
+ return { kind: "ref", defId };
1999
+ }
2000
+ return inner;
2001
+ }
2002
+ };
2003
+
2004
+ // src/base.ts
2005
+ async function initialize() {
2006
+ }
2007
+ function string() {
2008
+ return new StringSchema();
2009
+ }
2010
+ function number() {
2011
+ return new NumberSchema();
2012
+ }
2013
+ function integer() {
2014
+ return new IntegerSchema();
2015
+ }
2016
+ function boolean() {
2017
+ const schema = new BooleanSchema();
2018
+ const parser = new NativeParser(schema);
2019
+ return parser;
2020
+ }
2021
+ function nullable(valueParser) {
2022
+ const schema = new NullableSchema(valueParser);
2023
+ const parser = new NativeParser(schema);
2024
+ return parser;
2025
+ }
2026
+ function optional(valueParser) {
2027
+ const schema = new OptionalSchema(valueParser);
2028
+ const parser = new NativeParser(schema);
2029
+ return parser;
2030
+ }
2031
+ function object(shape) {
2032
+ const schema = new ObjectSchema(shape);
2033
+ const parser = new NativeParser(schema);
2034
+ return parser;
2035
+ }
2036
+ function array(elements) {
2037
+ return new ArraySchema(elements);
2038
+ }
2039
+ function literal(value) {
2040
+ const schema = new LiteralSchema(value);
2041
+ const parser = new NativeParser(schema);
2042
+ return parser;
2043
+ }
2044
+ function tuple(elements) {
2045
+ const schema = new TupleSchema(elements);
2046
+ const parser = new NativeParser(schema);
2047
+ return parser;
2048
+ }
2049
+ function record(valueSchema) {
2050
+ return new RecordSchema(valueSchema);
2051
+ }
2052
+ function union(variants) {
2053
+ const schema = new UnionSchema(variants);
2054
+ const parser = new NativeParser(schema);
2055
+ return parser;
2056
+ }
2057
+ function lazy(fn) {
2058
+ return new LazySchema(fn);
2059
+ }
2060
+
2061
+ Object.defineProperty(exports, "DeferredArray", {
2062
+ enumerable: true,
2063
+ get: function () { return core.DeferredArray; }
2064
+ });
2065
+ Object.defineProperty(exports, "DeferredNullable", {
2066
+ enumerable: true,
2067
+ get: function () { return core.DeferredNullable; }
2068
+ });
2069
+ Object.defineProperty(exports, "DeferredObject", {
2070
+ enumerable: true,
2071
+ get: function () { return core.DeferredObject; }
2072
+ });
2073
+ Object.defineProperty(exports, "DeferredPrimitive", {
2074
+ enumerable: true,
2075
+ get: function () { return core.DeferredPrimitive; }
2076
+ });
2077
+ Object.defineProperty(exports, "DeferredRecord", {
2078
+ enumerable: true,
2079
+ get: function () { return core.DeferredRecord; }
2080
+ });
2081
+ Object.defineProperty(exports, "DeferredTuple", {
2082
+ enumerable: true,
2083
+ get: function () { return core.DeferredTuple; }
2084
+ });
2085
+ Object.defineProperty(exports, "DeferredUnion", {
2086
+ enumerable: true,
2087
+ get: function () { return core.DeferredUnion; }
2088
+ });
2089
+ Object.defineProperty(exports, "isAtcharaError", {
2090
+ enumerable: true,
2091
+ get: function () { return core.isAtcharaError; }
2092
+ });
2093
+ Object.defineProperty(exports, "toBytes", {
2094
+ enumerable: true,
2095
+ get: function () { return core.toBytes; }
2096
+ });
2097
+ Object.defineProperty(exports, "wrapDeferred", {
2098
+ enumerable: true,
2099
+ get: function () { return core.wrapDeferred; }
2100
+ });
2101
+ exports.ArraySchema = ArraySchema;
2102
+ exports.IntegerSchema = IntegerSchema;
2103
+ exports.LazySchema = LazySchema;
2104
+ exports.NumberSchema = NumberSchema;
2105
+ exports.StringSchema = StringSchema;
2106
+ exports.array = array;
2107
+ exports.boolean = boolean;
2108
+ exports.initialize = initialize;
2109
+ exports.integer = integer;
2110
+ exports.lazy = lazy;
2111
+ exports.literal = literal;
2112
+ exports.nullable = nullable;
2113
+ exports.number = number;
2114
+ exports.object = object;
2115
+ exports.optional = optional;
2116
+ exports.record = record;
2117
+ exports.string = string;
2118
+ exports.tuple = tuple;
2119
+ exports.union = union;