@zakkster/lite-bake-stream 1.4.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js CHANGED
@@ -12,7 +12,7 @@
12
12
  import { Tokenizer, TokenizerError } from './Tokenizer.js';
13
13
  import { Writer, WriterError } from './Writer.js';
14
14
  import { Reader, ReaderError } from './Reader.js';
15
- import { StringTable } from './StringTable.js';
15
+ import { StringTable, StringTableError } from './StringTable.js';
16
16
  import { PreserveTokenizer, PreserveTokenizerError } from './PreserveTokenizer.js';
17
17
  import { PreserveWriter, PreserveWriterError } from './PreserveWriter.js';
18
18
  import { PreserveReader, PreserveReaderError } from './PreserveReader.js';
@@ -23,12 +23,12 @@ export {
23
23
  Tokenizer, TokenizerError,
24
24
  Writer, WriterError,
25
25
  Reader, ReaderError,
26
- StringTable,
26
+ StringTable, StringTableError,
27
27
  PreserveTokenizer, PreserveTokenizerError,
28
28
  PreserveWriter, PreserveWriterError,
29
29
  PreserveReader, PreserveReaderError,
30
30
  };
31
- export const VERSION = '1.4.1';
31
+ export const VERSION = '1.6.0';
32
32
 
33
33
  const encoder = new TextEncoder();
34
34
 
