spliterator 6.0.1 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/out/index.d.ts +2 -0
- package/out/index.d.ts.map +1 -1
- package/out/index.js +2 -0
- package/out/index.js.map +1 -1
- package/out/lib/CSVSpliterator.d.ts +8 -18
- package/out/lib/CSVSpliterator.d.ts.map +1 -1
- package/out/lib/CSVSpliterator.js +4 -47
- package/out/lib/CSVSpliterator.js.map +1 -1
- package/out/lib/XLSXSpliterator.d.ts +143 -0
- package/out/lib/XLSXSpliterator.d.ts.map +1 -0
- package/out/lib/XLSXSpliterator.js +161 -0
- package/out/lib/XLSXSpliterator.js.map +1 -0
- package/out/lib/row-emitters.d.ts +35 -0
- package/out/lib/row-emitters.d.ts.map +1 -0
- package/out/lib/row-emitters.js +50 -0
- package/out/lib/row-emitters.js.map +1 -0
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -92,6 +92,58 @@ for await (const columns of reader) {
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
## Excel workbooks (XLSX)
|
|
96
|
+
|
|
97
|
+
Spliterator can read and write `.xlsx` workbooks through `XLSXSpliterator`. Support is powered by two optional peer dependencies — install the one you need:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
yarn add read-excel-file # for XLSXSpliterator.fromAsync
|
|
101
|
+
yarn add write-excel-file # for XLSXSpliterator.write
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Reading mirrors `CSVSpliterator`'s options — `mode`, `header`, `normalizeKeys`, `transformers`, `drop`, and `take` — plus a `sheet` option to pick a sheet by 1-based number or name. Unlike CSV columns, XLSX cells arrive **typed**: numbers, booleans, and dates are real values rather than strings, and empty cells are `null`.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { XLSXSpliterator } from "spliterator"
|
|
108
|
+
|
|
109
|
+
const reader = XLSXSpliterator.fromAsync("people.xlsx", { mode: "object", sheet: "Employees" })
|
|
110
|
+
|
|
111
|
+
for await (const row of reader) {
|
|
112
|
+
console.log(row) // { full_name: "Morgan", hired: Date, age: 30 }, etc.
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Transformers receive those typed cell values, which makes them a natural place to coerce loosely-exported data — many real-world workbooks store everything as text:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
const reader = XLSXSpliterator.fromAsync("form499.xlsx", {
|
|
120
|
+
mode: "object",
|
|
121
|
+
transformers: {
|
|
122
|
+
filer_499_id: (value) => Number(value),
|
|
123
|
+
alabama: (value) => value === "TRUE",
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Writing accepts any iterable or async iterable of rows — arrays of cells, or records whose keys become the header row — so a Spliterator pipeline can terminate in a workbook:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
const rows = CSVSpliterator.fromAsync("people.csv", { mode: "object" }).map((person) => ({
|
|
132
|
+
...person,
|
|
133
|
+
age: Number(person.age),
|
|
134
|
+
}))
|
|
135
|
+
|
|
136
|
+
await XLSXSpliterator.write(rows, { sheet: "People" }).toFile("people.xlsx")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
A few caveats worth knowing:
|
|
140
|
+
|
|
141
|
+
- **The whole workbook is held in memory, in both directions.** XLSX is a ZIP archive of XML documents — shared strings live in a separate archive entry and the ZIP's central directory sits at the end of the file — so it cannot be parsed or produced as a bounded-memory stream the way delimited text can. Reading yields no rows until the entire sheet is parsed, and writing drains your source completely before producing bytes. Expect memory usage far above the file's size on disk (a 9 MB workbook can inflate to hundreds of MB parsed). For sources large enough that this matters, prefer CSV or JSONL.
|
|
142
|
+
- **There is no synchronous reader.** Decompression and XML parsing are asynchronous in the underlying reader, so `XLSXSpliterator.from()` always throws, pointing you to `fromAsync`.
|
|
143
|
+
- **One sheet at a time.** Reading targets a single sheet per call, and writing produces a single-sheet workbook. Cell styling, formats, and formulas are out of scope.
|
|
144
|
+
|
|
145
|
+
See `examples/xlsx-to-jsonl.ts` for a complete conversion script with derived transformers.
|
|
146
|
+
|
|
95
147
|
## CLI Usage
|
|
96
148
|
|
|
97
149
|
Spliterator also includes a CLI tool that can be used to stream delimited content from the command line, transform it, filter it, and more.
|
package/out/index.d.ts
CHANGED
|
@@ -11,11 +11,13 @@ export * from "./lib/CharacterSequence.js";
|
|
|
11
11
|
export * from "./lib/chunks.js";
|
|
12
12
|
export * from "./lib/CompositeDataView.js";
|
|
13
13
|
export * from "./lib/CSVSpliterator.js";
|
|
14
|
+
export * from "./lib/XLSXSpliterator.js";
|
|
14
15
|
export * from "./lib/IndexQueue.js";
|
|
15
16
|
export * from "./lib/JSONSpliterator.js";
|
|
16
17
|
export * from "./lib/parallel-map.js";
|
|
17
18
|
export * from "./lib/parallel-map-workers.js";
|
|
18
19
|
export * from "./lib/pivot.js";
|
|
20
|
+
export * from "./lib/row-emitters.js";
|
|
19
21
|
export * from "./lib/PSVSpliterator.js";
|
|
20
22
|
export * from "./lib/segments.js";
|
|
21
23
|
export * from "./lib/shared.js";
|
package/out/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
package/out/index.js
CHANGED
|
@@ -11,11 +11,13 @@ export * from "./lib/CharacterSequence.js";
|
|
|
11
11
|
export * from "./lib/chunks.js";
|
|
12
12
|
export * from "./lib/CompositeDataView.js";
|
|
13
13
|
export * from "./lib/CSVSpliterator.js";
|
|
14
|
+
export * from "./lib/XLSXSpliterator.js";
|
|
14
15
|
export * from "./lib/IndexQueue.js";
|
|
15
16
|
export * from "./lib/JSONSpliterator.js";
|
|
16
17
|
export * from "./lib/parallel-map.js";
|
|
17
18
|
export * from "./lib/parallel-map-workers.js";
|
|
18
19
|
export * from "./lib/pivot.js";
|
|
20
|
+
export * from "./lib/row-emitters.js";
|
|
19
21
|
export * from "./lib/PSVSpliterator.js";
|
|
20
22
|
export * from "./lib/segments.js";
|
|
21
23
|
export * from "./lib/shared.js";
|
package/out/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,0BAA0B,CAAA;AACxC,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA"}
|
|
@@ -5,30 +5,20 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { AsyncSequence } from "./AsyncSequence.js";
|
|
7
7
|
import { type CharacterSequenceInput } from "./CharacterSequence.js";
|
|
8
|
+
import { type RowEmitter, type RowOutputMode, type RowTransformer, type RowTransformerEntry, type RowTransformerRecord, type RowTuple } from "./row-emitters.js";
|
|
8
9
|
import type { AsyncChunkIterator, AsyncDataResource } from "./shared.js";
|
|
9
10
|
import { type AsyncSpliteratorInit, type SpliteratorInit } from "./Spliterator.js";
|
|
11
|
+
export type { RowTuple } from "./row-emitters.js";
|
|
10
12
|
/**
|
|
11
13
|
* An output mode for the CSV generator.
|
|
12
14
|
*/
|
|
13
|
-
export type CSVOutputMode =
|
|
14
|
-
export type CSVTransformer<T = unknown> =
|
|
15
|
-
export type CSVTransformerEntry<T = unknown> =
|
|
16
|
-
export type CSVTransformerRecord =
|
|
17
|
-
export type CSVEmitter<T = unknown> =
|
|
15
|
+
export type CSVOutputMode = RowOutputMode;
|
|
16
|
+
export type CSVTransformer<T = unknown> = RowTransformer<string, T>;
|
|
17
|
+
export type CSVTransformerEntry<T = unknown> = RowTransformerEntry<string, T>;
|
|
18
|
+
export type CSVTransformerRecord = RowTransformerRecord<string>;
|
|
19
|
+
export type CSVEmitter<T = unknown> = RowEmitter<string, T>;
|
|
18
20
|
export type CSVSpliteratorEmittedRecord<V = string | number | undefined> = Record<string, V>;
|
|
19
|
-
|
|
20
|
-
* A row emitted by the CSV generator, as a 3-tuple:
|
|
21
|
-
*
|
|
22
|
-
* - The key of the column.
|
|
23
|
-
* - The value of the column.
|
|
24
|
-
* - The index of the row.
|
|
25
|
-
*/
|
|
26
|
-
export type RowTuple<V = string | number> = [key: string, value: V, idx: number];
|
|
27
|
-
export declare const CSVSpliteratorEmitters: {
|
|
28
|
-
readonly array: null;
|
|
29
|
-
readonly entries: (columns: Iterable<string>, headerColumns?: Iterable<CSVTransformerEntry>) => RowTuple<unknown>[];
|
|
30
|
-
readonly object: (columns: Iterable<string>, headerColumns?: Iterable<CSVTransformerEntry>) => CSVSpliteratorEmittedRecord<unknown>;
|
|
31
|
-
};
|
|
21
|
+
export declare const CSVSpliteratorEmitters: Record<CSVOutputMode, CSVEmitter | null>;
|
|
32
22
|
export interface CSVSpliteratorInit extends SpliteratorInit {
|
|
33
23
|
/**
|
|
34
24
|
* The mode determines the shape of the data emitted by the generator.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CSVSpliterator.d.ts","sourceRoot":"","sources":["../../lib/CSVSpliterator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,OAAO,EAAqB,KAAK,sBAAsB,EAAc,MAAM,wBAAwB,CAAA;AACnG,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,EAAE,KAAK,oBAAoB,EAAe,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"CSVSpliterator.d.ts","sourceRoot":"","sources":["../../lib/CSVSpliterator.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,9 +7,8 @@ import { openDelimitedRows } from "./adaptive-source.js";
|
|
|
7
7
|
import { AsyncSequence } from "./AsyncSequence.js";
|
|
8
8
|
import { normalizeColumnNames } from "./casing.js";
|
|
9
9
|
import { CharacterSequence, Delimiters } from "./CharacterSequence.js";
|
|
10
|
+
import { bindTransformers, createRowEmitters, } from "./row-emitters.js";
|
|
10
11
|
import { Spliterator } from "./Spliterator.js";
|
|
11
|
-
import { zipSync } from "./zip.js";
|
|
12
|
-
const identity = (value) => value;
|
|
13
12
|
const doubleQuoteSequence = new CharacterSequence('"');
|
|
14
13
|
/**
|
|
15
14
|
* Decode a single column, stripping wrapping quotes and unescaping doubled quotes (`""` → `"`) when quote handling is
|
|
@@ -49,25 +48,7 @@ function splitRowColumns(row, columnDelimiter, decoder, enableQuoteHandling) {
|
|
|
49
48
|
columns.push(decodeColumn(row.subarray(sliceStart), decoder, enableQuoteHandling));
|
|
50
49
|
return columns;
|
|
51
50
|
}
|
|
52
|
-
export const CSVSpliteratorEmitters =
|
|
53
|
-
array: null,
|
|
54
|
-
entries(columns, headerColumns = []) {
|
|
55
|
-
return Array.from(zipSync(headerColumns, columns), ([transformer, value], idx) => {
|
|
56
|
-
const key = transformer?.[0];
|
|
57
|
-
const transform = transformer?.[1] ?? identity;
|
|
58
|
-
return [key ?? `column_${idx}`, transform(value ?? ""), idx];
|
|
59
|
-
});
|
|
60
|
-
},
|
|
61
|
-
object(columns, headerColumns = []) {
|
|
62
|
-
const record = {};
|
|
63
|
-
for (const [transformer, value, idx] of zipSync(headerColumns, columns)) {
|
|
64
|
-
const key = transformer?.[0] ?? `column_${idx}`;
|
|
65
|
-
const transform = transformer?.[1] ?? identity;
|
|
66
|
-
record[key] = transform(value ?? "");
|
|
67
|
-
}
|
|
68
|
-
return record;
|
|
69
|
-
},
|
|
70
|
-
};
|
|
51
|
+
export const CSVSpliteratorEmitters = createRowEmitters("");
|
|
71
52
|
/**
|
|
72
53
|
* A static class spliterator for comma-separated values.
|
|
73
54
|
*
|
|
@@ -121,19 +102,7 @@ export class CSVSpliterator {
|
|
|
121
102
|
return;
|
|
122
103
|
const columns = splitRowColumns(result.value, columnDelimiter, decoder, enableQuoteHandling);
|
|
123
104
|
const headers = normalizeKeys ? normalizeColumnNames(columns) : columns;
|
|
124
|
-
|
|
125
|
-
if (Array.isArray(transformersInput)) {
|
|
126
|
-
transformers = Array.from(zipSync(headers, transformersInput), ([columnName, transformer]) => [
|
|
127
|
-
columnName,
|
|
128
|
-
transformer ?? identity,
|
|
129
|
-
]);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
transformers = headers.map((columnName) => {
|
|
133
|
-
const transform = transformersInput[columnName] || identity;
|
|
134
|
-
return [columnName, transform];
|
|
135
|
-
});
|
|
136
|
-
}
|
|
105
|
+
transformers = bindTransformers(headers, transformersInput);
|
|
137
106
|
}
|
|
138
107
|
for (const row of rows) {
|
|
139
108
|
if (yieldCount < drop) {
|
|
@@ -183,19 +152,7 @@ export class CSVSpliterator {
|
|
|
183
152
|
return rows;
|
|
184
153
|
const columns = splitRowColumns(result.value, columnDelimiter, decoder, enableQuoteHandling);
|
|
185
154
|
const headers = normalizeKeys ? normalizeColumnNames(columns) : columns;
|
|
186
|
-
|
|
187
|
-
if (Array.isArray(transformersInput)) {
|
|
188
|
-
transformers = Array.from(zipSync(headers, transformersInput), ([columnName, transformer]) => [
|
|
189
|
-
columnName,
|
|
190
|
-
transformer ?? identity,
|
|
191
|
-
]);
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
transformers = headers.map((columnName) => {
|
|
195
|
-
const transform = transformersInput[columnName] || identity;
|
|
196
|
-
return [columnName, transform];
|
|
197
|
-
});
|
|
198
|
-
}
|
|
155
|
+
transformers = bindTransformers(headers, transformersInput);
|
|
199
156
|
}
|
|
200
157
|
return rows;
|
|
201
158
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CSVSpliterator.js","sourceRoot":"","sources":["../../lib/CSVSpliterator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAA2B,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAA+B,UAAU,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"CSVSpliterator.js","sourceRoot":"","sources":["../../lib/CSVSpliterator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAA2B,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,iBAAiB,EAA+B,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnG,OAAO,EACN,gBAAgB,EAChB,iBAAiB,GAOjB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAA6B,WAAW,EAAwB,MAAM,kBAAkB,CAAA;AAiB/F,MAAM,mBAAmB,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAA;AAEtD;;;GAGG;AACH,SAAS,YAAY,CAAC,KAAiB,EAAE,OAAoB,EAAE,mBAA4B;IAC1F,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAEnC,IAAI,mBAAmB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9F,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,KAAK,CAAA;AACb,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CACvB,GAAe,EACf,eAAkC,EAClC,OAAoB,EACpB,mBAA4B;IAE5B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC1B,OAAO,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IACtG,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,YAAY,GAAG,KAAK,CAAA;IAExB,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,aAAa,CAAC,GAAG,EAAE,mBAAmB,CAAC,EAAE,CAAC;QAC7E,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YAC3B,YAAY,GAAG,CAAC,YAAY,CAAA;YAE5B,SAAQ;QACT,CAAC;QAED,IAAI,YAAY;YAAE,SAAQ;QAE1B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAA;QAChG,UAAU,GAAG,KAAK,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAA;IACnD,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAElF,OAAO,OAAO,CAAA;AACf,CAAC;AAID,MAAM,CAAC,MAAM,sBAAsB,GAA6C,iBAAiB,CAAS,EAAE,CAAC,CAAA;AAmD7G;;;;;;;;;;GAUG;AACH,MAAM,OAAgB,cAAc;IACnC;;;;OAIG;IACI,MAAM,CAAC,eAAe,GAAW,UAAU,CAAC,KAAK,CAAA;IAExD;QACC,MAAM,IAAI,SAAS,CAAC,0EAA0E,CAAC,CAAA;IAChG,CAAC;IAuBD;;;;OAIG;IACH,MAAM,CAAC,CAAC,IAAI,CAAC,MAA8B,EAAE,IAAI,GAAuB,EAAE;QACzE,MAAM;QACL,MAAM;QACN,MAAM,GAAG,IAAI;QACb,uFAAuF;QACvF,IAAI,GAAG,OAAO,EACd,YAAY,EAAE,iBAAiB,GAAG,EAAE;QACpC,wFAAwF;QACxF,8FAA8F;QAC9F,aAAa,GAAG,IAAI,KAAK,OAAO,EAChC,eAAe,EAAE,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAC5D,mBAAmB,GAAG,KAAK;QAC3B,qFAAqF;QACrF,yDAAyD;QACzD,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,QAAQ,EACf,IAAI,GAAG,CAAC,EACR,GAAG,OAAO,EACV,GAAG,IAAI,CAAA;QAER,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAA;QAC5C,IAAI,YAAY,GAA0B,EAAE,CAAA;QAC5C,IAAI,UAAU,GAAG,CAAC,CAAA;QAClB,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAA;QAE9B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;QACjC,MAAM,eAAe,GAAG,IAAI,iBAAiB,CAAC,oBAAoB,IAAI,IAAI,CAAC,eAAe,CAAC,CAAA;QAE3F,wFAAwF;QACxF,sDAAsD;QACtD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAA;QAEpF,IAAI,MAAM,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;YAE1B,IAAI,MAAM,CAAC,IAAI;gBAAE,OAAM;YAEvB,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAA;YAC5F,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YAEvE,YAAY,GAAG,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAA;QAC5D,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,UAAU,GAAG,IAAI,EAAE,CAAC;gBACvB,UAAU,EAAE,CAAA;gBAEZ,SAAQ;YACT,CAAC;YAED,IAAI,UAAU,IAAI,UAAU;gBAAE,MAAK;YAEnC,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAA;YAEnF,MAAM,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;YAExD,UAAU,EAAE,CAAA;QACb,CAAC;IACF,CAAC;IAqCD;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,CACf,MAA8C,EAC9C,IAAI,GAA4C,EAAE;QAElD,MAAM,sBAAsB,GAAG,IAAI,CAAC,eAAe,CAAA;QAEnD,MAAM;QACL,MAAM;QACN,MAAM,GAAG,IAAI,EACb,IAAI,GAAG,OAAO,EACd,YAAY,EAAE,iBAAiB,GAAG,EAAE,EACpC,aAAa,GAAG,IAAI,KAAK,OAAO,EAChC,eAAe,EAAE,oBAAoB,EACrC,mBAAmB,GAAG,KAAK;QAC3B,qFAAqF;QACrF,yDAAyD;QACzD,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,QAAQ,EACf,IAAI,GAAG,CAAC,EACR,GAAG,OAAO,EACV,GAAG,IAAI,CAAA;QAER,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAA;QAC5C,MAAM,eAAe,GAAG,IAAI,iBAAiB,CAAC,oBAAoB,IAAI,sBAAsB,CAAC,CAAA;QAC7F,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;QAEjC,gHAAgH;QAChH,qDAAqD;QACrD,IAAI,YAAY,GAA0B,EAAE,CAAA;QAE5C,MAAM,QAAQ,GAAG,KAAK,IAA+D,EAAE;YACtF,wFAAwF;YACxF,sDAAsD;YACtD,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAA;YAEvF,IAAI,MAAM,EAAE,CAAC;gBACZ,4GAA4G;gBAC5G,uGAAuG;gBACvG,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAA;gBACtG,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;gBAEpC,IAAI,MAAM,CAAC,IAAI;oBAAE,OAAO,IAAI,CAAA;gBAE5B,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAA;gBAC5F,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;gBAEvE,YAAY,GAAG,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAA;YAC5D,CAAC;YAED,OAAO,IAAI,CAAA;QACZ,CAAC,CAAA;QAED,IAAI,QAAQ,GAA2B,aAAa,CAAC,IAAI,CAAa,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC3F,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAA;YAEnF,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAA;QAC1D,CAAC,CAAC,CAAA;QAEF,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACd,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC;QAED,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/B,CAAC;QAED,OAAO,QAAQ,CAAA;IAChB,CAAC;CACD"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
import { AsyncSequence } from "./AsyncSequence.js";
|
|
7
|
+
import { type RowEmitter, type RowOutputMode, type RowTransformer, type RowTransformerEntry, type RowTransformerRecord, type RowTuple } from "./row-emitters.js";
|
|
8
|
+
import type { AsyncChunkIterator } from "./shared.js";
|
|
9
|
+
/**
|
|
10
|
+
* A cell value as parsed from an XLSX sheet. Unlike CSV columns, XLSX cells arrive typed — numbers, booleans, and dates
|
|
11
|
+
* are real values, not strings — and an empty cell is `null`.
|
|
12
|
+
*/
|
|
13
|
+
export type XLSXCellValue = string | number | boolean | Date | null;
|
|
14
|
+
export type XLSXTransformer<T = unknown> = RowTransformer<XLSXCellValue, T>;
|
|
15
|
+
export type XLSXTransformerEntry<T = unknown> = RowTransformerEntry<XLSXCellValue, T>;
|
|
16
|
+
export type XLSXTransformerRecord = RowTransformerRecord<XLSXCellValue>;
|
|
17
|
+
export type XLSXSpliteratorEmittedRecord<V = XLSXCellValue> = Record<string, V>;
|
|
18
|
+
/**
|
|
19
|
+
* A readable XLSX source: a file path, a whole workbook in memory, or an asynchronous byte stream.
|
|
20
|
+
*/
|
|
21
|
+
export type XLSXSource = string | URL | Uint8Array | AsyncChunkIterator;
|
|
22
|
+
/**
|
|
23
|
+
* A row accepted by {@linkcode XLSXSpliterator.write}: either an array of cells, or a record whose keys become the
|
|
24
|
+
* header row. `undefined` cells are written as empty (`null`) cells, so records read under `noUncheckedIndexedAccess`
|
|
25
|
+
* pass through without ceremony.
|
|
26
|
+
*/
|
|
27
|
+
export type XLSXWritableRow = readonly (XLSXCellValue | undefined)[] | Readonly<Record<string, XLSXCellValue | undefined>>;
|
|
28
|
+
export declare const XLSXSpliteratorEmitters: Record<RowOutputMode, RowEmitter<XLSXCellValue> | null>;
|
|
29
|
+
export interface XLSXSpliteratorInit {
|
|
30
|
+
/**
|
|
31
|
+
* The sheet to read, as a 1-based sheet number or a sheet name.
|
|
32
|
+
*
|
|
33
|
+
* @default 1
|
|
34
|
+
*/
|
|
35
|
+
sheet?: number | string;
|
|
36
|
+
/**
|
|
37
|
+
* The mode determines the shape of the data emitted by the generator.
|
|
38
|
+
*
|
|
39
|
+
* - `object` will emit each row as an object with the header names as keys.
|
|
40
|
+
* - `array` will emit each row as an array.
|
|
41
|
+
* - `entries` will emit each row as an array of key-value pairs.
|
|
42
|
+
*
|
|
43
|
+
* @default "array"
|
|
44
|
+
*/
|
|
45
|
+
mode?: RowOutputMode;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to treat the first row as a header.
|
|
48
|
+
*
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
header?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Whether to normalize the keys of the header row into `snake_case`, matching {@linkcode CSVSpliterator}.
|
|
54
|
+
*
|
|
55
|
+
* @default `mode !== "array"`
|
|
56
|
+
*/
|
|
57
|
+
normalizeKeys?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Per-column transformers. Unlike CSV transformers, these receive typed cell values ({@linkcode XLSXCellValue}), not
|
|
60
|
+
* strings.
|
|
61
|
+
*/
|
|
62
|
+
transformers?: Iterable<XLSXTransformerEntry> | XLSXTransformerRecord;
|
|
63
|
+
/**
|
|
64
|
+
* The number of data rows to skip before yielding.
|
|
65
|
+
*/
|
|
66
|
+
drop?: number;
|
|
67
|
+
/**
|
|
68
|
+
* The maximum number of rows to yield.
|
|
69
|
+
*/
|
|
70
|
+
take?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface XLSXWriteInit {
|
|
73
|
+
/**
|
|
74
|
+
* The name of the written sheet.
|
|
75
|
+
*/
|
|
76
|
+
sheet?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Whether to emit a header row.
|
|
79
|
+
*
|
|
80
|
+
* @default true for record rows — the header is derived from the first record's keys. Array rows have no keys, so
|
|
81
|
+
* this defaults to false and enabling it is a `TypeError`.
|
|
82
|
+
*/
|
|
83
|
+
header?: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* A handle over a pending XLSX serialization. The source rows are materialized on the first invocation of any method —
|
|
87
|
+
* XLSX is a ZIP archive, so the workbook must be complete before any bytes can be produced.
|
|
88
|
+
*/
|
|
89
|
+
export interface XLSXWriteHandle {
|
|
90
|
+
toFile(path: string): Promise<void>;
|
|
91
|
+
toBuffer(): Promise<Buffer>;
|
|
92
|
+
toStream(writable?: NodeJS.WritableStream): Promise<unknown>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* A static class spliterator for XLSX workbooks, reading through the optional peer dependency `read-excel-file` and
|
|
96
|
+
* writing through `write-excel-file`.
|
|
97
|
+
*
|
|
98
|
+
* **Memory:** XLSX is a ZIP archive of XML documents — shared strings live in a separate archive entry, and the central
|
|
99
|
+
* directory sits at the end of the file. Both reading and writing therefore materialize the whole workbook, unlike the
|
|
100
|
+
* byte-level spliterators. Prefer CSV for sources large enough that bounded memory matters.
|
|
101
|
+
*
|
|
102
|
+
* @see {@linkcode XLSXSpliterator.fromAsync} for reading.
|
|
103
|
+
* @see {@linkcode XLSXSpliterator.write} for writing.
|
|
104
|
+
*/
|
|
105
|
+
export declare abstract class XLSXSpliterator {
|
|
106
|
+
constructor();
|
|
107
|
+
/**
|
|
108
|
+
* XLSX cannot be parsed synchronously — decompression and XML parsing are asynchronous in the underlying reader.
|
|
109
|
+
*
|
|
110
|
+
* @throws {TypeError} Always. Use {@linkcode XLSXSpliterator.fromAsync}.
|
|
111
|
+
*/
|
|
112
|
+
static from(_source?: unknown, _init?: unknown): never;
|
|
113
|
+
/**
|
|
114
|
+
* @yields Each row as an object with the header names as keys.
|
|
115
|
+
*/
|
|
116
|
+
static fromAsync<T extends XLSXSpliteratorEmittedRecord = XLSXSpliteratorEmittedRecord>(source: XLSXSource, options?: XLSXSpliteratorInit & {
|
|
117
|
+
mode: "object";
|
|
118
|
+
}): AsyncSequence<T>;
|
|
119
|
+
/**
|
|
120
|
+
* @yields Each row as a 3-tuple [key, value, idx].
|
|
121
|
+
*/
|
|
122
|
+
static fromAsync<T extends RowTuple<unknown>[] = RowTuple<XLSXCellValue>[]>(source: XLSXSource, options?: XLSXSpliteratorInit & {
|
|
123
|
+
mode: "entries";
|
|
124
|
+
}): AsyncSequence<T>;
|
|
125
|
+
/**
|
|
126
|
+
* @yields Each row as an array of typed cells.
|
|
127
|
+
*/
|
|
128
|
+
static fromAsync<T extends XLSXCellValue[] = XLSXCellValue[]>(source: XLSXSource, options?: XLSXSpliteratorInit & {
|
|
129
|
+
mode?: "array";
|
|
130
|
+
}): AsyncSequence<T>;
|
|
131
|
+
/**
|
|
132
|
+
* Serialize rows into an XLSX workbook through the optional peer dependency `write-excel-file`.
|
|
133
|
+
*
|
|
134
|
+
* Rows may be arrays of cells, or records — record keys become the header row, read in the first record's key order.
|
|
135
|
+
* The source is materialized on the first invocation of a handle method: the workbook must be complete before any
|
|
136
|
+
* bytes can be produced.
|
|
137
|
+
*
|
|
138
|
+
* @param source The rows to write, as any iterable or async iterable.
|
|
139
|
+
* @param init Options for the writer.
|
|
140
|
+
*/
|
|
141
|
+
static write(source: Iterable<XLSXWritableRow> | AsyncIterable<XLSXWritableRow>, init?: XLSXWriteInit): XLSXWriteHandle;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=XLSXSpliterator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"XLSXSpliterator.d.ts","sourceRoot":"","sources":["../../lib/XLSXSpliterator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
import { AsyncSequence } from "./AsyncSequence.js";
|
|
7
|
+
import { normalizeColumnNames } from "./casing.js";
|
|
8
|
+
import { bindTransformers, createRowEmitters, } from "./row-emitters.js";
|
|
9
|
+
export const XLSXSpliteratorEmitters = createRowEmitters(null);
|
|
10
|
+
/**
|
|
11
|
+
* Wrap the optional peer dependency import so a missing module names the package to install.
|
|
12
|
+
*/
|
|
13
|
+
async function importVendor(packageName, importer) {
|
|
14
|
+
try {
|
|
15
|
+
return await importer();
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
throw new Error(`XLSXSpliterator requires the optional peer dependency "${packageName}". Install it to use this API.`, { cause: error });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Adapt a {@linkcode XLSXSource} to what `read-excel-file/node` accepts: a path, a `Buffer`, or a Node stream.
|
|
23
|
+
*/
|
|
24
|
+
async function resolveVendorInput(source) {
|
|
25
|
+
if (typeof source === "string")
|
|
26
|
+
return source;
|
|
27
|
+
if (source instanceof URL) {
|
|
28
|
+
const { fileURLToPath } = await import("node:url");
|
|
29
|
+
return fileURLToPath(source);
|
|
30
|
+
}
|
|
31
|
+
if (source instanceof Uint8Array) {
|
|
32
|
+
// Respect the byte offset: small `Buffer`s share a pool, so offset 0 of the
|
|
33
|
+
// underlying `ArrayBuffer` may be another allocation's data.
|
|
34
|
+
return Buffer.from(source.buffer, source.byteOffset, source.byteLength);
|
|
35
|
+
}
|
|
36
|
+
const { Readable } = await import("node:stream");
|
|
37
|
+
return Readable.from(source);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A static class spliterator for XLSX workbooks, reading through the optional peer dependency `read-excel-file` and
|
|
41
|
+
* writing through `write-excel-file`.
|
|
42
|
+
*
|
|
43
|
+
* **Memory:** XLSX is a ZIP archive of XML documents — shared strings live in a separate archive entry, and the central
|
|
44
|
+
* directory sits at the end of the file. Both reading and writing therefore materialize the whole workbook, unlike the
|
|
45
|
+
* byte-level spliterators. Prefer CSV for sources large enough that bounded memory matters.
|
|
46
|
+
*
|
|
47
|
+
* @see {@linkcode XLSXSpliterator.fromAsync} for reading.
|
|
48
|
+
* @see {@linkcode XLSXSpliterator.write} for writing.
|
|
49
|
+
*/
|
|
50
|
+
export class XLSXSpliterator {
|
|
51
|
+
constructor() {
|
|
52
|
+
throw new TypeError("Static class cannot be instantiated. Did you mean `XLSXSpliterator.fromAsync`?");
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* XLSX cannot be parsed synchronously — decompression and XML parsing are asynchronous in the underlying reader.
|
|
56
|
+
*
|
|
57
|
+
* @throws {TypeError} Always. Use {@linkcode XLSXSpliterator.fromAsync}.
|
|
58
|
+
*/
|
|
59
|
+
static from(_source, _init) {
|
|
60
|
+
throw new TypeError("XLSX cannot be parsed synchronously. Did you mean `XLSXSpliterator.fromAsync`?");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Given an XLSX workbook, yield each row of a sheet, shaped according to the `mode` option.
|
|
64
|
+
*
|
|
65
|
+
* Note that unlike the byte-level spliterators, the whole sheet is materialized before the first row is yielded.
|
|
66
|
+
*
|
|
67
|
+
* @param source The workbook to read.
|
|
68
|
+
* @param init Options for the spliterator.
|
|
69
|
+
*
|
|
70
|
+
* @yields Each row, shaped according to the `mode` option.
|
|
71
|
+
*/
|
|
72
|
+
static fromAsync(source, init = {}) {
|
|
73
|
+
const {
|
|
74
|
+
// ---
|
|
75
|
+
sheet = 1, header = true, mode = "array", transformers: transformersInput = [], normalizeKeys = mode !== "array", take = Infinity, drop = 0, } = init;
|
|
76
|
+
const emitter = XLSXSpliteratorEmitters[mode];
|
|
77
|
+
// Populated by the header pass below before the first row op runs, matching `CSVSpliterator.fromAsync`.
|
|
78
|
+
let transformers = [];
|
|
79
|
+
const openRows = async () => {
|
|
80
|
+
const { readSheet } = await importVendor("read-excel-file", () => import("read-excel-file/node"));
|
|
81
|
+
const input = await resolveVendorInput(source);
|
|
82
|
+
const rows = (await readSheet(input, sheet));
|
|
83
|
+
if (!header)
|
|
84
|
+
return rows;
|
|
85
|
+
const headerRow = rows[0];
|
|
86
|
+
if (!headerRow)
|
|
87
|
+
return [];
|
|
88
|
+
// A header row may legally contain non-string cells — stringify before normalization.
|
|
89
|
+
const columns = headerRow.map((cell) => String(cell ?? ""));
|
|
90
|
+
const headers = normalizeKeys ? normalizeColumnNames(columns) : columns;
|
|
91
|
+
transformers = bindTransformers(headers, transformersInput);
|
|
92
|
+
return rows.slice(1);
|
|
93
|
+
};
|
|
94
|
+
let sequence = AsyncSequence.from(openRows).map((row) => {
|
|
95
|
+
return emitter ? emitter(row, transformers) : row;
|
|
96
|
+
});
|
|
97
|
+
if (drop > 0) {
|
|
98
|
+
sequence = sequence.drop(drop);
|
|
99
|
+
}
|
|
100
|
+
if (Number.isFinite(take)) {
|
|
101
|
+
sequence = sequence.take(take);
|
|
102
|
+
}
|
|
103
|
+
return sequence;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Serialize rows into an XLSX workbook through the optional peer dependency `write-excel-file`.
|
|
107
|
+
*
|
|
108
|
+
* Rows may be arrays of cells, or records — record keys become the header row, read in the first record's key order.
|
|
109
|
+
* The source is materialized on the first invocation of a handle method: the workbook must be complete before any
|
|
110
|
+
* bytes can be produced.
|
|
111
|
+
*
|
|
112
|
+
* @param source The rows to write, as any iterable or async iterable.
|
|
113
|
+
* @param init Options for the writer.
|
|
114
|
+
*/
|
|
115
|
+
static write(source, init = {}) {
|
|
116
|
+
const open = async () => {
|
|
117
|
+
const { default: writeXlsxFile } = await importVendor("write-excel-file", () => import("write-excel-file/node"));
|
|
118
|
+
const data = await materializeSheetData(source, init);
|
|
119
|
+
return writeXlsxFile(data, init.sheet === undefined ? undefined : { sheet: init.sheet });
|
|
120
|
+
};
|
|
121
|
+
return {
|
|
122
|
+
async toFile(path) {
|
|
123
|
+
await (await open()).toFile(path);
|
|
124
|
+
},
|
|
125
|
+
async toBuffer() {
|
|
126
|
+
return (await open()).toBuffer();
|
|
127
|
+
},
|
|
128
|
+
async toStream(writable) {
|
|
129
|
+
return (await open()).toStream(writable);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Materialize writable rows into `write-excel-file`'s sheet data: bare cell values, with a header row derived from
|
|
136
|
+
* record keys when the rows are records.
|
|
137
|
+
*/
|
|
138
|
+
async function materializeSheetData(source, init) {
|
|
139
|
+
const data = [];
|
|
140
|
+
let keys;
|
|
141
|
+
for await (const row of source) {
|
|
142
|
+
if (Array.isArray(row)) {
|
|
143
|
+
if (init.header) {
|
|
144
|
+
throw new TypeError("`header` requires record rows — array rows have no keys to derive a header from.");
|
|
145
|
+
}
|
|
146
|
+
data.push(row);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const record = row;
|
|
150
|
+
if (!keys) {
|
|
151
|
+
// The header is derived from the first record's keys; later records are read in that order.
|
|
152
|
+
keys = Object.keys(record);
|
|
153
|
+
if (init.header !== false) {
|
|
154
|
+
data.push(keys);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
data.push(keys.map((key) => record[key] ?? null));
|
|
158
|
+
}
|
|
159
|
+
return data;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=XLSXSpliterator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"XLSXSpliterator.js","sourceRoot":"","sources":["../../lib/XLSXSpliterator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* An output mode for row-emitting spliterators.
|
|
8
|
+
*/
|
|
9
|
+
export type RowOutputMode = "array" | "object" | "entries";
|
|
10
|
+
export type RowTransformer<V, T = unknown> = (value: V) => T;
|
|
11
|
+
export type RowTransformerEntry<V, T = unknown> = [columnName: string, transformer: RowTransformer<V, T>];
|
|
12
|
+
export type RowTransformerRecord<V> = Record<string, RowTransformer<V> | undefined>;
|
|
13
|
+
export type RowEmitter<V, T = unknown> = (columns: Iterable<V>, headerColumns?: Iterable<RowTransformerEntry<V>>) => T;
|
|
14
|
+
export type EmittedRecord<V = unknown> = Record<string, V>;
|
|
15
|
+
/**
|
|
16
|
+
* A row emitted in `entries` mode, as a 3-tuple:
|
|
17
|
+
*
|
|
18
|
+
* - The key of the column.
|
|
19
|
+
* - The value of the column.
|
|
20
|
+
* - The index of the row.
|
|
21
|
+
*/
|
|
22
|
+
export type RowTuple<V = string | number> = [key: string, value: V, idx: number];
|
|
23
|
+
export declare const identity: <V>(value: V) => V;
|
|
24
|
+
/**
|
|
25
|
+
* Create the `mode`-keyed emitter table for a cell type.
|
|
26
|
+
*
|
|
27
|
+
* `missingValue` fills columns absent from a short row (CSV binds `""`, XLSX binds `null`).
|
|
28
|
+
*/
|
|
29
|
+
export declare function createRowEmitters<V>(missingValue: V): Record<RowOutputMode, RowEmitter<V> | null>;
|
|
30
|
+
/**
|
|
31
|
+
* Bind a header row to the caller's transformers, producing the `headerColumns` entries the emitters consume. Columns
|
|
32
|
+
* without a transformer pass through {@linkcode identity}.
|
|
33
|
+
*/
|
|
34
|
+
export declare function bindTransformers<V>(headers: string[], transformersInput: Iterable<RowTransformerEntry<V>> | RowTransformerRecord<V>): RowTransformerEntry<V>[];
|
|
35
|
+
//# sourceMappingURL=row-emitters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-emitters.d.ts","sourceRoot":"","sources":["../../lib/row-emitters.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAA;AAE1D,MAAM,MAAM,cAAc,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAA;AAE5D,MAAM,MAAM,mBAAmB,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AAEzG,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;AAEnF,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;AAEtH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;AAE1D;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;AAEhF,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,CAAC,KAAG,CAAU,CAAA;AAEjD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAyBjG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EACjC,OAAO,EAAE,MAAM,EAAE,EACjB,iBAAiB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,GAC3E,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAa1B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*/
|
|
6
|
+
import { zipSync } from "./zip.js";
|
|
7
|
+
export const identity = (value) => value;
|
|
8
|
+
/**
|
|
9
|
+
* Create the `mode`-keyed emitter table for a cell type.
|
|
10
|
+
*
|
|
11
|
+
* `missingValue` fills columns absent from a short row (CSV binds `""`, XLSX binds `null`).
|
|
12
|
+
*/
|
|
13
|
+
export function createRowEmitters(missingValue) {
|
|
14
|
+
return {
|
|
15
|
+
array: null,
|
|
16
|
+
entries(columns, headerColumns = []) {
|
|
17
|
+
return Array.from(zipSync(headerColumns, columns), ([transformer, value], idx) => {
|
|
18
|
+
const key = transformer?.[0];
|
|
19
|
+
const transform = transformer?.[1] ?? identity;
|
|
20
|
+
return [key ?? `column_${idx}`, transform(value ?? missingValue), idx];
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
object(columns, headerColumns = []) {
|
|
24
|
+
const record = {};
|
|
25
|
+
for (const [transformer, value, idx] of zipSync(headerColumns, columns)) {
|
|
26
|
+
const key = transformer?.[0] ?? `column_${idx}`;
|
|
27
|
+
const transform = transformer?.[1] ?? identity;
|
|
28
|
+
record[key] = transform(value ?? missingValue);
|
|
29
|
+
}
|
|
30
|
+
return record;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Bind a header row to the caller's transformers, producing the `headerColumns` entries the emitters consume. Columns
|
|
36
|
+
* without a transformer pass through {@linkcode identity}.
|
|
37
|
+
*/
|
|
38
|
+
export function bindTransformers(headers, transformersInput) {
|
|
39
|
+
if (Array.isArray(transformersInput)) {
|
|
40
|
+
return Array.from(zipSync(headers, transformersInput), ([columnName, transformer]) => [
|
|
41
|
+
columnName,
|
|
42
|
+
transformer ?? identity,
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
return headers.map((columnName) => {
|
|
46
|
+
const transform = transformersInput[columnName] || identity;
|
|
47
|
+
return [columnName, transform];
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=row-emitters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-emitters.js","sourceRoot":"","sources":["../../lib/row-emitters.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AA0BlC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAI,KAAQ,EAAK,EAAE,CAAC,KAAK,CAAA;AAEjD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAI,YAAe;IACnD,OAAO;QACN,KAAK,EAAE,IAAI;QAEX,OAAO,CAAC,OAAoB,EAAE,aAAa,GAAqC,EAAE;YACjF,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE;gBAChF,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,CAAA;gBAC5B,MAAM,SAAS,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAA;gBAE9C,OAAO,CAAC,GAAG,IAAI,UAAU,GAAG,EAAE,EAAE,SAAS,CAAC,KAAK,IAAI,YAAY,CAAC,EAAE,GAAG,CAAC,CAAA;YACvE,CAAC,CAAC,CAAA;QACH,CAAC;QACD,MAAM,CAAC,OAAoB,EAAE,aAAa,GAAqC,EAAE;YAChF,MAAM,MAAM,GAA2B,EAAE,CAAA;YAEzC,KAAK,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,CAAC;gBACzE,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,GAAG,EAAE,CAAA;gBAC/C,MAAM,SAAS,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAA;gBAE9C,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,IAAI,YAAY,CAAC,CAAA;YAC/C,CAAC;YAED,OAAO,MAAM,CAAA;QACd,CAAC;KACD,CAAA;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC/B,OAAiB,EACjB,iBAA6E;IAE7E,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC;YACrF,UAAW;YACV,WAA6C,IAAI,QAAQ;SAC1D,CAAC,CAAA;IACH,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QACjC,MAAM,SAAS,GAAI,iBAA6C,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAA;QAExF,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spliterator",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Line-delimited iterator library for CSV, NDJSON, and other delimited formats.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"csv",
|
|
@@ -75,21 +75,31 @@
|
|
|
75
75
|
"oxfmt": "0.62.0",
|
|
76
76
|
"oxlint": "1.77.0",
|
|
77
77
|
"path-ts": "^2.1.0",
|
|
78
|
+
"read-excel-file": "^9.3.5",
|
|
78
79
|
"release-it": "^21.0.1",
|
|
79
80
|
"type-fest": "^5.8.0",
|
|
80
81
|
"typescript": "^7.0.2",
|
|
81
|
-
"vitest": "^4.1.10"
|
|
82
|
+
"vitest": "^4.1.10",
|
|
83
|
+
"write-excel-file": "^4.1.1"
|
|
82
84
|
},
|
|
83
85
|
"peerDependencies": {
|
|
84
86
|
"change-case": "^5.4.4",
|
|
85
|
-
"
|
|
87
|
+
"read-excel-file": "^9.3.5",
|
|
88
|
+
"type-fest": "^5.6.0",
|
|
89
|
+
"write-excel-file": "^4.1.1"
|
|
86
90
|
},
|
|
87
91
|
"peerDependenciesMeta": {
|
|
88
92
|
"change-case": {
|
|
89
93
|
"optional": true
|
|
90
94
|
},
|
|
95
|
+
"read-excel-file": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
91
98
|
"type-fest": {
|
|
92
99
|
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"write-excel-file": {
|
|
102
|
+
"optional": true
|
|
93
103
|
}
|
|
94
104
|
},
|
|
95
105
|
"engines": {
|