@tabnas/transduce 0.2.5 → 0.2.7
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.js +8 -4
- package/dist/capability.js.map +1 -1
- package/dist/table-from-json.js +55 -16
- package/dist/table-from-json.js.map +1 -1
- package/dist/transduce.d.ts +1 -1
- package/dist/transduce.js +1 -1
- package/package.json +1 -1
- package/src/capability.ts +8 -4
- package/src/table-from-json.ts +70 -23
- package/src/transduce.ts +1 -1
package/dist/capability.js
CHANGED
|
@@ -25,10 +25,13 @@ exports.isIncremental = isIncremental;
|
|
|
25
25
|
// repeated member name so that a `last_wins` router builds the walk's
|
|
26
26
|
// value, or fails before `end` with a documented code, never with a wrong
|
|
27
27
|
// stream.
|
|
28
|
-
// Measured: the TypeScript grammars earn the same
|
|
29
|
-
// `
|
|
30
|
-
//
|
|
31
|
-
//
|
|
28
|
+
// Measured: the TypeScript grammars earn the same nine as the Rust ones.
|
|
29
|
+
// `xml` builds each element in document order, in a node of its own made
|
|
30
|
+
// when the start tag is read, with `children` named before its list opens
|
|
31
|
+
// and the list in a node of its own. `toml` and `ini` open a section's
|
|
32
|
+
// container before its key, `csv` builds a record the stream does not see,
|
|
33
|
+
// and `feed` replaces xml's root element with the feed it makes of the tree
|
|
34
|
+
// when the root closes, so the adapter refuses each on its own samples.
|
|
32
35
|
// The grammars whose incremental events never contradict the whole-value
|
|
33
36
|
// walk on any fixture, by their package's name (`@tabnas/<name>`).
|
|
34
37
|
exports.INCREMENTAL = Object.freeze([
|
|
@@ -38,6 +41,7 @@ exports.INCREMENTAL = Object.freeze([
|
|
|
38
41
|
'jsonic',
|
|
39
42
|
'jsonl',
|
|
40
43
|
'markdown',
|
|
44
|
+
'xml',
|
|
41
45
|
'yaml',
|
|
42
46
|
'zon',
|
|
43
47
|
]);
|
package/dist/capability.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,0EAA0E;AAC1E,
|
|
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,mEAAmE;AACtD,QAAA,WAAW,GAAsB,MAAM,CAAC,MAAM,CAAC;IAC1D,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,OAAO;IACP,UAAU;IACV,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;AAEY,QAAA,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,WAAW,EAAX,QAAA,WAAW;IACX,WAAW,EAAE,aAAa;CAC3B,CAAC,CAAA"}
|
package/dist/table-from-json.js
CHANGED
|
@@ -15,7 +15,10 @@ exports.TableFromJson = void 0;
|
|
|
15
15
|
// document with no rows is a valid empty table, its schema emitted just
|
|
16
16
|
// before `end`. Rows are projected into schema order by path, so the order
|
|
17
17
|
// of members inside a row never matters, and a number keeps the lexeme the
|
|
18
|
-
// source events carried.
|
|
18
|
+
// source events carried. An inferred schema is the first row's, by its kind:
|
|
19
|
+
// an object's member names, an array's positions, or the one column `value`
|
|
20
|
+
// of a scalar; a later row of another kind projects through those paths and
|
|
21
|
+
// lands empty where they miss.
|
|
19
22
|
const shared_1 = require("@tabnas/alchemy/shared");
|
|
20
23
|
const route_1 = require("./route");
|
|
21
24
|
// The route sink behind the transducer: it owns the schema state and the
|
|
@@ -82,21 +85,8 @@ class Core {
|
|
|
82
85
|
const row = selected.value ?? shared_1.Datum.null;
|
|
83
86
|
if (!this.schemaSent) {
|
|
84
87
|
if ('infer' === this.columns.type && null === this.columns.bound) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
throw shared_1.Fail.input(`the first row at ${at} is not an object, so no columns can be inferred from it`).atPath(at);
|
|
88
|
-
}
|
|
89
|
-
// The names are the table's metadata for as long as it lasts, so
|
|
90
|
-
// they are held to the bound a metadata capture is: measured as the
|
|
91
|
-
// array of their strings would be.
|
|
92
|
-
let bytes = shared_1.NODE_BYTES;
|
|
93
|
-
for (const k of row.members.keys())
|
|
94
|
-
bytes += shared_1.NODE_BYTES + (0, shared_1.utf8Bytes)(k);
|
|
95
|
-
if (bytes > this.maxMetadataBytes) {
|
|
96
|
-
throw shared_1.Fail.limit('max_metadata_bytes', this.maxMetadataBytes, `the first row's ${row.members.size} member names take ${bytes} bytes as the ` +
|
|
97
|
-
`table's columns, more than ${this.maxMetadataBytes}`).atPath(at);
|
|
98
|
-
}
|
|
99
|
-
this.bind([...row.members.keys()].map((k) => (0, shared_1.boundColumn)(k, [k])), 'the first row');
|
|
88
|
+
const columns = inferColumns(row, this.maxColumns, this.maxMetadataBytes, selected.path.toString());
|
|
89
|
+
this.bind(columns, 'the first row');
|
|
100
90
|
}
|
|
101
91
|
if ('stop' === this.sendSchema())
|
|
102
92
|
return 'stop';
|
|
@@ -210,4 +200,53 @@ class TableFromJson {
|
|
|
210
200
|
}
|
|
211
201
|
}
|
|
212
202
|
exports.TableFromJson = TableFromJson;
|
|
203
|
+
// The columns the first row implies, by its kind: an object's member names,
|
|
204
|
+
// in its order, each sourced at its key; an array's positions, labelled
|
|
205
|
+
// `0`, `1`, ... up to its length, each sourced at its index; and for a
|
|
206
|
+
// scalar one column, `value`, sourced at the row itself. A later row of any
|
|
207
|
+
// kind projects through these paths, and lands empty where they miss.
|
|
208
|
+
function inferColumns(row, maxColumns, maxMetadataBytes, at) {
|
|
209
|
+
// The bounds are checked before a column is built: the labels are the
|
|
210
|
+
// table's metadata for as long as it lasts, so they are held to the bound
|
|
211
|
+
// a metadata capture is, measured as the array of their strings would be,
|
|
212
|
+
// and counted from the row itself, so a first row wider than either bound
|
|
213
|
+
// costs a walk of what it already holds and allocates nothing.
|
|
214
|
+
let count = 1;
|
|
215
|
+
let labels = 5; // "value"
|
|
216
|
+
if ('object' === row.type) {
|
|
217
|
+
count = row.members.size;
|
|
218
|
+
labels = 0;
|
|
219
|
+
for (const k of row.members.keys())
|
|
220
|
+
labels += (0, shared_1.utf8Bytes)(k);
|
|
221
|
+
}
|
|
222
|
+
else if ('array' === row.type) {
|
|
223
|
+
count = row.items.length;
|
|
224
|
+
labels = 0;
|
|
225
|
+
for (let i = 0; i < count; i++)
|
|
226
|
+
labels += decimalDigits(i);
|
|
227
|
+
}
|
|
228
|
+
const bytes = (count + 1) * shared_1.NODE_BYTES + labels;
|
|
229
|
+
if (bytes > maxMetadataBytes) {
|
|
230
|
+
throw shared_1.Fail.limit('max_metadata_bytes', maxMetadataBytes, `the first row's ${count} column labels take ${bytes} bytes as the ` +
|
|
231
|
+
`table's metadata, more than ${maxMetadataBytes}`).atPath(at);
|
|
232
|
+
}
|
|
233
|
+
if (count > maxColumns) {
|
|
234
|
+
throw shared_1.Fail.limit('max_columns', maxColumns, `the first row declares ${count} columns, more than ${maxColumns}`).atPath(at);
|
|
235
|
+
}
|
|
236
|
+
switch (row.type) {
|
|
237
|
+
case 'object':
|
|
238
|
+
return [...row.members.keys()].map((k) => (0, shared_1.boundColumn)(k, [k]));
|
|
239
|
+
case 'array':
|
|
240
|
+
return row.items.map((_, i) => (0, shared_1.boundColumn)(String(i), [i]));
|
|
241
|
+
default:
|
|
242
|
+
return [(0, shared_1.boundColumn)('value', [])];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// The length of `i` written in decimal: the bytes of an array row's label.
|
|
246
|
+
function decimalDigits(i) {
|
|
247
|
+
let digits = 1;
|
|
248
|
+
for (let n = i; n >= 10; n = Math.floor(n / 10))
|
|
249
|
+
digits++;
|
|
250
|
+
return digits;
|
|
251
|
+
}
|
|
213
252
|
//# sourceMappingURL=table-from-json.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-from-json.js","sourceRoot":"","sources":["../src/table-from-json.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;AAE5C,wEAAwE;AACxE,OAAO;AACP,EAAE;AACF,mEAAmE;AACnE,0EAA0E;AAC1E,0EAA0E;AAC1E,uEAAuE;AACvE,0EAA0E;AAC1E,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"table-from-json.js","sourceRoot":"","sources":["../src/table-from-json.ts"],"names":[],"mappings":";AAAA,4CAA4C;;;AAE5C,wEAAwE;AACxE,OAAO;AACP,EAAE;AACF,mEAAmE;AACnE,0EAA0E;AAC1E,0EAA0E;AAC1E,uEAAuE;AACvE,0EAA0E;AAC1E,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,6EAA6E;AAC7E,4EAA4E;AAC5E,4EAA4E;AAC5E,+BAA+B;AAE/B,mDAyB+B;AAE/B,mCAAgC;AAQhC,yEAAyE;AACzE,cAAc;AACd,MAAM,IAAI;IAYR,YACE,IAAO,EACP,KAAgB,EAChB,MAAwB,EACxB,OAAgB,EAChB,MAAc,EACd,OAAgB;QAblB,eAAU,GAAG,KAAK,CAAA;QAehB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,WAAW,CAAA;QACpC,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAA;QACjD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,IAAI,CAAC,OAAsB,EAAE,IAAY;QACvC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,aAAI,CAAC,KAAK,CACd,aAAa,EACb,IAAI,CAAC,UAAU,EACf,GAAG,IAAI,aAAa,OAAO,CAAC,MAAM,uBAAuB,IAAI,CAAC,UAAU,EAAE,CAC3E,CAAA;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAA;IAC9B,CAAC;IAEO,aAAa;QACnB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACpE,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;IAChF,CAAC;IAEO,QAAQ,CAAC,QAAkB;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAC5B,IAAI,UAAU,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC;YAChC,uEAAuE;YACvE,MAAM,aAAI,CAAC,QAAQ,CAAC,2CAA2C,CAAC,CAAA;QAClE,CAAC;QACD,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAA;QACnC,IAAI,IAAI,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;YAC3B,MAAM,IAAI,aAAI,CACZ,uBAAuB,EACvB,0BAA0B,EAAE,6CAA6C,CAC1E,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,IAAI,cAAK,CAAC,IAAI,CAAA;QAC1C,IAAI,OAAO,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,aAAI,CAAC,KAAK,CAAC,0BAA0B,EAAE,kBAAkB,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC7E,CAAC;QACD,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAA;QAC/B,IAAI,WAAW,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,aAAI,CAAC,KAAK,CACd,aAAa,EACb,IAAI,CAAC,UAAU,EACf,mBAAmB,EAAE,aAAa,WAAW,CAAC,MAAM,sBAAsB;gBACxE,GAAG,IAAI,CAAC,UAAU,EAAE,CACvB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACd,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACrC,IAAI,CAAC;gBACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YAC1B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,aAAI,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;oBAC5C,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;oBAC/B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;oBACT,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAA;gBACzB,CAAC;gBACD,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,cAAc,CAAC,CAAA;IAClC,CAAC;IAEO,GAAG,CAAC,QAAkB;QAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,IAAI,cAAK,CAAC,IAAI,CAAA;QACxC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjE,MAAM,OAAO,GAAG,YAAY,CAC1B,GAAG,EACH,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,gBAAgB,EACrB,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CACzB,CAAA;gBACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAA;YACrC,CAAC;YACD,IAAI,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE;gBAAE,OAAO,MAAM,CAAA;QACjD,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAA;QAClC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,aAAI,CAAC,QAAQ,CAAC,iDAAiD,CAAC,CAAA;QACxE,CAAC;QACD,MAAM,KAAK,GAAW,EAAE,CAAA;QACxB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAA,gBAAO,EAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;YACtC,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,aAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;gBACjC,SAAQ;YACV,CAAC;YACD,QAAQ,GAAG,CAAC,OAAO,EAAE,CAAC;gBACpB,KAAK,SAAS;oBACZ,KAAK,CAAC,IAAI,CAAC,aAAI,CAAC,OAAO,CAAC,CAAA;oBACxB,MAAK;gBACP,KAAK,MAAM;oBACT,KAAK,CAAC,IAAI,CAAC,aAAI,CAAC,IAAI,CAAC,CAAA;oBACrB,MAAK;gBACP,KAAK,OAAO,EAAE,CAAC;oBACb,MAAM,EAAE,GAAG,IAAI,aAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;oBAC1E,MAAM,IAAI,aAAI,CACZ,eAAe,EACf,UAAU,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,CAC5D,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;IACrD,CAAC;IAED,KAAK,CAAC,EAAa,EAAE,IAAY;QAC/B,IAAI,EAAE,KAAK,IAAI,CAAC,KAAK,IAAI,UAAU,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACzF,MAAM,IAAI,aAAI,CACZ,uBAAuB,EACvB,6CAA6C,IAAI,CAAC,OAAO,CAAC,QAAQ,kBAAkB;gBAClF,iCAAiC,CACpC,CAAA;QACH,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,QAAkB;QACzB,IAAI,QAAQ,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACvB,OAAO,UAAU,CAAA;QACnB,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC3B,CAAC;IAED,GAAG;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,UAAU,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACpE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAA;gBAC3C,MAAM,aAAI,CAAC,KAAK,CAAC,0CAA0C,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;YAC7E,CAAC;YACD,yDAAyD;YACzD,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBACjE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAA;YAC9B,CAAC;YACD,IAAI,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE;gBAAE,OAAO,MAAM,CAAA;QACjD,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9C,CAAC;CACF;AAED,sEAAsE;AACtE,2DAA2D;AAC3D;IAGE,wEAAwE;IACxE,wEAAwE;IACxE,yEAAyE;IACzE,oBAAoB;IACpB,YACE,OAAqB,EACrB,MAAc,EACd,UAAsB,EACtB,OAAgB,EAChB,IAAO;QAEP,MAAM,OAAO,GAAG,oBAAW,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CACrE,MAAM,CAAC,gBAAgB,EACvB,kBAAkB,CACnB,CAAA;QACD,IAAI,OAAgB,CAAA;QACpB,IAAI,KAAoB,CAAA;QACxB,IAAI,MAAM,GAAqB,IAAI,CAAA;QACnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;QAC7B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,QAAQ;gBACX,OAAO,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAA;gBAC3D,KAAK,GAAG,CAAC,OAAO,CAAC,CAAA;gBACjB,MAAK;YACP,KAAK,UAAU;gBACb,OAAO,GAAG;oBACR,IAAI,EAAE,UAAU;oBAChB,QAAQ,EAAE,MAAM,CAAC,OAAO;oBACxB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,KAAK,EAAE,IAAI;iBACZ,CAAA;gBACD,KAAK,GAAG;oBACN,oBAAW,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAC5D,MAAM,CAAC,kBAAkB,EACzB,oBAAoB,CACrB;oBACD,OAAO;iBACR,CAAA;gBACD,MAAM,GAAG,CAAC,CAAA;gBACV,MAAK;YACP,KAAK,OAAO;gBACV,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;gBACxC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAA;gBACjB,MAAK;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;QAC/E,IAAI,QAAQ,KAAK,OAAO,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,CAAA;QACtE,IAAI,CAAC,MAAM,GAAG,IAAI,cAAM,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;IACpE,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAA;IACpC,CAAC;IAED,8CAA8C;IAC9C,KAAK;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,EAAa;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;CACF;;AAED,4EAA4E;AAC5E,wEAAwE;AACxE,uEAAuE;AACvE,4EAA4E;AAC5E,sEAAsE;AACtE,SAAS,YAAY,CACnB,GAAU,EACV,UAAkB,EAClB,gBAAwB,EACxB,EAAU;IAEV,sEAAsE;IACtE,0EAA0E;IAC1E,0EAA0E;IAC1E,0EAA0E;IAC1E,+DAA+D;IAC/D,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,MAAM,GAAG,CAAC,CAAA,CAAC,UAAU;IACzB,IAAI,QAAQ,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAA;QACxB,MAAM,GAAG,CAAC,CAAA;QACV,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,IAAA,kBAAS,EAAC,CAAC,CAAC,CAAA;IAC5D,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;QAChC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAA;QACxB,MAAM,GAAG,CAAC,CAAA;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE;YAAE,MAAM,IAAI,aAAa,CAAC,CAAC,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,mBAAU,GAAG,MAAM,CAAA;IAC/C,IAAI,KAAK,GAAG,gBAAgB,EAAE,CAAC;QAC7B,MAAM,aAAI,CAAC,KAAK,CACd,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,KAAK,uBAAuB,KAAK,gBAAgB;YAClE,+BAA+B,gBAAgB,EAAE,CACpD,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACd,CAAC;IACD,IAAI,KAAK,GAAG,UAAU,EAAE,CAAC;QACvB,MAAM,aAAI,CAAC,KAAK,CACd,aAAa,EACb,UAAU,EACV,0BAA0B,KAAK,uBAAuB,UAAU,EAAE,CACnE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACd,CAAC;IACD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,oBAAW,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAChE,KAAK,OAAO;YACV,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAA,oBAAW,EAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7D;YACE,OAAO,CAAC,IAAA,oBAAW,EAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;IACrC,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,SAAS,aAAa,CAAC,CAAS;IAC9B,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,EAAE,CAAA;IACzD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/transduce.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const VERSION = "0.2.
|
|
1
|
+
export declare const VERSION = "0.2.7";
|
|
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';
|
package/dist/transduce.js
CHANGED
|
@@ -30,7 +30,7 @@ exports.routers = exports.TableFromJson = exports.columnFromMeta = exports.bound
|
|
|
30
30
|
// under the names it always exported them by. `routers` is this package's
|
|
31
31
|
// stages as alchemy's `Routers`, for a host to pass to alchemy's `compile`.
|
|
32
32
|
// This package's version, as package.json declares it.
|
|
33
|
-
exports.VERSION = '0.2.
|
|
33
|
+
exports.VERSION = '0.2.7';
|
|
34
34
|
var shared_1 = require("@tabnas/alchemy/shared");
|
|
35
35
|
Object.defineProperty(exports, "Datum", { enumerable: true, get: function () { return shared_1.Datum; } });
|
|
36
36
|
Object.defineProperty(exports, "DatumBuilder", { enumerable: true, get: function () { return shared_1.DatumBuilder; } });
|
package/package.json
CHANGED
package/src/capability.ts
CHANGED
|
@@ -23,10 +23,13 @@
|
|
|
23
23
|
// value, or fails before `end` with a documented code, never with a wrong
|
|
24
24
|
// stream.
|
|
25
25
|
|
|
26
|
-
// Measured: the TypeScript grammars earn the same
|
|
27
|
-
// `
|
|
28
|
-
//
|
|
29
|
-
//
|
|
26
|
+
// Measured: the TypeScript grammars earn the same nine as the Rust ones.
|
|
27
|
+
// `xml` builds each element in document order, in a node of its own made
|
|
28
|
+
// when the start tag is read, with `children` named before its list opens
|
|
29
|
+
// and the list in a node of its own. `toml` and `ini` open a section's
|
|
30
|
+
// container before its key, `csv` builds a record the stream does not see,
|
|
31
|
+
// and `feed` replaces xml's root element with the feed it makes of the tree
|
|
32
|
+
// when the root closes, so the adapter refuses each on its own samples.
|
|
30
33
|
|
|
31
34
|
// The grammars whose incremental events never contradict the whole-value
|
|
32
35
|
// walk on any fixture, by their package's name (`@tabnas/<name>`).
|
|
@@ -37,6 +40,7 @@ export const INCREMENTAL: readonly string[] = Object.freeze([
|
|
|
37
40
|
'jsonic',
|
|
38
41
|
'jsonl',
|
|
39
42
|
'markdown',
|
|
43
|
+
'xml',
|
|
40
44
|
'yaml',
|
|
41
45
|
'zon',
|
|
42
46
|
])
|
package/src/table-from-json.ts
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
// document with no rows is a valid empty table, its schema emitted just
|
|
14
14
|
// before `end`. Rows are projected into schema order by path, so the order
|
|
15
15
|
// of members inside a row never matters, and a number keeps the lexeme the
|
|
16
|
-
// source events carried.
|
|
16
|
+
// source events carried. An inferred schema is the first row's, by its kind:
|
|
17
|
+
// an object's member names, an array's positions, or the one column `value`
|
|
18
|
+
// of a scalar; a later row of another kind projects through those paths and
|
|
19
|
+
// lands empty where they miss.
|
|
17
20
|
|
|
18
21
|
import {
|
|
19
22
|
BoundColumn,
|
|
@@ -146,29 +149,13 @@ class Core<S extends TableSink> implements RouteSink {
|
|
|
146
149
|
const row = selected.value ?? Datum.null
|
|
147
150
|
if (!this.schemaSent) {
|
|
148
151
|
if ('infer' === this.columns.type && null === this.columns.bound) {
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
// The names are the table's metadata for as long as it lasts, so
|
|
156
|
-
// they are held to the bound a metadata capture is: measured as the
|
|
157
|
-
// array of their strings would be.
|
|
158
|
-
let bytes = NODE_BYTES
|
|
159
|
-
for (const k of row.members.keys()) bytes += NODE_BYTES + utf8Bytes(k)
|
|
160
|
-
if (bytes > this.maxMetadataBytes) {
|
|
161
|
-
throw Fail.limit(
|
|
162
|
-
'max_metadata_bytes',
|
|
163
|
-
this.maxMetadataBytes,
|
|
164
|
-
`the first row's ${row.members.size} member names take ${bytes} bytes as the ` +
|
|
165
|
-
`table's columns, more than ${this.maxMetadataBytes}`,
|
|
166
|
-
).atPath(at)
|
|
167
|
-
}
|
|
168
|
-
this.bind(
|
|
169
|
-
[...row.members.keys()].map((k) => boundColumn(k, [k])),
|
|
170
|
-
'the first row',
|
|
152
|
+
const columns = inferColumns(
|
|
153
|
+
row,
|
|
154
|
+
this.maxColumns,
|
|
155
|
+
this.maxMetadataBytes,
|
|
156
|
+
selected.path.toString(),
|
|
171
157
|
)
|
|
158
|
+
this.bind(columns, 'the first row')
|
|
172
159
|
}
|
|
173
160
|
if ('stop' === this.sendSchema()) return 'stop'
|
|
174
161
|
}
|
|
@@ -305,3 +292,63 @@ export class TableFromJson<S extends TableSink> implements Sink {
|
|
|
305
292
|
return this.router.event(ev)
|
|
306
293
|
}
|
|
307
294
|
}
|
|
295
|
+
|
|
296
|
+
// The columns the first row implies, by its kind: an object's member names,
|
|
297
|
+
// in its order, each sourced at its key; an array's positions, labelled
|
|
298
|
+
// `0`, `1`, ... up to its length, each sourced at its index; and for a
|
|
299
|
+
// scalar one column, `value`, sourced at the row itself. A later row of any
|
|
300
|
+
// kind projects through these paths, and lands empty where they miss.
|
|
301
|
+
function inferColumns(
|
|
302
|
+
row: Datum,
|
|
303
|
+
maxColumns: number,
|
|
304
|
+
maxMetadataBytes: number,
|
|
305
|
+
at: string,
|
|
306
|
+
): BoundColumn[] {
|
|
307
|
+
// The bounds are checked before a column is built: the labels are the
|
|
308
|
+
// table's metadata for as long as it lasts, so they are held to the bound
|
|
309
|
+
// a metadata capture is, measured as the array of their strings would be,
|
|
310
|
+
// and counted from the row itself, so a first row wider than either bound
|
|
311
|
+
// costs a walk of what it already holds and allocates nothing.
|
|
312
|
+
let count = 1
|
|
313
|
+
let labels = 5 // "value"
|
|
314
|
+
if ('object' === row.type) {
|
|
315
|
+
count = row.members.size
|
|
316
|
+
labels = 0
|
|
317
|
+
for (const k of row.members.keys()) labels += utf8Bytes(k)
|
|
318
|
+
} else if ('array' === row.type) {
|
|
319
|
+
count = row.items.length
|
|
320
|
+
labels = 0
|
|
321
|
+
for (let i = 0; i < count; i++) labels += decimalDigits(i)
|
|
322
|
+
}
|
|
323
|
+
const bytes = (count + 1) * NODE_BYTES + labels
|
|
324
|
+
if (bytes > maxMetadataBytes) {
|
|
325
|
+
throw Fail.limit(
|
|
326
|
+
'max_metadata_bytes',
|
|
327
|
+
maxMetadataBytes,
|
|
328
|
+
`the first row's ${count} column labels take ${bytes} bytes as the ` +
|
|
329
|
+
`table's metadata, more than ${maxMetadataBytes}`,
|
|
330
|
+
).atPath(at)
|
|
331
|
+
}
|
|
332
|
+
if (count > maxColumns) {
|
|
333
|
+
throw Fail.limit(
|
|
334
|
+
'max_columns',
|
|
335
|
+
maxColumns,
|
|
336
|
+
`the first row declares ${count} columns, more than ${maxColumns}`,
|
|
337
|
+
).atPath(at)
|
|
338
|
+
}
|
|
339
|
+
switch (row.type) {
|
|
340
|
+
case 'object':
|
|
341
|
+
return [...row.members.keys()].map((k) => boundColumn(k, [k]))
|
|
342
|
+
case 'array':
|
|
343
|
+
return row.items.map((_, i) => boundColumn(String(i), [i]))
|
|
344
|
+
default:
|
|
345
|
+
return [boundColumn('value', [])]
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// The length of `i` written in decimal: the bytes of an array row's label.
|
|
350
|
+
function decimalDigits(i: number): number {
|
|
351
|
+
let digits = 1
|
|
352
|
+
for (let n = i; n >= 10; n = Math.floor(n / 10)) digits++
|
|
353
|
+
return digits
|
|
354
|
+
}
|
package/src/transduce.ts
CHANGED