@jarenjs/josl 0.34.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.
@@ -0,0 +1,102 @@
1
+ import { stringifyCsvChunks, formatCsvValue } from './csv.js';
2
+ /**
3
+ * Create an incremental CSV reader.
4
+ *
5
+ * Events, in document order:
6
+ * {type:'header', fields, line} - column names resolved
7
+ * {type:'row', index, values, record, line} - a record completed
8
+ * {type:'repair', code, message, line, column} - damage healed
9
+ *
10
+ * @param {object} [options] - Reader options; see `parseCsv`
11
+ * @returns {{feed(chunk: string): void, end(): Array, rows(): Array,
12
+ * fields(): string[]|null, repairs(): object[]}} The reader: `feed`
13
+ * accepts chunks that may split any field, `end` flushes the pending
14
+ * record and returns every row, and the rest peek at partial results.
15
+ * @example
16
+ * const reader = createCsvStreamReader({ headers: true, onEvent: console.log });
17
+ * reader.feed('a,b\n1,');
18
+ * reader.feed('2\n');
19
+ * reader.end(); // [{ a: '1', b: '2' }]
20
+ */
21
+ export declare function createCsvStreamReader(options?: object): {
22
+ feed(chunk: string): void;
23
+ end(): any[];
24
+ rows(): any[];
25
+ fields(): string[] | null;
26
+ repairs(): object[];
27
+ };
28
+ /**
29
+ * Read an async iterable of string chunks (a fetch body, a file stream,
30
+ * an LLM response) into records.
31
+ * @param {AsyncIterable<string>|Iterable<string>} chunks - Source chunks
32
+ * @param {object} [options] - Reader options; see `parseCsv`
33
+ * @returns {Promise<Array>} Every record
34
+ */
35
+ export declare function parseCsvStream(chunks: AsyncIterable<string> | Iterable<string>, options?: object): Promise<any[]>;
36
+ /**
37
+ * Yield records as they complete, without ever holding the whole table.
38
+ *
39
+ * This is the reason to stream: `parseCsvStream` still accumulates every
40
+ * row, so a file larger than memory needs a reader that hands each record
41
+ * over and forgets it. Rows are dropped from the machine as they are
42
+ * yielded, so memory stays flat in the number of records.
43
+ * @param {AsyncIterable<string>|Iterable<string>} chunks - Source chunks
44
+ * @param {object} [options] - Reader options; see `parseCsv`
45
+ * @yields {Array|object} One record at a time
46
+ * @example
47
+ * for await (const row of iterateCsvStream(response.body, { headers: true }))
48
+ * await save(row);
49
+ */
50
+ export declare function iterateCsvStream(chunks: AsyncIterable<string> | Iterable<string>, options?: object): AsyncGenerator<any, void, unknown>;
51
+ /**
52
+ * An incremental CSV writer: rows in, chunks out.
53
+ */
54
+ export declare class CsvStreamWriter {
55
+ #private;
56
+ options: object;
57
+ chunks: any[];
58
+ onChunk: any;
59
+ fields: any;
60
+ wroteHeader: boolean;
61
+ /**
62
+ * @param {object} [options] - Writer options; see `stringifyCsv`
63
+ */
64
+ constructor(options?: object);
65
+ /**
66
+ * Write one record.
67
+ * @param {Array|object} row - An array, or an object keyed by column
68
+ * @returns {this} The writer, for chaining
69
+ */
70
+ write(row: any[] | object): this;
71
+ /**
72
+ * Write many records.
73
+ * @param {Iterable<Array|object>} rows - Records
74
+ * @returns {this} The writer, for chaining
75
+ */
76
+ writeAll(rows: Iterable<any[] | object>): this;
77
+ /**
78
+ * Concatenate the buffered chunks; empty when an `onChunk` sink is set.
79
+ * @returns {string} The document so far
80
+ */
81
+ toString(): string;
82
+ /**
83
+ * Finish writing.
84
+ * @returns {string} The complete document, or `''` with an `onChunk` sink
85
+ */
86
+ end(): string;
87
+ }
88
+ /**
89
+ * Create an incremental CSV writer.
90
+ * @param {object} [options] - Writer options; see `stringifyCsv`
91
+ * @param {(chunk: string) => void} [options.onChunk] - Chunk sink; without
92
+ * one, chunks buffer until `end()`
93
+ * @returns {CsvStreamWriter} The writer
94
+ * @example
95
+ * const w = createCsvStreamWriter();
96
+ * w.write({ a: 1, b: 2 }).write({ a: 3, b: 4 });
97
+ * w.end(); // 'a,b\r\n1,2\r\n3,4\r\n'
98
+ */
99
+ export declare function createCsvStreamWriter(options?: {
100
+ onChunk?: (chunk: string) => void;
101
+ }): CsvStreamWriter;
102
+ export { stringifyCsvChunks, formatCsvValue };
@@ -0,0 +1,141 @@
1
+ import { CSV_CODES, coerceCsvValue } from './csv-machine.js';
2
+ import { CsvSyntaxError } from './errors.js';
3
+ /**
4
+ * Parse a complete CSV document.
5
+ *
6
+ * Default is **strict**: anything RFC 4180 does not allow throws a
7
+ * `CsvSyntaxError` carrying a `CSV1xxx` code, a line and a column.
8
+ * `repair: true` instead takes the reading that loses the least data,
9
+ * records it, and carries on — see `parseCsvDocument` for the log.
10
+ *
11
+ * @param {string} text - CSV source text
12
+ * @param {object} [options] - Reader options
13
+ * @param {string} [options.delimiter=','] - Field separator, one character
14
+ * @param {string|null} [options.quote='"'] - Quote character; `null` disables quoting
15
+ * @param {string|null} [options.comment] - Lines starting with it are skipped
16
+ * @param {boolean|string[]} [options.headers=false] - `true` reads the first
17
+ * record as column names, an array supplies them; either way records become
18
+ * objects. `false` yields arrays, which allocate less.
19
+ * @param {boolean} [options.repair=false] - Heal damage instead of throwing
20
+ * @param {boolean} [options.trim=false] - Trim spaces/tabs around unquoted fields
21
+ * @param {boolean} [options.typed=false] - Coerce numbers, bigints, booleans,
22
+ * `null` and ISO dates; quoted cells always stay strings
23
+ * @param {boolean} [options.emptyAsNull=false] - Empty cells become `null`
24
+ * @param {boolean} [options.skipEmptyLines] - Drop blank lines (default: on
25
+ * in repair mode, off otherwise)
26
+ * @param {(event: object) => void} [options.onEvent] - Document-order event sink
27
+ * @param {(repair: object) => void} [options.onRepair] - Repair sink
28
+ * @returns {Array<string[]|object>} The records
29
+ * @throws {CsvSyntaxError} On malformed input, unless `repair` is set
30
+ * @example
31
+ * parseCsv('a,b\n1,2'); // [['a','b'], ['1','2']]
32
+ * parseCsv('a,b\n1,2', { headers: true }); // [{ a: '1', b: '2' }]
33
+ */
34
+ export declare function parseCsv(text: string, options?: {
35
+ delimiter?: string;
36
+ quote?: string | null;
37
+ comment?: string | null;
38
+ headers?: boolean | string[];
39
+ repair?: boolean;
40
+ trim?: boolean;
41
+ typed?: boolean;
42
+ emptyAsNull?: boolean;
43
+ skipEmptyLines?: boolean;
44
+ onEvent?: (event: object) => void;
45
+ onRepair?: (repair: object) => void;
46
+ }): Array<string[] | object>;
47
+ /**
48
+ * Parse a complete CSV document and report everything that was learned
49
+ * about it: the resolved dialect, the column names, the records, and the
50
+ * repair log. This is the form to use when the input is untrusted — it is
51
+ * the only way to see *what* had to be healed.
52
+ * @param {string} text - CSV source text
53
+ * @param {object} [options] - Reader options; see `parseCsv`. `delimiter:
54
+ * 'auto'` sniffs the dialect from the text first.
55
+ * @returns {{dialect: object, fields: string[]|null, rows: Array, repairs: object[]}}
56
+ * The document
57
+ * @example
58
+ * const doc = parseCsvDocument('a;b\n1;2', { delimiter: 'auto', headers: true });
59
+ * doc.dialect.delimiter; // ';'
60
+ * doc.rows; // [{ a: '1', b: '2' }]
61
+ */
62
+ export declare function parseCsvDocument(text: string, options?: object): {
63
+ dialect: object;
64
+ fields: string[] | null;
65
+ rows: any[];
66
+ repairs: object[];
67
+ };
68
+ /**
69
+ * Guess a CSV document's dialect from its text.
70
+ *
71
+ * The delimiter is chosen by consistency: each candidate is parsed and
72
+ * scored by how often it produces the same field count, because a
73
+ * separator that is really a separator divides every record the same way
74
+ * and one that is not divides them arbitrarily. Ties go to the delimiter
75
+ * yielding more columns, since a spurious separator can only ever split
76
+ * fewer.
77
+ *
78
+ * Header detection asks whether the first record looks unlike the rest:
79
+ * if every cell in it is a non-numeric string while some column below is
80
+ * consistently numeric or date-like, that first record is naming columns
81
+ * rather than carrying data.
82
+ *
83
+ * @param {string} text - CSV source text (a prefix is enough)
84
+ * @param {object} [options] - Reader options that affect parsing (`quote`, `comment`)
85
+ * @returns {{delimiter: string, quote: string|null, headers: boolean, width: number, confidence: number}}
86
+ * The guess, with `confidence` in 0..1
87
+ * @example
88
+ * sniffCsvDialect('a;b;c\n1;2;3'); // { delimiter: ';', headers: true, ... }
89
+ */
90
+ export declare function sniffCsvDialect(text: string, options?: object): {
91
+ delimiter: string;
92
+ quote: string | null;
93
+ headers: boolean;
94
+ width: number;
95
+ confidence: number;
96
+ };
97
+ /**
98
+ * Render one value as CSV cell text. `null`/`undefined` become empty,
99
+ * bigints lose the `n` suffix JOSL uses (CSV has no type marks), and the
100
+ * JOSL date classes and `Date` render as ISO-8601.
101
+ * @param {*} value - The value
102
+ * @returns {string} Cell text, unquoted
103
+ */
104
+ export declare function formatCsvValue(value: any): string;
105
+ /**
106
+ * Serialize records to a CSV document.
107
+ *
108
+ * A field is quoted only when it has to be — when it contains the
109
+ * delimiter, a quote, a newline, or edge whitespace a lenient reader
110
+ * might trim. Everything else is written bare, which keeps the output
111
+ * both smaller and diff-friendly.
112
+ *
113
+ * @param {Array<Array|object>} rows - Records: arrays, or objects keyed by column
114
+ * @param {object} [options] - Writer options
115
+ * @param {string} [options.delimiter=','] - Field separator
116
+ * @param {string} [options.quote='"'] - Quote character
117
+ * @param {string} [options.newline='\r\n'] - Record terminator; RFC 4180 §2.1
118
+ * specifies CRLF, which is also what spreadsheet software expects
119
+ * @param {string[]} [options.fields] - Column order; inferred from the first
120
+ * object record when omitted
121
+ * @param {boolean} [options.header=true] - Emit a header row for object records
122
+ * @returns {string} The CSV document
123
+ * @example
124
+ * stringifyCsv([{ a: 1, b: 'x,y' }]); // 'a,b\r\n1,"x,y"\r\n'
125
+ */
126
+ export declare function stringifyCsv(rows: Array<any[] | object>, options?: {
127
+ delimiter?: string;
128
+ quote?: string;
129
+ newline?: string;
130
+ fields?: string[];
131
+ header?: boolean;
132
+ }): string;
133
+ /**
134
+ * Serialize records as an iterable of chunks, one record at a time, so a
135
+ * large table never exists as a single string.
136
+ * @param {Iterable<Array|object>} rows - Records
137
+ * @param {object} [options] - Writer options; see `stringifyCsv`
138
+ * @yields {string} One record (or the header) at a time
139
+ */
140
+ export declare function stringifyCsvChunks(rows: Iterable<any[] | object>, options?: object): Generator<string, void, unknown>;
141
+ export { CsvSyntaxError, CSV_CODES, coerceCsvValue };
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Shared constructor body for the line/column syntax errors. The `name`
3
+ * is passed as a string literal because the bundle is minified and a
4
+ * mangled class name must not leak into `error.name`.
5
+ */
6
+ declare class LineColumnSyntaxError extends SyntaxError {
7
+ line: number;
8
+ column: number;
9
+ hint: string | undefined;
10
+ /**
11
+ * @param {string} name - The public class name for `error.name`
12
+ * @param {string} message - What is wrong
13
+ * @param {number} line - 1-based physical line number
14
+ * @param {number} column - 1-based column number
15
+ * @param {string} [hint] - Repair suggestion for machine-repair loops
16
+ */
17
+ constructor(name: string, message: string, line: number, column: number, hint?: string);
18
+ }
19
+ /**
20
+ * Error thrown when JOSL / TOML source text violates the grammar or the
21
+ * table redefinition rules.
22
+ */
23
+ export declare class JoslSyntaxError extends LineColumnSyntaxError {
24
+ /**
25
+ * @param {string} message - What is wrong
26
+ * @param {number} line - 1-based physical line number
27
+ * @param {number} column - 1-based column number
28
+ * @param {string} [hint] - Repair suggestion for machine-repair loops
29
+ */
30
+ constructor(message: string, line: number, column: number, hint?: string);
31
+ }
32
+ /**
33
+ * Error thrown when a value cannot be represented in the requested output
34
+ * mode (e.g. `null` or a RegExp in strict TOML mode, a scalar root).
35
+ */
36
+ export declare class JoslStringifyError extends Error {
37
+ path: (string | number)[];
38
+ /**
39
+ * @param {string} message - What is wrong
40
+ * @param {(string|number)[]} [path] - Path of the offending value
41
+ */
42
+ constructor(message: string, path?: (string | number)[]);
43
+ }
44
+ /**
45
+ * Error thrown when CSV source text violates RFC 4180 in strict mode.
46
+ *
47
+ * Every condition this reports is also a *repairable* one: `repair: true`
48
+ * turns each into a logged repair instead of a throw, so the same `code`
49
+ * appears either as `error.code` here or as an entry in the reader's
50
+ * repair log. Carrying the code both ways is what lets a caller move
51
+ * between the two modes without re-learning the diagnosis.
52
+ */
53
+ export declare class CsvSyntaxError extends SyntaxError {
54
+ code: string;
55
+ line: number;
56
+ column: number;
57
+ hint: string | undefined;
58
+ /**
59
+ * @param {string} code - Stable `CSV1xxx` diagnosis code
60
+ * @param {string} message - What is wrong
61
+ * @param {number} line - 1-based physical line number
62
+ * @param {number} column - 1-based column number
63
+ * @param {string} [hint] - Repair suggestion for machine-repair loops
64
+ */
65
+ constructor(code: string, message: string, line: number, column: number, hint?: string);
66
+ }
67
+ /**
68
+ * Error thrown when JSONX source text violates the grammar.
69
+ */
70
+ export declare class JsonxSyntaxError extends LineColumnSyntaxError {
71
+ /**
72
+ * @param {string} message - What is wrong
73
+ * @param {number} line - 1-based physical line number
74
+ * @param {number} column - 1-based column number
75
+ * @param {string} [hint] - Repair suggestion for machine-repair loops
76
+ */
77
+ constructor(message: string, line: number, column: number, hint?: string);
78
+ }
79
+ export {};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Build a GBNF grammar for raw JOSL or TOML text.
3
+ *
4
+ * The result is a complete grammar string with `root` as its entry rule,
5
+ * ready to hand to a llama.cpp-family sampler. It constrains syntax only —
6
+ * a document it accepts still has to go through `parseJosl` for the rules
7
+ * a context-free grammar cannot express (duplicate keys, table conflicts).
8
+ * @param {object} [options] - Grammar options
9
+ * @param {'josl'|'toml'} [options.mode] - 'toml' omits the JOSL-only value
10
+ * forms (null, bigint, regexp) and the `[[]]` root-array header
11
+ * @returns {string} The GBNF grammar
12
+ */
13
+ export declare function toGbnf(options?: {
14
+ mode?: 'josl' | 'toml';
15
+ }): string;
16
+ /**
17
+ * Build a GBNF grammar for strict TOML 1.0 text.
18
+ * @returns {string} The GBNF grammar
19
+ */
20
+ export declare function tomlToGbnf(): string;
@@ -0,0 +1,12 @@
1
+ export { parseJosl, parseToml } from './parse.js';
2
+ export { parseJoslCst, parseTomlCst, JoslCstDocument } from './cst.js';
3
+ export { createStreamReader, parseJoslStream } from './stream.js';
4
+ export { stringifyJosl, stringifyToml, formatKey, formatKeyPath, formatValue, formatSection, } from './stringify.js';
5
+ export { createStreamWriter, stringifyJoslChunks } from './write.js';
6
+ export { toGbnf, tomlToGbnf } from './gbnf.js';
7
+ export { parseJsonx, stringifyJsonx } from './jsonx.js';
8
+ export { createJsonxStreamReader, parseJsonxStream } from './jsonx-stream.js';
9
+ export { parseCsv, parseCsvDocument, stringifyCsv, stringifyCsvChunks, sniffCsvDialect, formatCsvValue, coerceCsvValue, CSV_CODES, } from './csv.js';
10
+ export { createCsvStreamReader, parseCsvStream, iterateCsvStream, createCsvStreamWriter, CsvStreamWriter, } from './csv-stream.js';
11
+ export { JoslSyntaxError, JoslStringifyError, JsonxSyntaxError, CsvSyntaxError } from './errors.js';
12
+ export { LocalDate, LocalTime, LocalDateTime, isValidDateParts, isValidTimeParts, } from './values.js';
@@ -0,0 +1,92 @@
1
+ export type JsonxErrCallback = (pos: number, message: string, hint?: string) => never;
2
+ export type JsonxCheckEndCallback = (pos: number) => void;
3
+ /**
4
+ * @callback JsonxErrCallback
5
+ * @param {number} pos - Offset of the error in the source text
6
+ * @param {string} message - What is wrong
7
+ * @param {string} [hint] - Repair suggestion
8
+ * @returns {never} Must throw
9
+ */
10
+ /**
11
+ * @callback JsonxCheckEndCallback
12
+ * @param {number} pos - Offset of the first character after the value
13
+ * @returns {void} Must throw when the character cannot follow a value
14
+ */
15
+ /**
16
+ * Whether a char code may legally follow a completed JSON/JSONX value
17
+ * (whitespace, `,`, `]` or `}`).
18
+ * @param {number} c - The char code
19
+ * @returns {boolean}
20
+ */
21
+ export declare function isValueEndCode(c: number): boolean;
22
+ /**
23
+ * Decode one escape sequence.
24
+ * @param {string} text - Source text
25
+ * @param {number} pos - Offset of the backslash
26
+ * @param {JsonxErrCallback} err - Error reporter
27
+ * @returns {[string, number]} The decoded text and the offset after it
28
+ */
29
+ export declare function decodeEscape(text: string, pos: number, err: JsonxErrCallback): [string, number];
30
+ /**
31
+ * Decode a double-quoted string.
32
+ * @param {string} text - Source text
33
+ * @param {number} pos - Offset of the opening quote
34
+ * @param {JsonxErrCallback} err - Error reporter
35
+ * @returns {[string, number]} The value and the offset after the close quote
36
+ */
37
+ export declare function decodeString(text: string, pos: number, err: JsonxErrCallback): [string, number];
38
+ /**
39
+ * Decode the body of a string between two offsets, stopping at the closing
40
+ * quote (which it does not consume) or at `stop`. In `partial` mode it also
41
+ * stops before an escape that is not complete within the span, so a
42
+ * still-arriving string can be decoded as far as it is safe to.
43
+ * @param {string} text - Source text
44
+ * @param {number} from - Offset of the first body character
45
+ * @param {number} stop - Exclusive end offset
46
+ * @param {JsonxErrCallback} err - Error reporter
47
+ * @param {boolean} partial - Whether the span may end mid-escape
48
+ * @returns {[string, number]} The decoded text and the offset reached
49
+ */
50
+ export declare function decodeStringSpan(text: string, from: number, stop: number, err: JsonxErrCallback, partial: boolean): [string, number];
51
+ /**
52
+ * Try to match an RFC 3339 datetime token (date, time, local or offset
53
+ * date-time; `T`, `t` or a single space may separate date and time).
54
+ * @param {string} text - Source text
55
+ * @param {number} pos - Offset of the first digit
56
+ * @param {JsonxErrCallback} err - Error reporter
57
+ * @param {JsonxCheckEndCallback} checkEnd - Value-terminator check
58
+ * @returns {[*, number]|null} The value and end offset, or null if the
59
+ * text at `pos` is not a datetime
60
+ */
61
+ export declare function matchDateTime(text: string, pos: number, err: JsonxErrCallback, checkEnd: JsonxCheckEndCallback): [any, number] | null;
62
+ /**
63
+ * Match a number token. Strict JSON follows RFC 8259; JSONX adds a
64
+ * leading `+`, `_` separators, an `n` bigint suffix, and auto-promotes
65
+ * unsafe integers to BigInt.
66
+ * @param {string} text - Source text
67
+ * @param {number} pos - Offset of the first sign or digit
68
+ * @param {'jsonx'|'json'} mode - Dialect
69
+ * @param {JsonxErrCallback} err - Error reporter
70
+ * @param {JsonxCheckEndCallback} checkEnd - Value-terminator check
71
+ * @returns {[number|bigint, number]} The value and end offset
72
+ */
73
+ export declare function matchNumber(text: string, pos: number, mode: 'jsonx' | 'json', err: JsonxErrCallback, checkEnd: JsonxCheckEndCallback): [number | bigint, number];
74
+ /**
75
+ * Match a word token (`true`, `false`, `null`, and in JSONX the
76
+ * optionally signed non-finite spellings `inf`/`Infinity`/`nan`/`NaN`).
77
+ * The caller performs the value-terminator check.
78
+ * @param {string} text - Source text
79
+ * @param {number} pos - Offset of the first sign or letter
80
+ * @param {'jsonx'|'json'} mode - Dialect
81
+ * @param {JsonxErrCallback} err - Error reporter
82
+ * @returns {[boolean|null|number, number]} The value and end offset
83
+ */
84
+ export declare function matchWord(text: string, pos: number, mode: 'jsonx' | 'json', err: JsonxErrCallback): [boolean | null | number, number];
85
+ /**
86
+ * Match a regexp literal. The caller performs the value-terminator check.
87
+ * @param {string} text - Source text
88
+ * @param {number} pos - Offset of the opening slash
89
+ * @param {JsonxErrCallback} err - Error reporter
90
+ * @returns {[RegExp, number]} The value and end offset
91
+ */
92
+ export declare function matchRegExp(text: string, pos: number, err: JsonxErrCallback): [RegExp, number];
@@ -0,0 +1,163 @@
1
+ export declare class JsonxMachine {
2
+ mode: string;
3
+ onEvent: ((event: JsonxStreamEvent) => void) | null;
4
+ partialText: boolean;
5
+ detach: (string | number)[] | null;
6
+ partialFrom: number;
7
+ partialHold: string;
8
+ buf: string;
9
+ pos: number;
10
+ state: number;
11
+ stack: any[];
12
+ path: any[];
13
+ rootValue: any;
14
+ ended: boolean;
15
+ curLine: number;
16
+ lineStart: number;
17
+ scanPos: number;
18
+ scanInFlags: boolean;
19
+ scanInClass: boolean;
20
+ scanDtSpace: boolean;
21
+ errCb: (pos: any, message: any, hint: any) => void;
22
+ endCb: (pos: any) => void;
23
+ /**
24
+ * @param {object} [options] - Reader options
25
+ * @param {'jsonx'|'json'} [options.mode] - 'json' rejects every JSONX
26
+ * extension (bigint, regexp, datetime, non-finite, separators, +)
27
+ * @param {(event: JsonxStreamEvent) => void} [options.onEvent] - Event sink
28
+ * @param {boolean} [options.partialText] - Also emit `text-partial`
29
+ * deltas while a string value is still arriving
30
+ * @param {(string|number)[]} [options.detach] - Path pattern whose
31
+ * matching values are NOT retained in the root (see `detachPattern`)
32
+ */
33
+ constructor(options?: {
34
+ mode?: 'jsonx' | 'json';
35
+ onEvent?: (event: JsonxStreamEvent) => void;
36
+ partialText?: boolean;
37
+ detach?: (string | number)[];
38
+ });
39
+ /**
40
+ * Feed the next chunk of source text; chunks may split any token.
41
+ * @param {string} chunk - Next piece of the document
42
+ * @returns {this} The machine, for chaining
43
+ */
44
+ feed(chunk: string): this;
45
+ /**
46
+ * Finish the document, flushing any pending token.
47
+ * @returns {*} The completed root value
48
+ * @throws {JsonxSyntaxError} When the document is incomplete or invalid
49
+ */
50
+ end(): any;
51
+ /**
52
+ * The (possibly still growing) root value. Undefined until the root
53
+ * value has started; container members appear as they complete.
54
+ *
55
+ * Under `detach`, matching values were never linked in — the root is
56
+ * the document's *frame* (its header members, and an empty array where
57
+ * the detached records would have been), which is the whole point.
58
+ * @returns {*} Current root value
59
+ */
60
+ root(): any;
61
+ errAt(pos: any, message: any, hint: any): void;
62
+ endError(): void;
63
+ pump(): void;
64
+ compact(): void;
65
+ parseValueAt(buf: any, pos: any, c: any): any;
66
+ decodeScalarToken(buf: any, pos: any, c: any): number;
67
+ checkValueEnd(buf: any, pos: any): void;
68
+ emitPartialText(buf: any, pos: any, stop: any, open: any): void;
69
+ valuePath(): any[];
70
+ /**
71
+ * Whether `this.path` plus one more segment matches the detach
72
+ * pattern. Spelled out rather than built on `valuePath()` so the
73
+ * common case — a document read with no `detach` at all — costs one
74
+ * null check, and the matching case costs no array allocation.
75
+ */
76
+ detaches(last: any): boolean;
77
+ completeScalar(value: any): void;
78
+ openContainer(isArray: any): void;
79
+ closeContainer(): void;
80
+ scanString(buf: any, pos: any): any;
81
+ scanRegExp(buf: any, pos: any): any;
82
+ scanScalar(buf: any, pos: any): any;
83
+ }
84
+ export type JsonxStreamPath = (string | number)[];
85
+ export type JsonxStreamEvent = ({
86
+ type: 'object-start' | 'array-start';
87
+ path: JsonxStreamPath;
88
+ line: number;
89
+ } | {
90
+ type: 'object-end' | 'array-end';
91
+ path: JsonxStreamPath;
92
+ value: any;
93
+ line: number;
94
+ } | {
95
+ type: 'pair';
96
+ path: JsonxStreamPath;
97
+ key: string;
98
+ value: any;
99
+ line: number;
100
+ } | {
101
+ type: 'item';
102
+ path: JsonxStreamPath;
103
+ index: number;
104
+ value: any;
105
+ line: number;
106
+ } | {
107
+ type: 'text-partial';
108
+ path: JsonxStreamPath;
109
+ text: string;
110
+ line: number;
111
+ });
112
+ /**
113
+ * Absolute document path: strings for object keys, numbers for array
114
+ * indices (JSON-Pointer-able).
115
+ * @typedef {(string|number)[]} JsonxStreamPath
116
+ */
117
+ /**
118
+ * Document-order reader event; see the module doc comment for semantics.
119
+ * @typedef {(
120
+ * {type: 'object-start'|'array-start', path: JsonxStreamPath, line: number}
121
+ * | {type: 'object-end'|'array-end', path: JsonxStreamPath, value: *, line: number}
122
+ * | {type: 'pair', path: JsonxStreamPath, key: string, value: *, line: number}
123
+ * | {type: 'item', path: JsonxStreamPath, index: number, value: *, line: number}
124
+ * | {type: 'text-partial', path: JsonxStreamPath, text: string, line: number}
125
+ * )} JsonxStreamEvent
126
+ */
127
+ /**
128
+ * Create an incremental JSONX / strict-JSON reader.
129
+ * @param {object} [options] - Reader options
130
+ * @param {'jsonx'|'json'} [options.mode] - 'json' rejects every JSONX
131
+ * extension and matches `JSON.parse` for accepted documents
132
+ * @param {(event: JsonxStreamEvent) => void} [options.onEvent] - Event sink
133
+ * @param {boolean} [options.partialText] - Also emit `text-partial` deltas
134
+ * while a string value is still arriving, for progressive display
135
+ * @param {(string|number)[]} [options.detach] - Path pattern (segments,
136
+ * or `'*'` for any one segment) whose matching values are never linked
137
+ * into the tree. Their completion events still carry them, so the
138
+ * consumer sees every record and the reader retains none — this is what
139
+ * makes a document larger than memory readable.
140
+ * @returns {{feed(chunk: string): void, end(): *, root(): *}} The reader:
141
+ * `feed` accepts chunks that may split any token, `end` flushes,
142
+ * validates completeness and returns the root, `root` peeks at the
143
+ * partial result.
144
+ * @throws {TypeError} On a malformed `detach` pattern
145
+ */
146
+ export declare function createJsonxStreamReader(options?: {
147
+ mode?: 'jsonx' | 'json';
148
+ onEvent?: (event: JsonxStreamEvent) => void;
149
+ partialText?: boolean;
150
+ detach?: (string | number)[];
151
+ }): {
152
+ feed(chunk: string): void;
153
+ end(): any;
154
+ root(): any;
155
+ };
156
+ /**
157
+ * Parse an async iterable of string chunks (e.g. an LLM output stream).
158
+ * @param {AsyncIterable<string>|Iterable<string>} chunks - Source chunks
159
+ * @param {object} [options] - Reader options; see `createJsonxStreamReader`
160
+ * @returns {Promise<*>} The completed root value
161
+ */
162
+ export declare function parseJsonxStream(chunks: AsyncIterable<string> | Iterable<string>, options?: object): Promise<any>;
163
+ export { JsonxSyntaxError } from './errors.js';
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Parse JSONX (or, with `mode: 'json'`, strict JSON) text.
3
+ * @param {string} text - Source text
4
+ * @param {object} [options] - Parser options
5
+ * @param {'jsonx'|'json'} [options.mode] - 'json' matches JSON.parse
6
+ * @param {(event: object) => void} [options.onEvent] - Document-order
7
+ * event sink: {type:'open', path, kind}, {type:'value', path, value},
8
+ * {type:'close', path, value} — paths are absolute (JSON-Pointer-able)
9
+ * @returns {*} The parsed value
10
+ * @throws {JsonxSyntaxError} On invalid input
11
+ */
12
+ export declare function parseJsonx(text: string, options?: {
13
+ mode?: 'jsonx' | 'json';
14
+ onEvent?: (event: object) => void;
15
+ }): any;
16
+ /**
17
+ * Serialize a value to JSONX text. With `mode: 'json'` this delegates to
18
+ * `JSON.stringify` for exact backward compatibility (bigints throw, dates
19
+ * become quoted strings, non-finite numbers become null, ...).
20
+ * @param {*} value - The value to serialize
21
+ * @param {object} [options] - Writer options
22
+ * @param {'jsonx'|'json'} [options.mode] - Output dialect
23
+ * @param {number|string} [options.indent] - Pretty-print indentation
24
+ * @returns {string|undefined} The text, or undefined for undefined input
25
+ */
26
+ export declare function stringifyJsonx(value: any, options?: {
27
+ mode?: 'jsonx' | 'json';
28
+ indent?: number | string;
29
+ }): string | undefined;
30
+ export { JsonxSyntaxError } from './errors.js';
31
+ export { LocalDate, LocalTime, LocalDateTime } from './values.js';