spliterator 6.0.1 → 6.2.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.
Files changed (195) hide show
  1. package/README.md +70 -0
  2. package/out/index.d.ts +26 -23
  3. package/out/index.d.ts.map +1 -1
  4. package/out/index.js +26 -23
  5. package/out/index.js.map +1 -1
  6. package/out/lib/AsyncSpliterator.d.ts.map +1 -1
  7. package/out/lib/AsyncSpliterator.js +28 -0
  8. package/out/lib/AsyncSpliterator.js.map +1 -1
  9. package/out/lib/CSVSpliterator.d.ts +8 -18
  10. package/out/lib/CSVSpliterator.d.ts.map +1 -1
  11. package/out/lib/CSVSpliterator.js +4 -47
  12. package/out/lib/CSVSpliterator.js.map +1 -1
  13. package/out/lib/CharacterSequence.d.ts +16 -1
  14. package/out/lib/CharacterSequence.d.ts.map +1 -1
  15. package/out/lib/CharacterSequence.js +37 -0
  16. package/out/lib/CharacterSequence.js.map +1 -1
  17. package/out/lib/XLSXSpliterator.d.ts +143 -0
  18. package/out/lib/XLSXSpliterator.d.ts.map +1 -0
  19. package/out/lib/XLSXSpliterator.js +161 -0
  20. package/out/lib/XLSXSpliterator.js.map +1 -0
  21. package/out/lib/core/AsyncSpliterator.d.ts +227 -0
  22. package/out/lib/core/AsyncSpliterator.d.ts.map +1 -0
  23. package/out/lib/core/AsyncSpliterator.js +510 -0
  24. package/out/lib/core/AsyncSpliterator.js.map +1 -0
  25. package/out/lib/core/BufferController.d.ts +77 -0
  26. package/out/lib/core/BufferController.d.ts.map +1 -0
  27. package/out/lib/core/BufferController.js +118 -0
  28. package/out/lib/core/BufferController.js.map +1 -0
  29. package/out/lib/core/CharacterSequence.d.ts +72 -0
  30. package/out/lib/core/CharacterSequence.d.ts.map +1 -0
  31. package/out/lib/core/CharacterSequence.js +347 -0
  32. package/out/lib/core/CharacterSequence.js.map +1 -0
  33. package/out/lib/core/CompositeDataView.d.ts +111 -0
  34. package/out/lib/core/CompositeDataView.d.ts.map +1 -0
  35. package/out/lib/core/CompositeDataView.js +241 -0
  36. package/out/lib/core/CompositeDataView.js.map +1 -0
  37. package/out/lib/core/IndexQueue.d.ts +48 -0
  38. package/out/lib/core/IndexQueue.d.ts.map +1 -0
  39. package/out/lib/core/IndexQueue.js +111 -0
  40. package/out/lib/core/IndexQueue.js.map +1 -0
  41. package/out/lib/core/SlidingWindow.d.ts +47 -0
  42. package/out/lib/core/SlidingWindow.d.ts.map +1 -0
  43. package/out/lib/core/SlidingWindow.js +63 -0
  44. package/out/lib/core/SlidingWindow.js.map +1 -0
  45. package/out/lib/core/Spliterator.d.ts +96 -0
  46. package/out/lib/core/Spliterator.d.ts.map +1 -0
  47. package/out/lib/core/Spliterator.js +330 -0
  48. package/out/lib/core/Spliterator.js.map +1 -0
  49. package/out/lib/core/wasm_base64.d.ts +19 -0
  50. package/out/lib/core/wasm_base64.d.ts.map +1 -0
  51. package/out/lib/core/wasm_base64.js +19 -0
  52. package/out/lib/core/wasm_base64.js.map +1 -0
  53. package/out/lib/core/wasm_module.d.ts +57 -0
  54. package/out/lib/core/wasm_module.d.ts.map +1 -0
  55. package/out/lib/core/wasm_module.js +34 -0
  56. package/out/lib/core/wasm_module.js.map +1 -0
  57. package/out/lib/formats/CSVSpliterator.d.ts +131 -0
  58. package/out/lib/formats/CSVSpliterator.d.ts.map +1 -0
  59. package/out/lib/formats/CSVSpliterator.js +172 -0
  60. package/out/lib/formats/CSVSpliterator.js.map +1 -0
  61. package/out/lib/formats/JSONSpliterator.d.ts +44 -0
  62. package/out/lib/formats/JSONSpliterator.d.ts.map +1 -0
  63. package/out/lib/formats/JSONSpliterator.js +77 -0
  64. package/out/lib/formats/JSONSpliterator.js.map +1 -0
  65. package/out/lib/formats/PSVSpliterator.d.ts +21 -0
  66. package/out/lib/formats/PSVSpliterator.d.ts.map +1 -0
  67. package/out/lib/formats/PSVSpliterator.js +22 -0
  68. package/out/lib/formats/PSVSpliterator.js.map +1 -0
  69. package/out/lib/formats/TSVSpliterator.d.ts +21 -0
  70. package/out/lib/formats/TSVSpliterator.d.ts.map +1 -0
  71. package/out/lib/formats/TSVSpliterator.js +22 -0
  72. package/out/lib/formats/TSVSpliterator.js.map +1 -0
  73. package/out/lib/formats/TextSpliterator.d.ts +53 -0
  74. package/out/lib/formats/TextSpliterator.d.ts.map +1 -0
  75. package/out/lib/formats/TextSpliterator.js +67 -0
  76. package/out/lib/formats/TextSpliterator.js.map +1 -0
  77. package/out/lib/formats/XLSXSpliterator.d.ts +143 -0
  78. package/out/lib/formats/XLSXSpliterator.d.ts.map +1 -0
  79. package/out/lib/formats/XLSXSpliterator.js +161 -0
  80. package/out/lib/formats/XLSXSpliterator.js.map +1 -0
  81. package/out/lib/formats/casing.d.ts +27 -0
  82. package/out/lib/formats/casing.d.ts.map +1 -0
  83. package/out/lib/formats/casing.js +68 -0
  84. package/out/lib/formats/casing.js.map +1 -0
  85. package/out/lib/formats/row-emitters.d.ts +35 -0
  86. package/out/lib/formats/row-emitters.d.ts.map +1 -0
  87. package/out/lib/formats/row-emitters.js +50 -0
  88. package/out/lib/formats/row-emitters.js.map +1 -0
  89. package/out/lib/internal/shared.d.ts +155 -0
  90. package/out/lib/internal/shared.d.ts.map +1 -0
  91. package/out/lib/internal/shared.js +41 -0
  92. package/out/lib/internal/shared.js.map +1 -0
  93. package/out/lib/internal/utils.d.ts +37 -0
  94. package/out/lib/internal/utils.d.ts.map +1 -0
  95. package/out/lib/internal/utils.js +39 -0
  96. package/out/lib/internal/utils.js.map +1 -0
  97. package/out/lib/io/adaptive-source.d.ts +39 -0
  98. package/out/lib/io/adaptive-source.d.ts.map +1 -0
  99. package/out/lib/io/adaptive-source.js +95 -0
  100. package/out/lib/io/adaptive-source.js.map +1 -0
  101. package/out/lib/io/writer.d.ts +45 -0
  102. package/out/lib/io/writer.d.ts.map +1 -0
  103. package/out/lib/io/writer.js +57 -0
  104. package/out/lib/io/writer.js.map +1 -0
  105. package/out/lib/iterators/AsyncSequence.d.ts +180 -0
  106. package/out/lib/iterators/AsyncSequence.d.ts.map +1 -0
  107. package/out/lib/iterators/AsyncSequence.js +432 -0
  108. package/out/lib/iterators/AsyncSequence.js.map +1 -0
  109. package/out/lib/iterators/chunks.d.ts +20 -0
  110. package/out/lib/iterators/chunks.d.ts.map +1 -0
  111. package/out/lib/iterators/chunks.js +36 -0
  112. package/out/lib/iterators/chunks.js.map +1 -0
  113. package/out/lib/iterators/pivot.d.ts +30 -0
  114. package/out/lib/iterators/pivot.d.ts.map +1 -0
  115. package/out/lib/iterators/pivot.js +47 -0
  116. package/out/lib/iterators/pivot.js.map +1 -0
  117. package/out/lib/iterators/zip.d.ts +33 -0
  118. package/out/lib/iterators/zip.d.ts.map +1 -0
  119. package/out/lib/iterators/zip.js +59 -0
  120. package/out/lib/iterators/zip.js.map +1 -0
  121. package/out/lib/parallel/merge-async-iterators.d.ts +12 -0
  122. package/out/lib/parallel/merge-async-iterators.d.ts.map +1 -0
  123. package/out/lib/parallel/merge-async-iterators.js +39 -0
  124. package/out/lib/parallel/merge-async-iterators.js.map +1 -0
  125. package/out/lib/parallel/parallel-map-runtime.d.ts +22 -0
  126. package/out/lib/parallel/parallel-map-runtime.d.ts.map +1 -0
  127. package/out/lib/parallel/parallel-map-runtime.js +60 -0
  128. package/out/lib/parallel/parallel-map-runtime.js.map +1 -0
  129. package/out/lib/parallel/parallel-map-worker-entry.d.ts +11 -0
  130. package/out/lib/parallel/parallel-map-worker-entry.d.ts.map +1 -0
  131. package/out/lib/parallel/parallel-map-worker-entry.js +41 -0
  132. package/out/lib/parallel/parallel-map-worker-entry.js.map +1 -0
  133. package/out/lib/parallel/parallel-map-workers.d.ts +57 -0
  134. package/out/lib/parallel/parallel-map-workers.d.ts.map +1 -0
  135. package/out/lib/parallel/parallel-map-workers.js +82 -0
  136. package/out/lib/parallel/parallel-map-workers.js.map +1 -0
  137. package/out/lib/parallel/parallel-map.d.ts +28 -0
  138. package/out/lib/parallel/parallel-map.d.ts.map +1 -0
  139. package/out/lib/parallel/parallel-map.js +30 -0
  140. package/out/lib/parallel/parallel-map.js.map +1 -0
  141. package/out/lib/parallel/segment-runtime.d.ts +27 -0
  142. package/out/lib/parallel/segment-runtime.d.ts.map +1 -0
  143. package/out/lib/parallel/segment-runtime.js +41 -0
  144. package/out/lib/parallel/segment-runtime.js.map +1 -0
  145. package/out/lib/parallel/segment-worker-entry.d.ts +10 -0
  146. package/out/lib/parallel/segment-worker-entry.d.ts.map +1 -0
  147. package/out/lib/parallel/segment-worker-entry.js +59 -0
  148. package/out/lib/parallel/segment-worker-entry.js.map +1 -0
  149. package/out/lib/parallel/segment-workers.d.ts +56 -0
  150. package/out/lib/parallel/segment-workers.d.ts.map +1 -0
  151. package/out/lib/parallel/segment-workers.js +110 -0
  152. package/out/lib/parallel/segment-workers.js.map +1 -0
  153. package/out/lib/parallel/segments.d.ts +31 -0
  154. package/out/lib/parallel/segments.d.ts.map +1 -0
  155. package/out/lib/parallel/segments.js +52 -0
  156. package/out/lib/parallel/segments.js.map +1 -0
  157. package/out/lib/row-emitters.d.ts +35 -0
  158. package/out/lib/row-emitters.d.ts.map +1 -0
  159. package/out/lib/row-emitters.js +50 -0
  160. package/out/lib/row-emitters.js.map +1 -0
  161. package/out/lib/wasm_base64.d.ts +4 -1
  162. package/out/lib/wasm_base64.d.ts.map +1 -1
  163. package/out/lib/wasm_base64.js +4 -1
  164. package/out/lib/wasm_base64.js.map +1 -1
  165. package/out/lib/wasm_module.d.ts +15 -0
  166. package/out/lib/wasm_module.d.ts.map +1 -1
  167. package/out/lib/wasm_module.js +2 -1
  168. package/out/lib/wasm_module.js.map +1 -1
  169. package/out/node/cli/commands/csv.d.ts +113 -0
  170. package/out/node/cli/commands/csv.d.ts.map +1 -1
  171. package/out/node/cli/commands/csv.js +34 -36
  172. package/out/node/cli/commands/csv.js.map +1 -1
  173. package/out/node/cli/commands/iterate.d.ts +92 -0
  174. package/out/node/cli/commands/iterate.d.ts.map +1 -1
  175. package/out/node/cli/commands/iterate.js +26 -28
  176. package/out/node/cli/commands/iterate.js.map +1 -1
  177. package/out/node/cli/commands/parallel.d.ts +102 -0
  178. package/out/node/cli/commands/parallel.d.ts.map +1 -0
  179. package/out/node/cli/commands/parallel.js +426 -0
  180. package/out/node/cli/commands/parallel.js.map +1 -0
  181. package/out/node/cli/index.js +5 -0
  182. package/out/node/cli/index.js.map +1 -1
  183. package/out/node/cli/spec.d.ts +51 -0
  184. package/out/node/cli/spec.d.ts.map +1 -0
  185. package/out/node/cli/spec.js +78 -0
  186. package/out/node/cli/spec.js.map +1 -0
  187. package/out/node/cli/utils.d.ts +36 -18
  188. package/out/node/cli/utils.d.ts.map +1 -1
  189. package/out/node/cli/utils.js +48 -39
  190. package/out/node/cli/utils.js.map +1 -1
  191. package/out/node/fs/index.d.ts +1 -1
  192. package/out/node/fs/index.d.ts.map +1 -1
  193. package/out/node/fs/index.js +1 -1
  194. package/out/node/fs/index.js.map +1 -1
  195. package/package.json +18 -8
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import { Spliterator } from "../core/Spliterator.js";
7
+ import { openDelimitedRows } from "../io/adaptive-source.js";
8
+ import { AsyncSequence } from "../iterators/AsyncSequence.js";
9
+ export class TextSpliterator {
10
+ constructor() {
11
+ throw new TypeError("Static class cannot be instantiated. Did you mean `TextSpliterator.from`?");
12
+ }
13
+ /**
14
+ * Synchronously yield delimited text from a byte array or string.
15
+ *
16
+ * @param source The source content to split.
17
+ * @param options The options to use when splitting the content.
18
+ *
19
+ * @yields Each slice of the source content.
20
+ * @see {@linkcode TextSpliterator.fromAsync} for asynchronous iteration with decoding.
21
+ * @see {@linkcode Spliterator.fromSync} for synchronous iteration without decoding.
22
+ */
23
+ static *from(source, { encoding, fatal, ignoreBOM, ...options } = {}) {
24
+ const decoder = new TextDecoder(encoding, { fatal, ignoreBOM });
25
+ let rowCursor = 0;
26
+ const spliterator = Spliterator.fromSync(source, options);
27
+ for (const row of spliterator) {
28
+ let decoded;
29
+ try {
30
+ decoded = decoder.decode(row);
31
+ }
32
+ catch (parsedError) {
33
+ const error = new SyntaxError(`Failed to decode data at row ${rowCursor}`);
34
+ error.cause = parsedError;
35
+ throw error;
36
+ }
37
+ yield decoded;
38
+ rowCursor++;
39
+ }
40
+ }
41
+ /**
42
+ * Asynchronously yield delimited text from a byte array or string.
43
+ *
44
+ * @param source The async data resource to split.
45
+ * @param options The options to use when splitting the content.
46
+ *
47
+ * @yields Each slice of the source content.
48
+ * @see {@linkcode TextSpliterator.from} for synchronous iteration with decoding.
49
+ * @see {@linkcode Spliterator.fromAsync} for asynchronous iteration without decoding.
50
+ */
51
+ static fromAsync(source, { encoding, fatal, ignoreBOM, ...options } = {}) {
52
+ const decoder = new TextDecoder(encoding, { fatal, ignoreBOM });
53
+ // Decoding is an op on the sequence, not a generator wrapped inside one. A wrapping generator adds an async frame
54
+ // per row on top of the sequence's own, which measured 297ms against 279ms over 500k rows.
55
+ return AsyncSequence.from(() => openDelimitedRows(source, options)).map((row, rowCursor) => {
56
+ try {
57
+ return decoder.decode(row);
58
+ }
59
+ catch (parsedError) {
60
+ const error = new SyntaxError(`Failed to decode data at row ${rowCursor}`);
61
+ error.cause = parsedError;
62
+ throw error;
63
+ }
64
+ });
65
+ }
66
+ }
67
+ //# sourceMappingURL=TextSpliterator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextSpliterator.js","sourceRoot":"","sources":["../../../lib/formats/TextSpliterator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAA6B,WAAW,EAAwB,MAAM,wBAAwB,CAAA;AAErG,OAAO,EAA2B,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAsB7D,MAAM,OAAgB,eAAe;IACpC;QACC,MAAM,IAAI,SAAS,CAAC,2EAA2E,CAAC,CAAA;IACjG,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,CAAC,IAAI,CACX,MAA8B,EAC9B,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,GAA0C,EAAE;QAEtF,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QAC/D,IAAI,SAAS,GAAG,CAAC,CAAA;QAEjB,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAEzD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC/B,IAAI,OAAe,CAAA;YAEnB,IAAI,CAAC;gBACJ,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC;YAAC,OAAO,WAAW,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAA;gBAC1E,KAAK,CAAC,KAAK,GAAG,WAAW,CAAA;gBAEzB,MAAM,KAAK,CAAA;YACZ,CAAC;YAED,MAAM,OAAO,CAAA;YAEb,SAAS,EAAE,CAAA;QACZ,CAAC;IACF,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,SAAS,CACf,MAAyB,EACzB,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,OAAO,EAAE,GAA6C,EAAE;QAEzF,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QAE/D,kHAAkH;QAClH,2FAA2F;QAC3F,OAAO,aAAa,CAAC,IAAI,CAAa,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE;YACtG,IAAI,CAAC;gBACJ,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC3B,CAAC;YAAC,OAAO,WAAW,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAA;gBAC1E,KAAK,CAAC,KAAK,GAAG,WAAW,CAAA;gBAEzB,MAAM,KAAK,CAAA;YACZ,CAAC;QACF,CAAC,CAAC,CAAA;IACH,CAAC;CACD"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import type { AsyncChunkIterator } from "../internal/shared.js";
7
+ import { AsyncSequence } from "../iterators/AsyncSequence.js";
8
+ import { type RowEmitter, type RowOutputMode, type RowTransformer, type RowTransformerEntry, type RowTransformerRecord, type RowTuple } from "./row-emitters.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/formats/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 "../iterators/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/formats/XLSXSpliterator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import type { CamelCase, SnakeCase } from "type-fest";
7
+ /**
8
+ * Converts a name to snake_case, unless the name is already in all caps.
9
+ */
10
+ export declare function smartSnakeCase<T extends string>(name: T): T extends Uppercase<T> ? T : SnakeCase<T>;
11
+ /**
12
+ * Converts a name to camelCase, unless the name is already in all caps.
13
+ */
14
+ export declare function smartCamelCase<T extends string>(name: T): T extends Uppercase<T> ? T : CamelCase<T>;
15
+ /**
16
+ * Predicate to determine if a given string is uniformly cased, i.e. all uppercase or all lowercase.
17
+ */
18
+ export declare function isUniformlyCased(input: string | null): boolean;
19
+ /**
20
+ * Capitalizes a string, unless the string is uniformly cased, or an email address.
21
+ */
22
+ export declare function smartCapitalCase(input: string): string;
23
+ /**
24
+ * Given an array of column names, normalize them to ensure they are unique and usable as object keys.
25
+ */
26
+ export declare function normalizeColumnNames(columnHeaders: Iterable<string>): string[];
27
+ //# sourceMappingURL=casing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"casing.d.ts","sourceRoot":"","sources":["../../../lib/formats/casing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErD;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAiBnG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAInG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAE9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,CAkB9E"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license MIT
4
+ * @author Teffen Ellis, et al.
5
+ */
6
+ import { camelCase, capitalCase, snakeCase } from "change-case";
7
+ /**
8
+ * Converts a name to snake_case, unless the name is already in all caps.
9
+ */
10
+ export function smartSnakeCase(name) {
11
+ const normalizedName = name
12
+ // Remove periods after capital letters, e.g. "U.S.A." -> "USA"
13
+ .replaceAll(/([A-Z])(\.+)/g, "$1")
14
+ .trim();
15
+ if (normalizedName.toUpperCase() === normalizedName) {
16
+ return name
17
+ // Replace all non-word characters with underscores...
18
+ .replaceAll(/\W{1,}/g, "_")
19
+ // ...and then replace all sequences of underscores with a single underscore.
20
+ .replaceAll(/_{2,}/g, "_");
21
+ }
22
+ return snakeCase(normalizedName);
23
+ }
24
+ /**
25
+ * Converts a name to camelCase, unless the name is already in all caps.
26
+ */
27
+ export function smartCamelCase(name) {
28
+ if (name.toUpperCase() === name)
29
+ return name;
30
+ return camelCase(name);
31
+ }
32
+ /**
33
+ * Predicate to determine if a given string is uniformly cased, i.e. all uppercase or all lowercase.
34
+ */
35
+ export function isUniformlyCased(input) {
36
+ return Boolean(input && (input === input.toUpperCase() || input === input.toLowerCase()));
37
+ }
38
+ /**
39
+ * Capitalizes a string, unless the string is uniformly cased, or an email address.
40
+ */
41
+ export function smartCapitalCase(input) {
42
+ if (input.includes("@"))
43
+ return input;
44
+ if (isUniformlyCased(input))
45
+ return input;
46
+ return capitalCase(input);
47
+ }
48
+ /**
49
+ * Given an array of column names, normalize them to ensure they are unique and usable as object keys.
50
+ */
51
+ export function normalizeColumnNames(columnHeaders) {
52
+ const columnInputCountMap = new Map();
53
+ const distinctColumns = new Set();
54
+ const keyableColumnNames = Iterator.from(columnHeaders).map(smartSnakeCase);
55
+ for (const columnHeader of keyableColumnNames) {
56
+ if (distinctColumns.has(columnHeader)) {
57
+ const headerCount = (columnInputCountMap.get(columnHeader) ?? 1) + 1;
58
+ columnInputCountMap.set(columnHeader, headerCount);
59
+ const uniqueColumnName = `${columnHeader}_${headerCount}`;
60
+ distinctColumns.add(uniqueColumnName);
61
+ }
62
+ else {
63
+ distinctColumns.add(columnHeader);
64
+ }
65
+ }
66
+ return Array.from(distinctColumns);
67
+ }
68
+ //# sourceMappingURL=casing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"casing.js","sourceRoot":"","sources":["../../../lib/formats/casing.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAG/D;;GAEG;AACH,MAAM,UAAU,cAAc,CAAmB,IAAO;IACvD,MAAM,cAAc,GAAG,IAAI;QAC1B,+DAA+D;SAC9D,UAAU,CAAC,eAAe,EAAE,IAAI,CAAC;SACjC,IAAI,EAAE,CAAA;IAER,IAAI,cAAc,CAAC,WAAW,EAAE,KAAK,cAAc,EAAE,CAAC;QACrD,OACC,IAAI;YACH,sDAAsD;aACrD,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC;YAC3B,6EAA6E;aAC5E,UAAU,CAAC,QAAQ,EAAE,GAAG,CAC1B,CAAA;IACF,CAAC;IAED,OAAO,SAAS,CAAC,cAAc,CAAQ,CAAA;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAmB,IAAO;IACvD,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI;QAAE,OAAO,IAAW,CAAA;IAEnD,OAAO,SAAS,CAAC,IAAI,CAAQ,CAAA;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAoB;IACpD,OAAO,OAAO,CAAC,KAAK,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;AAC1F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC7C,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAErC,IAAI,gBAAgB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAEzC,OAAO,WAAW,CAAC,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,aAA+B;IACnE,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAA;IACrD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAA;IACzC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IAE3E,KAAK,MAAM,YAAY,IAAI,kBAAkB,EAAE,CAAC;QAC/C,IAAI,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YACpE,mBAAmB,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;YAElD,MAAM,gBAAgB,GAAG,GAAG,YAAY,IAAI,WAAW,EAAE,CAAA;YACzD,eAAe,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;QACtC,CAAC;aAAM,CAAC;YACP,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAClC,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;AACnC,CAAC"}
@@ -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/formats/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 "../iterators/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/formats/row-emitters.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AA0B7C,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"}