@tabnas/transduce 0.2.10 → 0.2.11
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/dist/capability.d.ts +4 -0
- package/dist/capability.js +29 -1
- package/dist/capability.js.map +1 -1
- package/dist/parser-event-source.d.ts +11 -0
- package/dist/parser-event-source.js +101 -18
- package/dist/parser-event-source.js.map +1 -1
- package/dist/transduce.d.ts +2 -2
- package/dist/transduce.js +4 -2
- package/dist/transduce.js.map +1 -1
- package/package.json +1 -1
- package/src/capability.ts +29 -0
- package/src/parser-event-source.ts +107 -18
- package/src/transduce.ts +2 -2
package/dist/capability.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export declare const INCREMENTAL: readonly string[];
|
|
2
2
|
export declare function isIncremental(grammar: string): boolean;
|
|
3
|
+
export declare const PRUNABLE: readonly string[];
|
|
4
|
+
export declare function isPrunable(grammar: string): boolean;
|
|
3
5
|
export declare const capability: Readonly<{
|
|
4
6
|
INCREMENTAL: readonly string[];
|
|
5
7
|
incremental: typeof isIncremental;
|
|
8
|
+
PRUNABLE: readonly string[];
|
|
9
|
+
prunable: typeof isPrunable;
|
|
6
10
|
}>;
|
package/dist/capability.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* Copyright (c) 2026 tabnas, MIT License */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.capability = exports.INCREMENTAL = void 0;
|
|
4
|
+
exports.capability = exports.PRUNABLE = exports.INCREMENTAL = void 0;
|
|
5
5
|
exports.isIncremental = isIncremental;
|
|
6
|
+
exports.isPrunable = isPrunable;
|
|
6
7
|
// Which grammars the incremental source is verified for, in THIS runtime.
|
|
7
8
|
//
|
|
8
9
|
// Incremental streaming is a per-grammar VERIFIED capability, never an
|
|
@@ -57,8 +58,35 @@ exports.INCREMENTAL = Object.freeze([
|
|
|
57
58
|
function isIncremental(grammar) {
|
|
58
59
|
return exports.INCREMENTAL.includes(grammar);
|
|
59
60
|
}
|
|
61
|
+
// The grammars whose passes a `ParserEventSource` relays alike whether it
|
|
62
|
+
// prunes or not, on every document `test/prune.test.ts` reads them, by the
|
|
63
|
+
// name of the format each reads, as `INCREMENTAL` names them. The suite
|
|
64
|
+
// asserts the list in both directions; `toml` is not on it, since its
|
|
65
|
+
// message for a key defined twice quotes the value, which pruning empties.
|
|
66
|
+
exports.PRUNABLE = Object.freeze([
|
|
67
|
+
'csv',
|
|
68
|
+
'feed',
|
|
69
|
+
'ini',
|
|
70
|
+
'json',
|
|
71
|
+
'json5',
|
|
72
|
+
'jsonc',
|
|
73
|
+
'jsonic',
|
|
74
|
+
'jsonl',
|
|
75
|
+
'markdown',
|
|
76
|
+
'pgn',
|
|
77
|
+
'xml',
|
|
78
|
+
'yaml',
|
|
79
|
+
'zon',
|
|
80
|
+
]);
|
|
81
|
+
// Whether a `ParserEventSource` may empty `grammar`'s arrays behind its
|
|
82
|
+
// stream (`ParserEventSource.prune`).
|
|
83
|
+
function isPrunable(grammar) {
|
|
84
|
+
return exports.PRUNABLE.includes(grammar);
|
|
85
|
+
}
|
|
60
86
|
exports.capability = Object.freeze({
|
|
61
87
|
INCREMENTAL: exports.INCREMENTAL,
|
|
62
88
|
incremental: isIncremental,
|
|
89
|
+
PRUNABLE: exports.PRUNABLE,
|
|
90
|
+
prunable: isPrunable,
|
|
63
91
|
});
|
|
64
92
|
//# sourceMappingURL=capability.js.map
|
package/dist/capability.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":";AAAA,4CAA4C
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;;;AAE5C,0EAA0E;AAC1E,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,4EAA4E;AAC5E,6DAA6D;AAC7D,wEAAwE;AACxE,qEAAqE;AACrE,0EAA0E;AAC1E,uEAAuE;AACvE,sEAAsE;AACtE,2EAA2E;AAC3E,wEAAwE;AACxE,yEAAyE;AACzE,mCAAmC;AACnC,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,0EAA0E;AAC1E,sEAAsE;AACtE,0EAA0E;AAC1E,UAAU;AAEV,yEAAyE;AACzE,yEAAyE;AACzE,0EAA0E;AAC1E,uEAAuE;AACvE,2EAA2E;AAC3E,4EAA4E;AAC5E,wEAAwE;AAExE,yEAAyE;AACzE,2EAA2E;AAC3E,0EAA0E;AAC1E,uEAAuE;AACvE,qEAAqE;AACrE,yEAAyE;AACzE,sEAAsE;AACtE,0EAA0E;AAC1E,6EAA6E;AAChE,QAAA,WAAW,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC1D,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,UAAU;IACV,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;CACN,CAAC,CAAA;AAEF,oDAAoD;AACpD,uBAA8B,OAAe;IAC3C,OAAO,QAAA,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AACtC,CAAC;AAED,0EAA0E;AAC1E,2EAA2E;AAC3E,wEAAwE;AACxE,sEAAsE;AACtE,2EAA2E;AAC9D,QAAA,QAAQ,GAAsB,MAAM,CAAC,MAAM,CAAC;IACvD,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,UAAU;IACV,KAAK;IACL,KAAK;IACL,MAAM;IACN,KAAK;CACN,CAAC,CAAA;AAEF,wEAAwE;AACxE,sCAAsC;AACtC,oBAA2B,OAAe;IACxC,OAAO,QAAA,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AACnC,CAAC;AAEY,QAAA,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,WAAW,EAAX,QAAA,WAAW;IACX,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAR,QAAA,QAAQ;IACR,QAAQ,EAAE,UAAU;CACrB,CAAC,CAAA"}
|
|
@@ -7,11 +7,22 @@ export declare class ParserEventSource {
|
|
|
7
7
|
private sourceLimits;
|
|
8
8
|
private abortFlag;
|
|
9
9
|
private sourceMetrics;
|
|
10
|
+
private grammarName;
|
|
11
|
+
private pruning;
|
|
12
|
+
private isUnverified;
|
|
10
13
|
private used;
|
|
11
14
|
constructor(parser: Tabnas, text: string);
|
|
15
|
+
grammar(name: string): this;
|
|
16
|
+
prune(): this;
|
|
17
|
+
unverified(): this;
|
|
18
|
+
private gate;
|
|
12
19
|
limits(limits: Limits): this;
|
|
13
20
|
abort(abort: AbortFlag): this;
|
|
14
21
|
metrics(metrics: Metrics): this;
|
|
15
22
|
run(sink: ParserSink): Flow;
|
|
23
|
+
runWithValue(sink: ParserSink): {
|
|
24
|
+
flow: Flow;
|
|
25
|
+
value: unknown;
|
|
26
|
+
};
|
|
16
27
|
}
|
|
17
28
|
export declare function scalarOf(value: unknown, lexeme: string | undefined): Datum;
|
|
@@ -16,22 +16,21 @@ exports.scalarOf = scalarOf;
|
|
|
16
16
|
// What each pass carries is alchemy's `RulePass`:
|
|
17
17
|
//
|
|
18
18
|
// - the rule's `name`, its depth `d` and instance `i` (the engine's, which
|
|
19
|
-
//
|
|
20
|
-
// alternate that matched
|
|
21
|
-
// sorted, since they are tags
|
|
22
|
-
//
|
|
23
|
-
// `n`, sorted by name;
|
|
19
|
+
// numbers rules from 1, the start rule's, in the order it makes them),
|
|
20
|
+
// the alternate that matched
|
|
21
|
+
// (`alt`: `p`, `r`, `b`, and its groups `g`, sorted, since they are tags
|
|
22
|
+
// whose order the runtimes' engines keep differently), whether recovery
|
|
23
|
+
// forced the close, and its named counters `n`, sorted by name;
|
|
24
24
|
// - the `tokens` the pass consumed: those its alternate matched (the
|
|
25
25
|
// engine's `o[:oN]` or `c[:cN]`), less the `b` it gave back from their
|
|
26
26
|
// end, which are the next rule's to consume, and none when `b` is more
|
|
27
27
|
// than it recorded, since a close alternate can back up a token it did
|
|
28
28
|
// not record. A token is its name, its value, its source text and its
|
|
29
29
|
// 1-based row and column; a token with no value (the end of the source,
|
|
30
|
-
// a fixed token such as `[
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
// stands;
|
|
30
|
+
// or a fixed token such as `[`) has `null`, and a number carries
|
|
31
|
+
// its source text as its lexeme when that text is a JSON number spelling
|
|
32
|
+
// the value (RFC 8259), the rule the incremental source keeps lexemes by,
|
|
33
|
+
// so a renderer can write it as it stands;
|
|
35
34
|
// - on a close pass, the rule's node when that is a scalar (`value`), a
|
|
36
35
|
// number with the lexeme of the rule's first open token as above;
|
|
37
36
|
// nothing on an open pass, nor for a container.
|
|
@@ -55,21 +54,81 @@ exports.scalarOf = scalarOf;
|
|
|
55
54
|
// `AbortFlag` is `ABORTED`; any other engine error is `INPUT_INVALID` with
|
|
56
55
|
// the engine's code and position. A source runs once, as `ParserSource`
|
|
57
56
|
// does: its parser carries the run's subscriber and budget.
|
|
57
|
+
//
|
|
58
|
+
// The engine builds its value as it parses, so a long document's tree
|
|
59
|
+
// holds every record, though nothing reads the value the parse returns.
|
|
60
|
+
// `prune()` empties each array behind the stream: once the sink has seen a
|
|
61
|
+
// close pass whose rule's node is an array, the source empties that array
|
|
62
|
+
// in place, so the tree holds the elements of the passes since the last
|
|
63
|
+
// close on it. That alters the value the engine returns, which this source
|
|
64
|
+
// never reads, and it is sound for a grammar whose passes do not depend on
|
|
65
|
+
// what its arrays hold, so it is a verified capability, as the incremental
|
|
66
|
+
// source is: `test/prune.test.ts` runs every document of every grammar in
|
|
67
|
+
// the devDependencies pruned and not, and `capability.prunable` lists the
|
|
68
|
+
// grammars whose passes and outcomes never differed
|
|
69
|
+
// (rs/src/source/parser_events.rs has the contract's one difference, a
|
|
70
|
+
// token whose value is a container of the tree). A run that prunes is
|
|
71
|
+
// gated on the list, by the grammar's name (`grammar`), and without a
|
|
72
|
+
// listed name it fails with `STREAMABILITY_UNKNOWN` before the parse,
|
|
73
|
+
// having sent nothing; `unverified()` lifts the gate for the suite.
|
|
58
74
|
const shared_1 = require("@tabnas/alchemy/shared");
|
|
75
|
+
const capability_1 = require("./capability");
|
|
59
76
|
const rule_events_1 = require("./rule-events");
|
|
60
77
|
const source_1 = require("./source");
|
|
61
78
|
// A tabnas parser applied to one text, as a source of its rule passes.
|
|
62
79
|
class ParserEventSource {
|
|
63
|
-
// A source with default limits, its own abort flag and fresh metrics
|
|
64
|
-
// builder methods change each.
|
|
80
|
+
// A source with default limits, its own abort flag and fresh metrics,
|
|
81
|
+
// that prunes nothing; the builder methods change each.
|
|
65
82
|
constructor(parser, text) {
|
|
66
83
|
this.sourceLimits = shared_1.Limits.default();
|
|
67
84
|
this.abortFlag = new shared_1.AbortFlag();
|
|
68
85
|
this.sourceMetrics = new shared_1.Metrics();
|
|
86
|
+
this.grammarName = null;
|
|
87
|
+
this.pruning = false;
|
|
88
|
+
this.isUnverified = false;
|
|
69
89
|
this.used = false;
|
|
70
90
|
this.parser = parser;
|
|
71
91
|
this.text = text;
|
|
72
92
|
}
|
|
93
|
+
// The grammar the parser implements, by the name of the format it reads,
|
|
94
|
+
// as `ParserSource.grammar` takes it. A run that prunes needs a name
|
|
95
|
+
// `capability.prunable` lists; one that does not prune needs no name.
|
|
96
|
+
grammar(name) {
|
|
97
|
+
this.grammarName = name;
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
// Empty each array in the engine's tree once the sink has seen a close
|
|
101
|
+
// pass on it, so the tree does not hold the whole document. The passes
|
|
102
|
+
// are unchanged for a grammar `capability.prunable` lists, and `run`
|
|
103
|
+
// refuses to prune any other, with `STREAMABILITY_UNKNOWN` before the
|
|
104
|
+
// parse.
|
|
105
|
+
prune() {
|
|
106
|
+
this.pruning = true;
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
// Prune whatever the verified list says. This exists for the
|
|
110
|
+
// differential suite that maintains the list and for nothing else: a
|
|
111
|
+
// grammar that reads its arrays back may make other passes once they are
|
|
112
|
+
// emptied, and the run still returns.
|
|
113
|
+
unverified() {
|
|
114
|
+
this.isUnverified = true;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
// Why the run may not prune, when it may not.
|
|
118
|
+
gate() {
|
|
119
|
+
if (!this.pruning || this.isUnverified)
|
|
120
|
+
return null;
|
|
121
|
+
const name = this.grammarName;
|
|
122
|
+
if (null !== name && (0, capability_1.isPrunable)(name))
|
|
123
|
+
return null;
|
|
124
|
+
if (null !== name) {
|
|
125
|
+
return new shared_1.Fail('STREAMABILITY_UNKNOWN', `grammar ${JSON.stringify(name)} is not in capability.prunable: the differential suite ` +
|
|
126
|
+
'has not verified that its passes are the same when its arrays are emptied behind ' +
|
|
127
|
+
'the stream; run it without ParserEventSource.prune');
|
|
128
|
+
}
|
|
129
|
+
return new shared_1.Fail('STREAMABILITY_UNKNOWN', "ParserEventSource.prune needs the grammar's name (ParserEventSource.grammar) to check " +
|
|
130
|
+
'capability.prunable; without one, run it without pruning');
|
|
131
|
+
}
|
|
73
132
|
limits(limits) {
|
|
74
133
|
this.sourceLimits = limits;
|
|
75
134
|
return this;
|
|
@@ -84,19 +143,28 @@ class ParserEventSource {
|
|
|
84
143
|
}
|
|
85
144
|
// Parse, relaying each pass into `sink`, then `end`.
|
|
86
145
|
run(sink) {
|
|
146
|
+
return this.runWithValue(sink).flow;
|
|
147
|
+
}
|
|
148
|
+
// `run`, also handing back the value the engine returned: the engine's
|
|
149
|
+
// tree after pruning, when the run prunes. It is not the run's result
|
|
150
|
+
// (the passes are): it exists so a test can measure what pruning left in
|
|
151
|
+
// the tree, and nothing else should read it.
|
|
152
|
+
runWithValue(sink) {
|
|
87
153
|
if (this.used) {
|
|
88
154
|
throw new shared_1.Fail('STREAM_REUSED', "a ParserEventSource runs once: its parser carries the run's subscriber and budget; " +
|
|
89
155
|
'make a new source, with a new parser, for another run');
|
|
90
156
|
}
|
|
91
157
|
this.used = true;
|
|
158
|
+
const refused = this.gate();
|
|
159
|
+
if (null !== refused)
|
|
160
|
+
throw refused;
|
|
92
161
|
const abort = this.abortFlag;
|
|
93
162
|
const stop = new shared_1.AbortFlag();
|
|
94
|
-
const relay = new Relay(sink, this.sourceLimits.max_scalar_bytes, abort, stop);
|
|
163
|
+
const relay = new Relay(sink, this.sourceLimits.max_scalar_bytes, abort, stop, this.pruning);
|
|
95
164
|
(0, rule_events_1.prepare)(this.parser, () => !abort.isAborted() && !stop.isAborted(), (rule, done) => relay.onDone(rule, done));
|
|
96
165
|
let parsed;
|
|
97
166
|
try {
|
|
98
|
-
this.parser.parse(this.text);
|
|
99
|
-
parsed = { ok: true };
|
|
167
|
+
parsed = { ok: true, value: this.parser.parse(this.text) };
|
|
100
168
|
}
|
|
101
169
|
catch (error) {
|
|
102
170
|
parsed = { ok: false, error };
|
|
@@ -106,10 +174,10 @@ class ParserEventSource {
|
|
|
106
174
|
if ('failed' === status.type)
|
|
107
175
|
throw status.error;
|
|
108
176
|
if ('stopped' === status.type)
|
|
109
|
-
return 'stop';
|
|
177
|
+
return { flow: 'stop', value: undefined };
|
|
110
178
|
if (!parsed.ok)
|
|
111
179
|
throw (0, source_1.engineFailure)(parsed.error, abort);
|
|
112
|
-
return relay.send({ type: 'end' });
|
|
180
|
+
return { flow: relay.send({ type: 'end' }), value: parsed.value };
|
|
113
181
|
}
|
|
114
182
|
finally {
|
|
115
183
|
this.sourceMetrics.events += relay.events;
|
|
@@ -121,11 +189,14 @@ exports.ParserEventSource = ParserEventSource;
|
|
|
121
189
|
class Relay {
|
|
122
190
|
constructor(sink, maxScalarBytes, abort,
|
|
123
191
|
// Set to make the parse guard cancel the parse.
|
|
124
|
-
stop
|
|
192
|
+
stop,
|
|
193
|
+
// Empty the array a close pass's rule builds, once the sink has seen it.
|
|
194
|
+
prune) {
|
|
125
195
|
this.sink = sink;
|
|
126
196
|
this.maxScalarBytes = maxScalarBytes;
|
|
127
197
|
this.abort = abort;
|
|
128
198
|
this.stop = stop;
|
|
199
|
+
this.prune = prune;
|
|
129
200
|
this.status = { type: 'running' };
|
|
130
201
|
this.events = 0;
|
|
131
202
|
}
|
|
@@ -160,12 +231,24 @@ class Relay {
|
|
|
160
231
|
this.status = { type: 'stopped' };
|
|
161
232
|
this.stop.abort();
|
|
162
233
|
}
|
|
234
|
+
else if (this.prune && !open) {
|
|
235
|
+
emptyArray(rule);
|
|
236
|
+
}
|
|
163
237
|
}
|
|
164
238
|
catch (error) {
|
|
165
239
|
this.fail(error);
|
|
166
240
|
}
|
|
167
241
|
}
|
|
168
242
|
}
|
|
243
|
+
// Empty the array `rule`'s node is, in place, so every holder of it sees
|
|
244
|
+
// it emptied. Every element in it was built by passes the sink has seen,
|
|
245
|
+
// the last of them the close pass just sent, and what those passes carry
|
|
246
|
+
// is the sink's, so nothing sent so far changes.
|
|
247
|
+
function emptyArray(rule) {
|
|
248
|
+
const node = rule.node;
|
|
249
|
+
if (Array.isArray(node) && 0 < node.length)
|
|
250
|
+
node.length = 0;
|
|
251
|
+
}
|
|
169
252
|
// The pass as alchemy's `RulePass`, its sizes held to `max_scalar_bytes`.
|
|
170
253
|
function rulePass(rule, done, open, max) {
|
|
171
254
|
const r = rule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser-event-source.js","sourceRoot":"","sources":["../src/parser-event-source.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;;AAE5C,yEAAyE;AACzE,sEAAsE;AACtE,EAAE;AACF,wEAAwE;AACxE,2EAA2E;AAC3E,4EAA4E;AAC5E,oEAAoE;AACpE,2EAA2E;AAC3E,gDAAgD;AAChD,EAAE;AACF,kDAAkD;AAClD,EAAE;AACF,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"parser-event-source.js","sourceRoot":"","sources":["../src/parser-event-source.ts"],"names":[],"mappings":"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"}
|
package/dist/transduce.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.2.
|
|
1
|
+
export declare const VERSION = "0.2.11";
|
|
2
2
|
export { Datum, DatumBuilder, byteSize, fromJSON, fromTabnas, getPath, takePath, toJSON, toText, walkDatum, } from '@tabnas/alchemy/shared';
|
|
3
3
|
export type { Duplicates } from '@tabnas/alchemy/shared';
|
|
4
4
|
export { Code, Fail, isFail } from '@tabnas/alchemy/shared';
|
|
@@ -29,7 +29,7 @@ export { isTreeContainer, parserEventFromJSON, parserEventToJSON, treeTextRefusa
|
|
|
29
29
|
export type { ParserEvent, ParserSink, PassAlt, PassToken, RulePass, TreeContainer, TreeKey, TreeRule, TreeScalar, TreeSpec, } from '@tabnas/alchemy/shared';
|
|
30
30
|
export { DEFAULT_CHUNK_BYTES, LineFormat, LinesSource } from './lines';
|
|
31
31
|
export type { LinesChunk, LinesInput, LinesWriter } from './lines';
|
|
32
|
-
export { INCREMENTAL, capability, isIncremental } from './capability';
|
|
32
|
+
export { INCREMENTAL, PRUNABLE, capability, isIncremental, isPrunable } from './capability';
|
|
33
33
|
export { Cell, Schema, Table, boundColumn, columnFromMeta } from '@tabnas/alchemy/shared';
|
|
34
34
|
export type { BoundColumn, ColumnMapper, MissingPolicy, PublicColumn, TableBinding, TableEvent, TableSink, } from '@tabnas/alchemy/shared';
|
|
35
35
|
export { TableFromJson } from './table-from-json';
|
package/dist/transduce.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* Copyright (c) 2026 tabnas, MIT License */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.engineFailure = exports.ValueSource = exports.SourceMode = exports.Prune = exports.replay = exports.TreeContract = exports.FnSink = exports.EventRecorder = exports.CountSink = exports.pathText = exports.keyText = exports.Selector = exports.Path = exports.Transition = exports.ScanEmit = exports.CaptureSpec = exports.SelectedRecorder = exports.Router = exports.FnRoute = exports.Matcher = exports.utf8Bytes = exports.NODE_BYTES = exports.Metrics = exports.Limits = exports.LIMIT_NAMES = exports.AbortFlag = exports.numberText = exports.jsonString = exports.jsonNumber = exports.isJsonNumber = exports.isStart = exports.isScalar = exports.isEnd = exports.eventText = exports.eventEquals = exports.Ev = exports.isFail = exports.Fail = exports.Code = exports.walkDatum = exports.toText = exports.toJSON = exports.takePath = exports.getPath = exports.fromTabnas = exports.fromJSON = exports.byteSize = exports.DatumBuilder = exports.Datum = exports.VERSION = void 0;
|
|
5
|
-
exports.routers = exports.TableFromJson = exports.columnFromMeta = exports.boundColumn = exports.Table = exports.Schema = exports.Cell = exports.isIncremental = exports.capability = exports.INCREMENTAL = exports.LinesSource = exports.LineFormat = exports.DEFAULT_CHUNK_BYTES = exports.treeTextRefusal = exports.parserEventToJSON = exports.parserEventFromJSON = exports.isTreeContainer = exports.TransduceTree = exports.ParserEventSource = exports.ParserSource = exports.Guarded = exports.walkValue = void 0;
|
|
5
|
+
exports.routers = exports.TableFromJson = exports.columnFromMeta = exports.boundColumn = exports.Table = exports.Schema = exports.Cell = exports.isPrunable = exports.isIncremental = exports.capability = exports.PRUNABLE = exports.INCREMENTAL = exports.LinesSource = exports.LineFormat = exports.DEFAULT_CHUNK_BYTES = exports.treeTextRefusal = exports.parserEventToJSON = exports.parserEventFromJSON = exports.isTreeContainer = exports.TransduceTree = exports.ParserEventSource = exports.ParserSource = exports.Guarded = exports.walkValue = void 0;
|
|
6
6
|
// Streaming transducers over any tabnas parser.
|
|
7
7
|
//
|
|
8
8
|
// A transducer decides what a source contributes to an output model; a
|
|
@@ -34,7 +34,7 @@ exports.routers = exports.TableFromJson = exports.columnFromMeta = exports.bound
|
|
|
34
34
|
// under the names it always exported them by. `routers` is this package's
|
|
35
35
|
// stages as alchemy's `Routers`, for a host to pass to alchemy's `compile`.
|
|
36
36
|
// This package's version, as package.json declares it.
|
|
37
|
-
exports.VERSION = '0.2.
|
|
37
|
+
exports.VERSION = '0.2.11';
|
|
38
38
|
var shared_1 = require("@tabnas/alchemy/shared");
|
|
39
39
|
Object.defineProperty(exports, "Datum", { enumerable: true, get: function () { return shared_1.Datum; } });
|
|
40
40
|
Object.defineProperty(exports, "DatumBuilder", { enumerable: true, get: function () { return shared_1.DatumBuilder; } });
|
|
@@ -117,8 +117,10 @@ Object.defineProperty(exports, "LineFormat", { enumerable: true, get: function (
|
|
|
117
117
|
Object.defineProperty(exports, "LinesSource", { enumerable: true, get: function () { return lines_1.LinesSource; } });
|
|
118
118
|
var capability_1 = require("./capability");
|
|
119
119
|
Object.defineProperty(exports, "INCREMENTAL", { enumerable: true, get: function () { return capability_1.INCREMENTAL; } });
|
|
120
|
+
Object.defineProperty(exports, "PRUNABLE", { enumerable: true, get: function () { return capability_1.PRUNABLE; } });
|
|
120
121
|
Object.defineProperty(exports, "capability", { enumerable: true, get: function () { return capability_1.capability; } });
|
|
121
122
|
Object.defineProperty(exports, "isIncremental", { enumerable: true, get: function () { return capability_1.isIncremental; } });
|
|
123
|
+
Object.defineProperty(exports, "isPrunable", { enumerable: true, get: function () { return capability_1.isPrunable; } });
|
|
122
124
|
var shared_11 = require("@tabnas/alchemy/shared");
|
|
123
125
|
Object.defineProperty(exports, "Cell", { enumerable: true, get: function () { return shared_11.Cell; } });
|
|
124
126
|
Object.defineProperty(exports, "Schema", { enumerable: true, get: function () { return shared_11.Schema; } });
|
package/dist/transduce.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transduce.js","sourceRoot":"","sources":["../src/transduce.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;;AAE5C,gDAAgD;AAChD,EAAE;AACF,uEAAuE;AACvE,oEAAoE;AACpE,mBAAmB;AACnB,EAAE;AACF,2EAA2E;AAC3E,YAAY;AACZ,0EAA0E;AAC1E,wEAAwE;AACxE,4EAA4E;AAC5E,qDAAqD;AACrD,wEAAwE;AACxE,YAAY;AACZ,0EAA0E;AAC1E,yDAAyD;AACzD,qEAAqE;AACrE,qCAAqC;AACrC,0EAA0E;AAC1E,mBAAmB;AACnB,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,gEAAgE;AAChE,EAAE;AACF,wEAAwE;AACxE,6DAA6D;AAC7D,wEAAwE;AACxE,0EAA0E;AAC1E,4EAA4E;AAE5E,uDAAuD;AAC1C,QAAA,OAAO,GAAG,QAAQ,CAAA;AAE/B,iDAW+B;AAV7B,+FAAA,KAAK,OAAA;AACL,sGAAA,YAAY,OAAA;AACZ,kGAAA,QAAQ,OAAA;AACR,kGAAA,QAAQ,OAAA;AACR,oGAAA,UAAU,OAAA;AACV,iGAAA,OAAO,OAAA;AACP,kGAAA,QAAQ,OAAA;AACR,gGAAA,MAAM,OAAA;AACN,gGAAA,MAAM,OAAA;AACN,mGAAA,SAAS,OAAA;AAGX,iDAA2D;AAAlD,8FAAA,IAAI,OAAA;AAAE,8FAAA,IAAI,OAAA;AAAE,gGAAA,MAAM,OAAA;AAE3B,iDAA6F;AAApF,4FAAA,EAAE,OAAA;AAAE,qGAAA,WAAW,OAAA;AAAE,mGAAA,SAAS,OAAA;AAAE,+FAAA,KAAK,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAAE,iGAAA,OAAO,OAAA;AAE7D,iDAAyF;AAAhF,sGAAA,YAAY,OAAA;AAAE,oGAAA,UAAU,OAAA;AAAE,oGAAA,UAAU,OAAA;AAAE,oGAAA,UAAU,OAAA;AACzD,iDAO+B;AAN7B,mGAAA,SAAS,OAAA;AACT,qGAAA,WAAW,OAAA;AACX,gGAAA,MAAM,OAAA;AACN,iGAAA,OAAO,OAAA;AACP,oGAAA,UAAU,OAAA;AACV,mGAAA,SAAS,OAAA;AAEX,qCAAmC;AAA1B,kGAAA,OAAO,OAAA;AAGhB,iCAA2D;AAAlD,gGAAA,OAAO,OAAA;AAAE,+FAAA,MAAM,OAAA;AAAE,yGAAA,gBAAgB,OAAA;AAC1C,iDAAoD;AAA3C,qGAAA,WAAW,OAAA;AAEpB,+BAAiC;AAAxB,gGAAA,QAAQ,OAAA;AACjB,iDAAmD;AAA1C,oGAAA,UAAU,OAAA;AACnB,iDAA0E;AAAjE,8FAAA,IAAI,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAAE,iGAAA,OAAO,OAAA;AAAE,kGAAA,QAAQ,OAAA;AAE1C,iDAA+F;AAAtF,mGAAA,SAAS,OAAA;AAAE,uGAAA,aAAa,OAAA;AAAE,gGAAA,MAAM,OAAA;AAAE,sGAAA,YAAY,OAAA;AAAE,gGAAA,MAAM,OAAA;AAE/D,mCAAmF;AAA1E,+FAAA,KAAK,OAAA;AAAE,oGAAA,UAAU,OAAA;AAAE,qGAAA,WAAW,OAAA;AAAE,uGAAA,aAAa,OAAA;AAAE,mGAAA,SAAS,OAAA;AAEjE,iCAAiC;AAAxB,gGAAA,OAAO,OAAA;AAChB,iDAA8C;AAArC,6GAAA,YAAY,OAAA;AACrB,6DAAyD;AAAhD,wHAAA,iBAAiB,OAAA;AAC1B,mDAAgD;AAAvC,+GAAA,aAAa,OAAA;AACtB,kDAAiH;AAAxG,0GAAA,eAAe,OAAA;AAAE,8GAAA,mBAAmB,OAAA;AAAE,4GAAA,iBAAiB,OAAA;AAAE,0GAAA,eAAe,OAAA;AAajF,iCAAsE;AAA7D,4GAAA,mBAAmB,OAAA;AAAE,mGAAA,UAAU,OAAA;AAAE,oGAAA,WAAW,OAAA;AAErD,
|
|
1
|
+
{"version":3,"file":"transduce.js","sourceRoot":"","sources":["../src/transduce.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/capability.ts
CHANGED
|
@@ -58,7 +58,36 @@ export function isIncremental(grammar: string): boolean {
|
|
|
58
58
|
return INCREMENTAL.includes(grammar)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// The grammars whose passes a `ParserEventSource` relays alike whether it
|
|
62
|
+
// prunes or not, on every document `test/prune.test.ts` reads them, by the
|
|
63
|
+
// name of the format each reads, as `INCREMENTAL` names them. The suite
|
|
64
|
+
// asserts the list in both directions; `toml` is not on it, since its
|
|
65
|
+
// message for a key defined twice quotes the value, which pruning empties.
|
|
66
|
+
export const PRUNABLE: readonly string[] = Object.freeze([
|
|
67
|
+
'csv',
|
|
68
|
+
'feed',
|
|
69
|
+
'ini',
|
|
70
|
+
'json',
|
|
71
|
+
'json5',
|
|
72
|
+
'jsonc',
|
|
73
|
+
'jsonic',
|
|
74
|
+
'jsonl',
|
|
75
|
+
'markdown',
|
|
76
|
+
'pgn',
|
|
77
|
+
'xml',
|
|
78
|
+
'yaml',
|
|
79
|
+
'zon',
|
|
80
|
+
])
|
|
81
|
+
|
|
82
|
+
// Whether a `ParserEventSource` may empty `grammar`'s arrays behind its
|
|
83
|
+
// stream (`ParserEventSource.prune`).
|
|
84
|
+
export function isPrunable(grammar: string): boolean {
|
|
85
|
+
return PRUNABLE.includes(grammar)
|
|
86
|
+
}
|
|
87
|
+
|
|
61
88
|
export const capability = Object.freeze({
|
|
62
89
|
INCREMENTAL,
|
|
63
90
|
incremental: isIncremental,
|
|
91
|
+
PRUNABLE,
|
|
92
|
+
prunable: isPrunable,
|
|
64
93
|
})
|
|
@@ -13,22 +13,21 @@
|
|
|
13
13
|
// What each pass carries is alchemy's `RulePass`:
|
|
14
14
|
//
|
|
15
15
|
// - the rule's `name`, its depth `d` and instance `i` (the engine's, which
|
|
16
|
-
//
|
|
17
|
-
// alternate that matched
|
|
18
|
-
// sorted, since they are tags
|
|
19
|
-
//
|
|
20
|
-
// `n`, sorted by name;
|
|
16
|
+
// numbers rules from 1, the start rule's, in the order it makes them),
|
|
17
|
+
// the alternate that matched
|
|
18
|
+
// (`alt`: `p`, `r`, `b`, and its groups `g`, sorted, since they are tags
|
|
19
|
+
// whose order the runtimes' engines keep differently), whether recovery
|
|
20
|
+
// forced the close, and its named counters `n`, sorted by name;
|
|
21
21
|
// - the `tokens` the pass consumed: those its alternate matched (the
|
|
22
22
|
// engine's `o[:oN]` or `c[:cN]`), less the `b` it gave back from their
|
|
23
23
|
// end, which are the next rule's to consume, and none when `b` is more
|
|
24
24
|
// than it recorded, since a close alternate can back up a token it did
|
|
25
25
|
// not record. A token is its name, its value, its source text and its
|
|
26
26
|
// 1-based row and column; a token with no value (the end of the source,
|
|
27
|
-
// a fixed token such as `[
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
// stands;
|
|
27
|
+
// or a fixed token such as `[`) has `null`, and a number carries
|
|
28
|
+
// its source text as its lexeme when that text is a JSON number spelling
|
|
29
|
+
// the value (RFC 8259), the rule the incremental source keeps lexemes by,
|
|
30
|
+
// so a renderer can write it as it stands;
|
|
32
31
|
// - on a close pass, the rule's node when that is a scalar (`value`), a
|
|
33
32
|
// number with the lexeme of the rule's first open token as above;
|
|
34
33
|
// nothing on an open pass, nor for a container.
|
|
@@ -52,6 +51,23 @@
|
|
|
52
51
|
// `AbortFlag` is `ABORTED`; any other engine error is `INPUT_INVALID` with
|
|
53
52
|
// the engine's code and position. A source runs once, as `ParserSource`
|
|
54
53
|
// does: its parser carries the run's subscriber and budget.
|
|
54
|
+
//
|
|
55
|
+
// The engine builds its value as it parses, so a long document's tree
|
|
56
|
+
// holds every record, though nothing reads the value the parse returns.
|
|
57
|
+
// `prune()` empties each array behind the stream: once the sink has seen a
|
|
58
|
+
// close pass whose rule's node is an array, the source empties that array
|
|
59
|
+
// in place, so the tree holds the elements of the passes since the last
|
|
60
|
+
// close on it. That alters the value the engine returns, which this source
|
|
61
|
+
// never reads, and it is sound for a grammar whose passes do not depend on
|
|
62
|
+
// what its arrays hold, so it is a verified capability, as the incremental
|
|
63
|
+
// source is: `test/prune.test.ts` runs every document of every grammar in
|
|
64
|
+
// the devDependencies pruned and not, and `capability.prunable` lists the
|
|
65
|
+
// grammars whose passes and outcomes never differed
|
|
66
|
+
// (rs/src/source/parser_events.rs has the contract's one difference, a
|
|
67
|
+
// token whose value is a container of the tree). A run that prunes is
|
|
68
|
+
// gated on the list, by the grammar's name (`grammar`), and without a
|
|
69
|
+
// listed name it fails with `STREAMABILITY_UNKNOWN` before the parse,
|
|
70
|
+
// having sent nothing; `unverified()` lifts the gate for the suite.
|
|
55
71
|
|
|
56
72
|
import {
|
|
57
73
|
AbortFlag,
|
|
@@ -67,6 +83,7 @@ import {
|
|
|
67
83
|
import type { Flow, ParserEvent, ParserSink, PassAlt, PassToken, RulePass } from '@tabnas/alchemy/shared'
|
|
68
84
|
import type { Rule, RuleDone, Tabnas } from '@tabnas/parser'
|
|
69
85
|
|
|
86
|
+
import { isPrunable } from './capability'
|
|
70
87
|
import { prepare } from './rule-events'
|
|
71
88
|
import { engineFailure } from './source'
|
|
72
89
|
|
|
@@ -77,15 +94,65 @@ export class ParserEventSource {
|
|
|
77
94
|
private sourceLimits: Limits = Limits.default()
|
|
78
95
|
private abortFlag: AbortFlag = new AbortFlag()
|
|
79
96
|
private sourceMetrics: Metrics = new Metrics()
|
|
97
|
+
private grammarName: string | null = null
|
|
98
|
+
private pruning = false
|
|
99
|
+
private isUnverified = false
|
|
80
100
|
private used = false
|
|
81
101
|
|
|
82
|
-
// A source with default limits, its own abort flag and fresh metrics
|
|
83
|
-
// builder methods change each.
|
|
102
|
+
// A source with default limits, its own abort flag and fresh metrics,
|
|
103
|
+
// that prunes nothing; the builder methods change each.
|
|
84
104
|
constructor(parser: Tabnas, text: string) {
|
|
85
105
|
this.parser = parser
|
|
86
106
|
this.text = text
|
|
87
107
|
}
|
|
88
108
|
|
|
109
|
+
// The grammar the parser implements, by the name of the format it reads,
|
|
110
|
+
// as `ParserSource.grammar` takes it. A run that prunes needs a name
|
|
111
|
+
// `capability.prunable` lists; one that does not prune needs no name.
|
|
112
|
+
grammar(name: string): this {
|
|
113
|
+
this.grammarName = name
|
|
114
|
+
return this
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Empty each array in the engine's tree once the sink has seen a close
|
|
118
|
+
// pass on it, so the tree does not hold the whole document. The passes
|
|
119
|
+
// are unchanged for a grammar `capability.prunable` lists, and `run`
|
|
120
|
+
// refuses to prune any other, with `STREAMABILITY_UNKNOWN` before the
|
|
121
|
+
// parse.
|
|
122
|
+
prune(): this {
|
|
123
|
+
this.pruning = true
|
|
124
|
+
return this
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Prune whatever the verified list says. This exists for the
|
|
128
|
+
// differential suite that maintains the list and for nothing else: a
|
|
129
|
+
// grammar that reads its arrays back may make other passes once they are
|
|
130
|
+
// emptied, and the run still returns.
|
|
131
|
+
unverified(): this {
|
|
132
|
+
this.isUnverified = true
|
|
133
|
+
return this
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Why the run may not prune, when it may not.
|
|
137
|
+
private gate(): Fail | null {
|
|
138
|
+
if (!this.pruning || this.isUnverified) return null
|
|
139
|
+
const name = this.grammarName
|
|
140
|
+
if (null !== name && isPrunable(name)) return null
|
|
141
|
+
if (null !== name) {
|
|
142
|
+
return new Fail(
|
|
143
|
+
'STREAMABILITY_UNKNOWN',
|
|
144
|
+
`grammar ${JSON.stringify(name)} is not in capability.prunable: the differential suite ` +
|
|
145
|
+
'has not verified that its passes are the same when its arrays are emptied behind ' +
|
|
146
|
+
'the stream; run it without ParserEventSource.prune',
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
return new Fail(
|
|
150
|
+
'STREAMABILITY_UNKNOWN',
|
|
151
|
+
"ParserEventSource.prune needs the grammar's name (ParserEventSource.grammar) to check " +
|
|
152
|
+
'capability.prunable; without one, run it without pruning',
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
89
156
|
limits(limits: Limits): this {
|
|
90
157
|
this.sourceLimits = limits
|
|
91
158
|
return this
|
|
@@ -103,6 +170,14 @@ export class ParserEventSource {
|
|
|
103
170
|
|
|
104
171
|
// Parse, relaying each pass into `sink`, then `end`.
|
|
105
172
|
run(sink: ParserSink): Flow {
|
|
173
|
+
return this.runWithValue(sink).flow
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// `run`, also handing back the value the engine returned: the engine's
|
|
177
|
+
// tree after pruning, when the run prunes. It is not the run's result
|
|
178
|
+
// (the passes are): it exists so a test can measure what pruning left in
|
|
179
|
+
// the tree, and nothing else should read it.
|
|
180
|
+
runWithValue(sink: ParserSink): { flow: Flow; value: unknown } {
|
|
106
181
|
if (this.used) {
|
|
107
182
|
throw new Fail(
|
|
108
183
|
'STREAM_REUSED',
|
|
@@ -111,27 +186,28 @@ export class ParserEventSource {
|
|
|
111
186
|
)
|
|
112
187
|
}
|
|
113
188
|
this.used = true
|
|
189
|
+
const refused = this.gate()
|
|
190
|
+
if (null !== refused) throw refused
|
|
114
191
|
const abort = this.abortFlag
|
|
115
192
|
const stop = new AbortFlag()
|
|
116
|
-
const relay = new Relay(sink, this.sourceLimits.max_scalar_bytes, abort, stop)
|
|
193
|
+
const relay = new Relay(sink, this.sourceLimits.max_scalar_bytes, abort, stop, this.pruning)
|
|
117
194
|
prepare(
|
|
118
195
|
this.parser,
|
|
119
196
|
() => !abort.isAborted() && !stop.isAborted(),
|
|
120
197
|
(rule, done) => relay.onDone(rule, done),
|
|
121
198
|
)
|
|
122
|
-
let parsed: { ok: true } | { ok: false; error: unknown }
|
|
199
|
+
let parsed: { ok: true; value: unknown } | { ok: false; error: unknown }
|
|
123
200
|
try {
|
|
124
|
-
this.parser.parse(this.text)
|
|
125
|
-
parsed = { ok: true }
|
|
201
|
+
parsed = { ok: true, value: this.parser.parse(this.text) }
|
|
126
202
|
} catch (error) {
|
|
127
203
|
parsed = { ok: false, error }
|
|
128
204
|
}
|
|
129
205
|
try {
|
|
130
206
|
const status = relay.status
|
|
131
207
|
if ('failed' === status.type) throw status.error
|
|
132
|
-
if ('stopped' === status.type) return 'stop'
|
|
208
|
+
if ('stopped' === status.type) return { flow: 'stop', value: undefined }
|
|
133
209
|
if (!parsed.ok) throw engineFailure(parsed.error, abort)
|
|
134
|
-
return relay.send({ type: 'end' })
|
|
210
|
+
return { flow: relay.send({ type: 'end' }), value: parsed.value }
|
|
135
211
|
} finally {
|
|
136
212
|
this.sourceMetrics.events += relay.events
|
|
137
213
|
}
|
|
@@ -151,6 +227,8 @@ class Relay {
|
|
|
151
227
|
readonly abort: AbortFlag,
|
|
152
228
|
// Set to make the parse guard cancel the parse.
|
|
153
229
|
readonly stop: AbortFlag,
|
|
230
|
+
// Empty the array a close pass's rule builds, once the sink has seen it.
|
|
231
|
+
readonly prune: boolean,
|
|
154
232
|
) {}
|
|
155
233
|
|
|
156
234
|
send(ev: ParserEvent): Flow {
|
|
@@ -183,6 +261,8 @@ class Relay {
|
|
|
183
261
|
if ('stop' === this.send(ev)) {
|
|
184
262
|
this.status = { type: 'stopped' }
|
|
185
263
|
this.stop.abort()
|
|
264
|
+
} else if (this.prune && !open) {
|
|
265
|
+
emptyArray(rule)
|
|
186
266
|
}
|
|
187
267
|
} catch (error) {
|
|
188
268
|
this.fail(error)
|
|
@@ -190,6 +270,15 @@ class Relay {
|
|
|
190
270
|
}
|
|
191
271
|
}
|
|
192
272
|
|
|
273
|
+
// Empty the array `rule`'s node is, in place, so every holder of it sees
|
|
274
|
+
// it emptied. Every element in it was built by passes the sink has seen,
|
|
275
|
+
// the last of them the close pass just sent, and what those passes carry
|
|
276
|
+
// is the sink's, so nothing sent so far changes.
|
|
277
|
+
function emptyArray(rule: Rule): void {
|
|
278
|
+
const node: unknown = (rule as any).node
|
|
279
|
+
if (Array.isArray(node) && 0 < node.length) node.length = 0
|
|
280
|
+
}
|
|
281
|
+
|
|
193
282
|
// The pass as alchemy's `RulePass`, its sizes held to `max_scalar_bytes`.
|
|
194
283
|
function rulePass(rule: Rule, done: RuleDone, open: boolean, max: number): RulePass {
|
|
195
284
|
const r: any = rule
|
package/src/transduce.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
// stages as alchemy's `Routers`, for a host to pass to alchemy's `compile`.
|
|
33
33
|
|
|
34
34
|
// This package's version, as package.json declares it.
|
|
35
|
-
export const VERSION = '0.2.
|
|
35
|
+
export const VERSION = '0.2.11'
|
|
36
36
|
|
|
37
37
|
export {
|
|
38
38
|
Datum,
|
|
@@ -93,7 +93,7 @@ export type {
|
|
|
93
93
|
} from '@tabnas/alchemy/shared'
|
|
94
94
|
export { DEFAULT_CHUNK_BYTES, LineFormat, LinesSource } from './lines'
|
|
95
95
|
export type { LinesChunk, LinesInput, LinesWriter } from './lines'
|
|
96
|
-
export { INCREMENTAL, capability, isIncremental } from './capability'
|
|
96
|
+
export { INCREMENTAL, PRUNABLE, capability, isIncremental, isPrunable } from './capability'
|
|
97
97
|
export { Cell, Schema, Table, boundColumn, columnFromMeta } from '@tabnas/alchemy/shared'
|
|
98
98
|
export type {
|
|
99
99
|
BoundColumn,
|