@@ -188,12 +188,12 @@ async function _serializeAsyncIterablePreserve(iterable, opts) {
188
188
 
189
189
  // Deserialize LBK1 bytes into the right Reader for the container's mode.
190
190
  // Auto-detects preserve vs schema via header flag byte at offset 7 bit 0.
191
- export function deserialize(bytes) {
191
+ export function deserialize(bytes, opts) {
192
192
  const buffer = toContainerBuffer(bytes, 'deserialize');
193
193
  if (buffer.byteLength < 8) {
194
194
  throw new ReaderError('R_TRUNCATED', 'container too small to inspect header flags');
195
195
  }
196
196
  const flags = new Uint8Array(buffer, 7, 1)[0];
197
- if (flags & 0x01) return new PreserveReader(buffer);
198
- return new Reader(buffer);
197
+ if (flags & 0x01) return new PreserveReader(buffer, opts);
198
+ return new Reader(buffer, opts);
199
199
  }
@@ -13,9 +13,17 @@ export interface PreserveShardHandle {
13
13
  endRow: number;
14
14
  }
15
15
 
16
+ export interface PreserveReaderOptions {
17
+ /** Verify the footer CRC-32C at open; throws R_BAD_CRC on mismatch, R_CRC_ABSENT if absent. */
18
+ verifyCrc?: boolean;
19
+ }
20
+
16
21
  export class PreserveReader {
17
- static fromBuffer(input: ArrayBuffer | Uint8Array): PreserveReader;
18
- constructor(buffer: ArrayBuffer);
22
+ static fromBuffer(input: ArrayBuffer | Uint8Array, opts?: PreserveReaderOptions): PreserveReader;
23
+ constructor(buffer: ArrayBuffer, opts?: PreserveReaderOptions);
24
+
25
+ /** Recompute the footer CRC-32C over [0, footer_off): 'ok' | 'absent'; throws R_BAD_CRC on mismatch. */
26
+ verifyCrc(): 'ok' | 'absent';
19
27
 
20
28
  readonly totalRows: number;
21
29
  readonly shardCount: number;
@@ -8,6 +8,8 @@ export interface PreserveWriterOptions {
8
8
  targetShardBytes?: number;
9
9
  /** Passed to PreserveTokenizer via the top-level API. */
10
10
  maxRecordBytes?: number;
11
+ /** Emit a CRC-32C over [0, footer_off) into the footer. Default false. */
12
+ crc?: boolean;
11
13
  }
12
14
 
13
15
  export interface PreserveContainer {
@@ -17,6 +19,24 @@ export interface PreserveContainer {
17
19
  mode: 'preserve';
18
20
  }
19
21
 
22
+ export interface PreserveContainerSink {
23
+ write(bytes: Uint8Array): void;
24
+ writeAt?(bytes: Uint8Array, position: number): void;
25
+ }
26
+
27
+ export interface PreserveFinalizeToSinkOptions {
28
+ layout?: 'prefix' | 'stream';
29
+ crc?: boolean;
30
+ }
31
+
32
+ export interface PreserveSinkResult {
33
+ totalRows: number;
34
+ shardCount: number;
35
+ mode: 'preserve';
36
+ bytesWritten: number;
37
+ layout: 'prefix' | 'stream';
38
+ }
39
+
20
40
  export class PreserveWriter {
21
41
  constructor(opts?: PreserveWriterOptions);
22
42
  /** Sink protocol. Called by PreserveTokenizer for each detected record. */
@@ -24,6 +44,16 @@ export class PreserveWriter {
24
44
  /** Public API for direct record writes. */
25
45
  writeRecord(bytes: Uint8Array): void;
26
46
  finalize(): PreserveContainer;
47
+ /**
48
+ * Bind a sink and stream shards as they finalize (bounded RAM). Call BEFORE
49
+ * feeding, then finish with finalizeToSink. opts.layout must be 'stream'.
50
+ */
51
+ beginStream(sink: PreserveContainerSink, opts?: PreserveFinalizeToSinkOptions): void;
52
+ /**
53
+ * Emit to a caller sink. Preceded by beginStream it writes only the trailer
54
+ * (O(shard)); called alone it buffers first (O(container)).
55
+ */
56
+ finalizeToSink(sink: PreserveContainerSink, opts?: PreserveFinalizeToSinkOptions): PreserveSinkResult;
27
57
  readonly totalRows: number;
28
58
  readonly shardCount: number;
29
59
  }
@@ -36,6 +36,8 @@ export class MockRangeAdapter implements IOAdapter {
36
36
  export interface RangeReaderOptions {
37
37
  /** Bounded LRU cache size. Default 8. */
38
38
  maxCachedShards?: number;
39
+ /** Verify the footer CRC-32C at open; rejects R_BAD_CRC on mismatch, R_CRC_ABSENT if absent. */
40
+ verifyCrc?: boolean;
39
41
  }
40
42
 
41
43
  export interface RangeShardHandle {
@@ -60,6 +62,9 @@ export class RangeReader {
60
62
  readonly cachedShardCount: number;
61
63
  readonly hasZoneMaps: boolean;
62
64
 
65
+ /** Ranged-fetch the body [0, footer_off) and verify its CRC-32C: 'ok' | 'absent'; rejects R_BAD_CRC on mismatch. */
66
+ verifyCrc(): Promise<'ok' | 'absent'>;
67
+
63
68
  fieldIndex(name: string): number;
64
69
 
65
70
  /** Fetch a shard's payload+string-table (one range request), cache, return record. */
package/types/Reader.d.ts CHANGED
@@ -42,9 +42,17 @@ export interface FindShardsOptions {
42
42
  max?: number;
43
43
  }
44
44
 
45
+ export interface ReaderOptions {
46
+ /** Verify the footer CRC-32C at open; throws R_BAD_CRC on mismatch, R_CRC_ABSENT if absent. */
47
+ verifyCrc?: boolean;
48
+ }
49
+
45
50
  export class Reader {
46
- static fromBuffer(bufferOrArrayBuffer: ArrayBuffer | Uint8Array): Reader;
47
- constructor(buffer: ArrayBuffer);
51
+ static fromBuffer(bufferOrArrayBuffer: ArrayBuffer | Uint8Array, opts?: ReaderOptions): Reader;
52
+ constructor(buffer: ArrayBuffer, opts?: ReaderOptions);
53
+
54
+ /** Recompute the footer CRC-32C over [0, footer_off): 'ok' | 'absent'; throws R_BAD_CRC on mismatch. */
55
+ verifyCrc(): 'ok' | 'absent';
48
56
 
49
57
  readonly schema: FrozenSchema;
50
58
  readonly totalRows: number;
@@ -3,6 +3,11 @@
3
3
 
4
4
  export const VERSION: string;
5
5
 
6
+ export class StringTableError extends Error {
7
+ readonly code: string;
8
+ readonly name: 'StringTableError';
9
+ }
10
+
6
11
  export class StringTable {
7
12
  constructor();
8
13
  /** Intern a byte range. Zero-alloc on the hit path. Returns u32 index. */
package/types/Writer.d.ts CHANGED
@@ -30,6 +30,30 @@ export interface WriterOptions {
30
30
  * Default = targetShardBytes.
31
31
  */
32
32
  sampleBytes?: number;
33
+ /** Emit a CRC-32C over [0, footer_off) into the footer. Default false. */
34
+ crc?: boolean;
35
+ }
36
+
37
+ /** A synchronous byte sink for `finalizeToSink`. */
38
+ export interface ContainerSink {
39
+ write(bytes: Uint8Array): void;
40
+ /** Required for layout:'stream' (one header backpatch at position 0). */
41
+ writeAt?(bytes: Uint8Array, position: number): void;
42
+ }
43
+
44
+ export interface FinalizeToSinkOptions {
45
+ /** 'prefix' (classic, byte-identical to finalize()) or 'stream'. Default 'stream'. */
46
+ layout?: 'prefix' | 'stream';
47
+ /** Override the constructor `crc`. */
48
+ crc?: boolean;
49
+ }
50
+
51
+ export interface SinkResult {
52
+ totalRows: number;
53
+ shardCount: number;
54
+ schema: FrozenSchema;
55
+ bytesWritten: number;
56
+ layout: 'prefix' | 'stream';
33
57
  }
34
58
 
35
59
  export interface FrozenField {
@@ -85,6 +109,19 @@ export class Writer implements TokenizerSinkForWriter {
85
109
  * Tokenizer has been given `end()`.
86
110
  */
87
111
  finalize(): Container;
112
+ /**
113
+ * Bind a sink and stream shards as they finalize, for bounded-RAM output.
114
+ * Call BEFORE feeding the tokenizer, then finish with finalizeToSink. Peak
115
+ * memory is O(targetShardBytes + directory). opts.layout must be 'stream'.
116
+ */
117
+ beginStream(sink: ContainerSink, opts?: FinalizeToSinkOptions): void;
118
+ /**
119
+ * Emit the container to a caller sink instead of returning a buffer. Preceded
120
+ * by beginStream it writes only the trailer (bounded RAM, O(shard)); called
121
+ * alone it buffers the shards first (O(container)). With layout:'prefix' the
122
+ * emitted bytes are identical to finalize().
123
+ */
124
+ finalizeToSink(sink: ContainerSink, opts?: FinalizeToSinkOptions): SinkResult;
88
125
  readonly schema: FrozenSchema | null;
89
126
  readonly totalRows: number;
90
127
  readonly shardCount: number;
package/types/index.d.ts CHANGED
@@ -13,7 +13,7 @@ export { Reader, ReaderError } from './Reader.d.ts';
13
13
  export type {
14
14
  ShardHandle, StringTableView, Bounds, FindShardsOptions,
15
15
  } from './Reader.d.ts';
16
- export { StringTable } from './StringTable.d.ts';
16
+ export { StringTable, StringTableError } from './StringTable.d.ts';
17
17
  export { PreserveTokenizer, PreserveTokenizerError } from './PreserveTokenizer.d.ts';
18
18
  export type { PreserveSink, PreserveTokenizerOptions } from './PreserveTokenizer.d.ts';
19
19
  export { PreserveWriter, PreserveWriterError } from './PreserveWriter.d.ts';
@@ -54,5 +54,6 @@ export function serialize(
54
54
  * Auto-detects preserve vs schema via the header flag byte.
55
55
  */
56
56
  export function deserialize(
57
- bytes: Uint8Array | ArrayBuffer
57
+ bytes: Uint8Array | ArrayBuffer,
58
+ opts?: { verifyCrc?: boolean }
58
59
  ): import('./Reader.d.ts').Reader | import('./PreserveReader.d.ts').PreserveReader;